Newest version of dotfiles with Ghostty, Fish, kickstart vim and zsh updates

This commit is contained in:
2025-06-04 16:33:07 +02:00
parent ee2a3a74ca
commit 778d39833c
132 changed files with 6177 additions and 5317 deletions

View File

@@ -0,0 +1,7 @@
complete --command fisher --exclusive --long help --description "Print help"
complete --command fisher --exclusive --long version --description "Print version"
complete --command fisher --exclusive --condition __fish_use_subcommand --arguments install --description "Install plugins"
complete --command fisher --exclusive --condition __fish_use_subcommand --arguments update --description "Update installed plugins"
complete --command fisher --exclusive --condition __fish_use_subcommand --arguments remove --description "Remove installed plugins"
complete --command fisher --exclusive --condition __fish_use_subcommand --arguments list --description "List installed plugins matching regex"
complete --command fisher --exclusive --condition "__fish_seen_subcommand_from update remove" --arguments "(fisher list)"

View File

@@ -0,0 +1,8 @@
complete fzf_configure_bindings --no-files
complete fzf_configure_bindings --long help --short h --description "Print help" --condition "not __fish_seen_argument --help -h"
complete fzf_configure_bindings --long directory --description "Change the key binding for Search Directory" --condition "not __fish_seen_argument --directory"
complete fzf_configure_bindings --long git_log --description "Change the key binding for Search Git Log" --condition "not __fish_seen_argument --git_log"
complete fzf_configure_bindings --long git_status --description "Change the key binding for Search Git Status" --condition "not __fish_seen_argument --git_status"
complete fzf_configure_bindings --long history --description "Change the key binding for Search History" --condition "not __fish_seen_argument --history"
complete fzf_configure_bindings --long processes --description "Change the key binding for Search Processes" --condition "not __fish_seen_argument --processes"
complete fzf_configure_bindings --long variables --description "Change the key binding for Search Variables" --condition "not __fish_seen_argument --variables"

View File

@@ -0,0 +1,21 @@
complete --command nvm --exclusive
complete --command nvm --exclusive --long version --description "Print version"
complete --command nvm --exclusive --long help --description "Print help"
complete --command nvm --long silent --description "Suppress standard output"
complete --command nvm --exclusive --condition __fish_use_subcommand --arguments install --description "Download and activate the specified Node version"
complete --command nvm --exclusive --condition __fish_use_subcommand --arguments use --description "Activate the specified Node version in the current shell"
complete --command nvm --exclusive --condition __fish_use_subcommand --arguments list --description "List installed Node versions"
complete --command nvm --exclusive --condition __fish_use_subcommand --arguments list-remote --description "List available Node versions to install"
complete --command nvm --exclusive --condition __fish_use_subcommand --arguments current --description "Print the currently-active Node version"
complete --command nvm --exclusive --condition "__fish_seen_subcommand_from install" --arguments "(
test -e $nvm_data && string split ' ' <$nvm_data/.index
)"
complete --command nvm --exclusive --condition "__fish_seen_subcommand_from use" --arguments "(_nvm_list | string split ' ')"
complete --command nvm --exclusive --condition __fish_use_subcommand --arguments uninstall --description "Uninstall the specified Node version"
complete --command nvm --exclusive --condition "__fish_seen_subcommand_from uninstall" --arguments "(
_nvm_list | string split ' ' | string replace system ''
)"
complete --command nvm --exclusive --condition "__fish_seen_subcommand_from use uninstall" --arguments "(
set --query nvm_default_version && echo default
)"

View File

@@ -0,0 +1,47 @@
# All your aliases
alias ld="ls -lisaGh"
alias g="goto"
alias vim="nvim"
alias code="open -a 'Visual Studio Code'"
alias kubi="open -a 'Lens'"
alias update-system="brew update && brew upgrade && npm update -g"
alias do-st="docker compose"
alias do-re="docker compose down && docker compose up -d"
alias hetzi="ssh root@128.140.71.88"
alias qaserv="TERM=xterm-256color ssh root@195.201.17.47"
alias kc1="set -gx KUBECONFIG ~/.kube/config"
alias kc2="set -gx KUBECONFIG ~/.kube/mobilistics"
alias ram="vm_stat"
# DevOps Core Tools
alias d="docker"
alias dc="docker compose"
alias dcu="docker compose up -d"
alias dcd="docker compose down"
alias dcl="docker compose logs -f"
alias dce="docker compose exec"
alias dps="docker ps --format 'table {{.Names}}\t{{.Status}}\t{{.Ports}}'"
# Kubernetes power aliases
alias k="kubectl"
alias kx="kubectx" # Context switching
alias kn="kubens" # Namespace switching
alias kgp="kubectl get pods -o wide"
alias kgs="kubectl get svc -o wide"
alias kgd="kubectl get deploy -o wide"
alias kl="kubectl logs -f"
alias ke="kubectl exec -it"
alias kdesc="kubectl describe"
alias kpf="kubectl port-forward"
# Testing
alias pw="npx playwright"
alias pwt="npx playwright test"
alias pwh="npx playwright test --headed"
alias pwr="npx playwright show-report"
# Python/Go
alias py="python3"
alias pip="pip3"
alias venv="python3 -m venv"
alias activate="source venv/bin/activate"

View File

@@ -0,0 +1,34 @@
# Quick project setup
function mkproj
mkdir -p $argv[1]
cd $argv[1]
git init
touch README.md .gitignore
echo "# $argv[1]" > README.md
end
# Docker cleanup
function docker-cleanup
docker system prune -af
docker volume prune -f
end
# Kubernetes context info
function kinfo
echo "Context: "(kubectl config current-context)
echo "Namespace: "(kubectl config view --minify -o jsonpath='{..namespace}')
kubectl get nodes --no-headers | wc -l | xargs echo "Nodes:"
end
# Quick YAML validation
function yaml-check
python3 -c "import yaml; yaml.safe_load(open('$argv[1]'))"
end
# Environment file loader
function loadenv
if test -f .env
export (cat .env | grep -v '^#' | xargs)
echo "Loaded .env"
end
end

View File

