#!/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 </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 "$@"