docs: add fish-to-zsh conversion plan
Add a structured plan for translating Fish shell config.fish into equivalent Zsh .zshrc syntax, preserving the existing Forge-managed block in the target file.
This commit is contained in:
@@ -0,0 +1,276 @@
|
|||||||
|
# Convert Fish config.fish to Zsh .zshrc
|
||||||
|
|
||||||
|
## Objective
|
||||||
|
|
||||||
|
Translate all functional content from `~/.config/fish/config.fish` into equivalent Zsh syntax, append it **below** the existing Forge-managed block in `~/.config/zsh/.zshrc`, and leave the existing content untouched.
|
||||||
|
|
||||||
|
## Source Analysis
|
||||||
|
|
||||||
|
### Fish config breakdown (`~/.config/fish/config.fish`, 178 lines)
|
||||||
|
|
||||||
|
| Lines | Category | Notes |
|
||||||
|
|-------|----------|-------|
|
||||||
|
| 1 | Comment (collapsed) | Multi-line comment got collapsed into one line; contains `set fish_greeting`, `set VIRTUAL_ENV_DISABLE_PROMPT`, `set -x SHELL /usr/bin/fish` |
|
||||||
|
| 2-3 | Man pager (bat) | `set -xU` universal env vars |
|
||||||
|
| 5-6 | Paru pager | `set -x` exported env var |
|
||||||
|
| 8-10 | Done plugin settings | `set -U` universal vars for `done` notification plugin |
|
||||||
|
| 12-16 | Source `~/.fish_profile` | Fish-specific profile file |
|
||||||
|
| 18-23 | PATH: `~/.local/bin` | Already in .zshrc (line 2) |
|
||||||
|
| 25-30 | PATH: `depot_tools` | Conditional PATH prepend |
|
||||||
|
| 32-37 | Starship + zoxide + atuin | Interactive-only init |
|
||||||
|
| 39-40 | find-the-command hook | Fish-specific (`ftc.fish`) |
|
||||||
|
| 42-76 | Bang-bang + history functions | `!!` and `!$` support + history formatting |
|
||||||
|
| 78-80 | `backup` function | Simple `cp` backup |
|
||||||
|
| 83-92 | `copy` function | Smart `cp` with directory detection |
|
||||||
|
| 94-102 | `cleanup` function | Remove orphaned pacman packages |
|
||||||
|
| 104-163 | Aliases & abbreviations | Many aliases, some with Fish-specific syntax |
|
||||||
|
| 165-168 | Fastfetch on interactive | Run fastfetch if available |
|
||||||
|
| 170-172 | PATH: opencode + local bin | PATH additions (local bin already covered) |
|
||||||
|
| 174-178 | Qt/KDE theming | Conditional `QT_STYLE_OVERRIDE` |
|
||||||
|
|
||||||
|
### Existing .zshrc breakdown (`~/.config/zsh/.zshrc`, 48 lines)
|
||||||
|
|
||||||
|
Lines 1-47 are Forge-managed and must remain untouched. The new content should be appended **after line 48** (end of file).
|
||||||
|
|
||||||
|
## Implementation Plan
|
||||||
|
|
||||||
|
- [ ] **Step 1.** Append all converted content below the existing Forge block (after line 48). Do not modify any existing lines.
|
||||||
|
|
||||||
|
## Converted Zsh Code (to append after line 48 of `~/.config/zsh/.zshrc`)
|
||||||
|
|
||||||
|
```zsh
|
||||||
|
# ============================================================
|
||||||
|
# Converted from ~/.config/fish/config.fish
|
||||||
|
# ============================================================
|
||||||
|
|
||||||
|
# --- Environment Variables ---
|
||||||
|
|
||||||
|
# Hide welcome message (Zsh equivalent: set empty PS1 greeting or just skip)
|
||||||
|
VIRTUAL_ENV_DISABLE_PROMPT="1"
|
||||||
|
export VIRTUAL_ENV_DISABLE_PROMPT
|
||||||
|
|
||||||
|
# Use bat for man pages
|
||||||
|
export MANPAGER="sh -c 'col -bx | bat -l man -p'"
|
||||||
|
export MANROFFOPT="-c"
|
||||||
|
|
||||||
|
# Hint to exit PKGBUILD review in Paru
|
||||||
|
export PARU_PAGER="less -P \"Press 'q' to exit the PKGBUILD review.\""
|
||||||
|
|
||||||
|
# --- PATH Additions ---
|
||||||
|
|
||||||
|
# Add ~/.local/bin to PATH (already present via Forge, but kept for completeness)
|
||||||
|
if [[ -d ~/.local/bin ]]; then
|
||||||
|
case ":${PATH}:" in
|
||||||
|
*:"$HOME/.local/bin":*) ;;
|
||||||
|
*) export PATH="$HOME/.local/bin:$PATH" ;;
|
||||||
|
esac
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Add depot_tools to PATH
|
||||||
|
if [[ -d ~/Applications/depot_tools ]]; then
|
||||||
|
case ":${PATH}:" in
|
||||||
|
*:"$HOME/Applications/depot_tools":*) ;;
|
||||||
|
*) export PATH="$HOME/Applications/depot_tools:$PATH" ;;
|
||||||
|
esac
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Add opencode to PATH
|
||||||
|
if [[ -d ~/.opencode/bin ]]; then
|
||||||
|
case ":${PATH}:" in
|
||||||
|
*:"$HOME/.opencode/bin":*) ;;
|
||||||
|
*) export PATH="$HOME/.opencode/bin:$PATH" ;;
|
||||||
|
esac
|
||||||
|
fi
|
||||||
|
|
||||||
|
# --- Interactive Shell Setup ---
|
||||||
|
|
||||||
|
if [[ -o interactive ]]; then
|
||||||
|
# Zoxide (smart cd)
|
||||||
|
eval "$(zoxide init zsh)"
|
||||||
|
|
||||||
|
# Atuin (shell history)
|
||||||
|
eval "$(atuin init zsh)"
|
||||||
|
|
||||||
|
# Starship prompt
|
||||||
|
eval "$(starship init zsh)"
|
||||||
|
fi
|
||||||
|
|
||||||
|
# --- Bang-Bang Support (!!) ---
|
||||||
|
|
||||||
|
# Zsh has built-in bang-bang via `setopt bang_hist` (default on).
|
||||||
|
# Enable history expansion:
|
||||||
|
setopt bang_hist
|
||||||
|
setopt hist_expand
|
||||||
|
|
||||||
|
# --- History Settings ---
|
||||||
|
|
||||||
|
HISTFILE=~/.config/zsh/.zsh_history
|
||||||
|
HISTSIZE=10000
|
||||||
|
SAVEHIST=10000
|
||||||
|
setopt extended_history # Record timestamps (equivalent to --show-time='%F %T ')
|
||||||
|
setopt share_history # Share history across sessions
|
||||||
|
setopt hist_ignore_all_dups # Remove older duplicate entries
|
||||||
|
setopt hist_ignore_space # Ignore commands starting with space
|
||||||
|
setopt hist_save_no_dups # Don't save duplicates
|
||||||
|
|
||||||
|
# --- Functions ---
|
||||||
|
|
||||||
|
# Create a backup of a file
|
||||||
|
backup() {
|
||||||
|
cp "$1" "${1}.bak"
|
||||||
|
}
|
||||||
|
|
||||||
|
# Smart copy: if source is a directory and exactly 2 args, copy recursively
|
||||||
|
copy() {
|
||||||
|
if [[ $# -eq 2 && -d "$1" ]]; then
|
||||||
|
command cp -r "${1%/}" "$2"
|
||||||
|
else
|
||||||
|
command cp "$@"
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
# Cleanup orphaned packages
|
||||||
|
cleanup() {
|
||||||
|
local orphans
|
||||||
|
orphans=$(pacman -Qdtq 2>/dev/null)
|
||||||
|
while [[ -n "$orphans" ]]; do
|
||||||
|
sudo pacman -R $orphans || break
|
||||||
|
orphans=$(pacman -Qdtq 2>/dev/null)
|
||||||
|
done
|
||||||
|
}
|
||||||
|
|
||||||
|
# --- Aliases ---
|
||||||
|
|
||||||
|
# Replace ls with eza
|
||||||
|
alias ls='eza -al --color=always --group-directories-first --icons'
|
||||||
|
alias lsz='eza -al --color=always --total-size --group-directories-first --icons'
|
||||||
|
alias la='eza -a --color=always --group-directories-first --icons'
|
||||||
|
alias ll='eza -l --color=always --group-directories-first --icons'
|
||||||
|
alias lt='eza -aT --color=always --group-directories-first --icons'
|
||||||
|
alias l.='eza -ald --color=always --group-directories-first --icons .*'
|
||||||
|
|
||||||
|
# Replace cat with bat
|
||||||
|
alias cat='bat --style header,snip,changes'
|
||||||
|
|
||||||
|
# Use paru as yay if yay is not installed
|
||||||
|
if ! command -v yay &>/dev/null && command -v paru &>/dev/null; then
|
||||||
|
alias yay='paru'
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Directory navigation
|
||||||
|
alias ..='cd ..'
|
||||||
|
alias ...='cd ../..'
|
||||||
|
alias ....='cd ../../..'
|
||||||
|
alias .....='cd ../../../..'
|
||||||
|
alias ......='cd ../../../../..'
|
||||||
|
|
||||||
|
# Package management
|
||||||
|
alias big='expac -H M "%m\t%n" | sort -h | nl'
|
||||||
|
alias fixpacman='sudo rm /var/lib/pacman/db.lck'
|
||||||
|
alias gitpkg='pacman -Q | grep -i "\-git" | wc -l'
|
||||||
|
alias rmpkg='sudo pacman -Rdd'
|
||||||
|
alias upd='/usr/bin/garuda-update'
|
||||||
|
|
||||||
|
# Grep replacements (ugrep)
|
||||||
|
alias grep='ugrep --color=auto'
|
||||||
|
alias egrep='ugrep -E --color=auto'
|
||||||
|
alias fgrep='ugrep -F --color=auto'
|
||||||
|
|
||||||
|
# Tar
|
||||||
|
alias tarnow='tar -acf '
|
||||||
|
alias untar='tar -zxvf '
|
||||||
|
|
||||||
|
# Misc
|
||||||
|
alias dir='dir --color=auto'
|
||||||
|
alias grubup='sudo update-grub'
|
||||||
|
alias hw='hwinfo --short'
|
||||||
|
alias ip='ip -color'
|
||||||
|
alias psmem='ps auxf | sort -nr -k 4'
|
||||||
|
alias psmem10='ps auxf | sort -nr -k 4 | head -10'
|
||||||
|
alias vdir='vdir --color=auto'
|
||||||
|
alias wget='wget -c '
|
||||||
|
|
||||||
|
# Mirror management (reflector)
|
||||||
|
alias mirror='sudo reflector -f 30 -l 30 --number 10 --verbose --save /etc/pacman.d/mirrorlist'
|
||||||
|
alias mirrora='sudo reflector --latest 50 --number 20 --sort age --save /etc/pacman.d/mirrorlist'
|
||||||
|
alias mirrord='sudo reflector --latest 50 --number 20 --sort delay --save /etc/pacman.d/mirrorlist'
|
||||||
|
alias mirrors='sudo reflector --latest 50 --number 20 --sort score --save /etc/pacman.d/mirrorlist'
|
||||||
|
|
||||||
|
# Help for newcomers to Arch
|
||||||
|
alias apt='man pacman'
|
||||||
|
alias apt-get='man pacman'
|
||||||
|
alias please='sudo'
|
||||||
|
alias tb='nc termbin.com 9999'
|
||||||
|
alias helpme='echo "To print basic information about a command use tldr <command>"'
|
||||||
|
alias pacdiff='sudo -H DIFFPROG=meld pacdiff'
|
||||||
|
|
||||||
|
# Journalctl errors
|
||||||
|
alias jctl='journalctl -p 3 -xb'
|
||||||
|
|
||||||
|
# Recent installed packages
|
||||||
|
alias rip='expac --timefmt="%Y-%m-%d %T" "%l\t%n %v" | sort | tail -200 | nl'
|
||||||
|
|
||||||
|
# --- Run fastfetch if session is interactive ---
|
||||||
|
|
||||||
|
if [[ -o interactive ]] && command -v fastfetch &>/dev/null; then
|
||||||
|
fastfetch --config dr460nized.jsonc
|
||||||
|
fi
|
||||||
|
|
||||||
|
# --- Qt/KDE Theming ---
|
||||||
|
|
||||||
|
# Set for non-Plasma sessions (Hyprland, etc.)
|
||||||
|
if [[ -z "$XDG_CURRENT_DESKTOP" ]] || [[ "$XDG_CURRENT_DESKTOP" != "KDE" ]]; then
|
||||||
|
export QT_STYLE_OVERRIDE=kvantum
|
||||||
|
fi
|
||||||
|
```
|
||||||
|
|
||||||
|
## Items Intentionally Excluded
|
||||||
|
|
||||||
|
| Fish Line(s) | Item | Reason for Exclusion |
|
||||||
|
|---|---|---|
|
||||||
|
| 1 | `set -x SHELL /usr/bin/fish` | Fish-specific; should be `SHELL=/usr/bin/zsh` if anything, but zsh sets this automatically |
|
||||||
|
| 1 | `set fish_greeting` | Fish-specific; Zsh has no equivalent greeting mechanism |
|
||||||
|
| 8-10 | `__done_*` settings | These are Fish `done` plugin variables; Zsh equivalent would need a different notification plugin |
|
||||||
|
| 12-16 | Source `~/.fish_profile` | Fish-specific profile file; if needed, convert to `~/.zprofile` or source a zsh-compatible profile |
|
||||||
|
| 39-40 | `source /usr/share/doc/find-the-command/ftc.fish` | Fish-specific command-not-found hook; Zsh has `command-not-found-handler` or uses pkgfile |
|
||||||
|
| 42-76 | `__history_previous_command` / `__history_previous_command_arguments` + bind | Fish-specific bang-bang plugin; Zsh has built-in `!!` and `!$` via `setopt bang_hist hist_expand` |
|
||||||
|
|
||||||
|
## Verification Criteria
|
||||||
|
|
||||||
|
- [ ] All aliases work: open a new zsh shell and run `alias` to confirm they are loaded
|
||||||
|
- [ ] `eza` aliases produce colored output with icons
|
||||||
|
- [ ] `bat` alias shows headers/snippets
|
||||||
|
- [ ] `backup testfile.txt` creates `testfile.txt.bak`
|
||||||
|
- [ ] `copy dir1 dir2` copies recursively; `copy file1 file2` copies normally
|
||||||
|
- [ ] `cleanup` removes orphaned pacman packages without error
|
||||||
|
- [ ] `fastfetch` runs on interactive shell launch
|
||||||
|
- [ ] `QT_STYLE_OVERRIDE=kvantum` is set when not in KDE
|
||||||
|
- [ ] PATH includes `~/.local/bin`, `~/Applications/depot_tools`, and `~/.opencode/bin` (when dirs exist)
|
||||||
|
- [ ] `zoxide`, `atuin`, and `starship` initialize in interactive sessions
|
||||||
|
- [ ] Existing Forge-managed block (lines 1-47) is completely untouched
|
||||||
|
- [ ] History expansion works: try `!!` to repeat last command
|
||||||
|
|
||||||
|
## Potential Risks and Mitigations
|
||||||
|
|
||||||
|
1. **Alias name conflicts with existing commands**
|
||||||
|
Mitigation: All aliases use the same names as the Fish config, which was already working. The `cat` alias overriding `cat` with `bat` is intentional but could break scripts that call `cat` and expect raw output. Use `\cat` or `command cat` when needed.
|
||||||
|
|
||||||
|
2. **Forge-managed block interference**
|
||||||
|
Mitigation: The Forge block already sets up `compinit`, zsh-autosuggestions, zsh-syntax-highlighting, and a prompt theme. The converted Starship init will override the Forge prompt theme. If you want to keep the Forge prompt, remove the `eval "$(starship init zsh)"` line.
|
||||||
|
|
||||||
|
3. **`cleanup` function subshell variable scope**
|
||||||
|
Mitigation: The Fish version used a while loop with `$status`. The Zsh version captures orphan list in a variable and uses the `-n` test instead, which is more reliable.
|
||||||
|
|
||||||
|
4. **`garuda-update` alias may not exist**
|
||||||
|
Mitigation: The alias is a direct path reference. If the binary doesn't exist, the alias simply won't work when invoked — same behavior as Fish.
|
||||||
|
|
||||||
|
5. **Fastfetch config path**
|
||||||
|
Mitigation: `fastfetch --config dr460nized.jsonc` uses a relative config name. Ensure the config file is discoverable by fastfetch (typically in `~/.config/fastfetch/`).
|
||||||
|
|
||||||
|
## Alternative Approaches
|
||||||
|
|
||||||
|
1. **Use a framework (oh-my-zsh / zinit)**: Instead of manual conversion, use a Zsh framework that provides bang-bang, aliases, and plugin management out of the box. Trade-off: adds framework dependency and complexity.
|
||||||
|
|
||||||
|
2. **Use `babelfish` or `fish2zsh` tools**: Automated Fish-to-Zsh converters exist but may not handle all Fish-specific constructs correctly. Trade-off: faster but less reliable for edge cases.
|
||||||
|
|
||||||
|
3. **Source a separate file**: Instead of appending to `.zshrc`, place converted content in `~/.config/zsh/.zshrc.fish-converted` and source it from `.zshrc`. Trade-off: cleaner separation but adds an extra file to manage.
|
||||||
Reference in New Issue
Block a user