mirror of
https://github.com/roosta/tmux-fuzzback.git
synced 2026-09-10 07:36:29 -04:00
Add tmux-test as a submodule Run tmux test setup script Fix example test Move scripts to scripts subfolder WIP Remove submodule WIP Change dist to xenial Ignore log files Remove sourcing bashrc Use xenial as dist Attempt to install fzf under vagrant user Add fzf to path WIP Fix expect script Comments Move provisions to separate folder Move fixtures to separate folder Set TERM to prevent tmux errors WIP Enable checking pos properly WIP Ensure display-message works Test fuzzback Add checker to assert_pos WIP: add more assertions WIP: fix running multiple assertions Change TERM to tmux-256color Fix issue with fuzzback position Move quit call to associated function Assert scroll position Dont export TERM Include tmux-test in license Update top level comment Mention where its copied from Update header comment Fix issue with fuzz that caused return to not work Make create_output take n argument Fix top of pane tests Rearrange copy-mode assertion Caused issues with cursor_pos when it was before that assertion Set mode-keys to vi Add middle search tests Update puts comments, reorder some assertions Change tests failed message Fix issue with checking mode Simplify display_text Remove unused functions Fix header lengths Cleanup, refactor Rename _private functions, no distinction Remove empty git modules file Fix issue with window height passthrough
179 lines
5.3 KiB
Bash
Executable file
179 lines
5.3 KiB
Bash
Executable file
#!/usr/bin/env bash
|
|
# shellcheck disable=SC2001
|
|
|
|
# Strict mode
|
|
# http://redsymbol.net/articles/unofficial-bash-strict-mode/
|
|
set -uo pipefail
|
|
IFS=$'\n\t'
|
|
|
|
# Pull in helpers
|
|
CURRENT_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"
|
|
# shellcheck source=helpers.sh
|
|
. "$CURRENT_DIR/helpers.sh"
|
|
|
|
fuzzback::fzf_cmd() {
|
|
fzf-tmux --delimiter=":" \
|
|
--ansi \
|
|
--with-nth="2.." \
|
|
--no-multi \
|
|
--no-sort \
|
|
--no-preview \
|
|
--print-query
|
|
}
|
|
|
|
# Move cursor up in scrollback buffer, used when goto_line fails and we have to
|
|
# correct
|
|
fuzzback::cursor_up() {
|
|
local line_number
|
|
line_number="$1"
|
|
tmux send-keys -X -N "$line_number" cursor-up
|
|
}
|
|
|
|
# https://github.com/tmux-plugins/tmux-copycat/blob/d7f7e6c1de0bc0d6915f4beea5be6a8a42045c09/scripts/copycat_jump.sh#L68
|
|
fuzzback::escape_backslash() {
|
|
local string="$1"
|
|
echo "$string" | sed 's/\\/\\\\/g'
|
|
}
|
|
|
|
# Get columns position of search query
|
|
# https://github.com/tmux-plugins/tmux-copycat/blob/d7f7e6c1de0bc0d6915f4beea5be6a8a42045c09/scripts/copycat_jump.sh#L73
|
|
fuzzback::query_column() {
|
|
local query="$1"
|
|
local result_line="$2"
|
|
local column zero_index platform
|
|
|
|
# OS X awk cannot have `=` as the first char in the variable (bug in awk).
|
|
# If exists, changing the `=` character with `.` to avoid error.
|
|
platform="$(uname)"
|
|
if [ "$platform" == "Darwin" ]; then
|
|
result_line="$(echo "$result_line" | sed 's/^=/./')"
|
|
query="$(echo "$query" | sed 's/^=/./')"
|
|
fi
|
|
|
|
# awk treats \r, \n, \t etc as single characters and that messes up match
|
|
# highlighting. For that reason, we're escaping backslashes so above chars
|
|
# are treated literally.
|
|
result_line="$(fuzzback::escape_backslash "$result_line")"
|
|
query="$(fuzzback::escape_backslash "$query")"
|
|
|
|
column=$($AWK_CMD -v a="$result_line" -v b="$query" 'BEGIN{print index(a,b)}')
|
|
zero_index=$((column - 1))
|
|
echo "$zero_index"
|
|
}
|
|
|
|
# maximum line number that can be reached via tmux goto-line
|
|
# https://github.com/tmux-plugins/tmux-copycat/blob/e95528ebaeb6300d8620c8748a686b786056f374/scripts/copycat_jump.sh#L159
|
|
fuzzback::get_max_jump() {
|
|
local max_jump max_lines window_height
|
|
local max_lines="$1"
|
|
local window_height="$2"
|
|
max_jump=$((max_lines - window_height))
|
|
# max jump can't be lower than zero
|
|
if [ "$max_jump" -lt "0" ]; then
|
|
max_jump="0"
|
|
fi
|
|
echo "$max_jump"
|
|
}
|
|
|
|
# Goto line in scrollback buffer
|
|
fuzzback::goto_line() {
|
|
local line_number="$1"
|
|
tmux send-keys -X goto-line "$line_number"
|
|
}
|
|
|
|
# Center result on screen
|
|
# https://github.com/tmux-plugins/tmux-copycat/blob/e95528ebaeb6300d8620c8748a686b786056f374/scripts/copycat_jump.sh#L127
|
|
fuzzback::center() {
|
|
local number_of_lines="$1"
|
|
local maximum_padding="$2"
|
|
local padding
|
|
|
|
# Padding should not be greater than half pane height
|
|
# (it wouldn't be centered then).
|
|
if [ "$number_of_lines" -gt "$maximum_padding" ]; then
|
|
padding="$maximum_padding"
|
|
else
|
|
padding="$number_of_lines"
|
|
fi
|
|
|
|
# cannot create padding, exit function
|
|
if [ "$padding" -eq "0" ]; then
|
|
return
|
|
fi
|
|
|
|
tmux send-keys -X -N "$padding" cursor-down
|
|
tmux send-keys -X -N "$padding" cursor-up
|
|
}
|
|
|
|
fuzzback::get_line_number() {
|
|
local position line_number
|
|
position=$(echo "$1" | cut -d':' -f1 | tr -d '[:space:]')
|
|
line_number=$((position - 1))
|
|
echo "$line_number"
|
|
}
|
|
|
|
main() {
|
|
|
|
local content match line_number window_height query max_lines max_jump
|
|
local correction correct_line_number trimmed_line column
|
|
|
|
content="$(tmux capture-pane -e -p -S -)"
|
|
match=$(echo "$content" | tac | nl -b 'a' -s ':' | fuzzback::fzf_cmd)
|
|
|
|
if [ -n "$match" ]; then
|
|
|
|
query=$(echo "$match" | cut -d$'\n' -f1)
|
|
rest=$(echo "$match" | cut -d$'\n' -f2)
|
|
trimmed_line=$(echo "$rest" | sed 's/[[:space:]]\+[[:digit:]]\+://')
|
|
line_number=$(fuzzback::get_line_number "$rest")
|
|
window_height="$(tmux display-message -p '#{pane_height}')"
|
|
max_lines=$(echo "$content" | wc -l)
|
|
max_jump=$(fuzzback::get_max_jump "$max_lines" "$window_height")
|
|
correction="0"
|
|
column=$(fuzzback::query_column "$query" "$trimmed_line")
|
|
|
|
# To go line
|
|
# -----------------
|
|
if [ "$line_number" -gt "$max_jump" ]; then
|
|
# We need to reach a line number that is not accessible via goto-line.
|
|
# So we need to correct position to reach the desired line number
|
|
correct_line_number="$max_jump"
|
|
correction=$((line_number - correct_line_number))
|
|
else
|
|
# we can reach the desired line number via goto-line. Correction not
|
|
# needed.
|
|
correct_line_number="$line_number"
|
|
fi
|
|
|
|
tmux copy-mode
|
|
fuzzback::goto_line "$correct_line_number"
|
|
|
|
# Correct if needed
|
|
if [ "$correction" -gt "0" ]; then
|
|
fuzzback::cursor_up "$correction"
|
|
fi
|
|
|
|
# Set cursor to start of line when all vertical movement is done
|
|
tmux send-keys -X start-of-line
|
|
|
|
# Centering
|
|
# -------------
|
|
# If no corrections (meaning result is not at the top of scrollback)
|
|
# we can then 'center' the result within a pane.
|
|
if [ "$correction" -eq "0" ]; then
|
|
local half_window_height="$((window_height / 2))"
|
|
# creating as much padding as possible, up to half pane height
|
|
fuzzback::center "$line_number" "$half_window_height"
|
|
fi
|
|
|
|
# Move to column
|
|
# ------------------
|
|
if [ "$column" -gt "0" ]; then
|
|
tmux send-keys -X -N "$column" cursor-right
|
|
fi
|
|
|
|
fi
|
|
}
|
|
|
|
main
|