mirror of
https://github.com/Xevion/dotfiles.git
synced 2025-12-09 18:06:55 -06:00
feat: migrate from Zsh to Fish shell with comprehensive configuration
Major shell migration replacing Zsh/Oh-My-Zsh with Fish shell: - Remove all Zsh configurations (dot_zshrc.tmpl, dot_p10k.zsh) - Remove Oh-My-Zsh external dependencies from .chezmoiexternal.toml - Add complete Fish shell setup with config.fish.tmpl and abbr.fish.tmpl - Implement Fish-native functions for lazy-loading tools (mise, pyenv, zoxide, etc.) - Create commonrc.fish.tmpl for cross-shell compatibility - Add Fish plugin management via Fisher (tide prompt, fzf.fish) - Update documentation (CLAUDE.md, TODO.md, ONBOARDING.md) to reflect Fish - Add .fish.tmpl file association to VS Code settings - Enhance PowerShell profile with lsd aliases - Configure git delta pager and zdiff3 merge conflict style - Update WSL keychain integration for Fish shell This migration maintains all existing tool integrations while improving startup performance through lazy-loading and Fish's native features.
This commit is contained in:
92
home/dot_config/fish/conf.d/abbr.fish.tmpl
Normal file
92
home/dot_config/fish/conf.d/abbr.fish.tmpl
Normal file
@@ -0,0 +1,92 @@
|
||||
# Fish abbreviations (aliases that expand in place)
|
||||
# Managed by chezmoi
|
||||
|
||||
# System
|
||||
abbr -a sctl 'systemctl'
|
||||
abbr -a sctlu 'systemctl --user'
|
||||
abbr -a jctl 'journalctl'
|
||||
|
||||
# Core aliases - lsd (modern ls replacement)
|
||||
abbr -a ls 'lsd'
|
||||
abbr -a l 'lsd -l'
|
||||
abbr -a la 'lsd -a'
|
||||
abbr -a lla 'lsd -la'
|
||||
abbr -a lt 'lsd --tree'
|
||||
abbr -a ll 'lsd -AlFh'
|
||||
abbr -a nano 'micro'
|
||||
abbr -a lg 'lazygit'
|
||||
abbr -a vim 'nvim'
|
||||
abbr -a chlg 'lazygit --path ~/.local/share/chezmoi'
|
||||
abbr -a es 'exec fish'
|
||||
|
||||
# Chezmoi
|
||||
abbr -a cha 'chezmoi apply --interactive'
|
||||
abbr -a ch 'chezmoi'
|
||||
|
||||
# Remote Management
|
||||
abbr -a romanlog "ssh roman 'tail -F /var/log/syslog' --lines 100"
|
||||
|
||||
# Other aliases
|
||||
abbr -a gpt 'chatgpt'
|
||||
abbr -a copilot 'gh copilot'
|
||||
abbr -a suggest 'gh copilot suggest -t shell'
|
||||
abbr -a spt 'spotify_player'
|
||||
abbr -a gitalias 'alias | grep "git "'
|
||||
abbr -a mousefix 'sudo udevadm trigger'
|
||||
abbr -a bw_login 'set -gx BW_SESSION (bw unlock --raw)'
|
||||
|
||||
# Clipboard aliases
|
||||
{{ if not .wsl -}}
|
||||
abbr -a copy 'xsel -ib'
|
||||
abbr -a paste 'xsel -b'
|
||||
abbr -a cdp 'cd (xsel -b)'
|
||||
{{- else -}}
|
||||
abbr -a copy 'clip.exe'
|
||||
abbr -a paste 'powershell.exe -noprofile Get-Clipboard'
|
||||
abbr -a cdp 'cd (xsel -b)'
|
||||
{{- end }}
|
||||
|
||||
# Bluetooth device aliases
|
||||
abbr -a budsOff 'bluetoothctl block 60:3A:AF:75:61:80'
|
||||
abbr -a budsOn 'bluetoothctl unblock 60:3A:AF:75:61:80 && bluetoothctl connect 60:3A:AF:75:61:80'
|
||||
abbr -a maestroOff 'bluetoothctl block AC:BF:71:66:FE:B2'
|
||||
abbr -a maestroOn 'bluetoothctl unblock AC:BF:71:66:FE:B2 && bluetoothctl connect AC:BF:71:66:FE:B2'
|
||||
|
||||
# Git Aliases
|
||||
abbr -a ga 'git add'
|
||||
abbr -a gaa 'git add .'
|
||||
abbr -a gaaa 'git add --all'
|
||||
abbr -a gau 'git add --update'
|
||||
abbr -a gb 'git branch'
|
||||
abbr -a gbd 'git branch --delete'
|
||||
abbr -a gc 'git commit'
|
||||
abbr -a gcm 'git commit --message'
|
||||
abbr -a gcf 'git commit --fixup'
|
||||
abbr -a gco 'git checkout'
|
||||
abbr -a gcob 'git checkout -b'
|
||||
abbr -a gcom 'git checkout master'
|
||||
abbr -a gcos 'git checkout staging'
|
||||
abbr -a gcod 'git checkout develop'
|
||||
abbr -a gd 'git diff'
|
||||
abbr -a gda 'git diff HEAD'
|
||||
abbr -a glg 'git log --graph --oneline --decorate --all'
|
||||
abbr -a gld 'git log --pretty=format:"%h %ad %s" --date=short --all'
|
||||
abbr -a gm 'git merge --no-ff'
|
||||
abbr -a gma 'git merge --abort'
|
||||
abbr -a gmc 'git merge --continue'
|
||||
abbr -a gp 'git pull'
|
||||
abbr -a gpr 'git pull --rebase'
|
||||
abbr -a gr 'git rebase'
|
||||
abbr -a gs 'git status'
|
||||
abbr -a gss 'git status --short'
|
||||
abbr -a gst 'git stash'
|
||||
abbr -a gsta 'git stash apply'
|
||||
abbr -a gstd 'git stash drop'
|
||||
abbr -a gstl 'git stash list'
|
||||
abbr -a gstp 'git stash pop'
|
||||
abbr -a gsts 'git stash save'
|
||||
|
||||
# KiTTY SSH kitten
|
||||
if test "$TERM" = "xterm-kitty"
|
||||
abbr -a ssh 'kitty +kitten ssh'
|
||||
end
|
||||
0
home/dot_config/fish/conf.d/keychain.fish
Normal file
0
home/dot_config/fish/conf.d/keychain.fish
Normal file
38
home/dot_config/fish/config.fish.tmpl
Normal file
38
home/dot_config/fish/config.fish.tmpl
Normal file
@@ -0,0 +1,38 @@
|
||||
# Fish shell configuration
|
||||
# Managed by chezmoi
|
||||
|
||||
# Disable greeting
|
||||
set -g fish_greeting
|
||||
|
||||
{{- if .wsl }}
|
||||
if status is-login
|
||||
and status is-interactive
|
||||
keychain --quiet --agents ssh --eval ~/.ssh/id_rsa | source
|
||||
end
|
||||
{{- end }}
|
||||
|
||||
# Common shared configuration (environment variables, PATH, tool setup)
|
||||
{{ template "scripts/commonrc.fish.tmpl" dict "data" . }}
|
||||
|
||||
# Chezmoi shell completion
|
||||
{{ completion "fish" }}
|
||||
|
||||
# VS Code / Cursor shell integration
|
||||
if test "$TERM_PROGRAM" = "vscode"
|
||||
if command -q code
|
||||
string replace -r '^' '' (code --locate-shell-integration-path fish) | source
|
||||
else if command -q cursor
|
||||
string replace -r '^' '' (cursor --locate-shell-integration-path fish) | source
|
||||
end
|
||||
end
|
||||
|
||||
# fzf key bindings (if fzf.fish plugin installed via Fisher)
|
||||
# Note: This is handled automatically by Fisher plugin
|
||||
|
||||
# Load custom functions from ~/.config/fish/functions/
|
||||
# (Fish does this automatically, no explicit sourcing needed)
|
||||
|
||||
# Load abbreviations
|
||||
if test -f ~/.config/fish/conf.d/abbr.fish
|
||||
source ~/.config/fish/conf.d/abbr.fish
|
||||
end
|
||||
10
home/dot_config/fish/fish_plugins
Normal file
10
home/dot_config/fish/fish_plugins
Normal file
@@ -0,0 +1,10 @@
|
||||
# Fish shell plugins managed by Fisher
|
||||
# https://github.com/jorgebucaran/fisher
|
||||
#
|
||||
# To install all plugins: fisher update
|
||||
# To add a plugin: fisher install <plugin>
|
||||
# To remove a plugin: fisher remove <plugin>
|
||||
|
||||
jorgebucaran/fisher
|
||||
ilancosman/tide@v6
|
||||
patrickf1/fzf.fish
|
||||
12
home/dot_config/fish/functions/__init_hishtory.fish.tmpl
Normal file
12
home/dot_config/fish/functions/__init_hishtory.fish.tmpl
Normal file
@@ -0,0 +1,12 @@
|
||||
# Defer hishtory initialization to first prompt
|
||||
# This runs after startup but before user interaction
|
||||
function __init_hishtory --on-event fish_prompt
|
||||
# Remove this function after first run
|
||||
functions --erase __init_hishtory
|
||||
|
||||
# Only initialize if hishtory config exists
|
||||
if test -f $HOME/.hishtory/config.fish
|
||||
set -gx HISHTORY_SERVER "https://hsh.{{ dopplerProjectJson.PRIVATE_DOMAIN }}"
|
||||
source $HOME/.hishtory/config.fish
|
||||
end
|
||||
end
|
||||
18
home/dot_config/fish/functions/chatgpt.fish
Normal file
18
home/dot_config/fish/functions/chatgpt.fish
Normal file
@@ -0,0 +1,18 @@
|
||||
# Lazy-load chatgpt completions on first use
|
||||
function chatgpt --wraps chatgpt
|
||||
# Initialize chatgpt completions only once
|
||||
if not set -q __chatgpt_initialized
|
||||
set -g __chatgpt_initialized 1
|
||||
|
||||
# Generate and source completions
|
||||
if command -q chatgpt
|
||||
command chatgpt --set-completions fish | source
|
||||
else
|
||||
echo "chatgpt is not installed" >&2
|
||||
return 1
|
||||
end
|
||||
end
|
||||
|
||||
# Execute the actual chatgpt command
|
||||
command chatgpt $argv
|
||||
end
|
||||
24
home/dot_config/fish/functions/chcode.fish
Normal file
24
home/dot_config/fish/functions/chcode.fish
Normal file
@@ -0,0 +1,24 @@
|
||||
function chcode --description "Edit chezmoi files in VS Code"
|
||||
set -gx EDITOR "code --wait"
|
||||
|
||||
# Check if --watch is in arguments
|
||||
set -l has_watch false
|
||||
set -l has_file false
|
||||
|
||||
for arg in $argv
|
||||
if test "$arg" = "--watch"
|
||||
set has_watch true
|
||||
else if not string match -q -- '-*' $arg
|
||||
set has_file true
|
||||
end
|
||||
end
|
||||
|
||||
# If --watch is provided but no file, show error
|
||||
if test $has_watch = true -a $has_file = false
|
||||
echo "--watch requires a file to be provided, directories aren't supported with watch mode"
|
||||
return 1
|
||||
end
|
||||
|
||||
# Execute chezmoi edit with all arguments
|
||||
chezmoi edit $argv
|
||||
end
|
||||
12
home/dot_config/fish/functions/chfix.fish
Normal file
12
home/dot_config/fish/functions/chfix.fish
Normal file
@@ -0,0 +1,12 @@
|
||||
function chfix --description "chmod +x the last command (if it's a file)"
|
||||
# Get the last command from Fish history
|
||||
set -l last_command (history --max 1 | string trim)
|
||||
|
||||
if test -f "$last_command"
|
||||
chmod +x "$last_command"
|
||||
echo "Made executable: $last_command"
|
||||
else
|
||||
echo "Error: $last_command is not a valid file"
|
||||
return 1
|
||||
end
|
||||
end
|
||||
6
home/dot_config/fish/functions/chshow.fish.tmpl
Normal file
6
home/dot_config/fish/functions/chshow.fish.tmpl
Normal file
@@ -0,0 +1,6 @@
|
||||
function chshow --description "Show rendered chezmoi template via fzf"
|
||||
set -l target (find {{ .chezmoi.sourceDir | quote }} -name "*.tmpl" -type f | fzf)
|
||||
if test -n "$target"
|
||||
cat $target | chezmoi execute-template
|
||||
end
|
||||
end
|
||||
19
home/dot_config/fish/functions/fuck.fish
Normal file
19
home/dot_config/fish/functions/fuck.fish
Normal file
@@ -0,0 +1,19 @@
|
||||
# Lazy-load thefuck on first use
|
||||
function fuck --description "Correct your previous console command"
|
||||
# Initialize thefuck only once
|
||||
if not set -q __thefuck_initialized
|
||||
set -g __thefuck_initialized 1
|
||||
|
||||
# Run thefuck alias generation
|
||||
if command -q thefuck
|
||||
thefuck --alias | source
|
||||
else
|
||||
echo "thefuck is not installed" >&2
|
||||
return 1
|
||||
end
|
||||
end
|
||||
|
||||
# Execute the fuck command (which thefuck creates)
|
||||
# After initialization, the actual fuck function will be defined
|
||||
fuck $argv
|
||||
end
|
||||
3
home/dot_config/fish/functions/gi.fish
Normal file
3
home/dot_config/fish/functions/gi.fish
Normal file
@@ -0,0 +1,3 @@
|
||||
function gi --description "Generate .gitignore from gitignore.io"
|
||||
curl -sL https://www.toptal.com/developers/gitignore/api/$argv
|
||||
end
|
||||
3
home/dot_config/fish/functions/glf.fish
Normal file
3
home/dot_config/fish/functions/glf.fish
Normal file
@@ -0,0 +1,3 @@
|
||||
function glf --description "Git log find by commit message"
|
||||
git log --all --grep="$argv"
|
||||
end
|
||||
18
home/dot_config/fish/functions/just.fish
Normal file
18
home/dot_config/fish/functions/just.fish
Normal file
@@ -0,0 +1,18 @@
|
||||
# Lazy-load just completions on first use
|
||||
function just --wraps just
|
||||
# Initialize just completions only once
|
||||
if not set -q __just_initialized
|
||||
set -g __just_initialized 1
|
||||
|
||||
# Generate and source completions
|
||||
if command -q just
|
||||
command just --completions fish | source
|
||||
else
|
||||
echo "just is not installed" >&2
|
||||
return 1
|
||||
end
|
||||
end
|
||||
|
||||
# Execute the actual just command
|
||||
command just $argv
|
||||
end
|
||||
7
home/dot_config/fish/functions/lastRuns.fish
Normal file
7
home/dot_config/fish/functions/lastRuns.fish
Normal file
@@ -0,0 +1,7 @@
|
||||
function lastRuns --description "Show last N GitHub Actions runs"
|
||||
set -l runs 10
|
||||
if test (count $argv) -gt 0
|
||||
set runs $argv[1]
|
||||
end
|
||||
gh run list -L $runs --json name,url | jq -c '.[] | [.name, .url] | join(" ")' -r
|
||||
end
|
||||
11
home/dot_config/fish/functions/mise.fish
Normal file
11
home/dot_config/fish/functions/mise.fish
Normal file
@@ -0,0 +1,11 @@
|
||||
# Lazy-load mise on first use
|
||||
function mise --wraps mise
|
||||
# Initialize mise only once
|
||||
if not set -q __mise_initialized
|
||||
set -g __mise_initialized 1
|
||||
command mise activate fish | source
|
||||
end
|
||||
|
||||
# Execute the actual mise command
|
||||
command mise $argv
|
||||
end
|
||||
4
home/dot_config/fish/functions/mktouch.fish
Normal file
4
home/dot_config/fish/functions/mktouch.fish
Normal file
@@ -0,0 +1,4 @@
|
||||
function mktouch --description "Touch a file while creating parent directories"
|
||||
mkdir -p (dirname $argv[1])
|
||||
touch $argv[1]
|
||||
end
|
||||
23
home/dot_config/fish/functions/pyenv.fish
Normal file
23
home/dot_config/fish/functions/pyenv.fish
Normal file
@@ -0,0 +1,23 @@
|
||||
# Lazy-load pyenv on first use
|
||||
function pyenv --wraps pyenv
|
||||
# Initialize pyenv only once
|
||||
if not set -q __pyenv_initialized
|
||||
set -g __pyenv_initialized 1
|
||||
|
||||
# Add to PATH if not already there
|
||||
if test -d $PYENV_ROOT/bin; and not contains $PYENV_ROOT/bin $PATH
|
||||
set -gx PATH $PYENV_ROOT/bin $PATH
|
||||
end
|
||||
|
||||
# Run pyenv init
|
||||
command pyenv init - fish | source
|
||||
|
||||
# pyenv-virtualenv if available
|
||||
if command -q pyenv-virtualenv-init
|
||||
command pyenv virtualenv-init - fish | source
|
||||
end
|
||||
end
|
||||
|
||||
# Execute the actual pyenv command
|
||||
command pyenv $argv
|
||||
end
|
||||
13
home/dot_config/fish/functions/tempCode.fish
Normal file
13
home/dot_config/fish/functions/tempCode.fish
Normal file
@@ -0,0 +1,13 @@
|
||||
function tempCode --description "Create a temporary file and open in VS Code"
|
||||
if test (count $argv) -eq 0
|
||||
echo "Must provide filetype argument (ex: py, .xml, html)"
|
||||
return 1
|
||||
end
|
||||
|
||||
# Remove preceding dot, then re-add to support both '.py' and 'py' as arguments
|
||||
set -l extension (string replace -r '^\.' '' $argv[1])
|
||||
set -l temp_file (mktemp /tmp/XXXXXXXXXXXX_(uuidgen).$extension)
|
||||
|
||||
echo "Temporary $argv[1] file created at $temp_file"
|
||||
code --file-uri "file://$temp_file"
|
||||
end
|
||||
18
home/dot_config/fish/functions/z.fish
Normal file
18
home/dot_config/fish/functions/z.fish
Normal file
@@ -0,0 +1,18 @@
|
||||
# Lazy-load zoxide on first use of z command
|
||||
function z --description "zoxide smart cd"
|
||||
# Initialize zoxide only once
|
||||
if not set -q __zoxide_initialized
|
||||
set -g __zoxide_initialized 1
|
||||
|
||||
# Run zoxide init
|
||||
if command -q zoxide
|
||||
zoxide init fish | source
|
||||
else
|
||||
echo "zoxide is not installed" >&2
|
||||
return 1
|
||||
end
|
||||
end
|
||||
|
||||
# Execute the actual z command (defined by zoxide init)
|
||||
__zoxide_z $argv
|
||||
end
|
||||
18
home/dot_config/fish/functions/zi.fish
Normal file
18
home/dot_config/fish/functions/zi.fish
Normal file
@@ -0,0 +1,18 @@
|
||||
# Lazy-load zoxide on first use of zi command
|
||||
function zi --description "zoxide interactive smart cd"
|
||||
# Initialize zoxide only once (shared flag with z.fish)
|
||||
if not set -q __zoxide_initialized
|
||||
set -g __zoxide_initialized 1
|
||||
|
||||
# Run zoxide init
|
||||
if command -q zoxide
|
||||
zoxide init fish | source
|
||||
else
|
||||
echo "zoxide is not installed" >&2
|
||||
return 1
|
||||
end
|
||||
end
|
||||
|
||||
# Execute the actual zi command (defined by zoxide init)
|
||||
__zoxide_zi $argv
|
||||
end
|
||||
Reference in New Issue
Block a user