diff options
Diffstat (limited to 'fedora/.local/bin/tmuxopen')
| -rwxr-xr-x | fedora/.local/bin/tmuxopen | 208 |
1 files changed, 208 insertions, 0 deletions
diff --git a/fedora/.local/bin/tmuxopen b/fedora/.local/bin/tmuxopen new file mode 100755 index 0000000..5362215 --- /dev/null +++ b/fedora/.local/bin/tmuxopen @@ -0,0 +1,208 @@ +#!/bin/sh + +wrapper() { + usage() { + echo "Search for files and open them in Neovim within tmux panes." + echo "" + echo "Usage: tmuxopen [OPTIONS]" + echo "" + echo "Options:" + echo " -h, --help : Show this help message" + echo "" + echo "Controls:" + echo " Tab Select files" + echo " Ctrl+f Search filenames" + echo " Ctrl+g Search file contents" + echo " Ctrl+d Search directories" + echo "" + echo "Environment Variables:" + echo " NVIM_SEARCH_REGISTRY Set to the search query, allowing Neovim to highlight matches" + echo "" + echo "Example:" + echo " tmuxopen # Run the normal search and open" + } + + get_fzf_output() { + # Create temporary files to store search state + tmp_files="/tmp/search-files-$$" + tmp_content_query="/tmp/search-content-query-$$" + + # Cleanup on exit + trap "rm -f $tmp_files $tmp_content_query" EXIT + + rg_fixed_bind="ctrl-g:transform-query( + echo {q} > $tmp_content_query; + echo {q} + )+reload( + rm -f $tmp_files; + rg --line-number --follow --fixed-strings --hidden --no-heading --color=always --smart-case --glob '!**/.git/**' --glob '!node_modules/**' {q} 2>/dev/null || true + )" + file_bind="ctrl-f:transform-query( + current_query={q}; + if [ ! -s $tmp_content_query ]; then + echo \$current_query > $tmp_content_query; + fi; + rg --hidden --follow --files-with-matches --no-messages --glob '!**/.git/**' --glob '!node_modules/**' -- \$current_query > $tmp_files; + )+reload( + if [ -s $tmp_files ]; then + if [ -n {q} ]; then + grep -i -- {q} $tmp_files || true; + else + cat $tmp_files; + fi | while IFS= read -r file; do + if [ -f \"\$file\" ]; then + echo \"\$file:1\"; + fi; + done; + else + echo 'No matching files found'; + fi + )" + if command -v fd >/dev/null 2>&1; then + dir_bind="ctrl-d:change-prompt(📁 )+reload(fd --follow --type d --hidden --absolute-path --color never --exclude .git --exclude node_modules --search-path \"\$PWD\")" + else + dir_bind="ctrl-d:change-prompt(📁 )+reload(find \"\$PWD\" -L -type d -name node_modules -prune -o -name .git -prune -o -type d -print)" + fi + + rg --line-number --follow --no-heading --color=always --smart-case --glob '!**/.git/**' --glob '!LICENSE' '' 2>/dev/null | + fzf-tmux \ + --ansi --multi --delimiter : \ + --reverse \ + --print-query \ + --preview 'bat --style=numbers --color=always --highlight-line {2} {1} 2>/dev/null || bat --color=always {} 2>/dev/null || ls -la {} 2>/dev/null || echo "Preview is not available."' \ + --preview-window 'right,55%,border-bottom,+{2}+3/3,~3' \ + --bind "$file_bind" \ + --bind "$rg_fixed_bind" \ + --bind "$dir_bind" \ + --bind 'ctrl-c:abort' \ + --header "^f filenames | ^g contents | ^d directories" \ + --prompt "🔎 " + } + + set_nvim_search_variable() { + raw_output="$1" + tmp_content_query="/tmp/search-content-query-$$" + if [ -f "$tmp_content_query" ]; then + saved_query=$(cat "$tmp_content_query" 2>/dev/null) + if [ -n "$saved_query" ]; then + export NVIM_SEARCH_REGISTRY="$saved_query" + return + fi + fi + query=$(echo "$raw_output" | head -n1) + export NVIM_SEARCH_REGISTRY="$query" + } + + open_files_in_nvim() { + pane="$1" + shift + file_indices="$*" + nvim_cmd="nvim" + for index in $file_indices; do + file=$(echo "$files" | awk -v idx="$index" '{print $idx}') + line=$(echo "$lines" | awk -v idx="$index" '{print $idx}') + nvim_cmd="$nvim_cmd +$line $file" + done + nvim_cmd="$nvim_cmd -c 'let @/=\"$NVIM_SEARCH_REGISTRY\"'" + tmux send-keys -t "$pane" "$nvim_cmd" C-m + } + + # Parse command line arguments + while [ "$#" -gt 0 ]; do + case "$1" in + -h | --help) + usage + exit 0 + ;; + *) + echo "Unknown option: $1" >&2 + usage + exit 1 + ;; + esac + done + + raw_output=$(get_fzf_output) + set_nvim_search_variable "$raw_output" + + # Split the newline-delimited output into an array, skipping the first line (query) + selections=$(echo "$raw_output" | sed 1d) + + if [ -z "$selections" ]; then + echo "No selections made" + exit 0 + fi + + files="" + lines="" + count=0 + + # Use a here document to avoid subshell issues + while IFS= read -r selection; do + file=$(echo "$selection" | awk -F: '{print $1}') + line=$(echo "$selection" | awk -F: '{print $2}') + if [ -f "$file" ]; then + files="$files $file" + lines="$lines $line" + count=$((count + 1)) + else + echo "File not found: $file" + fi + done <<EOF +$selections +EOF + + if [ "$count" -eq 0 ]; then + echo "No valid files selected" + exit 0 + fi + + if [ "$count" -eq 1 ]; then + open_files_in_nvim "$(tmux display-message -p '#P')" 1 + else + window_name="$(date +%s)" + tmux new-window -n "$window_name" + case "$count" in + 2) + tmux split-window -t "$window_name" -h -p 50 + open_files_in_nvim "$window_name.1" 1 + open_files_in_nvim "$window_name.2" 2 + tmux select-pane -t "$window_name.1" + ;; + 3) + tmux split-window -t "$window_name" -h -p 50 + tmux split-window -t "$window_name.2" -v -p 50 + open_files_in_nvim "$window_name.1" 1 + open_files_in_nvim "$window_name.2" 2 + open_files_in_nvim "$window_name.3" 3 + ;; + *) + tmux split-window -t "$window_name" -h -p 50 + tmux split-window -t "$window_name.1" -v -p 50 + tmux split-window -t "$window_name.3" -v -p 50 + open_files_in_nvim "$window_name.1" 1 + open_files_in_nvim "$window_name.2" 2 + open_files_in_nvim "$window_name.3" 3 + remaining_indices="" + for i in $(seq 4 "$count"); do + remaining_indices="$remaining_indices $i" + done + open_files_in_nvim "$window_name.4" "$remaining_indices" + ;; + esac + fi +} + +for cmd in rg fzf bat tmux nvim; do + if ! command -v $cmd >/dev/null 2>&1; then + echo "Error: $cmd not found" >&2 + exit 1 + fi +done + +if [ -z "$TMUX" ]; then + echo "Error: Not in a tmux session" >&2 + exit 1 +fi + +wrapper "$@" |
