#!/bin/sh # Usage function to display script options usage() { echo "Find files using ripgrep and open them in Neovim." echo "" echo "Usage: ${0##*/} [-s] [-i] [-l] [-p] [] " echo "" echo "Options:" echo " -h : Show this message" echo " -i : Perform a case-insensitive search (default)" echo " -l : List files associated with the given tag" echo " -p : Search for files in the specified project directories using the specified tag (default: PROJECT)" echo " -s : Perform a case-sensitive search" echo " [] : Optional tag for project mode, followed by the search query" echo "" echo "Examples:" echo " ${0##*/} -p TODO 'KEYWORD' # Search for 'KEYWORD' in files tagged with 'TODO' in the project directories" echo " ${0##*/} -l -p 'KEYWORD' # List files associated with the default 'PROJECT' tag and 'KEYWORD'" echo " ${0##*/} 'KEYWORD' # Open files containing 'KEYWORD' in nvim" exit 0 } search_term() { case_flag="$1" shift if ! command -v rga >/dev/null 2>&1; then echo "Error: 'rga' is not installed." >&2 exit 1 fi if ! command -v xclip >/dev/null 2>&1; then echo "Error: 'xclip' is not installed." >&2 exit 1 fi # Construct the preview command preview_cmd=$(printf "rga %s --pretty --context 10 '%s' {}" "$case_flag" "$*") rga_output=$(rga --follow --no-ignore --hidden --text --max-count=1 ${case_flag:+$case_flag} --files-with-matches --no-messages --glob '!**/.git/*' "$*") # Use fzf to select files files=$(echo "$rga_output" | fzf-tmux +m --preview="$preview_cmd" --reverse --multi --select-1 --exit-0) || return 1 # Check if files are selected if [ -z "$files" ]; then echo "No files selected." return 0 fi # copy target to the clipboard echo "$@" | xclip -selection clipboard 2>/dev/null openfiles "$files" # print the file names echo "$rga_output" } # Function to list and/or open all files associated with a given project tag list_or_open_project_files() { # Use the provided tag or default to "PROJECT" project_tag="${1:-PROJECT}: $2" # Define the project paths as a space-separated string project_paths="$HOME/.dotfiles $HOME/.local/src/suckless $HOME/Public/repos" # Use rga to find files containing the project tag across all project paths rga_output="" for path in $project_paths; do if [ -d "$path" ]; then rga_result=$(rga --follow --no-ignore --hidden --text --max-count=1 --files-with-matches --no-messages --glob '!**/.git/*' "$project_tag" "$path") rga_output="$rga_output $rga_result" fi done # Remove leading/trailing whitespace rga_output=$(echo "$rga_output" | sed 's/^[[:space:]]*//;s/[[:space:]]*$//') # Check if any files were found if [ -z "$rga_output" ]; then echo "No files found for tag $project_tag." return 0 fi # If the script was called in list mode, simply print the files if [ "$list_mode" -eq 1 ]; then echo "$rga_output" else # Otherwise, open the files with nvim set -- "$(printf "%s\n" "$rga_output")" openfiles "$@" fi } # Main function to handle options case_flag="--ignore-case" # Default to case-insensitive list_mode=0 project_mode=0 # Parse the options while getopts "silph" opt; do case $opt in s) case_flag="--case-sensitive" ;; # Case-sensitive i) case_flag="--ignore-case" ;; # Case-insensitive l) list_mode=1 ;; # List mode p) project_mode=1 ;; # Project mode h) usage ;; *) ;; esac done shift $((OPTIND - 1)) # Handle project mode search if [ "$project_mode" -eq 1 ]; then list_or_open_project_files "$1" "$2" else # Otherwise, call the common search function search_term "$case_flag" "$@" fi