@@ -0,0 +1,340 @@
# MIT License
# Copyright (c) 2016 Francisco Lourenço & Daniel Wehner
# Permission is hereby granted, free of charge, to any person obtaining a copy
# of this software and associated documentation files (the "Software"), to deal
# in the Software without restriction, including without limitation the rights
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
# copies of the Software, and to permit persons to whom the Software is
# furnished to do so, subject to the following conditions:
# The above copyright notice and this permission notice shall be included in all
# copies or substantial portions of the Software.
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
# SOFTWARE.
if not status is-interactive
exit
end
set -g __done_version 1.20.0
function __done_run_powershell_script
set -l powershell_exe (command --search "powershell.exe")
if test $status -ne 0
and command --search wslvar
set -l powershell_exe (wslpath (wslvar windir)/System32/WindowsPowerShell/v1.0/powershell.exe)
end
if string length --quiet "$powershell_exe"
and test -x "$powershell_exe"
set cmd (string escape $argv)
eval "$powershell_exe -Command $cmd"
end
end
function __done_windows_notification -a title -a message
if test "$__done_notify_sound" -eq 1
set soundopt "<audio silent=\"false\" src=\"ms-winsoundevent:Notification.Default\" />"
else
set soundopt "<audio silent=\"true\" />"
end
__done_run_powershell_script "
[Windows.Data.Xml.Dom.XmlDocument, Windows.Data.Xml.Dom.XmlDocument, ContentType = WindowsRuntime] | Out-Null
[Windows.UI.Notifications.ToastNotification, Windows.UI.Notifications, ContentType = WindowsRuntime] | Out-Null
\$toast_xml_source = @\"
<toast>
$soundopt
<visual>
<binding template=\"ToastText02\">
<text id=\"1\">$title</text>
<text id=\"2\">$message</text>
</binding>
</visual>
</toast>
\"@
\$toast_xml = New-Object Windows.Data.Xml.Dom.XmlDocument
\$toast_xml.loadXml(\$toast_xml_source)
\$toast = New-Object Windows.UI.Notifications.ToastNotification \$toast_xml
[Windows.UI.Notifications.ToastNotificationManager]::CreateToastNotifier(\"fish\").Show(\$toast)
"
end
function __done_get_focused_window_id
if type -q lsappinfo
lsappinfo info -only bundleID (lsappinfo front | string replace 'ASN:0x0-' '0x') | cut -d '"' -f4
else if test -n "$SWAYSOCK"
and type -q jq
swaymsg --type get_tree | jq '.. | objects | select(.focused == true) | .id'
else if test -n "$HYPRLAND_INSTANCE_SIGNATURE"
hyprctl activewindow | awk 'NR==1 {print $2}'
else if test -n "$NIRI_SOCKET"
and type -q jq
niri msg --json focused-window | jq ".id"
else if begin
test "$XDG_SESSION_DESKTOP" = gnome; and type -q gdbus
end
gdbus call --session --dest org.gnome.Shell --object-path /org/gnome/Shell --method org.gnome.Shell.Eval 'global.display.focus_window.get_id()'
else if type -q xprop
and test -n "$DISPLAY"
# Test that the X server at $DISPLAY is running
and xprop -grammar >/dev/null 2>&1
xprop -root 32x '\t$0' _NET_ACTIVE_WINDOW | cut -f 2
else if uname -a | string match --quiet --ignore-case --regex microsoft
__done_run_powershell_script '
Add-Type @"
using System;
using System.Runtime.InteropServices;
public class WindowsCompat {
[DllImport("user32.dll")]
public static extern IntPtr GetForegroundWindow();
}
"@
[WindowsCompat]::GetForegroundWindow()
'
else if set -q __done_allow_nongraphical
echo 12345 # dummy value
end
end
function __done_is_tmux_window_active
set -q fish_pid; or set -l fish_pid %self
# find the outermost process within tmux
# ppid != "tmux" -> pid = ppid
# ppid == "tmux" -> break
set tmux_fish_pid $fish_pid
while set tmux_fish_ppid (ps -o ppid= -p $tmux_fish_pid | string trim)
# remove leading hyphen so that basename does not treat it as an argument (e.g. -fish), and return only
# the actual command and not its arguments so that basename finds the correct command name.
# (e.g. '/usr/bin/tmux' from command '/usr/bin/tmux new-session -c /some/start/dir')
and ! string match -q "tmux*" (basename (ps -o command= -p $tmux_fish_ppid | string replace -r '^-' '' | string split ' ')[1])
set tmux_fish_pid $tmux_fish_ppid
end
# tmux session attached and window is active -> no notification
# all other combinations -> send notification
tmux list-panes -a -F "#{session_attached} #{window_active} #{pane_pid}" | string match -q "1 1 $tmux_fish_pid"
end
function __done_is_screen_window_active
string match --quiet --regex "$STY\s+\(Attached" (screen -ls)
end
function __done_is_process_window_focused
# Return false if the window is not focused
if set -q __done_allow_nongraphical
return 1
end
if set -q __done_kitty_remote_control
kitty @ --password="$__done_kitty_remote_control_password" ls | jq -e ".[].tabs[] | select(any(.windows[]; .is_self)) | .is_focused" >/dev/null
return $status
end
set __done_focused_window_id (__done_get_focused_window_id)
if test "$__done_sway_ignore_visible" -eq 1
and test -n "$SWAYSOCK"
string match --quiet --regex "^true" (swaymsg -t get_tree | jq ".. | objects | select(.id == "$__done_initial_window_id") | .visible")
return $status
else if test -n "$HYPRLAND_INSTANCE_SIGNATURE"
and test $__done_initial_window_id = (hyprctl activewindow | awk 'NR==1 {print $2}')
return $status
else if test -n "$NIRI_SOCKET"
and test $__done_initial_window_id = (niri msg --json focused-window | jq ".id")
return $status
else if test "$__done_initial_window_id" != "$__done_focused_window_id"
return 1
end
# If inside a tmux session, check if the tmux window is focused
if type -q tmux
and test -n "$TMUX"
__done_is_tmux_window_active
return $status
end
# If inside a screen session, check if the screen window is focused
if type -q screen
and test -n "$STY"
__done_is_screen_window_active
return $status
end
return 0
end
function __done_humanize_duration -a milliseconds
set -l seconds (math --scale=0 "$milliseconds/1000" % 60)
set -l minutes (math --scale=0 "$milliseconds/60000" % 60)
set -l hours (math --scale=0 "$milliseconds/3600000")
if test $hours -gt 0
printf '%s' $hours'h '
end
if test $minutes -gt 0
printf '%s' $minutes'm '
end
if test $seconds -gt 0
printf '%s' $seconds's'
end
end
# verify that the system has graphical capabilities before initializing
if test -z "$SSH_CLIENT" # not over ssh
and count (__done_get_focused_window_id) >/dev/null # is able to get window id
set __done_enabled
end
if set -q __done_allow_nongraphical
and set -q __done_notification_command
set __done_enabled
end
if set -q __done_enabled
set -g __done_initial_window_id ''
set -q __done_min_cmd_duration; or set -g __done_min_cmd_duration 5000
set -q __done_exclude; or set -g __done_exclude '^git (?!push|pull|fetch)'
set -q __done_notify_sound; or set -g __done_notify_sound 0
set -q __done_sway_ignore_visible; or set -g __done_sway_ignore_visible 0
set -q __done_tmux_pane_format; or set -g __done_tmux_pane_format '[#{window_index}]'
set -q __done_notification_duration; or set -g __done_notification_duration 3000
function __done_started --on-event fish_preexec
set __done_initial_window_id (__done_get_focused_window_id)
end
function __done_ended --on-event fish_postexec
set -l exit_status $status
# backwards compatibility for fish < v3.0
set -q cmd_duration; or set -l cmd_duration $CMD_DURATION
if test $cmd_duration
and test $cmd_duration -gt $__done_min_cmd_duration # longer than notify_duration
and not __done_is_process_window_focused # process pane or window not focused
# don't notify if command matches exclude list
for pattern in $__done_exclude
if string match -qr $pattern $argv[1]
return
end
end
# Store duration of last command
set -l humanized_duration (__done_humanize_duration "$cmd_duration")
set -l title "Done in $humanized_duration"
set -l wd (string replace --regex "^$HOME" "~" (pwd))
set -l message "$wd/ $argv[1]"
set -l sender $__done_initial_window_id
if test $exit_status -ne 0
set title "Failed ($exit_status) after $humanized_duration"
end
if test -n "$TMUX_PANE"
set message (tmux lsw -F"$__done_tmux_pane_format" -f '#{==:#{pane_id},'$TMUX_PANE'}')" $message"
end
if set -q __done_notification_command
eval $__done_notification_command
if test "$__done_notify_sound" -eq 1
echo -e "\a" # bell sound
end
else if set -q KITTY_WINDOW_ID
printf "\x1b]99;i=done:d=0;$title\x1b\\"
printf "\x1b]99;i=done:d=1:p=body;$message\x1b\\"
else if type -q terminal-notifier # https://github.com/julienXX/terminal-notifier
if test "$__done_notify_sound" -eq 1
# pipe message into terminal-notifier to avoid escaping issues (https://github.com/julienXX/terminal-notifier/issues/134). fixes #140
echo "$message" | terminal-notifier -title "$title" -sender "$__done_initial_window_id" -sound default
else
echo "$message" | terminal-notifier -title "$title" -sender "$__done_initial_window_id"
end
else if type -q osascript # AppleScript
# escape double quotes that might exist in the message and break osascript. fixes #133
set -l message (string replace --all '"' '\"' "$message")
set -l title (string replace --all '"' '\"' "$title")
if test "$__done_notify_sound" -eq 1
osascript -e "display notification \"$message\" with title \"$title\" sound name \"Glass\""
else
osascript -e "display notification \"$message\" with title \"$title\""
end
else if type -q notify-send # Linux notify-send
# set urgency to normal
set -l urgency normal
# use user-defined urgency if set
if set -q __done_notification_urgency_level
set urgency "$__done_notification_urgency_level"
end
# override user-defined urgency level if non-zero exitstatus
if test $exit_status -ne 0
set urgency critical
if set -q __done_notification_urgency_level_failure
set urgency "$__done_notification_urgency_level_failure"
end
end
notify-send --hint=int:transient:1 --urgency=$urgency --icon=utilities-terminal --app-name=fish --expire-time=$__done_notification_duration "$title" "$message"
if test "$__done_notify_sound" -eq 1
echo -e "\a" # bell sound
end
else if type -q notify-desktop # Linux notify-desktop
set -l urgency
if test $exit_status -ne 0
set urgency "--urgency=critical"
end
notify-desktop $urgency --icon=utilities-terminal --app-name=fish "$title" "$message"
if test "$__done_notify_sound" -eq 1
echo -e "\a" # bell sound
end
else if uname -a | string match --quiet --ignore-case --regex microsoft
__done_windows_notification "$title" "$message"
else # anything else
echo -e "\a" # bell sound
end
end
end
end
function __done_uninstall -e done_uninstall
# Erase all __done_* functions
functions -e __done_ended
functions -e __done_started
functions -e __done_get_focused_window_id
functions -e __done_is_tmux_window_active
functions -e __done_is_screen_window_active
functions -e __done_is_process_window_focused
functions -e __done_windows_notification
functions -e __done_run_powershell_script
functions -e __done_humanize_duration
# Erase __done variables
set -e __done_version
end

View File

@@ -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

View File

@@ -0,0 +1,42 @@
# Kubernetes setup
set -gx KUBECONFIG ~/.kube/config
# Kubernetes aliases
alias k="kubectl"
alias kgp="kubectl get pods"
alias kgn="kubectl get nodes"
alias kgs="kubectl get services"
alias kgc="kubectl config get-contexts"
alias kuc="kubectl config use-context"
alias kns="kubectl config set-context --current --namespace"
# Kubernetes context function
function update_kubernetes_context
if command -q kubectl
set -l kube_ctx (kubectl config current-context 2>/dev/null)
if test $status -eq 0
set -l kube_ns (kubectl config view --minify --output 'jsonpath={..namespace}' 2>/dev/null)
set -gx STARSHIP_KUBERNETES_CONTEXT $kube_ctx
if test -n "$kube_ns"
set -gx STARSHIP_KUBERNETES_NAMESPACE $kube_ns
end
else
set -e STARSHIP_KUBERNETES_CONTEXT
set -e STARSHIP_KUBERNETES_NAMESPACE
end
end
end
# Wrapper for kubectl
function kubectl
command kubectl $argv
set -l exit_code $status
if test $exit_code -eq 0; and test "$argv[1]" = "config"; and contains "$argv[2]" "use-context" "set-context"
update_kubernetes_context
end
return $exit_code
end
# Update context on startup
update_kubernetes_context

View File

@@ -0,0 +1,34 @@
# Enhanced nvim with project detection
function v
if test (count $argv) -eq 0
# Open nvim in project root or current dir
if test -f package.json; or test -f go.mod; or test -f requirements.txt; or test -f Dockerfile; or test -f docker-compose.yml
nvim .
else
nvim
end
else
nvim $argv
end
end
# Quick config edit
function vconfig
nvim ~/.config/nvim/
end
# Edit dockerfile
function vdocker
if test -f Dockerfile
nvim Dockerfile
else if test -f docker-compose.yml
nvim docker-compose.yml
else
echo "No Docker files found"
end
end
# Edit kubernetes manifests
function vk8s
find . -name "*.yaml" -o -name "*.yml" | grep -E "(k8s|kubernetes|deploy)" | head -5 | xargs nvim
end

View File

@@ -0,0 +1,28 @@
set --query XDG_DATA_HOME || set --local XDG_DATA_HOME ~/.local/share
set --query nvm_mirror || set --global nvm_mirror https://nodejs.org/dist
set --query nvm_data || set --global nvm_data $XDG_DATA_HOME/nvm
function _nvm_install --on-event nvm_install
test ! -d $nvm_data && command mkdir -p $nvm_data
echo "Downloading the Node distribution index..." 2>/dev/null
_nvm_index_update
end
function _nvm_update --on-event nvm_update
set --query --universal nvm_data && set --erase --universal nvm_data
set --query --universal nvm_mirror && set --erase --universal nvm_mirror
set --query nvm_mirror || set --global nvm_mirror https://nodejs.org/dist
end
function _nvm_uninstall --on-event nvm_uninstall
command rm -rf $nvm_data
set --query nvm_current_version && _nvm_version_deactivate $nvm_current_version
set --names | string replace --filter --regex -- "^nvm" "set --erase nvm" | source
functions --erase (functions --all | string match --entire --regex -- "^_nvm_")
end
if status is-interactive && set --query nvm_default_version && ! set --query nvm_current_version
nvm use --silent $nvm_default_version
end

View File

@@ -0,0 +1,10 @@
# Development paths
fish_add_path /opt/homebrew/bin
fish_add_path ~/.cargo/bin
fish_add_path ~/.local/bin
fish_add_path /usr/local/go/bin
fish_add_path $GOPATH/bin
# Go environment
set -gx GOPATH ~/go
set -gx GO111MODULE on

View File

@@ -0,0 +1,10 @@
# SSH/GPG setup
set -gx GPG_TTY (tty)
set -gx SSH_AUTH_SOCK ~/.gnupg/S.gpg-agent.ssh
# Launch GPG agent
gpgconf --launch gpg-agent
if test "$gnupg_SSH_AUTH_SOCK_by" != "$fish_pid"
set -gx SSH_AUTH_SOCK (gpgconf --list-dirs agent-ssh-socket)
end

View File

@@ -0,0 +1,7 @@
# Testing environment variables
set -gx PLAYWRIGHT_BROWSERS_PATH ~/.cache/ms-playwright
set -gx PYTEST_CURRENT_TEST ""
# Test result formatting
alias pytest="python -m pytest -v --tb=short"
alias test-docker="docker run --rm -v (pwd):/app -w /app"

View File

@@ -0,0 +1,14 @@
# Starship
if command -q starship
starship init fish | source
end
# Zoxide
if command -q zoxide
zoxide init --cmd cd fish | source
end
# GPG
set -gx GPG_TTY (tty)
set -gx SSH_AUTH_SOCK ~/.gnupg/S.gpg-agent.ssh
gpgconf --launch gpg-agent

4
.config/fish/config.fish Normal file
View File

@@ -0,0 +1,4 @@
# ~/.config/fish/config.fish
# Startup commands only
neofetch

View File

@@ -0,0 +1,4 @@
jorgebucaran/fisher
jorgebucaran/nvm.fish
patrickf1/fzf.fish
franciscolourenco/done

View File

@@ -0,0 +1,43 @@
function _fzf_configure_bindings_help --description "Prints the help message for fzf_configure_bindings."
echo "\
USAGE:
fzf_configure_bindings [--COMMAND=[KEY_SEQUENCE]...]
DESCRIPTION
fzf_configure_bindings installs key bindings for fzf.fish's commands and erases any bindings it
previously installed. It installs bindings for both default and insert modes. fzf.fish executes
it without options on fish startup to install the out-of-the-box key bindings.
By default, commands are bound to a mnemonic key sequence, shown below. Each command's binding
can be configured using a namesake corresponding option:
COMMAND | DEFAULT 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 Processes | Ctrl+Alt+P (P for process) | --processes
Search Variables | Ctrl+V (V for variable) | --variables
Override a command's binding by specifying its corresponding option with the desired key
sequence. Disable a command's binding by specifying its corresponding option with no value.
Because fzf_configure_bindings erases bindings it previously installed, it can be cleanly
executed multiple times. Once the desired fzf_configure_bindings command has been found, add it
to your config.fish in order to persist the customized bindings.
In terms of validation, fzf_configure_bindings fails if passed unknown options. It expects an
equals sign between an option's name and value. However, it does not validate key sequences.
Pass -h or --help to print this help message and exit.
EXAMPLES
Default bindings but bind Search Directory to Ctrl+F and Search Variables to Ctrl+Alt+V
\$ fzf_configure_bindings --directory=\cf --variables=\e\cv
Default bindings but disable Search History
\$ fzf_configure_bindings --history=
An agglomeration of different options
\$ fzf_configure_bindings --git_status=\cg --history=\ch --variables= --processes=
SEE Also
To learn more about fish key bindings, see bind(1) and fish_key_reader(1).
"
end

View File

@@ -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

View File

@@ -0,0 +1,49 @@
# 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 -> "New 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 -f 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 -f index_status (string sub --length 1 $path_status)
set -f working_tree_status (string sub --start 2 --length 1 $path_status)
set -f diff_opts --color=always
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
# renames are only detected in the index, never working tree, so only need to test for it here
# https://stackoverflow.com/questions/73954214
if test $index_status = R
# diff the post-rename path with the original path, otherwise the diff will show the entire file as being added
set -f orig_and_new_path (string split --max 1 -- ' -> ' $path)
git diff --staged $diff_opts -- $orig_and_new_path[1] $orig_and_new_path[2]
# path currently has the form of "original -> current", so we need to correct it before it's used below
set path $orig_and_new_path[2]
else
git diff --staged $diff_opts -- $path
end
end
if test $working_tree_status != ' '
_fzf_report_diff_type Unstaged
git diff $diff_opts -- $path
end
end
end

View File

@@ -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 -f 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

View File

@@ -0,0 +1,18 @@
# 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 -f repeat_count (math 2 + (string length $diff_type))
set -f line (string repeat --count $repeat_count)
set -f top_border$line
set -f btm_border$line
set_color yellow
echo $top_border
echo "$diff_type"
echo $btm_border
set_color normal
end

View File

@@ -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

View File

@@ -0,0 +1,33 @@
function _fzf_search_directory --description "Search the current directory. Replace the current token with the selected file paths."
# Directly use fd binary to avoid output buffering delay caused by a fd alias, if any.
# Debian-based distros install fd as fdfind and the fd package is something else, so
# check for fdfind first. Fall back to "fd" for a clear error message.
set -f fd_cmd (command -v fdfind || command -v fd || echo "fd")
set -f --append fd_cmd --color=always $fzf_fd_opts
set -f fzf_arguments --multi --ansi $fzf_directory_opts
set -f token (commandline --current-token)
# expand any variables or leading tilde (~) in the token
set -f expanded_token (eval echo -- $token)
# unescape token because it's already quoted so backslashes will mess up the path
set -f 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_cmd --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="Directory $unescaped_exp_token> " --preview="_fzf_preview_file $expanded_token{}"
set -f file_paths_selected $unescaped_exp_token($fd_cmd 2>/dev/null | _fzf_wrapper $fzf_arguments)
else
set --prepend fzf_arguments --prompt="Directory> " --query="$unescaped_exp_token" --preview='_fzf_preview_file {}'
set -f file_paths_selected ($fd_cmd 2>/dev/null | _fzf_wrapper $fzf_arguments)
end
if test $status -eq 0
commandline --current-token --replace -- (string escape -- $file_paths_selected | string join ' ')
end
commandline --function repaint
end

View File

@@ -0,0 +1,36 @@
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
if not set --query fzf_git_log_format
# %h gives you the abbreviated commit hash, which is useful for saving screen space, but we will have to expand it later below
set -f fzf_git_log_format '%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)'
end
set -f preview_cmd 'git show --color=always --stat --patch {1}'
if set --query fzf_diff_highlighter
set preview_cmd "$preview_cmd | $fzf_diff_highlighter"
end
set -f selected_log_lines (
git log --no-show-signature --color=always --format=format:$fzf_git_log_format --date=short | \
_fzf_wrapper --ansi \
--multi \
--scheme=history \
--prompt="Git Log> " \
--preview=$preview_cmd \
--query=(commandline --current-token) \
$fzf_git_log_opts
)
if test $status -eq 0
for line in $selected_log_lines
set -f abbreviated_commit_hash (string split --field 1 " " $line)
set -f full_commit_hash (git rev-parse $abbreviated_commit_hash)
set -f --append commit_hashes $full_commit_hash
end
commandline --current-token --replace (string join ' ' $commit_hashes)
end
end
commandline --function repaint
end

View File

@@ -0,0 +1,41 @@
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 -f preview_cmd '_fzf_preview_changed_file {}'
if set --query fzf_diff_highlighter
set preview_cmd "$preview_cmd | $fzf_diff_highlighter"
end
set -f 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 \
--prompt="Git Status> " \
--query=(commandline --current-token) \
--preview=$preview_cmd \
--nth="2.." \
$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 -f 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

View File

@@ -0,0 +1,39 @@
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
if not set --query fzf_history_time_format
# Reference https://devhints.io/strftime to understand strftime format symbols
set -f fzf_history_time_format "%m-%d %H:%M:%S"
end
# Delinate time from command in history entries using the vertical box drawing char (U+2502).
# Then, to get raw command from history entries, delete everything up to it. The ? on regex is
# necessary to make regex non-greedy so it won't match into commands containing the char.
set -f time_prefix_regex '^.*? │ '
# Delinate commands throughout pipeline using null rather than newlines because commands can be multi-line
set -f commands_selected (
builtin history --null --show-time="$fzf_history_time_format" |
_fzf_wrapper --read0 \
--print0 \
--multi \
--scheme=history \
--prompt="History> " \
--query=(commandline) \
--preview="string replace --regex '$time_prefix_regex' '' -- {} | fish_indent --ansi" \
--preview-window="bottom:3:wrap" \
$fzf_history_opts |
string split0 |
# remove timestamps from commands selected
string replace --regex $time_prefix_regex ''
)
if test $status -eq 0
commandline --replace -- $commands_selected
end
commandline --function repaint
end

View File

@@ -0,0 +1,32 @@
function _fzf_search_processes --description "Search all running processes. Replace the current token with the pid of the selected process."
# Directly use ps command because it is often aliased to a different command entirely
# or with options that dirty the search results and preview output
set -f ps_cmd (command -v ps || echo "ps")
# 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 -f ps_preview_fmt (string join ',' 'pid' 'ppid=PARENT' 'user' '%cpu' 'rss=RSS_IN_KB' 'start=START_TIME' 'command')
set -f processes_selected (
$ps_cmd -A -opid,command | \
_fzf_wrapper --multi \
--prompt="Processes> " \
--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_cmd -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 -f --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

View File

@@ -0,0 +1,47 @@
# 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 -f all_variable_names (string match --invert history <$set_names_output)
set -f 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 -f cleaned_curr_token (string replace -- '$' '' $current_token)
set -f variable_names_selected (
printf '%s\n' $all_variable_names |
_fzf_wrapper --preview "_fzf_extract_var_info {} $set_show_output" \
--prompt="Variables> " \
--preview-window="wrap" \
--multi \
--query=$cleaned_curr_token \
$fzf_variables_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

View File

@@ -0,0 +1,21 @@
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 --function so that it doesn't clobber SHELL outside this function.
set -f --export SHELL (command --search fish)
# If neither FZF_DEFAULT_OPTS nor FZF_DEFAULT_OPTS_FILE are set, then set some sane defaults.
# See https://github.com/junegunn/fzf#environment-variables
set --query FZF_DEFAULT_OPTS FZF_DEFAULT_OPTS_FILE
if test $status -eq 2
# 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

View File

@@ -0,0 +1,20 @@
function _nvm_index_update
test ! -d $nvm_data && command mkdir -p $nvm_data
set --local index $nvm_data/.index
if not command curl -q --location --silent $nvm_mirror/index.tab >$index.temp
command rm -f $index.temp
echo "nvm: Can't update index, host unavailable: \"$nvm_mirror\"" >&2
return 1
end
command awk -v OFS=\t '
/v0.9.12/ { exit } # Unsupported
NR > 1 {
print $1 (NR == 2 ? " latest" : $10 != "-" ? " lts/" tolower($10) : "")
}
' $index.temp >$index
command rm -f $index.temp
end

View File

@@ -0,0 +1,14 @@
function _nvm_list
set --local versions $nvm_data/*
set --query versions[1] &&
string match --entire --regex -- (
string replace --all -- $nvm_data/ "" $versions |
string match --regex -- "v\d.+" |
string escape --style=regex |
string join "|"
) <$nvm_data/.index
command --all node |
string match --quiet --invert --regex -- "^$nvm_data" && echo system
end

View File

@@ -0,0 +1,4 @@
function _nvm_version_activate --argument-names ver
set --global --export nvm_current_version $ver
set --prepend PATH $nvm_data/$ver/bin
end

View File

@@ -0,0 +1,5 @@
function _nvm_version_deactivate --argument-names ver
test "$nvm_current_version" = "$ver" && set --erase nvm_current_version
set --local index (contains --index -- $nvm_data/$ver/bin $PATH) &&
set --erase PATH[$index]
end

View File

@@ -0,0 +1,8 @@
function colormap
for i in (seq 0 255)
printf "%b%03d%b " (set_color -b $i) $i (set_color normal)
if test (math $i % 6) -eq 3
echo
end
end
end

View File

@@ -0,0 +1,240 @@
function fisher --argument-names cmd --description "A plugin manager for Fish"
set --query fisher_path || set --local fisher_path $__fish_config_dir
set --local fisher_version 4.4.5
set --local fish_plugins $__fish_config_dir/fish_plugins
switch "$cmd"
case -v --version
echo "fisher, version $fisher_version"
case "" -h --help
echo "Usage: fisher install <plugins...> Install plugins"
echo " fisher remove <plugins...> Remove installed plugins"
echo " fisher update <plugins...> Update installed plugins"
echo " fisher update Update all installed plugins"
echo " fisher list [<regex>] List installed plugins matching regex"
echo "Options:"
echo " -v, --version Print version"
echo " -h, --help Print this help message"
echo "Variables:"
echo " \$fisher_path Plugin installation path. Default: $__fish_config_dir" | string replace --regex -- $HOME \~
case ls list
string match --entire --regex -- "$argv[2]" $_fisher_plugins
case install update remove
isatty || read --local --null --array stdin && set --append argv $stdin
set --local install_plugins
set --local update_plugins
set --local remove_plugins
set --local arg_plugins $argv[2..-1]
set --local old_plugins $_fisher_plugins
set --local new_plugins
test -e $fish_plugins && set --local file_plugins (string match --regex -- '^[^\s]+$' <$fish_plugins | string replace -- \~ ~)
if ! set --query argv[2]
if test "$cmd" != update
echo "fisher: Not enough arguments for command: \"$cmd\"" >&2 && return 1
else if ! set --query file_plugins
echo "fisher: \"$fish_plugins\" file not found: \"$cmd\"" >&2 && return 1
end
set arg_plugins $file_plugins
end
for plugin in $arg_plugins
set plugin (test -e "$plugin" && realpath $plugin || string lower -- $plugin)
contains -- "$plugin" $new_plugins || set --append new_plugins $plugin
end
if set --query argv[2]
for plugin in $new_plugins
if contains -- "$plugin" $old_plugins
test "$cmd" = remove &&
set --append remove_plugins $plugin ||
set --append update_plugins $plugin
else if test "$cmd" = install
set --append install_plugins $plugin
else
echo "fisher: Plugin not installed: \"$plugin\"" >&2 && return 1
end
end
else
for plugin in $new_plugins
contains -- "$plugin" $old_plugins &&
set --append update_plugins $plugin ||
set --append install_plugins $plugin
end
for plugin in $old_plugins
contains -- "$plugin" $new_plugins || set --append remove_plugins $plugin
end
end
set --local pid_list
set --local source_plugins
set --local fetch_plugins $update_plugins $install_plugins
set --local fish_path (status fish-path)
echo (set_color --bold)fisher $cmd version $fisher_version(set_color normal)
for plugin in $fetch_plugins
set --local source (command mktemp -d)
set --append source_plugins $source
command mkdir -p $source/{completions,conf.d,themes,functions}
$fish_path --command "
if test -e $plugin
command cp -Rf $plugin/* $source
else
set temp (command mktemp -d)
set repo (string split -- \@ $plugin) || set repo[2] HEAD
if set path (string replace --regex -- '^(https://)?gitlab.com/' '' \$repo[1])
set name (string split -- / \$path)[-1]
set url https://gitlab.com/\$path/-/archive/\$repo[2]/\$name-\$repo[2].tar.gz
else
set url https://api.github.com/repos/\$repo[1]/tarball/\$repo[2]
end
echo Fetching (set_color --underline)\$url(set_color normal)
if command curl -q --silent -L \$url | command tar -xzC \$temp -f - 2>/dev/null
command cp -Rf \$temp/*/* $source
else
echo fisher: Invalid plugin name or host unavailable: \\\"$plugin\\\" >&2
command rm -rf $source
end
command rm -rf \$temp
end
set files $source/* && string match --quiet --regex -- .+\.fish\\\$ \$files
" &
set --append pid_list (jobs --last --pid)
end
wait $pid_list 2>/dev/null
for plugin in $fetch_plugins
if set --local source $source_plugins[(contains --index -- "$plugin" $fetch_plugins)] && test ! -e $source
if set --local index (contains --index -- "$plugin" $install_plugins)
set --erase install_plugins[$index]
else
set --erase update_plugins[(contains --index -- "$plugin" $update_plugins)]
end
end
end
for plugin in $update_plugins $remove_plugins
if set --local index (contains --index -- "$plugin" $_fisher_plugins)
set --local plugin_files_var _fisher_(string escape --style=var -- $plugin)_files
if contains -- "$plugin" $remove_plugins
for name in (string replace --filter --regex -- '.+/conf\.d/([^/]+)\.fish$' '$1' $$plugin_files_var)
emit {$name}_uninstall
end
printf "%s\n" Removing\ (set_color red --bold)$plugin(set_color normal) " "$$plugin_files_var | string replace -- \~ ~
set --erase _fisher_plugins[$index]
end
command rm -rf (string replace -- \~ ~ $$plugin_files_var)
functions --erase (string replace --filter --regex -- '.+/functions/([^/]+)\.fish$' '$1' $$plugin_files_var)
for name in (string replace --filter --regex -- '.+/completions/([^/]+)\.fish$' '$1' $$plugin_files_var)
complete --erase --command $name
end
set --erase $plugin_files_var
end
end
if set --query update_plugins[1] || set --query install_plugins[1]
command mkdir -p $fisher_path/{functions,themes,conf.d,completions}
end
for plugin in $update_plugins $install_plugins
set --local source $source_plugins[(contains --index -- "$plugin" $fetch_plugins)]
set --local files $source/{functions,themes,conf.d,completions}/*
if set --local index (contains --index -- $plugin $install_plugins)
set --local user_files $fisher_path/{functions,themes,conf.d,completions}/*
set --local conflict_files
for file in (string replace -- $source/ $fisher_path/ $files)
contains -- $file $user_files && set --append conflict_files $file
end
if set --query conflict_files[1] && set --erase install_plugins[$index]
echo -s "fisher: Cannot install \"$plugin\": please remove or move conflicting files first:" \n" "$conflict_files >&2
continue
end
end
for file in (string replace -- $source/ "" $files)
command cp -RLf $source/$file $fisher_path/$file
end
set --local plugin_files_var _fisher_(string escape --style=var -- $plugin)_files
set --query files[1] && set --universal $plugin_files_var (string replace -- $source $fisher_path $files | string replace -- ~ \~)
contains -- $plugin $_fisher_plugins || set --universal --append _fisher_plugins $plugin
contains -- $plugin $install_plugins && set --local event install || set --local event update
printf "%s\n" Installing\ (set_color --bold)$plugin(set_color normal) " "$$plugin_files_var | string replace -- \~ ~
for file in (string match --regex -- '.+/[^/]+\.fish$' $$plugin_files_var | string replace -- \~ ~)
source $file
if set --local name (string replace --regex -- '.+conf\.d/([^/]+)\.fish$' '$1' $file)
emit {$name}_$event
end
end
end
command rm -rf $source_plugins
if set --query _fisher_plugins[1]
set --local commit_plugins
for plugin in $file_plugins
contains -- (string lower -- $plugin) (string lower -- $_fisher_plugins) && set --append commit_plugins $plugin
end
for plugin in $_fisher_plugins
contains -- (string lower -- $plugin) (string lower -- $commit_plugins) || set --append commit_plugins $plugin
end
string replace --regex -- $HOME \~ $commit_plugins >$fish_plugins
else
set --erase _fisher_plugins
command rm -f $fish_plugins
end
set --local total (count $install_plugins) (count $update_plugins) (count $remove_plugins)
test "$total" != "0 0 0" && echo (string join ", " (
test $total[1] = 0 || echo "Installed $total[1]") (
test $total[2] = 0 || echo "Updated $total[2]") (
test $total[3] = 0 || echo "Removed $total[3]")
) plugin/s
case \*
echo "fisher: Unknown command: \"$cmd\"" >&2 && return 1
end
end
if ! set --query _fisher_upgraded_to_4_4
set --universal _fisher_upgraded_to_4_4
if functions --query _fisher_list
set --query XDG_DATA_HOME[1] || set --local XDG_DATA_HOME ~/.local/share
command rm -rf $XDG_DATA_HOME/fisher
functions --erase _fisher_{list,plugin_parse}
fisher update >/dev/null 2>/dev/null
else
for var in (set --names | string match --entire --regex '^_fisher_.+_files$')
set $var (string replace -- ~ \~ $$var)
end
functions --erase _fisher_fish_postexec
end
end

View File

@@ -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 -f options_spec h/help 'directory=?' 'git_log=?' 'git_status=?' 'history=?' 'processes=?' 'variables=?'
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 = processes, 6 = variables
set -f key_sequences \e\cf \e\cl \e\cs \cr \e\cp \cv # \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_processes && set key_sequences[5] "$_flag_processes"
set --query _flag_variables && set key_sequences[6] "$_flag_variables"
# 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_processes
test -n $key_sequences[6] && bind --mode $mode $key_sequences[6] "$_fzf_search_vars_command"
end
function _fzf_uninstall_bindings --inherit-variable key_sequences
bind --erase -- $key_sequences
bind --erase --mode insert -- $key_sequences
end
end
end

View File

@@ -0,0 +1,237 @@
function nvm --description "Node version manager"
for silent in --silent -s
if set --local index (contains --index -- $silent $argv)
set --erase argv[$index] && break
end
set --erase silent
end
set --local cmd $argv[1]
set --local ver $argv[2]
if set --query silent && ! set --query cmd[1]
echo "nvm: Version number not specified (see nvm -h for usage)" >&2
return 1
end
if ! set --query ver[1] && contains -- "$cmd" install use
for file in .nvmrc .node-version
set file (_nvm_find_up $PWD $file) && read ver <$file && break
end
if ! set --query ver[1]
echo "nvm: Invalid version or missing \".nvmrc\" file" >&2
return 1
end
end
set --local their_version $ver
switch "$cmd"
case -v --version
echo "nvm, version 2.2.18"
case "" -h --help
echo "Usage: nvm install <version> Download and activate the specified Node version"
echo " nvm install Install the version specified in the nearest .nvmrc file"
echo " nvm use <version> Activate the specified Node version in the current shell"
echo " nvm use Activate the version specified in the nearest .nvmrc file"
echo " nvm list List installed Node versions"
echo " nvm list-remote List available Node versions to install"
echo " nvm list-remote <regex> List Node versions matching a given regex pattern"
echo " nvm current Print the currently-active Node version"
echo " nvm uninstall <version> Uninstall the specified Node version"
echo "Options:"
echo " -s, --silent Suppress standard output"
echo " -v, --version Print the version of nvm"
echo " -h, --help Print this help message"
echo "Variables:"
echo " nvm_arch Override architecture, e.g. x64-musl"
echo " nvm_mirror Use a mirror for downloading Node binaries"
echo " nvm_default_version Set the default version for new shells"
echo " nvm_default_packages Install a list of packages every time a Node version is installed"
echo " nvm_data Set a custom directory for storing nvm data"
echo "Examples:"
echo " nvm install latest Install the latest version of Node"
echo " nvm use 14.15.1 Use Node version 14.15.1"
echo " nvm use system Activate the system's Node version"
case install
_nvm_index_update
string match --entire --regex -- (_nvm_version_match $ver) <$nvm_data/.index | read ver alias
if ! set --query ver[1]
echo "nvm: Invalid version number or alias: \"$their_version\"" >&2
return 1
end
if test ! -e $nvm_data/$ver
set --local os (command uname -s | string lower)
set --local ext tar.gz
set --local arch (command uname -m)
set --local tarcmd tar
switch $os
case aix
set arch ppc64
case sunos
case linux
case darwin
case {msys_nt,mingw\*_nt}\*
set os win
set ext zip
set tarcmd bsdtar
case \*
echo "nvm: Unsupported operating system: \"$os\"" >&2
return 1
end
switch $arch
case i\*86
set arch x86
case x86_64
set arch x64
case arm64
string match --regex --quiet "v(?<major>\d+)" $ver
if test "$os" = darwin -a $major -lt 16
set arch x64
end
case armv6 armv6l
set arch armv6l
case armv7 armv7l
set arch armv7l
case armv8 armv8l aarch64
set arch arm64
end
set --query nvm_arch && set arch $nvm_arch
set --local dir "node-$ver-$os-$arch"
set --local url $nvm_mirror/$ver/$dir.$ext
command mkdir -p $nvm_data/$ver
if ! set --query silent
echo -e "Installing Node \x1b[1m$ver\x1b[22m $alias"
echo -e "Fetching \x1b[4m$url\x1b[24m\x1b[7m"
end
if ! command curl -q $silent --progress-bar --location $url |
command $tarcmd --extract --gzip --directory $nvm_data/$ver 2>/dev/null
command rm -rf $nvm_data/$ver
echo -e "\033[F\33[2K\x1b[0mnvm: Invalid mirror or host unavailable: \"$url\"" >&2
return 1
end
set --query silent || echo -en "\033[F\33[2K\x1b[0m"
if test "$os" = win
command mv $nvm_data/$ver/$dir $nvm_data/$ver/bin
else
command mv $nvm_data/$ver/$dir/* $nvm_data/$ver
command rm -rf $nvm_data/$ver/$dir
end
end
if test $ver != "$nvm_current_version"
set --query nvm_current_version && _nvm_version_deactivate $nvm_current_version
_nvm_version_activate $ver
set --query nvm_default_packages[1] && npm install --global $silent $nvm_default_packages
end
set --query silent || printf "Now using Node %s (npm %s) %s\n" (_nvm_node_info)
case use
test $ver = default && set ver $nvm_default_version
_nvm_list | string match --entire --regex -- (_nvm_version_match $ver) | read ver __
if ! set --query ver[1]
echo "nvm: Can't use Node \"$their_version\", version must be installed first" >&2
return 1
end
if test $ver != "$nvm_current_version"
set --query nvm_current_version && _nvm_version_deactivate $nvm_current_version
test $ver != system && _nvm_version_activate $ver
end
set --query silent || printf "Now using Node %s (npm %s) %s\n" (_nvm_node_info)
case uninstall
if test -z "$ver"
echo "nvm: Not enough arguments for command: \"$cmd\"" >&2
return 1
end
test $ver = default && test ! -z "$nvm_default_version" && set ver $nvm_default_version
_nvm_list | string match --entire --regex -- (_nvm_version_match $ver) | read ver __
if ! set -q ver[1]
echo "nvm: Node version not installed or invalid: \"$their_version\"" >&2
return 1
end
set --query silent || printf "Uninstalling Node %s %s\n" $ver (string replace ~ \~ "$nvm_data/$ver/bin/node")
_nvm_version_deactivate $ver
command rm -rf $nvm_data/$ver
case current
_nvm_current
case ls list
_nvm_list | _nvm_list_format (_nvm_current) $argv[2]
case lsr {ls,list}-remote
_nvm_index_update || return
_nvm_list | command awk '
FILENAME == "-" && (is_local[$1] = FNR == NR) { next } {
print $0 (is_local[$1] ? " ✓" : "")
}
' - $nvm_data/.index | _nvm_list_format (_nvm_current) $argv[2]
case \*
echo "nvm: Unknown command or option: \"$cmd\" (see nvm -h for usage)" >&2
return 1
end
end
function _nvm_find_up --argument-names path file
test -e "$path/$file" && echo $path/$file || begin
test ! -z "$path" || return
_nvm_find_up (string replace --regex -- '/[^/]*$' "" $path) $file
end
end
function _nvm_version_match --argument-names ver
string replace --regex -- '^v?(\d+|\d+\.\d+)$' 'v$1.' $ver |
string replace --filter --regex -- '^v?(\d+)' 'v$1' |
string escape --style=regex || string lower '\b'$ver'(?:/\w+)?$'
end
function _nvm_list_format --argument-names current regex
command awk -v current="$current" -v regex="$regex" '
$0 ~ regex {
aliases[versions[i++] = $1] = $2 " " $3
pad = (n = length($1)) > pad ? n : pad
}
END {
if (!i) exit 1
while (i--)
printf((current == versions[i] ? " ▶ " : " ") "%"pad"s %s\n",
versions[i], aliases[versions[i]])
}
'
end
function _nvm_current
command --search --quiet node || return
set --query nvm_current_version && echo $nvm_current_version || echo system
end
function _nvm_node_info
set --local npm_path (string replace bin/npm-cli.js "" (realpath (command --search npm)))
test -f $npm_path/package.json || set --local npm_version_default (command npm --version)
command node --eval "
console.log(process.version)
console.log('$npm_version_default' ? '$npm_version_default': require('$npm_path/package.json').version)
console.log(process.execPath)
" | string replace -- ~ \~
end