From 4f90e22f58d2142b99f3d350dd69305aebe8a2bf Mon Sep 17 00:00:00 2001 From: Tyrel Souza Date: Wed, 5 Oct 2022 10:10:20 -0400 Subject: [PATCH] plugins, and shell aliases break apart --- .../completions/fzf_configure_bindings.fish | 7 +++ config/fish/conf.d/fish-ssh-agent.fish | 7 +++ config/fish/conf.d/fzf.fish | 28 +++++++++++ config/fish/config.fish | 10 +++- config/fish/fish_plugins | 3 ++ config/fish/fish_variables | 10 +++- .../functions/__ssh_agent_is_started.fish | 14 ++++++ config/fish/functions/__ssh_agent_start.fish | 5 ++ .../_fzf_configure_bindings_help.fish | 43 +++++++++++++++++ .../fish/functions/_fzf_extract_var_info.fish | 15 ++++++ .../functions/_fzf_preview_changed_file.fish | 38 +++++++++++++++ config/fish/functions/_fzf_preview_file.fish | 43 +++++++++++++++++ .../fish/functions/_fzf_report_diff_type.fish | 16 +++++++ .../fish/functions/_fzf_report_file_type.fish | 6 +++ .../fish/functions/_fzf_search_directory.fish | 44 ++++++++++++++++++ .../fish/functions/_fzf_search_git_log.fish | 28 +++++++++++ .../functions/_fzf_search_git_status.fish | 34 ++++++++++++++ .../fish/functions/_fzf_search_history.fish | 30 ++++++++++++ .../fish/functions/_fzf_search_processes.fish | 28 +++++++++++ .../fish/functions/_fzf_search_variables.fish | 46 +++++++++++++++++++ config/fish/functions/_fzf_wrapper.fish | 20 ++++++++ config/fish/functions/cless.fish | 10 ++++ .../functions/fish_user_key_bindings.fish | 3 ++ .../functions/fzf_configure_bindings.fish | 46 +++++++++++++++++++ config/fish/functions/fzf_key_bindings.fish | 1 + config/fish/functions/man.fish | 21 +++++++++ config/nvim/init.vim | 4 +- shell_aliases | 8 ++++ shell_funcs | 16 ------- shell_funcs.fish | 33 ++++++------- 30 files changed, 579 insertions(+), 38 deletions(-) create mode 100644 config/fish/completions/fzf_configure_bindings.fish create mode 100644 config/fish/conf.d/fish-ssh-agent.fish create mode 100644 config/fish/conf.d/fzf.fish create mode 100644 config/fish/functions/__ssh_agent_is_started.fish create mode 100644 config/fish/functions/__ssh_agent_start.fish create mode 100644 config/fish/functions/_fzf_configure_bindings_help.fish create mode 100644 config/fish/functions/_fzf_extract_var_info.fish create mode 100644 config/fish/functions/_fzf_preview_changed_file.fish create mode 100644 config/fish/functions/_fzf_preview_file.fish create mode 100644 config/fish/functions/_fzf_report_diff_type.fish create mode 100644 config/fish/functions/_fzf_report_file_type.fish create mode 100644 config/fish/functions/_fzf_search_directory.fish create mode 100644 config/fish/functions/_fzf_search_git_log.fish create mode 100644 config/fish/functions/_fzf_search_git_status.fish create mode 100644 config/fish/functions/_fzf_search_history.fish create mode 100644 config/fish/functions/_fzf_search_processes.fish create mode 100644 config/fish/functions/_fzf_search_variables.fish create mode 100644 config/fish/functions/_fzf_wrapper.fish create mode 100644 config/fish/functions/cless.fish create mode 100644 config/fish/functions/fish_user_key_bindings.fish create mode 100644 config/fish/functions/fzf_configure_bindings.fish create mode 120000 config/fish/functions/fzf_key_bindings.fish create mode 100644 config/fish/functions/man.fish create mode 100644 shell_aliases diff --git a/config/fish/completions/fzf_configure_bindings.fish b/config/fish/completions/fzf_configure_bindings.fish new file mode 100644 index 0000000..a78fd54 --- /dev/null +++ b/config/fish/completions/fzf_configure_bindings.fish @@ -0,0 +1,7 @@ +complete fzf_configure_bindings --no-files +complete fzf_configure_bindings --long help --short h --description "Print help" +complete fzf_configure_bindings --long directory --description "Change the key binding for searching directory" +complete fzf_configure_bindings --long git_log --description "Change the key binding for searching git log" +complete fzf_configure_bindings --long git_status --description "Change the key binding for searching git status" +complete fzf_configure_bindings --long history --description "Change the key binding for searching history" +complete fzf_configure_bindings --long variables --description "Change the key binding for searching variables" diff --git a/config/fish/conf.d/fish-ssh-agent.fish b/config/fish/conf.d/fish-ssh-agent.fish new file mode 100644 index 0000000..719087a --- /dev/null +++ b/config/fish/conf.d/fish-ssh-agent.fish @@ -0,0 +1,7 @@ +if test -z "$SSH_ENV" + set -xg SSH_ENV $HOME/.ssh/environment +end + +if not __ssh_agent_is_started + __ssh_agent_start +end diff --git a/config/fish/conf.d/fzf.fish b/config/fish/conf.d/fzf.fish new file mode 100644 index 0000000..8156c11 --- /dev/null +++ b/config/fish/conf.d/fzf.fish @@ -0,0 +1,28 @@ +# fzf.fish is only meant to be used in interactive mode. If not in interactive mode and not in CI, skip the config to speed up shell startup +if not status is-interactive && test "$CI" != true + exit +end + +# Because of scoping rules, to capture the shell variables exactly as they are, we must read +# them before even executing _fzf_search_variables. We use psub to store the +# variables' info in temporary files and pass in the filenames as arguments. +# This variable is global so that it can be referenced by fzf_configure_bindings and in tests +set --global _fzf_search_vars_command '_fzf_search_variables (set --show | psub) (set --names | psub)' + + +# Install the default bindings, which are mnemonic and minimally conflict with fish's preset bindings +fzf_configure_bindings + +# Doesn't erase autoloaded _fzf_* functions because they are not easily accessible once key bindings are erased +function _fzf_uninstall --on-event fzf_uninstall + _fzf_uninstall_bindings + + set --erase _fzf_search_vars_command + functions --erase _fzf_uninstall _fzf_migration_message _fzf_uninstall_bindings fzf_configure_bindings + complete --erase fzf_configure_bindings + + set_color cyan + echo "fzf.fish uninstalled." + echo "You may need to manually remove fzf_configure_bindings from your config.fish if you were using custom key bindings." + set_color normal +end diff --git a/config/fish/config.fish b/config/fish/config.fish index 0b12e0e..b7a4155 100644 --- a/config/fish/config.fish +++ b/config/fish/config.fish @@ -1,11 +1,17 @@ if status is-interactive - nitch + if type -q nitch + nitch + end + + set -x EDITOR nvim + set -x VISUAL nvim set fish_greeting + # Commands to run in interactive sessions can go here set --universal hydro_color_pwd green set --universal hydro_color_git red - + source ~/code/dotfiles/shell_aliases source ~/code/dotfiles/shell_funcs.fish end diff --git a/config/fish/fish_plugins b/config/fish/fish_plugins index 95cbf4c..7e2785e 100644 --- a/config/fish/fish_plugins +++ b/config/fish/fish_plugins @@ -1,2 +1,5 @@ jorgebucaran/fisher jorgebucaran/hydro +danhper/fish-ssh-agent +patrickf1/fzf.fish +patrickf3139/colored-man-pages diff --git a/config/fish/fish_variables b/config/fish/fish_variables index 8d6c45a..a6cd728 100644 --- a/config/fish/fish_variables +++ b/config/fish/fish_variables @@ -1,10 +1,14 @@ # This file contains fish universal variable definitions. # VERSION: 3.0 -SETUVAR __fish_initialized:3100 +SETUVAR __fish_initialized:3400 +SETUVAR _fisher_danhper_2F_fish_2D_ssh_2D_agent_files:\x7e/\x2econfig/fish/functions/__ssh_agent_is_started\x2efish\x1e\x7e/\x2econfig/fish/functions/__ssh_agent_start\x2efish\x1e\x7e/\x2econfig/fish/conf\x2ed/fish\x2dssh\x2dagent\x2efish SETUVAR _fisher_jorgebucaran_2F_fisher_files:\x7e/\x2econfig/fish/functions/fisher\x2efish\x1e\x7e/\x2econfig/fish/completions/fisher\x2efish SETUVAR _fisher_jorgebucaran_2F_hydro_files:\x7e/\x2econfig/fish/functions/fish_mode_prompt\x2efish\x1e\x7e/\x2econfig/fish/functions/fish_prompt\x2efish\x1e\x7e/\x2econfig/fish/conf\x2ed/hydro\x2efish -SETUVAR _fisher_plugins:jorgebucaran/fisher\x1ejorgebucaran/hydro +SETUVAR _fisher_patrickf1_2F_fzf_2E_fish_files:\x7e/\x2econfig/fish/functions/_fzf_configure_bindings_help\x2efish\x1e\x7e/\x2econfig/fish/functions/_fzf_extract_var_info\x2efish\x1e\x7e/\x2econfig/fish/functions/_fzf_preview_changed_file\x2efish\x1e\x7e/\x2econfig/fish/functions/_fzf_preview_file\x2efish\x1e\x7e/\x2econfig/fish/functions/_fzf_report_diff_type\x2efish\x1e\x7e/\x2econfig/fish/functions/_fzf_report_file_type\x2efish\x1e\x7e/\x2econfig/fish/functions/_fzf_search_directory\x2efish\x1e\x7e/\x2econfig/fish/functions/_fzf_search_git_log\x2efish\x1e\x7e/\x2econfig/fish/functions/_fzf_search_git_status\x2efish\x1e\x7e/\x2econfig/fish/functions/_fzf_search_history\x2efish\x1e\x7e/\x2econfig/fish/functions/_fzf_search_processes\x2efish\x1e\x7e/\x2econfig/fish/functions/_fzf_search_variables\x2efish\x1e\x7e/\x2econfig/fish/functions/_fzf_wrapper\x2efish\x1e\x7e/\x2econfig/fish/functions/fzf_configure_bindings\x2efish\x1e\x7e/\x2econfig/fish/conf\x2ed/fzf\x2efish\x1e\x7e/\x2econfig/fish/completions/fzf_configure_bindings\x2efish +SETUVAR _fisher_patrickf3139_2F_colored_2D_man_2D_pages_files:\x7e/\x2econfig/fish/functions/cless\x2efish\x1e\x7e/\x2econfig/fish/functions/man\x2efish +SETUVAR _fisher_plugins:jorgebucaran/fisher\x1ejorgebucaran/hydro\x1edanhper/fish\x2dssh\x2dagent\x1epatrickf1/fzf\x2efish\x1epatrickf3139/colored\x2dman\x2dpages SETUVAR _fisher_upgraded_to_4_4:\x1d +SETUVAR _hydro_git_64715:main\u2022\x20 SETUVAR _hydro_git_69626:main\u2022\x20 SETUVAR _hydro_git_72501:main\u2022\x20\u21911\x20 SETUVAR fish_color_autosuggestion:555\x1ebrblack @@ -34,5 +38,7 @@ SETUVAR fish_pager_color_completion:\x1d SETUVAR fish_pager_color_description:B3A06D\x1eyellow SETUVAR fish_pager_color_prefix:normal\x1e\x2d\x2dbold\x1e\x2d\x2dunderline SETUVAR fish_pager_color_progress:brwhite\x1e\x2d\x2dbackground\x3dcyan +SETUVAR fish_pager_color_selected_background:\x2dr +SETUVAR fish_user_paths:/opt/homebrew/bin\x1e/Users/tyrel\x2esouza/\x2efzf/bin SETUVAR hydro_color_git:red SETUVAR hydro_color_pwd:green diff --git a/config/fish/functions/__ssh_agent_is_started.fish b/config/fish/functions/__ssh_agent_is_started.fish new file mode 100644 index 0000000..7d481ee --- /dev/null +++ b/config/fish/functions/__ssh_agent_is_started.fish @@ -0,0 +1,14 @@ +function __ssh_agent_is_started -d "check if ssh agent is already started" + if begin; test -f $SSH_ENV; and test -z "$SSH_AGENT_PID"; end + source $SSH_ENV > /dev/null + end + + if begin; test -z "$SSH_AGENT_PID"; and test -z "$SSH_CONNECTION"; end + return 1 + end + + ssh-add -l > /dev/null 2>&1 + if test $status -eq 2 + return 1 + end +end diff --git a/config/fish/functions/__ssh_agent_start.fish b/config/fish/functions/__ssh_agent_start.fish new file mode 100644 index 0000000..3766fe4 --- /dev/null +++ b/config/fish/functions/__ssh_agent_start.fish @@ -0,0 +1,5 @@ +function __ssh_agent_start -d "start a new ssh agent" + ssh-agent -c | sed 's/^echo/#echo/' > $SSH_ENV + chmod 600 $SSH_ENV + source $SSH_ENV > /dev/null +end diff --git a/config/fish/functions/_fzf_configure_bindings_help.fish b/config/fish/functions/_fzf_configure_bindings_help.fish new file mode 100644 index 0000000..1209e49 --- /dev/null +++ b/config/fish/functions/_fzf_configure_bindings_help.fish @@ -0,0 +1,43 @@ +function _fzf_configure_bindings_help --description "Prints the help message for fzf_configure_bindings." + echo "\ +USAGE: + fzf_configure_bindings [--FEATURE[=KEY_SEQUENCE]...] + +DESCRIPTION + By default, fzf_configure_bindings installs mnemonic key bindings for fzf.fish's features. Each + feature's binding can be customized through a corresponding namesake option: + FEATURE | MNEMONIC KEY SEQUENCE | CORRESPONDING OPTION + Search directory | Ctrl+Alt+F (F for file) | --directory + Search git log | Ctrl+Alt+L (L for log) | --git_log + Search git status | Ctrl+Alt+S (S for status) | --git_status + Search history | Ctrl+R (R for reverse) | --history + Search variables | Ctrl+V (V for variable) | --variables + Search processes | Ctrl+Alt+P (P for process) | --processes + An option with a key sequence value overrides the binding for its feature, while an option + without a value disables the binding. A feature that is not customized retains its default + menomonic binding specified above. Key bindings are installed for default and insert modes. + + In terms of validation, fzf_configure_bindings fails if passed unknown options. Furthermore, it + expects an equals sign between an option's name and value. However, it does not validate key + sequences. Rather, consider using fish_key_reader to manually validate them. + + In terms of experimentation, fzf_configure_bindings erases any bindings it previously installed + before installing new ones so it can be repeatedly executed in the same fish session without + problem. Once the desired fzf_configure_bindings command has been found, add it to config.fish + in order to persist the bindings. + + The -h and --help options print this help message. + +EXAMPLES + Install the default mnemonic bindings + \$ fzf_configure_bindings + Install the default bindings but override git log's binding to Ctrl+G + \$ fzf_configure_bindings --git_log=\cg + Install the default bindings but leave search history unbound + \$ fzf_configure_bindings --history + Alternative style of disabling search history + \$ fzf_configure_bindings --history= + An agglomeration of all the options + \$ fzf_configure_bindings --git_status=\cg --history=\ch --variables --directory --git_log +" +end diff --git a/config/fish/functions/_fzf_extract_var_info.fish b/config/fish/functions/_fzf_extract_var_info.fish new file mode 100644 index 0000000..dd4e952 --- /dev/null +++ b/config/fish/functions/_fzf_extract_var_info.fish @@ -0,0 +1,15 @@ +# helper function for _fzf_search_variables +function _fzf_extract_var_info --argument-names variable_name set_show_output --description "Extract and reformat lines pertaining to \$variable_name from \$set_show_output." + # Extract only the lines about the variable, all of which begin with either + # $variable_name: ...or... $variable_name[ + string match --regex "^\\\$$variable_name(?::|\[).*" <$set_show_output | + + # Strip the variable name prefix, including ": " for scope info lines + string replace --regex "^\\\$$variable_name(?:: )?" '' | + + # Distill the lines of values, replacing... + # [1]: |value| + # ...with... + # [1] value + string replace --regex ": \|(.*)\|" ' $1' +end diff --git a/config/fish/functions/_fzf_preview_changed_file.fish b/config/fish/functions/_fzf_preview_changed_file.fish new file mode 100644 index 0000000..e22139f --- /dev/null +++ b/config/fish/functions/_fzf_preview_changed_file.fish @@ -0,0 +1,38 @@ +# helper for _fzf_search_git_status +# arg should be a line from git status --short, e.g. +# MM functions/_fzf_preview_changed_file.fish +# D README.md +# R LICENSE.md -> LICENSE +function _fzf_preview_changed_file --argument-names path_status --description "Show the git diff of the given file." + # remove quotes because they'll be interpreted literally by git diff + # no need to requote when referencing $path because fish does not perform word splitting + # https://fishshell.com/docs/current/fish_for_bash_users.html + set -l path (string unescape (string sub --start 4 $path_status)) + # first letter of short format shows index, second letter shows working tree + # https://git-scm.com/docs/git-status/2.35.0#_short_format + set -l index_status (string sub --length 1 $path_status) + set -l working_tree_status (string sub --start 2 --length 1 $path_status) + # no-prefix because the file is always being compared to itself so is unecessary + set diff_opts --color=always --no-prefix + + if test $index_status = '?' + _fzf_report_diff_type Untracked + _fzf_preview_file $path + else if contains {$index_status}$working_tree_status DD AU UD UA DU AA UU + # Unmerged statuses taken directly from git status help's short format table + # Unmerged statuses are mutually exclusive with other statuses, so if we see + # these, then safe to assume the path is unmerged + _fzf_report_diff_type Unmerged + git diff $diff_opts -- $path + else + if test $index_status != ' ' + _fzf_report_diff_type Staged + git diff --staged $diff_opts -- $path + end + + if test $working_tree_status != ' ' + _fzf_report_diff_type Unstaged + git diff $diff_opts -- $path + end + end +end diff --git a/config/fish/functions/_fzf_preview_file.fish b/config/fish/functions/_fzf_preview_file.fish new file mode 100644 index 0000000..eaa68d0 --- /dev/null +++ b/config/fish/functions/_fzf_preview_file.fish @@ -0,0 +1,43 @@ +# helper function for _fzf_search_directory and _fzf_search_git_status +function _fzf_preview_file --description "Print a preview for the given file based on its file type." + # because there's no way to guarantee that _fzf_search_directory passes the path to _fzf_preview_file + # as one argument, we collect all the arguments into one single variable and treat that as the path + set file_path $argv + + if test -L "$file_path" # symlink + # notify user and recurse on the target of the symlink, which can be any of these file types + set -l target_path (realpath "$file_path") + + set_color yellow + echo "'$file_path' is a symlink to '$target_path'." + set_color normal + + _fzf_preview_file "$target_path" + else if test -f "$file_path" # regular file + if set --query fzf_preview_file_cmd + # need to escape quotes to make sure eval receives file_path as a single arg + eval "$fzf_preview_file_cmd '$file_path'" + else + bat --style=numbers --color=always "$file_path" + end + else if test -d "$file_path" # directory + if set --query fzf_preview_dir_cmd + # see above + eval "$fzf_preview_dir_cmd '$file_path'" + else + # -A list hidden files as well, except for . and .. + # -F helps classify files by appending symbols after the file name + command ls -A -F "$file_path" + end + else if test -c "$file_path" + _fzf_report_file_type "$file_path" "character device file" + else if test -b "$file_path" + _fzf_report_file_type "$file_path" "block device file" + else if test -S "$file_path" + _fzf_report_file_type "$file_path" socket + else if test -p "$file_path" + _fzf_report_file_type "$file_path" "named pipe" + else + echo "$file_path doesn't exist." >&2 + end +end diff --git a/config/fish/functions/_fzf_report_diff_type.fish b/config/fish/functions/_fzf_report_diff_type.fish new file mode 100644 index 0000000..1edef78 --- /dev/null +++ b/config/fish/functions/_fzf_report_diff_type.fish @@ -0,0 +1,16 @@ +# helper for _fzf_preview_changed_file +# prints out something like +# +--------+ +# | Staged | +# +--------+ +function _fzf_report_diff_type --argument-names diff_type --description "Print a distinct colored header meant to preface a git patch." + # number of "-" to draw is the length of the string to box + 2 for padding + set repeat_count (math 2 + (string length $diff_type)) + set horizontal_border +(string repeat --count $repeat_count -)+ + + set_color yellow + echo $horizontal_border + echo "| $diff_type |" + echo $horizontal_border + set_color normal +end diff --git a/config/fish/functions/_fzf_report_file_type.fish b/config/fish/functions/_fzf_report_file_type.fish new file mode 100644 index 0000000..49e02e1 --- /dev/null +++ b/config/fish/functions/_fzf_report_file_type.fish @@ -0,0 +1,6 @@ +# helper function for _fzf_preview_file +function _fzf_report_file_type --argument-names file_path file_type --description "Explain the file type for a file." + set_color red + echo "Cannot preview '$file_path': it is a $file_type." + set_color normal +end diff --git a/config/fish/functions/_fzf_search_directory.fish b/config/fish/functions/_fzf_search_directory.fish new file mode 100644 index 0000000..fee6308 --- /dev/null +++ b/config/fish/functions/_fzf_search_directory.fish @@ -0,0 +1,44 @@ +function _fzf_search_directory --description "Search the current directory. Replace the current token with the selected file paths." + # --string-cwd-prefix prevents fd >= 8.3.0 from prepending ./ to relative paths + set fd_opts --color=always --strip-cwd-prefix $fzf_fd_opts + + set fzf_arguments --multi --ansi $fzf_dir_opts + set token (commandline --current-token) + # expand any variables or leading tilde (~) in the token + set expanded_token (eval echo -- $token) + # unescape token because it's already quoted so backslashes will mess up the path + set unescaped_exp_token (string unescape -- $expanded_token) + + # If the current token is a directory and has a trailing slash, + # then use it as fd's base directory. + if string match --quiet -- "*/" $unescaped_exp_token && test -d "$unescaped_exp_token" + set --append fd_opts --base-directory=$unescaped_exp_token + # use the directory name as fzf's prompt to indicate the search is limited to that directory + set --prepend fzf_arguments --prompt="$unescaped_exp_token" --preview="_fzf_preview_file $expanded_token{}" + set file_paths_selected $unescaped_exp_token(fd $fd_opts 2>/dev/null | _fzf_wrapper $fzf_arguments) + else + set --prepend fzf_arguments --query="$unescaped_exp_token" --preview='_fzf_preview_file {}' + set file_paths_selected (fd $fd_opts 2>/dev/null | _fzf_wrapper $fzf_arguments) + end + + + if test $status -eq 0 + # Fish will cd implicitly if a directory name ending in a slash is provided. + # To help the user leverage this feature, we automatically append / to the selected path if + # - only one path was selected, + # - the user was in the middle of inputting the first token, + # - the path is a directory + # Then, the user only needs to hit Enter once more to cd into that directory. + if test (count $file_paths_selected) = 1 + set commandline_tokens (commandline --tokenize) + if test "$commandline_tokens" = "$token" -a -d "$file_paths_selected" \ + -a (fd --version | string replace --regex --all '[^\d]' '') -lt 840 + set file_paths_selected $file_paths_selected/ + end + end + + commandline --current-token --replace -- (string escape -- $file_paths_selected | string join ' ') + end + + commandline --function repaint +end diff --git a/config/fish/functions/_fzf_search_git_log.fish b/config/fish/functions/_fzf_search_git_log.fish new file mode 100644 index 0000000..3375c1d --- /dev/null +++ b/config/fish/functions/_fzf_search_git_log.fish @@ -0,0 +1,28 @@ +function _fzf_search_git_log --description "Search the output of git log and preview commits. Replace the current token with the selected commit hash." + if not git rev-parse --git-dir >/dev/null 2>&1 + echo '_fzf_search_git_log: Not in a git repository.' >&2 + else + # see documentation for git format placeholders at https://git-scm.com/docs/git-log#Documentation/git-log.txt-emnem + # %h gives you the abbreviated commit hash, which is useful for saving screen space, but we will have to expand it later below + set log_fmt_str '%C(bold blue)%h%C(reset) - %C(cyan)%ad%C(reset) %C(yellow)%d%C(reset) %C(normal)%s%C(reset) %C(dim normal)[%an]%C(reset)' + set selected_log_lines ( + git log --color=always --format=format:$log_fmt_str --date=short | \ + _fzf_wrapper --ansi \ + --multi \ + --tiebreak=index \ + --preview='git show --color=always --stat --patch {1}' \ + --query=(commandline --current-token) \ + $fzf_git_log_opts + ) + if test $status -eq 0 + for line in $selected_log_lines + set abbreviated_commit_hash (string split --field 1 " " $line) + set full_commit_hash (git rev-parse $abbreviated_commit_hash) + set --append commit_hashes $full_commit_hash + end + commandline --current-token --replace (string join ' ' $commit_hashes) + end + end + + commandline --function repaint +end diff --git a/config/fish/functions/_fzf_search_git_status.fish b/config/fish/functions/_fzf_search_git_status.fish new file mode 100644 index 0000000..f8ae375 --- /dev/null +++ b/config/fish/functions/_fzf_search_git_status.fish @@ -0,0 +1,34 @@ +function _fzf_search_git_status --description "Search the output of git status. Replace the current token with the selected file paths." + if not git rev-parse --git-dir >/dev/null 2>&1 + echo '_fzf_search_git_status: Not in a git repository.' >&2 + else + set selected_paths ( + # Pass configuration color.status=always to force status to use colors even though output is sent to a pipe + git -c color.status=always status --short | + _fzf_wrapper --ansi \ + --multi \ + --query=(commandline --current-token) \ + --preview='_fzf_preview_changed_file {}' \ + $fzf_git_status_opts + ) + if test $status -eq 0 + # git status --short automatically escapes the paths of most files for us so not going to bother trying to handle + # the few edges cases of weird file names that should be extremely rare (e.g. "this;needs;escaping") + set cleaned_paths + + for path in $selected_paths + if test (string sub --length 1 $path) = R + # path has been renamed and looks like "R LICENSE -> LICENSE.md" + # extract the path to use from after the arrow + set --append cleaned_paths (string split -- "-> " $path)[-1] + else + set --append cleaned_paths (string sub --start=4 $path) + end + end + + commandline --current-token --replace -- (string join ' ' $cleaned_paths) + end + end + + commandline --function repaint +end diff --git a/config/fish/functions/_fzf_search_history.fish b/config/fish/functions/_fzf_search_history.fish new file mode 100644 index 0000000..d795c5c --- /dev/null +++ b/config/fish/functions/_fzf_search_history.fish @@ -0,0 +1,30 @@ +function _fzf_search_history --description "Search command history. Replace the command line with the selected command." + # history merge incorporates history changes from other fish sessions + # it errors out if called in private mode + if test -z "$fish_private_mode" + builtin history merge + end + + # Delinate commands throughout pipeline using null rather than newlines because commands can be multi-line + set commands_selected ( + # Reference https://devhints.io/strftime to understand strftime format symbols + builtin history --null --show-time="%m-%d %H:%M:%S │ " | + _fzf_wrapper --read0 \ + --print0 \ + --multi \ + --tiebreak=index \ + --query=(commandline) \ + --preview="echo -- {4..} | fish_indent --ansi" \ + --preview-window="bottom:3:wrap" \ + $fzf_history_opts | + string split0 | + # remove timestamps from commands selected + string replace --regex '^\d\d-\d\d \d\d:\d\d:\d\d │ ' '' + ) + + if test $status -eq 0 + commandline --replace -- $commands_selected + end + + commandline --function repaint +end diff --git a/config/fish/functions/_fzf_search_processes.fish b/config/fish/functions/_fzf_search_processes.fish new file mode 100644 index 0000000..e3ef59f --- /dev/null +++ b/config/fish/functions/_fzf_search_processes.fish @@ -0,0 +1,28 @@ +function _fzf_search_processes --description "Search all running processes. Replace the current token with the pid of the selected process." + # use all caps to be consistent with ps default format + # snake_case because ps doesn't seem to allow spaces in the field names + set ps_preview_fmt (string join ',' 'pid' 'ppid=PARENT' 'user' '%cpu' 'rss=RSS_IN_KB' 'start=START_TIME' 'command') + set processes_selected ( + ps -A -opid,command | \ + _fzf_wrapper --multi \ + --query (commandline --current-token) \ + --ansi \ + # first line outputted by ps is a header, so we need to mark it as so + --header-lines=1 \ + # ps uses exit code 1 if the process was not found, in which case show an message explaining so + --preview="ps -o '$ps_preview_fmt' -p {1} || echo 'Cannot preview {1} because it exited.'" \ + --preview-window="bottom:4:wrap" \ + $fzf_processes_opts + ) + + if test $status -eq 0 + for process in $processes_selected + set --append pids_selected (string split --no-empty --field=1 -- " " $process) + end + + # string join to replace the newlines outputted by string split with spaces + commandline --current-token --replace -- (string join ' ' $pids_selected) + end + + commandline --function repaint +end diff --git a/config/fish/functions/_fzf_search_variables.fish b/config/fish/functions/_fzf_search_variables.fish new file mode 100644 index 0000000..744f226 --- /dev/null +++ b/config/fish/functions/_fzf_search_variables.fish @@ -0,0 +1,46 @@ +# This function expects the following two arguments: +# argument 1 = output of (set --show | psub), i.e. a file with the scope info and values of all variables +# argument 2 = output of (set --names | psub), i.e. a file with all variable names +function _fzf_search_variables --argument-names set_show_output set_names_output --description "Search and preview shell variables. Replace the current token with the selected variable." + if test -z "$set_names_output" + printf '%s\n' '_fzf_search_variables requires 2 arguments.' >&2 + + commandline --function repaint + return 22 # 22 means invalid argument in POSIX + end + + # Exclude the history variable from being piped into fzf because + # 1. it's not included in $set_names_output + # 2. it tends to be a very large value => increases computation time + # 3._fzf_search_history is a much better way to examine history anyway + set all_variable_names (string match --invert history <$set_names_output) + + set current_token (commandline --current-token) + # Use the current token to pre-populate fzf's query. If the current token begins + # with a $, remove it from the query so that it will better match the variable names + set cleaned_curr_token (string replace -- '$' '' $current_token) + + set variable_names_selected ( + printf '%s\n' $all_variable_names | + _fzf_wrapper --preview "_fzf_extract_var_info {} $set_show_output" \ + --preview-window="wrap" \ + --multi \ + --query=$cleaned_curr_token \ + $fzf_shell_vars_opts + ) + + if test $status -eq 0 + # If the current token begins with a $, do not overwrite the $ when + # replacing the current token with the selected variable. + # Uses brace expansion to prepend $ to each variable name. + commandline --current-token --replace ( + if string match --quiet -- '$*' $current_token + string join " " \${$variable_names_selected} + else + string join " " $variable_names_selected + end + ) + end + + commandline --function repaint +end diff --git a/config/fish/functions/_fzf_wrapper.fish b/config/fish/functions/_fzf_wrapper.fish new file mode 100644 index 0000000..a928701 --- /dev/null +++ b/config/fish/functions/_fzf_wrapper.fish @@ -0,0 +1,20 @@ +function _fzf_wrapper --description "Prepares some environment variables before executing fzf." + # Make sure fzf uses fish to execute preview commands, some of which + # are autoloaded fish functions so don't exist in other shells. + # Use --local so that it doesn't clobber SHELL outside of this function. + set --local --export SHELL (command --search fish) + + # If FZF_DEFAULT_OPTS is not set, then set some sane defaults. + # See https://github.com/junegunn/fzf#environment-variables + if not set --query FZF_DEFAULT_OPTS + # cycle allows jumping between the first and last results, making scrolling faster + # layout=reverse lists results top to bottom, mimicking the familiar layouts of git log, history, and env + # border shows where the fzf window begins and ends + # height=90% leaves space to see the current command and some scrollback, maintaining context of work + # preview-window=wrap wraps long lines in the preview window, making reading easier + # marker=* makes the multi-select marker more distinguishable from the pointer (since both default to >) + set --export FZF_DEFAULT_OPTS '--cycle --layout=reverse --border --height=90% --preview-window=wrap --marker="*"' + end + + fzf $argv +end diff --git a/config/fish/functions/cless.fish b/config/fish/functions/cless.fish new file mode 100644 index 0000000..7c4f621 --- /dev/null +++ b/config/fish/functions/cless.fish @@ -0,0 +1,10 @@ +function cless -d "Configure less to colorize styled text using environment variables before executing a command that will use less" + set -x LESS_TERMCAP_md (set_color --bold 0280A5) # start bold + set -x LESS_TERMCAP_me (set_color normal) # end bold + set -x LESS_TERMCAP_us (set_color --underline 5BA502) # start underline + set -x LESS_TERMCAP_ue (set_color normal) # end underline + set -x LESS_TERMCAP_so (set_color --reverse F0CB02) # start standout + set -x LESS_TERMCAP_se (set_color normal) # end standout + + $argv +end diff --git a/config/fish/functions/fish_user_key_bindings.fish b/config/fish/functions/fish_user_key_bindings.fish new file mode 100644 index 0000000..350a9da --- /dev/null +++ b/config/fish/functions/fish_user_key_bindings.fish @@ -0,0 +1,3 @@ +function fish_user_key_bindings + fzf_key_bindings +end diff --git a/config/fish/functions/fzf_configure_bindings.fish b/config/fish/functions/fzf_configure_bindings.fish new file mode 100644 index 0000000..addb55c --- /dev/null +++ b/config/fish/functions/fzf_configure_bindings.fish @@ -0,0 +1,46 @@ +# Always installs bindings for insert and default mode for simplicity and b/c it has almost no side-effect +# https://gitter.im/fish-shell/fish-shell?at=60a55915ee77a74d685fa6b1 +function fzf_configure_bindings --description "Installs the default key bindings for fzf.fish with user overrides passed as options." + # no need to install bindings if not in interactive mode or running tests + status is-interactive || test "$CI" = true; or return + + set options_spec h/help 'directory=?' 'git_log=?' 'git_status=?' 'history=?' 'variables=?' 'processes=?' + argparse --max-args=0 --ignore-unknown $options_spec -- $argv 2>/dev/null + if test $status -ne 0 + echo "Invalid option or a positional argument was provided." >&2 + _fzf_configure_bindings_help + return 22 + else if set --query _flag_help + _fzf_configure_bindings_help + return + else + # Initialize with default key sequences and then override or disable them based on flags + # index 1 = directory, 2 = git_log, 3 = git_status, 4 = history, 5 = variables, 6 = processes + set key_sequences \e\cf \e\cl \e\cs \cr \cv \e\cp # \c = control, \e = escape + set --query _flag_directory && set key_sequences[1] "$_flag_directory" + set --query _flag_git_log && set key_sequences[2] "$_flag_git_log" + set --query _flag_git_status && set key_sequences[3] "$_flag_git_status" + set --query _flag_history && set key_sequences[4] "$_flag_history" + set --query _flag_variables && set key_sequences[5] "$_flag_variables" + set --query _flag_processes && set key_sequences[6] "$_flag_processes" + + # If fzf bindings already exists, uninstall it first for a clean slate + if functions --query _fzf_uninstall_bindings + _fzf_uninstall_bindings + end + + for mode in default insert + test -n $key_sequences[1] && bind --mode $mode $key_sequences[1] _fzf_search_directory + test -n $key_sequences[2] && bind --mode $mode $key_sequences[2] _fzf_search_git_log + test -n $key_sequences[3] && bind --mode $mode $key_sequences[3] _fzf_search_git_status + test -n $key_sequences[4] && bind --mode $mode $key_sequences[4] _fzf_search_history + test -n $key_sequences[5] && bind --mode $mode $key_sequences[5] "$_fzf_search_vars_command" + test -n $key_sequences[6] && bind --mode $mode $key_sequences[6] _fzf_search_processes + end + + function _fzf_uninstall_bindings --inherit-variable key_sequences + bind --erase -- $key_sequences + bind --erase --mode insert -- $key_sequences + end + end +end diff --git a/config/fish/functions/fzf_key_bindings.fish b/config/fish/functions/fzf_key_bindings.fish new file mode 120000 index 0000000..92ede6d --- /dev/null +++ b/config/fish/functions/fzf_key_bindings.fish @@ -0,0 +1 @@ +/Users/tyrel.souza/.fzf/shell/key-bindings.fish \ No newline at end of file diff --git a/config/fish/functions/man.fish b/config/fish/functions/man.fish new file mode 100644 index 0000000..f1ab1e8 --- /dev/null +++ b/config/fish/functions/man.fish @@ -0,0 +1,21 @@ +function man --wraps man -d "Run man with added colors" + set --local --export MANPATH $MANPATH + + # special case for NetBSD and FreeBSD: set MANPATH if not already set + # see https://github.com/fish-shell/fish-shell/blob/555af37616893160ad1afb208a957d6a01a7a315/share/functions/man.fish#L15 + if test -z "$MANPATH" + if set path (command man -p 2>/dev/null) + set MANPATH (string replace --regex '[^/]+$' '' $path) + else + set MANPATH "" + end + end + + # prepend the directory of fish manpages to MANPATH + set fish_manpath $__fish_data_dir/man + if test -d $fish_manpath + set --prepend MANPATH $fish_manpath + end + + cless (command --search man) $argv +end diff --git a/config/nvim/init.vim b/config/nvim/init.vim index 1fd41de..11b6c6a 100644 --- a/config/nvim/init.vim +++ b/config/nvim/init.vim @@ -48,7 +48,7 @@ map v :WhichKey set tabstop=2 -set shell=/usr/bin/zsh +set shell=/bin/zsh set shiftwidth=2 set expandtab set hidden @@ -163,7 +163,7 @@ require'nvim-treesitter.configs'.setup { enable = false, -- list of language that will be disabled - disable = {"vim"}, + disable = {"vim", "c", "rust"}, -- Setting this to true will run `:h syntax` and tree-sitter at the same time. -- Set this to `true` if you depend on 'syntax' being enabled (like for indentation). diff --git a/shell_aliases b/shell_aliases new file mode 100644 index 0000000..4b1db02 --- /dev/null +++ b/shell_aliases @@ -0,0 +1,8 @@ +alias cat='bat' +alias dots='cd ~/code/dotfiles/' +alias fuckingip="curl https://wtfismyip.com/json" +alias g='git' +alias gp='git push -u' +alias ls="exa -lhFgxUm --git --time-style long-iso --group-directories-first" +alias vimini="vim ~/.config/nvim/init.vim" +alias vim=nvim diff --git a/shell_funcs b/shell_funcs index c1f002e..053943b 100644 --- a/shell_funcs +++ b/shell_funcs @@ -2,22 +2,6 @@ export EDITOR=nvim export VISUAL=nvim -# Aliases -alias ag='\ag --pager="less -r"' -alias c='\cat' -alias cat='bat' -alias cg='cd "$(git rev-parse --show-toplevel)"' -alias dots='cd ~/code/dotfiles/' -alias fuckingip="curl https://wtfismyip.com/json" -alias g='git' -alias gp='git push -u' -alias httpie="http" -alias ls="exa -lhFgxUm --git --time-style long-iso --group-directories-first" -alias pg='pushd "$(git rev-parse --show-toplevel)"' -alias ppjson="python -m json.tool" -alias shrug="echo -n '¯\_(ツ)_/¯' | pbcopy" -alias vimini="vim ~/.config/nvim/init.vim" - # Functions function httpdiff () { diff --color -r -c <(curl -s "$1" 2>&1) <(curl -s "$2" 2>&1) diff --git a/shell_funcs.fish b/shell_funcs.fish index 8ee0af4..a764272 100644 --- a/shell_funcs.fish +++ b/shell_funcs.fish @@ -1,17 +1,4 @@ #!/usr/bin/fish -set -x EDITOR nvim -set -x VISUAL nvim - -# Aliases -#alias ag='ag --pager="less -r"' -alias cat='bat' -alias dots='cd ~/code/dotfiles/' -alias fuckingip="curl https://wtfismyip.com/json" -alias g='git' -alias gp='git push -u' -alias ls="exa -lhFgxUm --git --time-style long-iso --group-directories-first" -alias vimini="vim ~/.config/nvim/init.vim" -alias vim=nvim # Functions function httpdiff @@ -23,6 +10,11 @@ function cg cd $_dir_ end +function gact + set base (git rev-parse --show-toplevel) + source $base/venv/bin/activate.fish +end + function cpbr set branch (git symbolic-ref --short -q HEAD) if test branch @@ -40,15 +32,24 @@ end function pullall - for d in ./*/ ; do (cd "$d" && pwd && git pull); end + for d in ./*/ + cd "$d" && pwd && git pull + cd .. + end end function gh_mainall - for d in ./*/ ; do (cd "$d" && pwd && git checkout main && git pull); end + for d in ./*/ + cd "$d" && pwd && git checkout main; git pull + cd .. + end end function allbranches - for d in ./*/ ; do (cd "$d" && pwd && git remote -v origin && git pull); end + for d in ./*/ + cd "$d" && pwd && git remote -v;git pull + cd .. + end end function new_dock_space