commit f5306476ea72d9688fa66cd538782271979e5dc5 Author: Hydroxycarbamide Date: Tue Jun 7 21:48:28 2022 +0200 Added my fish config diff --git a/completions/fzf_configure_bindings.fish b/completions/fzf_configure_bindings.fish new file mode 100644 index 0000000..a78fd54 --- /dev/null +++ b/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/conf.d/fzf.fish b/conf.d/fzf.fish new file mode 100644 index 0000000..8156c11 --- /dev/null +++ b/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/conf.d/git_aliases.fish b/conf.d/git_aliases.fish new file mode 100644 index 0000000..7d58671 --- /dev/null +++ b/conf.d/git_aliases.fish @@ -0,0 +1,159 @@ +# migrating from https://github.com/robbyrussell/oh-my-zsh/blob/master/plugins/git/git.plugin.zsh + +# Aliases +alias g='git' +#compdef g=git +alias gst='git status' +#compdef _git gst=git-status +alias gd='git diff' +#compdef _git gd=git-diff +alias gdc='git diff --cached' +#compdef _git gdc=git-diff +alias gl='git pull' +#compdef _git gl=git-pull +alias gup='git pull --rebase' +#compdef _git gup=git-fetch +alias gp='git push' +#compdef _git gp=git-push +alias gd='git diff' + +function gdv + git diff -w $argv | view - +end + +#compdef _git gdv=git-diff +alias gc='git commit -v' +#compdef _git gc=git-commit +alias gc!='git commit -v --amend' +#compdef _git gc!=git-commit +alias gca='git commit -v -a' +#compdef _git gc=git-commit +alias gca!='git commit -v -a --amend' +#compdef _git gca!=git-commit +alias gcmsg='git commit -m' +#compdef _git gcmsg=git-commit +alias gco='git checkout' +#compdef _git gco=git-checkout +alias gcm='git checkout master' +alias gr='git remote' +#compdef _git gr=git-remote +alias grv='git remote -v' +#compdef _git grv=git-remote +alias grmv='git remote rename' +#compdef _git grmv=git-remote +alias grrm='git remote remove' +#compdef _git grrm=git-remote +alias grset='git remote set-url' +#compdef _git grset=git-remote +alias grup='git remote update' +#compdef _git grset=git-remote +alias grbi='git rebase -i' +#compdef _git grbi=git-rebase +alias grbc='git rebase --continue' +#compdef _git grbc=git-rebase +alias grba='git rebase --abort' +#compdef _git grba=git-rebase +alias gb='git branch' +#compdef _git gb=git-branch +alias gba='git branch -a' +#compdef _git gba=git-branch +alias gcount='git shortlog -sn' +#compdef gcount=git +alias gcl='git config --list' +alias gcp='git cherry-pick' +#compdef _git gcp=git-cherry-pick +alias glg='git log --stat --max-count=10' +#compdef _git glg=git-log +alias glgg='git log --graph --max-count=10' +#compdef _git glgg=git-log +alias glgga='git log --graph --decorate --all' +#compdef _git glgga=git-log +alias glo='git log --oneline' +#compdef _git glo=git-log +alias gss='git status -s' +#compdef _git gss=git-status +alias ga='git add' +#compdef _git ga=git-add +alias gm='git merge' +#compdef _git gm=git-merge +alias grh='git reset HEAD' +alias grhh='git reset HEAD --hard' +alias gclean='git reset --hard; and git clean -dfx' +alias gwc='git whatchanged -p --abbrev-commit --pretty=medium' + +#remove the gf alias +#alias gf='git ls-files | grep' + +alias gpoat='git push origin --all; and git push origin --tags' +alias gmt='git mergetool --no-prompt' +#compdef _git gm=git-mergetool + +alias gg='git gui citool' +alias gga='git gui citool --amend' +alias gk='gitk --all --branches' + +alias gsts='git stash show --text' +alias gsta='git stash' +alias gstp='git stash pop' +alias gstd='git stash drop' + +# Will cd into the top of the current repository +# or submodule. +alias grt='cd (git rev-parse --show-toplevel; or echo ".")' + +# Git and svn mix +alias git-svn-dcommit-push='git svn dcommit; and git push github master:svntrunk' +#compdef git-svn-dcommit-push=git + +alias gsr='git svn rebase' +alias gsd='git svn dcommit' +# +# Will return the current branch name +# Usage example: git pull origin $(current_branch) +# +function current_branch + set ref (git symbolic-ref HEAD 2> /dev/null); or \ + set ref (git rev-parse --short HEAD 2> /dev/null); or return + echo ref | sed s-refs/heads-- +end + +function current_repository + set ref (git symbolic-ref HEAD 2> /dev/null); or \ + set ref (git rev-parse --short HEAD 2> /dev/null); or return + echo (git remote -v | cut -d':' -f 2) +end + +# these aliases take advantage of the previous function +alias ggpull='git pull origin (current_branch)' +#compdef ggpull=git +alias ggpur='git pull --rebase origin (current_branch)' +#compdef ggpur=git +alias ggpush='git push origin (current_branch)' +#compdef ggpush=git +alias ggpnp='git pull origin (current_branch); and git push origin (current_branch)' +#compdef ggpnp=git + +# Pretty log messages +function _git_log_prettily + if ! [ -z $1 ]; then + git log --pretty=$1 + end +end + +alias glp="_git_log_prettily" +#compdef _git glp=git-log + +# Work In Progress (wip) +# These features allow to pause a branch development and switch to another one (wip) +# When you want to go back to work, just unwip it +# +# This function return a warning if the current branch is a wip +function work_in_progress + if git log -n 1 | grep -q -c wip; then + echo "WIP!!" + end +end + +# these alias commit and uncomit wip branches +alias gwip='git add -A; git ls-files --deleted -z | xargs -0 git rm; git commit -m "wip"' +alias gunwip='git log -n 1 | grep -q -c wip; and git reset HEAD~1' \ No newline at end of file diff --git a/conf.d/omf.fish b/conf.d/omf.fish new file mode 100644 index 0000000..3e0f6d6 --- /dev/null +++ b/conf.d/omf.fish @@ -0,0 +1,7 @@ +# Path to Oh My Fish install. +set -q XDG_DATA_HOME + and set -gx OMF_PATH "$XDG_DATA_HOME/omf" + or set -gx OMF_PATH "$HOME/.local/share/omf" + +# Load Oh My Fish configuration. +source $OMF_PATH/init.fish diff --git a/config.fish b/config.fish new file mode 100644 index 0000000..84fb64f --- /dev/null +++ b/config.fish @@ -0,0 +1,32 @@ +zoxide init fish | source +if status is-interactive + # Commands to run in interactive sessions can go here + # ls + alias l='exa -lh' + alias ls='exa' + alias ll='exa -lah' + alias la='ls -A' + alias lm='ls -m' + alias lr='exa -R' + alias lg='exa -l --group-directories-first' + alias tree='exa --tree' + + # git + alias gcl='git clone --depth 1' + alias gi='git init' + alias ga='git add' + alias gc='git commit -m' + alias gp='git push origin master' + + # cat + alias cat='bat -p' + + # cd/zoxide + alias cd='z' + + # vim + alias vim='nvim' + + # emacs + alias emacs='emacsclient -nc -s instance1' +end diff --git a/fish_plugins b/fish_plugins new file mode 100644 index 0000000..7f03e18 --- /dev/null +++ b/fish_plugins @@ -0,0 +1,2 @@ +mattgreen/lucid.fish +PatrickF1/fzf.fish diff --git a/fish_variables b/fish_variables new file mode 100644 index 0000000..30d6f84 --- /dev/null +++ b/fish_variables @@ -0,0 +1,36 @@ +# This file contains fish universal variable definitions. +# VERSION: 3.0 +SETUVAR __fish_initialized:3400 +SETUVAR _fisher_PatrickF1_2F_fzf_2E_fish_files:/home/eric/\x2econfig/fish/functions/_fzf_configure_bindings_help\x2efish\x1e/home/eric/\x2econfig/fish/functions/_fzf_extract_var_info\x2efish\x1e/home/eric/\x2econfig/fish/functions/_fzf_preview_file\x2efish\x1e/home/eric/\x2econfig/fish/functions/_fzf_report_file_type\x2efish\x1e/home/eric/\x2econfig/fish/functions/_fzf_search_directory\x2efish\x1e/home/eric/\x2econfig/fish/functions/_fzf_search_git_log\x2efish\x1e/home/eric/\x2econfig/fish/functions/_fzf_search_git_status\x2efish\x1e/home/eric/\x2econfig/fish/functions/_fzf_search_history\x2efish\x1e/home/eric/\x2econfig/fish/functions/_fzf_search_processes\x2efish\x1e/home/eric/\x2econfig/fish/functions/_fzf_search_variables\x2efish\x1e/home/eric/\x2econfig/fish/functions/_fzf_wrapper\x2efish\x1e/home/eric/\x2econfig/fish/functions/fzf_configure_bindings\x2efish\x1e/home/eric/\x2econfig/fish/conf\x2ed/fzf\x2efish\x1e/home/eric/\x2econfig/fish/completions/fzf_configure_bindings\x2efish +SETUVAR _fisher_mattgreen_2F_lucid_2E_fish_files:/home/eric/\x2econfig/fish/functions/fish_prompt\x2efish +SETUVAR _fisher_plugins:mattgreen/lucid\x2efish\x1ePatrickF1/fzf\x2efish +SETUVAR fish_color_autosuggestion:BD93F9 +SETUVAR fish_color_cancel:\x2d\x2dreverse +SETUVAR fish_color_command:F8F8F2 +SETUVAR fish_color_comment:6272A4 +SETUVAR fish_color_cwd:green +SETUVAR fish_color_cwd_root:red +SETUVAR fish_color_end:50FA7B +SETUVAR fish_color_error:FFB86C +SETUVAR fish_color_escape:00a6b2 +SETUVAR fish_color_history_current:\x2d\x2dbold +SETUVAR fish_color_host:normal +SETUVAR fish_color_host_remote:yellow +SETUVAR fish_color_match:\x2d\x2dbackground\x3dbrblue +SETUVAR fish_color_normal:normal +SETUVAR fish_color_operator:00a6b2 +SETUVAR fish_color_param:FF79C6 +SETUVAR fish_color_quote:F1FA8C +SETUVAR fish_color_redirection:8BE9FD +SETUVAR fish_color_search_match:bryellow\x1e\x2d\x2dbackground\x3dbrblack +SETUVAR fish_color_selection:white\x1e\x2d\x2dbold\x1e\x2d\x2dbackground\x3dbrblack +SETUVAR fish_color_status:red +SETUVAR fish_color_user:brgreen +SETUVAR fish_color_valid_path:\x2d\x2dunderline +SETUVAR fish_greeting:\x1d +SETUVAR fish_key_bindings:fish_vi_key_bindings +SETUVAR fish_pager_color_completion:normal +SETUVAR fish_pager_color_description:B3A06D +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:\x2d\x2dbackground\x3dbrblack diff --git a/functions/_fzf_configure_bindings_help.fish b/functions/_fzf_configure_bindings_help.fish new file mode 100644 index 0000000..1209e49 --- /dev/null +++ b/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/functions/_fzf_extract_var_info.fish b/functions/_fzf_extract_var_info.fish new file mode 100644 index 0000000..dd4e952 --- /dev/null +++ b/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/functions/_fzf_preview_file.fish b/functions/_fzf_preview_file.fish new file mode 100644 index 0000000..29e7405 --- /dev/null +++ b/functions/_fzf_preview_file.fish @@ -0,0 +1,43 @@ +# helper function for _fzf_search_directory +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/functions/_fzf_report_file_type.fish b/functions/_fzf_report_file_type.fish new file mode 100644 index 0000000..49e02e1 --- /dev/null +++ b/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/functions/_fzf_search_directory.fish b/functions/_fzf_search_directory.fish new file mode 100644 index 0000000..57d3d13 --- /dev/null +++ b/functions/_fzf_search_directory.fish @@ -0,0 +1,43 @@ +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" + 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/functions/_fzf_search_git_log.fish b/functions/_fzf_search_git_log.fish new file mode 100644 index 0000000..3375c1d --- /dev/null +++ b/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/functions/_fzf_search_git_status.fish b/functions/_fzf_search_git_status.fish new file mode 100644 index 0000000..79a5c79 --- /dev/null +++ b/functions/_fzf_search_git_status.fish @@ -0,0 +1,33 @@ +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) \ + $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/functions/_fzf_search_history.fish b/functions/_fzf_search_history.fish new file mode 100644 index 0000000..271cfcc --- /dev/null +++ b/functions/_fzf_search_history.fish @@ -0,0 +1,24 @@ +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 + builtin history merge + + set command_with_ts ( + # Reference https://devhints.io/strftime to understand strftime format symbols + builtin history --null --show-time="%m-%d %H:%M:%S │ " | + _fzf_wrapper --read0 \ + --tiebreak=index \ + --query=(commandline) \ + # preview current command using fish_ident in a window at the bottom 3 lines tall + --preview="echo -- {4..} | fish_indent --ansi" \ + --preview-window="bottom:3:wrap" \ + $fzf_history_opts | + string collect + ) + + if test $status -eq 0 + set command_selected (string split --max 1 " │ " $command_with_ts)[2] + commandline --replace -- $command_selected + end + + commandline --function repaint +end diff --git a/functions/_fzf_search_processes.fish b/functions/_fzf_search_processes.fish new file mode 100644 index 0000000..e3ef59f --- /dev/null +++ b/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/functions/_fzf_search_variables.fish b/functions/_fzf_search_variables.fish new file mode 100644 index 0000000..744f226 --- /dev/null +++ b/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/functions/_fzf_wrapper.fish b/functions/_fzf_wrapper.fish new file mode 100644 index 0000000..a928701 --- /dev/null +++ b/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/functions/fish_prompt.old.fish b/functions/fish_prompt.old.fish new file mode 100644 index 0000000..ac30d7d --- /dev/null +++ b/functions/fish_prompt.old.fish @@ -0,0 +1,55 @@ +function fish_prompt + set -l last_status $status + + set -l normal (set_color normal) + set -l usercolor (set_color $fish_color_user) + + set -l delim \U25BA + # If we don't have unicode use a simpler delimiter + string match -qi "*.utf-8" -- $LANG $LC_CTYPE $LC_ALL; or set delim ">" + + fish_is_root_user; and set delim "#" + + set -l cwd (set_color $fish_color_cwd) + if command -sq cksum + # randomized cwd color + # We hash the physical PWD and turn that into a color. That means directories (usually) get different colors, + # but every directory always gets the same color. It's deterministic. + # We use cksum because 1. it's fast, 2. it's in POSIX, so it should be available everywhere. + set -l shas (pwd -P | cksum | string split -f1 ' ' | math --base=hex | string sub -s 3 | string match -ra ..) + set -l col 0x$shas[1..3] + + # If the (simplified idea of) luminance is below 120 (out of 255), add some more. + # (this runs at most twice because we add 60) + while test (math 0.2126 x $col[1] + 0.7152 x $col[2] + 0.0722 x $col[3]) -lt 120 + set col[1] (math --base=hex "min(255, $col[1] + 60)") + set col[2] (math --base=hex "min(255, $col[2] + 60)") + set col[3] (math --base=hex "min(255, $col[3] + 60)") + end + set -l col (string replace 0x '' $col | string pad -c 0 -w 2 | string join "") + + set cwd (set_color $col) + end + + # Prompt status only if it's not 0 + set -l prompt_status + test $last_status -ne 0; and set prompt_status (set_color $fish_color_error)"[$last_status]$normal" + + # Only show host if in SSH or container + # Store this in a global variable because it's slow and unchanging + if not set -q prompt_host + set -g prompt_host "" + if set -q SSH_TTY + or begin + command -sq systemd-detect-virt + and systemd-detect-virt -q + end + set prompt_host $usercolor$USER$normal@(set_color $fish_color_host)$hostname$normal":" + end + end + + # Shorten pwd if prompt is too long + set -l pwd (prompt_pwd) + + echo -n -s $prompt_host $cwd $pwd $normal $prompt_status $delim +end diff --git a/functions/fzf_configure_bindings.fish b/functions/fzf_configure_bindings.fish new file mode 100644 index 0000000..addb55c --- /dev/null +++ b/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/functions/su.fish b/functions/su.fish new file mode 100644 index 0000000..a9f271f --- /dev/null +++ b/functions/su.fish @@ -0,0 +1,3 @@ +function su + command su --shell=/usr/bin/fish $argv +end