Move tmux-plugins (tmux-prefix-highlight, tmux-copycat) to git submodules.
This commit is contained in:
6
.gitmodules
vendored
Normal file
6
.gitmodules
vendored
Normal file
@@ -0,0 +1,6 @@
|
||||
[submodule ".tmux/plugins/tmux-prefix-highlight"]
|
||||
path = .tmux/plugins/tmux-prefix-highlight
|
||||
url = https://github.com/tmux-plugins/tmux-prefix-highlight.git
|
||||
[submodule ".tmux/plugins/tmux-copycat"]
|
||||
path = .tmux/plugins/tmux-copycat
|
||||
url = https://github.com/tmux-plugins/tmux-copycat
|
||||
@@ -151,14 +151,14 @@ if-shell 'test "$(uname)" = "Darwin"' 'source ~/.tmux-osx.conf'
|
||||
##########################################
|
||||
|
||||
# prefix_highlight (https://github.com/tmux-plugins/tmux-prefix-highlight)
|
||||
run-shell ~/.tmux/prefix_highlight.tmux
|
||||
run-shell ~/.tmux/plugins/tmux-prefix-highlight/prefix_highlight.tmux
|
||||
set -g @prefix_highlight_fg 'white' # default is 'colour231'
|
||||
set -g @prefix_highlight_bg 'blue' # default is 'colour04'
|
||||
set -g @prefix_highlight_show_copy_mode 'on'
|
||||
set -g @prefix_highlight_copy_mode_attr 'fg=black,bg=yellow,bold' # default is 'fg=default,bg=yellow'
|
||||
|
||||
# tmux-copycat (https://github.com/tmux-plugins/tmux-copycat)
|
||||
run-shell ~/.tmux/copycat/copycat.tmux
|
||||
run-shell ~/.tmux/plugins/tmux-copycat/copycat.tmux
|
||||
set -g @copycat_search_C-d "[[:digit:]]+"
|
||||
set -g @copycat_search_C-f "(^|^\.|[[:space:]]|[[:space:]]\.|[[:space:]]\.\.|^\.\.)[[:alnum:]~_-]*/[][[:alnum:]_.#$%&+=/@-]*"
|
||||
set -g @copycat_search_C-u "(https?://|git@|git://|ssh://|ftp://|file:///)[[:alnum:]?=%/_.:,;~@!#$&()*+-]*"
|
||||
|
||||
@@ -1,68 +0,0 @@
|
||||
#!/usr/bin/env bash
|
||||
|
||||
CURRENT_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"
|
||||
|
||||
source "$CURRENT_DIR/scripts/variables.sh"
|
||||
source "$CURRENT_DIR/scripts/helpers.sh"
|
||||
source "$CURRENT_DIR/scripts/stored_search_helpers.sh"
|
||||
|
||||
# this function defines default stored searches
|
||||
set_default_stored_searches() {
|
||||
local file_search="$(get_tmux_option "$copycat_file_search_option" "$default_file_search_key")"
|
||||
local url_search="$(get_tmux_option "$copycat_url_search_option" "$default_url_search_key")"
|
||||
local digit_search="$(get_tmux_option "$copycat_digit_search_option" "$default_digit_search_key")"
|
||||
local hash_search="$(get_tmux_option "$copycat_hash_search_option" "$default_hash_search_key")"
|
||||
local ip_search="$(get_tmux_option "$copycat_ip_search_option" "$default_ip_search_key")"
|
||||
|
||||
if stored_search_not_defined "$url_search"; then
|
||||
tmux set-option -g "${COPYCAT_VAR_PREFIX}_${url_search}" "(https?://|git@|git://|ssh://|ftp://|file:///)[[:alnum:]?=%/_.:,;~@!#$&()*+-]*"
|
||||
fi
|
||||
if stored_search_not_defined "$file_search"; then
|
||||
tmux set-option -g "${COPYCAT_VAR_PREFIX}_${file_search}" "(^|^\.|[[:space:]]|[[:space:]]\.|[[:space:]]\.\.|^\.\.)[[:alnum:]~_-]*/[][[:alnum:]_.#$%&+=/@-]*"
|
||||
fi
|
||||
if stored_search_not_defined "$digit_search"; then
|
||||
tmux set-option -g "${COPYCAT_VAR_PREFIX}_${digit_search}" "[[:digit:]]+"
|
||||
fi
|
||||
if stored_search_not_defined "$hash_search"; then
|
||||
tmux set-option -g "${COPYCAT_VAR_PREFIX}_${hash_search}" "\b[0-9a-f]{7,40}\b"
|
||||
fi
|
||||
if stored_search_not_defined "$ip_search"; then
|
||||
tmux set-option -g "${COPYCAT_VAR_PREFIX}_${ip_search}" "[[:digit:]]{1,3}\.[[:digit:]]{1,3}\.[[:digit:]]{1,3}\.[[:digit:]]{1,3}"
|
||||
fi
|
||||
}
|
||||
|
||||
set_start_bindings() {
|
||||
set_default_stored_searches
|
||||
local stored_search_vars="$(stored_search_vars)"
|
||||
local search_var
|
||||
local key
|
||||
local pattern
|
||||
for search_var in $stored_search_vars; do
|
||||
key="$(get_stored_search_key "$search_var")"
|
||||
pattern="$(get_stored_search_pattern "$search_var")"
|
||||
tmux bind-key "$key" run-shell "$CURRENT_DIR/scripts/copycat_mode_start.sh '$pattern'"
|
||||
done
|
||||
}
|
||||
|
||||
set_copycat_search_binding() {
|
||||
local key_bindings=$(get_tmux_option "$copycat_search_option" "$default_copycat_search_key")
|
||||
local key
|
||||
for key in $key_bindings; do
|
||||
tmux bind-key "$key" run-shell "$CURRENT_DIR/scripts/copycat_search.sh"
|
||||
done
|
||||
}
|
||||
|
||||
set_copycat_git_special_binding() {
|
||||
local key_bindings=$(get_tmux_option "$copycat_git_search_option" "$default_git_search_key")
|
||||
local key
|
||||
for key in $key_bindings; do
|
||||
tmux bind-key "$key" run-shell "$CURRENT_DIR/scripts/copycat_git_special.sh #{pane_current_path}"
|
||||
done
|
||||
}
|
||||
|
||||
main() {
|
||||
set_start_bindings
|
||||
set_copycat_search_binding
|
||||
set_copycat_git_special_binding
|
||||
}
|
||||
main
|
||||
@@ -1,78 +0,0 @@
|
||||
#!/usr/bin/env bash
|
||||
|
||||
VERSION="$1"
|
||||
UNSUPPORTED_MSG="$2"
|
||||
|
||||
get_tmux_option() {
|
||||
local option=$1
|
||||
local default_value=$2
|
||||
local option_value=$(tmux show-option -gqv "$option")
|
||||
if [ -z "$option_value" ]; then
|
||||
echo "$default_value"
|
||||
else
|
||||
echo "$option_value"
|
||||
fi
|
||||
}
|
||||
|
||||
# Ensures a message is displayed for 5 seconds in tmux prompt.
|
||||
# Does not override the 'display-time' tmux option.
|
||||
display_message() {
|
||||
local message="$1"
|
||||
|
||||
# display_duration defaults to 5 seconds, if not passed as an argument
|
||||
if [ "$#" -eq 2 ]; then
|
||||
local display_duration="$2"
|
||||
else
|
||||
local display_duration="5000"
|
||||
fi
|
||||
|
||||
# saves user-set 'display-time' option
|
||||
local saved_display_time=$(get_tmux_option "display-time" "750")
|
||||
|
||||
# sets message display time to 5 seconds
|
||||
tmux set-option -gq display-time "$display_duration"
|
||||
|
||||
# displays message
|
||||
tmux display-message "$message"
|
||||
|
||||
# restores original 'display-time' value
|
||||
tmux set-option -gq display-time "$saved_display_time"
|
||||
}
|
||||
|
||||
# this is used to get "clean" integer version number. Examples:
|
||||
# `tmux 1.9` => `19`
|
||||
# `1.9a` => `19`
|
||||
get_digits_from_string() {
|
||||
local string="$1"
|
||||
local only_digits="$(echo "$string" | tr -dC '[:digit:]')"
|
||||
echo "$only_digits"
|
||||
}
|
||||
|
||||
tmux_version_int() {
|
||||
local tmux_version_string=$(tmux -V)
|
||||
echo "$(get_digits_from_string "$tmux_version_string")"
|
||||
}
|
||||
|
||||
unsupported_version_message() {
|
||||
if [ -n "$UNSUPPORTED_MSG" ]; then
|
||||
echo "$UNSUPPORTED_MSG"
|
||||
else
|
||||
echo "Error, Tmux version unsupported! Please install Tmux version $VERSION or greater!"
|
||||
fi
|
||||
}
|
||||
|
||||
exit_if_unsupported_version() {
|
||||
local current_version="$1"
|
||||
local supported_version="$2"
|
||||
if [ "$current_version" -lt "$supported_version" ]; then
|
||||
display_message "$(unsupported_version_message)"
|
||||
exit 1
|
||||
fi
|
||||
}
|
||||
|
||||
main() {
|
||||
local supported_version_int="$(get_digits_from_string "$VERSION")"
|
||||
local current_version_int="$(tmux_version_int)"
|
||||
exit_if_unsupported_version "$current_version_int" "$supported_version_int"
|
||||
}
|
||||
main
|
||||
@@ -1,57 +0,0 @@
|
||||
#!/usr/bin/env bash
|
||||
|
||||
CURRENT_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"
|
||||
|
||||
source "$CURRENT_DIR/helpers.sh"
|
||||
|
||||
search_pattern="$1"
|
||||
|
||||
capture_pane() {
|
||||
local file=$1
|
||||
# copying 9M lines back will hopefully fetch the whole scrollback
|
||||
tmux capture-pane -S -9000000 -p > "$file"
|
||||
}
|
||||
|
||||
# doing 2 things in 1 step so that we don't write to disk too much
|
||||
reverse_and_create_copycat_file() {
|
||||
local file=$1
|
||||
local copycat_file=$2
|
||||
local grep_pattern=$3
|
||||
(tac 2>/dev/null || tail -r) < "$file" | grep -oniE "$grep_pattern" > "$copycat_file"
|
||||
}
|
||||
|
||||
delete_old_files() {
|
||||
local scrollback_filename="$(get_scrollback_filename)"
|
||||
local copycat_filename="$(get_copycat_filename)"
|
||||
rm -f "$scrollback_filename" "$copycat_filename"
|
||||
}
|
||||
|
||||
generate_copycat_file() {
|
||||
local grep_pattern="$1"
|
||||
local scrollback_filename="$(get_scrollback_filename)"
|
||||
local copycat_filename="$(get_copycat_filename)"
|
||||
mkdir -p "$(_get_tmp_dir)"
|
||||
capture_pane "$scrollback_filename"
|
||||
reverse_and_create_copycat_file "$scrollback_filename" "$copycat_filename" "$grep_pattern"
|
||||
}
|
||||
|
||||
if_no_results_exit_with_message() {
|
||||
local copycat_filename="$(get_copycat_filename)"
|
||||
# check for empty filename
|
||||
if ! [ -s "$copycat_filename" ]; then
|
||||
display_message "No results!"
|
||||
exit 0
|
||||
fi
|
||||
}
|
||||
|
||||
main() {
|
||||
local grep_pattern="$1"
|
||||
if not_in_copycat_mode; then
|
||||
delete_old_files
|
||||
generate_copycat_file "$grep_pattern"
|
||||
if_no_results_exit_with_message
|
||||
set_copycat_mode
|
||||
copycat_increase_counter
|
||||
fi
|
||||
}
|
||||
main "$search_pattern"
|
||||
@@ -1,58 +0,0 @@
|
||||
#!/usr/bin/env bash
|
||||
|
||||
CURRENT_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"
|
||||
|
||||
PANE_CURRENT_PATH="$1"
|
||||
|
||||
source "$CURRENT_DIR/helpers.sh"
|
||||
|
||||
git_status_files() {
|
||||
local git_working_dir="$PANE_CURRENT_PATH"
|
||||
local git_dir="$PANE_CURRENT_PATH/.git"
|
||||
echo "$(git --git-dir="$git_dir" --work-tree="$git_working_dir" status --porcelain)"
|
||||
}
|
||||
|
||||
formatted_git_status() {
|
||||
local raw_gist_status="$(git_status_files)"
|
||||
echo "$(echo "$raw_gist_status" | cut -c 4-)"
|
||||
}
|
||||
|
||||
exit_if_no_results() {
|
||||
local results="$1"
|
||||
if [ -z "$results" ]; then
|
||||
display_message "No results!"
|
||||
exit 0
|
||||
fi
|
||||
}
|
||||
|
||||
concatenate_files() {
|
||||
local git_status_files="$(formatted_git_status)"
|
||||
exit_if_no_results "$git_status_files"
|
||||
|
||||
local result=""
|
||||
# Undefined until later within a while loop.
|
||||
local file_separator
|
||||
while read -r line; do
|
||||
result="${result}${file_separator}${line}"
|
||||
file_separator="|"
|
||||
done <<< "$git_status_files"
|
||||
echo "$result"
|
||||
}
|
||||
|
||||
# Creates one, big regex out of git status files.
|
||||
# Example:
|
||||
# `git status` shows files `foo.txt` and `bar.txt`
|
||||
# output regex will be:
|
||||
# `(foo.txt|bar.txt)
|
||||
git_status_files_regex() {
|
||||
local concatenated_files="$(concatenate_files)"
|
||||
local regex_result="(${concatenated_files})"
|
||||
echo "$regex_result"
|
||||
}
|
||||
|
||||
main() {
|
||||
local search_regex="$(git_status_files_regex)"
|
||||
# starts copycat mode
|
||||
$CURRENT_DIR/copycat_mode_start.sh "$search_regex"
|
||||
}
|
||||
main
|
||||
@@ -1,334 +0,0 @@
|
||||
#!/usr/bin/env bash
|
||||
|
||||
CURRENT_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"
|
||||
|
||||
source "$CURRENT_DIR/helpers.sh"
|
||||
|
||||
MAXIMUM_PADDING="25" # maximum padding below the result when it can't be centered
|
||||
|
||||
# jump to 'next' or 'prev' match
|
||||
# global var for this file
|
||||
NEXT_PREV="$1"
|
||||
|
||||
# 'vi' or 'emacs', this variable used as a global file constant
|
||||
TMUX_COPY_MODE="$(tmux_copy_mode)"
|
||||
|
||||
_file_number_of_lines() {
|
||||
local file="$1"
|
||||
echo "$(wc -l $file | $AWK_CMD '{print $1}')"
|
||||
}
|
||||
|
||||
_get_result_line() {
|
||||
local file="$1"
|
||||
local number="$2"
|
||||
echo "$(head -"$number" "$file" | tail -1)"
|
||||
}
|
||||
|
||||
_string_starts_with_digit() {
|
||||
local string="$1"
|
||||
echo "$string" |
|
||||
\grep -q '^[[:digit:]]\+:'
|
||||
}
|
||||
|
||||
_get_line_number() {
|
||||
local string="$1"
|
||||
local copycat_file="$2" # args 2 & 3 used to handle bug in OSX grep
|
||||
local position_number="$3"
|
||||
if _string_starts_with_digit "$string"; then
|
||||
# we have a number!
|
||||
local grep_line_number="$(echo "$string" | cut -f1 -d:)"
|
||||
# grep line number index starts from 1, tmux line number index starts from 0
|
||||
local tmux_line_number="$((grep_line_number - 1))"
|
||||
else
|
||||
# no number in the results line This is a bug in OSX grep.
|
||||
# Fetching a number from a previous line.
|
||||
local previous_line_num="$((position_number - 1))"
|
||||
local result_line="$(_get_result_line "$copycat_file" "$previous_line_num")"
|
||||
# recursively invoke this same function
|
||||
tmux_line_number="$(_get_line_number "$result_line" "$copycat_file" "$previous_line_num")"
|
||||
fi
|
||||
echo "$tmux_line_number"
|
||||
}
|
||||
|
||||
_get_match() {
|
||||
local string="$1"
|
||||
local full_match
|
||||
if _string_starts_with_digit "$string"; then
|
||||
full_match="$(echo "$string" | cut -f2- -d:)"
|
||||
else
|
||||
# This scenario handles OS X grep bug "no number in the results line".
|
||||
# When there's no number at the beginning of the line, we're taking the
|
||||
# whole line as a match. This handles the result line like this:
|
||||
# `http://www.example.com` (the `http` would otherwise get cut off)
|
||||
full_match="$string"
|
||||
fi
|
||||
echo -n "$full_match"
|
||||
}
|
||||
|
||||
_escape_backslash() {
|
||||
local string="$1"
|
||||
echo "$(echo "$string" | sed 's/\\/\\\\/g')"
|
||||
}
|
||||
|
||||
_get_match_line_position() {
|
||||
local file="$1"
|
||||
local line_number="$2"
|
||||
local match="$3"
|
||||
local adjusted_line_num=$((line_number + 1))
|
||||
local result_line=$(tail -"$adjusted_line_num" "$file" | head -1)
|
||||
|
||||
# OS X awk cannot have `=` as the first char in the variable (bug in awk).
|
||||
# If exists, changing the `=` character with `.` to avoid error.
|
||||
local platform="$(uname)"
|
||||
if [ "$platform" == "Darwin" ]; then
|
||||
result_line="$(echo "$result_line" | sed 's/^=/./')"
|
||||
match="$(echo "$match" | 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="$(_escape_backslash "$result_line")"
|
||||
match="$(_escape_backslash "$match")"
|
||||
|
||||
local index=$($AWK_CMD -v a="$result_line" -v b="$match" 'BEGIN{print index(a,b)}')
|
||||
local zero_index=$((index - 1))
|
||||
echo "$zero_index"
|
||||
}
|
||||
|
||||
_copycat_jump() {
|
||||
local line_number="$1"
|
||||
local match_line_position="$2"
|
||||
local match="$3"
|
||||
local scrollback_line_number="$4"
|
||||
_copycat_enter_mode
|
||||
_copycat_exit_select_mode
|
||||
_copycat_jump_to_line "$line_number" "$scrollback_line_number"
|
||||
_copycat_position_to_match_start "$match_line_position"
|
||||
_copycat_select "$match"
|
||||
}
|
||||
|
||||
_copycat_enter_mode() {
|
||||
tmux copy-mode
|
||||
}
|
||||
|
||||
# clears selection from a previous match
|
||||
_copycat_exit_select_mode() {
|
||||
if [ "$TMUX_COPY_MODE" == "vi" ]; then
|
||||
# vi mode
|
||||
tmux send-keys Escape
|
||||
else
|
||||
# emacs mode
|
||||
tmux send-keys C-g
|
||||
fi
|
||||
}
|
||||
|
||||
# "manually" go up in the scrollback for a number of lines
|
||||
_copycat_manually_go_up() {
|
||||
local line_number="$1"
|
||||
if [ "$TMUX_COPY_MODE" == "vi" ]; then
|
||||
# vi copy mode
|
||||
tmux send-keys "$line_number" k 0
|
||||
else
|
||||
# emacs copy mode
|
||||
for (( c=1; c<="$line_number"; c++ )); do
|
||||
tmux send-keys C-p
|
||||
done
|
||||
tmux send-keys C-a
|
||||
fi
|
||||
}
|
||||
|
||||
_copycat_create_padding_below_result() {
|
||||
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
|
||||
|
||||
if [ "$TMUX_COPY_MODE" == "vi" ]; then
|
||||
# vi copy mode
|
||||
tmux send-keys "$padding" j "$padding" k
|
||||
else
|
||||
# emacs copy mode
|
||||
for (( c=1; c<="$padding"; c++ )); do
|
||||
tmux send-keys C-n
|
||||
done
|
||||
for (( c=1; c<="$padding"; c++ )); do
|
||||
tmux send-keys C-p
|
||||
done
|
||||
fi
|
||||
}
|
||||
|
||||
# performs a jump to go to line
|
||||
_copycat_go_to_line_with_jump() {
|
||||
local line_number="$1"
|
||||
# first jumps to the "bottom" in copy mode so that jumps are consistent
|
||||
if [ "$TMUX_COPY_MODE" == "vi" ]; then
|
||||
# vi copy mode
|
||||
tmux send-keys G 0 :
|
||||
else
|
||||
# emacs copy mode
|
||||
tmux send-keys "M->" C-a g
|
||||
fi
|
||||
tmux send-keys "$line_number" C-m
|
||||
}
|
||||
|
||||
# maximum line number that can be reached via tmux 'jump'
|
||||
_get_max_jump() {
|
||||
local scrollback_line_number="$1"
|
||||
local window_height="$2"
|
||||
local max_jump=$((scrollback_line_number - $window_height))
|
||||
# max jump can't be lower than zero
|
||||
if [ "$max_jump" -lt "0" ]; then
|
||||
max_jump="0"
|
||||
fi
|
||||
echo "$max_jump"
|
||||
}
|
||||
|
||||
_copycat_jump_to_line() {
|
||||
local line_number="$1"
|
||||
local scrollback_line_number="$2"
|
||||
local window_height="$(tmux display-message -p '#{pane_height}')"
|
||||
local correct_line_number
|
||||
|
||||
local max_jump=$(_get_max_jump "$scrollback_line_number" "$window_height")
|
||||
local correction="0"
|
||||
|
||||
if [ "$line_number" -gt "$max_jump" ]; then
|
||||
# We need to 'reach' a line number that is not accessible via 'jump'.
|
||||
# Introducing 'correction'
|
||||
correct_line_number="$max_jump"
|
||||
correction=$((line_number - $correct_line_number))
|
||||
else
|
||||
# we can reach the desired line number via 'jump'. Correction not needed.
|
||||
correct_line_number="$line_number"
|
||||
fi
|
||||
|
||||
_copycat_go_to_line_with_jump "$correct_line_number"
|
||||
|
||||
if [ "$correction" -gt "0" ]; then
|
||||
_copycat_manually_go_up "$correction"
|
||||
fi
|
||||
|
||||
# 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
|
||||
_copycat_create_padding_below_result "$line_number" "$half_window_height"
|
||||
fi
|
||||
}
|
||||
|
||||
_copycat_position_to_match_start() {
|
||||
local match_line_position="$1"
|
||||
[ "$match_line_position" -eq "0" ] && return 0
|
||||
|
||||
if [ "$TMUX_COPY_MODE" == "vi" ]; then
|
||||
# vi copy mode
|
||||
tmux send-keys "$match_line_position" l
|
||||
else
|
||||
# emacs copy mode
|
||||
# emacs doesn't have repeat, so we're manually looping :(
|
||||
for (( c=1; c<="$match_line_position"; c++ )); do
|
||||
tmux send-keys C-f
|
||||
done
|
||||
fi
|
||||
}
|
||||
|
||||
_copycat_select() {
|
||||
local match="$1"
|
||||
local length="${#match}"
|
||||
if [ "$TMUX_COPY_MODE" == "vi" ]; then
|
||||
# vi copy mode
|
||||
tmux send-keys Space "$length" l h # selection correction for 1 char
|
||||
else
|
||||
# emacs copy mode
|
||||
tmux send-keys C-Space
|
||||
# emacs doesn't have repeat, so we're manually looping :(
|
||||
for (( c=1; c<="$length"; c++ )); do
|
||||
tmux send-keys C-f
|
||||
done
|
||||
# NO selection correction for emacs mode
|
||||
fi
|
||||
}
|
||||
|
||||
# all functions above are "private", called from `do_next_jump` function
|
||||
|
||||
get_new_position_number() {
|
||||
local copycat_file="$1"
|
||||
local current_position="$2"
|
||||
local new_position
|
||||
|
||||
# doing a forward/up jump
|
||||
if [ "$NEXT_PREV" == "next" ]; then
|
||||
local number_of_results=$(wc -l "$copycat_file" | $AWK_CMD '{ print $1 }')
|
||||
if [ "$current_position" -eq "$number_of_results" ]; then
|
||||
# position can't go beyond the last result
|
||||
new_position="$current_position"
|
||||
else
|
||||
new_position="$((current_position + 1))"
|
||||
fi
|
||||
|
||||
# doing a backward/down jump
|
||||
elif [ "$NEXT_PREV" == "prev" ]; then
|
||||
if [ "$current_position" -eq "1" ]; then
|
||||
# position can't go below 1
|
||||
new_position="1"
|
||||
else
|
||||
new_position="$((current_position - 1))"
|
||||
fi
|
||||
fi
|
||||
echo "$new_position"
|
||||
}
|
||||
|
||||
do_next_jump() {
|
||||
local position_number="$1"
|
||||
local copycat_file="$2"
|
||||
local scrollback_file="$3"
|
||||
|
||||
local scrollback_line_number=$(_file_number_of_lines "$scrollback_file")
|
||||
local result_line="$(_get_result_line "$copycat_file" "$position_number")"
|
||||
local line_number=$(_get_line_number "$result_line" "$copycat_file" "$position_number")
|
||||
local match=$(_get_match "$result_line")
|
||||
local match_line_position=$(_get_match_line_position "$scrollback_file" "$line_number" "$match")
|
||||
_copycat_jump "$line_number" "$match_line_position" "$match" "$scrollback_line_number"
|
||||
}
|
||||
|
||||
notify_about_first_last_match() {
|
||||
local current_position="$1"
|
||||
local next_position="$2"
|
||||
local message_duration="1500"
|
||||
|
||||
# if position didn't change, we are either on a 'first' or 'last' match
|
||||
if [ "$current_position" -eq "$next_position" ]; then
|
||||
if [ "$NEXT_PREV" == "next" ]; then
|
||||
display_message "Last match!" "$message_duration"
|
||||
elif [ "$NEXT_PREV" == "prev" ]; then
|
||||
display_message "First match!" "$message_duration"
|
||||
fi
|
||||
fi
|
||||
}
|
||||
|
||||
main() {
|
||||
if in_copycat_mode; then
|
||||
local copycat_file="$(get_copycat_filename)"
|
||||
local scrollback_file="$(get_scrollback_filename)"
|
||||
local current_position="$(get_copycat_position)"
|
||||
local next_position="$(get_new_position_number "$copycat_file" "$current_position")"
|
||||
do_next_jump "$next_position" "$copycat_file" "$scrollback_file"
|
||||
notify_about_first_last_match "$current_position" "$next_position"
|
||||
set_copycat_position "$next_position"
|
||||
fi
|
||||
}
|
||||
main
|
||||
@@ -1,40 +0,0 @@
|
||||
#!/usr/bin/env bash
|
||||
|
||||
CURRENT_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"
|
||||
|
||||
source "$CURRENT_DIR/helpers.sh"
|
||||
|
||||
# Extends a keyboard key.
|
||||
# Benefits: tmux won't report errors and everything will work fine even if the
|
||||
# script is deleted.
|
||||
extend_key() {
|
||||
local key="$1"
|
||||
local script="$2"
|
||||
|
||||
# 1. 'key' is sent to tmux. This ensures the default key action is done.
|
||||
# 2. Script is executed.
|
||||
# 3. `true` command ensures an exit status 0 is returned. This ensures a
|
||||
# user never gets an error msg - even if the script file from step 2 is
|
||||
# deleted.
|
||||
tmux bind-key -n "$key" run-shell "tmux send-keys '$key'; $script; true"
|
||||
}
|
||||
|
||||
copycat_cancel_bindings() {
|
||||
# keys that quit copy mode are enhanced to quit copycat mode as well.
|
||||
local cancel_mode_bindings=$(copycat_quit_copy_mode_keys)
|
||||
local key
|
||||
for key in $cancel_mode_bindings; do
|
||||
extend_key "$key" "$CURRENT_DIR/copycat_mode_quit.sh"
|
||||
done
|
||||
}
|
||||
|
||||
copycat_mode_bindings() {
|
||||
extend_key "$(copycat_next_key)" "$CURRENT_DIR/copycat_jump.sh 'next'"
|
||||
extend_key "$(copycat_prev_key)" "$CURRENT_DIR/copycat_jump.sh 'prev'"
|
||||
}
|
||||
|
||||
main() {
|
||||
copycat_mode_bindings
|
||||
copycat_cancel_bindings
|
||||
}
|
||||
main
|
||||
@@ -1,36 +0,0 @@
|
||||
#!/usr/bin/env bash
|
||||
|
||||
CURRENT_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"
|
||||
|
||||
source "$CURRENT_DIR/helpers.sh"
|
||||
|
||||
unbind_cancel_bindings() {
|
||||
local cancel_mode_bindings=$(copycat_quit_copy_mode_keys)
|
||||
local key
|
||||
for key in $cancel_mode_bindings; do
|
||||
tmux unbind-key -n "$key"
|
||||
done
|
||||
}
|
||||
|
||||
unbind_prev_next_bindings() {
|
||||
tmux unbind-key -n "$(copycat_next_key)"
|
||||
tmux unbind-key -n "$(copycat_prev_key)"
|
||||
}
|
||||
|
||||
unbind_all_bindings() {
|
||||
unbind_cancel_bindings
|
||||
unbind_prev_next_bindings
|
||||
}
|
||||
|
||||
main() {
|
||||
if in_copycat_mode; then
|
||||
reset_copycat_position
|
||||
unset_copycat_mode
|
||||
copycat_decrease_counter
|
||||
# removing all bindings only if no panes are in copycat mode
|
||||
if copycat_counter_zero; then
|
||||
unbind_all_bindings
|
||||
fi
|
||||
fi
|
||||
}
|
||||
main
|
||||
@@ -1,21 +0,0 @@
|
||||
#!/usr/bin/env bash
|
||||
|
||||
CURRENT_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"
|
||||
|
||||
SUPPORTED_VERSION="1.9"
|
||||
|
||||
PATTERN="$1"
|
||||
|
||||
supported_tmux_version_ok() {
|
||||
$CURRENT_DIR/check_tmux_version.sh "$SUPPORTED_VERSION"
|
||||
}
|
||||
|
||||
main() {
|
||||
local pattern="$1"
|
||||
if supported_tmux_version_ok; then
|
||||
$CURRENT_DIR/copycat_generate_results.sh "$pattern" # will `exit 0` if no results
|
||||
$CURRENT_DIR/copycat_mode_bindings.sh
|
||||
$CURRENT_DIR/copycat_jump.sh 'next'
|
||||
fi
|
||||
}
|
||||
main "$PATTERN"
|
||||
@@ -1,8 +0,0 @@
|
||||
#!/usr/bin/env bash
|
||||
|
||||
CURRENT_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"
|
||||
|
||||
main() {
|
||||
tmux command-prompt -p "copycat search:" "run-shell \"$CURRENT_DIR/copycat_mode_start.sh '%1'\""
|
||||
}
|
||||
main
|
||||
@@ -1,184 +0,0 @@
|
||||
# config options
|
||||
|
||||
default_next_key="n"
|
||||
tmux_option_next="@copycat_next"
|
||||
|
||||
default_prev_key="N"
|
||||
tmux_option_prev="@copycat_prev"
|
||||
|
||||
# keeps track of number of panes in copycat mode
|
||||
tmux_option_counter="@copycat_counter"
|
||||
|
||||
# === awk vs gawk ===
|
||||
command_exists() {
|
||||
command -v "$@" > /dev/null 2>&1
|
||||
}
|
||||
AWK_CMD='awk'
|
||||
if command_exists gawk; then
|
||||
AWK_CMD='gawk'
|
||||
fi
|
||||
|
||||
# === general helpers ===
|
||||
|
||||
get_tmux_option() {
|
||||
local option=$1
|
||||
local default_value=$2
|
||||
local option_value=$(tmux show-option -gqv "$option")
|
||||
if [ -z "$option_value" ]; then
|
||||
echo "$default_value"
|
||||
else
|
||||
echo "$option_value"
|
||||
fi
|
||||
}
|
||||
|
||||
set_tmux_option() {
|
||||
local option=$1
|
||||
local value=$2
|
||||
tmux set-option -gq "$option" "$value"
|
||||
}
|
||||
|
||||
tmux_copy_mode() {
|
||||
tmux show-option -gwv mode-keys
|
||||
}
|
||||
|
||||
# === copycat mode specific helpers ===
|
||||
|
||||
set_copycat_mode() {
|
||||
set_tmux_option "$(_copycat_mode_var)" "true"
|
||||
}
|
||||
|
||||
unset_copycat_mode() {
|
||||
set_tmux_option "$(_copycat_mode_var)" "false"
|
||||
}
|
||||
|
||||
in_copycat_mode() {
|
||||
local copycat_mode=$(get_tmux_option "$(_copycat_mode_var)" "false")
|
||||
[ "$copycat_mode" == "true" ]
|
||||
}
|
||||
|
||||
not_in_copycat_mode() {
|
||||
if in_copycat_mode; then
|
||||
return 1
|
||||
else
|
||||
return 0
|
||||
fi
|
||||
}
|
||||
|
||||
# === copycat mode position ===
|
||||
|
||||
get_copycat_position() {
|
||||
local copycat_position_variable=$(_copycat_position_var)
|
||||
echo $(get_tmux_option "$copycat_position_variable" "0")
|
||||
}
|
||||
|
||||
set_copycat_position() {
|
||||
local position="$1"
|
||||
local copycat_position_variable=$(_copycat_position_var)
|
||||
set_tmux_option "$copycat_position_variable" "$position"
|
||||
}
|
||||
|
||||
reset_copycat_position() {
|
||||
set_copycat_position "0"
|
||||
}
|
||||
|
||||
# === scrollback and results position ===
|
||||
|
||||
get_scrollback_filename() {
|
||||
echo "$(_get_tmp_dir)/scrollback-$(_pane_unique_id)"
|
||||
}
|
||||
|
||||
get_copycat_filename() {
|
||||
echo "$(_get_tmp_dir)/results-$(_pane_unique_id)"
|
||||
}
|
||||
|
||||
# Ensures a message is displayed for 5 seconds in tmux prompt.
|
||||
# Does not override the 'display-time' tmux option.
|
||||
display_message() {
|
||||
local message="$1"
|
||||
|
||||
# display_duration defaults to 5 seconds, if not passed as an argument
|
||||
if [ "$#" -eq 2 ]; then
|
||||
local display_duration="$2"
|
||||
else
|
||||
local display_duration="5000"
|
||||
fi
|
||||
|
||||
# saves user-set 'display-time' option
|
||||
local saved_display_time=$(get_tmux_option "display-time" "750")
|
||||
|
||||
# sets message display time to 5 seconds
|
||||
tmux set-option -gq display-time "$display_duration"
|
||||
|
||||
# displays message
|
||||
tmux display-message "$message"
|
||||
|
||||
# restores original 'display-time' value
|
||||
tmux set-option -gq display-time "$saved_display_time"
|
||||
}
|
||||
|
||||
# === counter functions ===
|
||||
|
||||
copycat_increase_counter() {
|
||||
local count=$(get_tmux_option "$tmux_option_counter" "0")
|
||||
local new_count="$((count + 1))"
|
||||
set_tmux_option "$tmux_option_counter" "$new_count"
|
||||
}
|
||||
|
||||
copycat_decrease_counter() {
|
||||
local count="$(get_tmux_option "$tmux_option_counter" "0")"
|
||||
if [ "$count" -gt "0" ]; then
|
||||
# decreasing the counter only if it won't go below 0
|
||||
local new_count="$((count - 1))"
|
||||
set_tmux_option "$tmux_option_counter" "$new_count"
|
||||
fi
|
||||
}
|
||||
|
||||
copycat_counter_zero() {
|
||||
local count="$(get_tmux_option "$tmux_option_counter" "0")"
|
||||
[ "$count" -eq "0" ]
|
||||
}
|
||||
|
||||
# === key binding functions ===
|
||||
|
||||
copycat_next_key() {
|
||||
echo "$(get_tmux_option "$tmux_option_next" "$default_next_key")"
|
||||
}
|
||||
|
||||
copycat_prev_key() {
|
||||
echo "$(get_tmux_option "$tmux_option_prev" "$default_prev_key")"
|
||||
}
|
||||
|
||||
# function expected output: 'C-c Enter q'
|
||||
copycat_quit_copy_mode_keys() {
|
||||
local commands_that_quit_copy_mode="cancel\|copy-selection\|copy-pipe"
|
||||
local copy_mode="$(tmux_copy_mode)-copy"
|
||||
tmux list-keys -t "$copy_mode" |
|
||||
\grep "$commands_that_quit_copy_mode" |
|
||||
$AWK_CMD '{ print $4}' |
|
||||
sort -u |
|
||||
sed 's/C-j//g' |
|
||||
xargs echo
|
||||
}
|
||||
|
||||
# === 'private' functions ===
|
||||
|
||||
_copycat_mode_var() {
|
||||
local pane_id="$(_pane_unique_id)"
|
||||
echo "@copycat_mode_$pane_id"
|
||||
}
|
||||
|
||||
_copycat_position_var() {
|
||||
local pane_id="$(_pane_unique_id)"
|
||||
echo "@copycat_position_$pane_id"
|
||||
}
|
||||
|
||||
_get_tmp_dir() {
|
||||
echo "${TMPDIR:-/tmp}/tmux-$EUID-copycat"
|
||||
}
|
||||
|
||||
# returns a string unique to current pane
|
||||
# sed removes `$` sign because `session_id` contains is
|
||||
_pane_unique_id() {
|
||||
tmux display-message -p "#{session_id}-#{window_index}-#{pane_index}" |
|
||||
sed 's/\$//'
|
||||
}
|
||||
@@ -1,23 +0,0 @@
|
||||
stored_search_not_defined() {
|
||||
local key="$1"
|
||||
local search_value="$(tmux show-option -gqv "${COPYCAT_VAR_PREFIX}_${key}")"
|
||||
[ -z $search_value ]
|
||||
}
|
||||
|
||||
stored_search_vars() {
|
||||
tmux show-options -g |
|
||||
\grep -i "^${COPYCAT_VAR_PREFIX}_" |
|
||||
cut -d ' ' -f1 | # cut just variable names
|
||||
xargs # splat var names in one line
|
||||
}
|
||||
|
||||
# get the search key from the variable name
|
||||
get_stored_search_key() {
|
||||
local search_var="$1"
|
||||
echo "$(echo "$search_var" | sed "s/^${COPYCAT_VAR_PREFIX}_//")"
|
||||
}
|
||||
|
||||
get_stored_search_pattern() {
|
||||
local search_var="$1"
|
||||
echo "$(get_tmux_option "$search_var" "")"
|
||||
}
|
||||
@@ -1,26 +0,0 @@
|
||||
# stored search variable prefix
|
||||
COPYCAT_VAR_PREFIX="@copycat_search"
|
||||
|
||||
# basic search
|
||||
default_copycat_search_key="/"
|
||||
copycat_search_option="@copycat_search"
|
||||
|
||||
# git special search
|
||||
default_git_search_key="C-g"
|
||||
copycat_git_search_option="@copycat_git_special"
|
||||
|
||||
# regular searches
|
||||
default_file_search_key="C-f"
|
||||
copycat_file_search_option="@copycat_file_search"
|
||||
|
||||
default_url_search_key="C-u"
|
||||
copycat_url_search_option="@copycat_url_search"
|
||||
|
||||
default_digit_search_key="C-d"
|
||||
copycat_digit_search_option="@copycat_digit_search"
|
||||
|
||||
default_hash_search_key="M-h"
|
||||
copycat_hash_search_option="@copycat_hash_search"
|
||||
|
||||
default_ip_search_key="M-i"
|
||||
copycat_ip_search_option="@copycat_ip_search"
|
||||
1
.tmux/plugins/tmux-copycat
Submodule
1
.tmux/plugins/tmux-copycat
Submodule
Submodule .tmux/plugins/tmux-copycat added at dd24d3623b
1
.tmux/plugins/tmux-prefix-highlight
Submodule
1
.tmux/plugins/tmux-prefix-highlight
Submodule
Submodule .tmux/plugins/tmux-prefix-highlight added at b64828f858
@@ -1,70 +0,0 @@
|
||||
#!/usr/bin/env bash
|
||||
|
||||
set -e
|
||||
|
||||
# Place holder for status left/right
|
||||
place_holder="\#{prefix_highlight}"
|
||||
|
||||
# Possible configurations
|
||||
fg_color_config='@prefix_highlight_fg'
|
||||
bg_color_config='@prefix_highlight_bg'
|
||||
show_copy_config='@prefix_highlight_show_copy_mode'
|
||||
copy_attr_config='@prefix_highlight_copy_mode_attr'
|
||||
|
||||
# Defaults
|
||||
default_fg='colour231'
|
||||
default_bg='colour04'
|
||||
default_copy_attr='fg=default,bg=yellow'
|
||||
|
||||
tmux_option() {
|
||||
local -r value=$(tmux show-option -gqv "$1")
|
||||
local -r default="$2"
|
||||
|
||||
if [ ! -z "$value" ]; then
|
||||
echo "$value"
|
||||
else
|
||||
echo "$default"
|
||||
fi
|
||||
}
|
||||
|
||||
highlight() {
|
||||
local -r \
|
||||
status="$1" \
|
||||
prefix="$2" \
|
||||
prefix_highlight="$3" \
|
||||
show_copy_mode="$4" \
|
||||
copy_highlight="$5"
|
||||
|
||||
local -r status_value="$(tmux_option "$status")"
|
||||
|
||||
if [[ "on" = "$show_copy_mode" ]]; then
|
||||
local -r fallback="${copy_highlight}#{?pane_in_mode,Copy,}"
|
||||
else
|
||||
local -r fallback=""
|
||||
fi
|
||||
|
||||
local -r highlight_on_prefix="${prefix_highlight}#{?client_prefix, $prefix ,$fallback}#[default]"
|
||||
tmux set-option -gq "$status" "${status_value/$place_holder/$highlight_on_prefix}"
|
||||
}
|
||||
|
||||
main() {
|
||||
local -r \
|
||||
prefix=$(tmux_option prefix) \
|
||||
fg_color=$(tmux_option "$fg_color_config" "$default_fg") \
|
||||
bg_color=$(tmux_option "$bg_color_config" "$default_bg") \
|
||||
show_copy_mode=$(tmux_option "$show_copy_config" "off") \
|
||||
copy_attr=$(tmux_option "$copy_attr_config" "$default_copy_attr")
|
||||
|
||||
local -r short_prefix=$(
|
||||
echo "$prefix" | tr "[:lower:]" "[:upper:]" | sed 's/C-/\^/'
|
||||
)
|
||||
|
||||
local -r \
|
||||
prefix_highlight="#[fg=$fg_color,bg=$bg_color]" \
|
||||
copy_highlight="${copy_attr:+#[default,$copy_attr]}"
|
||||
|
||||
highlight "status-right" "$short_prefix" "$prefix_highlight" "$show_copy_mode" "$copy_highlight"
|
||||
highlight "status-left" "$short_prefix" "$prefix_highlight" "$show_copy_mode" "$copy_highlight"
|
||||
}
|
||||
|
||||
main
|
||||
Reference in New Issue
Block a user