This README provides an overview of a custom .zshrc file. This Zsh environment is designed for system administration and secure file management on a Fedora Asahi based system (specifically optimized for Apple Silicon).
Workflow & Function Overview
1. Secure File Staging & Deployment
These functions provide a controlled way to move files between user space and system directories.
prep-upload <file>: Copies a file to a dedicated~/uploadsdirectory, sets user ownership, and checks for existing files to prevent accidental overwrites.deploy-upload <filename> <destination>: Moves a file from the staging area to a system path. If the destination is asudoersfile, it automatically runsvisudo -cto verify syntax before finishing.sedit <file>: A wrapper forsudoeditthat ensures the editor remainsnanofor quick, secure system file changes.
2. System Maintenance & Diagnostics
timeback: A robust Timeshift wrapper. It automatically kills hanging Timeshift processes and removes lock files before prompting for a backup comment and starting a verbose backup.purge_ram: Syncs the filesystem and clears kernel caches to release memory.setboot: Quickly displays the current boot configuration usingasahi-bless.sysstat: A comprehensive alias that shows memory usage, disk health for the root partition, swap status, and the current swappiness value.checkdns: Checks DNS status, DNS servers, VPN status and DNS protocols.ez: Opens Kate to edit .zshrc file and when saved and closed, the .zshrc file is automatically sourced and reloaded. Same functionality foresandeswaliases for sudoers and sudoers.d file editing withvisudosyntax verification.
3. Compatibility & Conflict Checks
check_alias_conflicts: Scans a list of aliases to see if any of them “shadow” (hide) actual system binaries, helping prevent unexpected behavior.check_ls_compat/check_grep_compat: Probes the installed versions oflsandgrepto ensure they support specific flags like--group-directories-firstor--exclude-dir.
4. UI/UX Enhancements
expand-alias-space: A “magic” spacebar function. When you type an alias and hit space, it expands the alias to the full command immediately on the command line.tmux-status: Reports the last time atmux-resurrectsession was saved.C(Global Alias): A global alias that allows you to pipe any command output to the system clipboard (e.g.,cat file.txt C). It automatically detectswl-copy,xclip, orpbcopy.
5. Git Integration
current_branch: A helper function that robustly identifies the current Git branch name for use in prompts or scripts, with fallbacks for older Git versions.- Extensive Aliases: Includes a comprehensive set of shortcuts for nearly every Git operation, including branch cleaning (
gbgd), stashing, and verbose commits.
Installation Note
When using this configuration:
- Ensure the
~/uploadsdirectory exists or letprep-uploadcreate it. - Update placeholders in the
.zshrc(such as<your_city>,<your_username>, and<server_ip_or_hostname>) to match your environment. - Requires
oh-my-zshwith thegit,sudo, anddnfplugins enabled. - If you wish to use the ZFS filesystem aliases for external zpools, you must use the Virtual Machine Manager to install a VM Ubuntu ZFS-Appliance system with SSH and an /etc/fstab entry to be able to auto-mount ZFS drives to your /mnt/ in Fedora. Fedora Asahi does not support native ZFS operation at this time.
- Requires
fastfetchandtmuxto be installed.
# ~/.zshrc (Fedora Asahi / Apple Silicon)
# --- 1. Environment & Paths ---
export PATH="$HOME/bin:$HOME/.local/bin:$PATH"
export ZSH="$HOME/.oh-my-zsh"
export EDITOR="nano"
export VISUAL="kate"
# ZFS VM address for mount aliases (resetzfs, dropzfs).
ZFS_VM_IP="<your_vm_ip>"
# --- 2. History Configuration ---
HISTFILE="$HOME/.zsh_history"
HISTSIZE=100000
SAVEHIST=100000
setopt INC_APPEND_HISTORY SHARE_HISTORY
setopt HIST_EXPIRE_DUPS_FIRST HIST_IGNORE_DUPS HIST_IGNORE_ALL_DUPS
setopt HIST_IGNORE_SPACE HIST_FIND_NO_DUPS HIST_SAVE_NO_DUPS
# --- 3. Oh My Zsh Configuration ---
if [ -d /usr/share/zsh/site-functions ]; then
fpath=(/usr/share/zsh/site-functions $fpath)
fi
autoload -Uz compinit && compinit
ZSH_THEME="robbyrussell"
plugins=(git colored-man-pages zsh-autosuggestions zsh-syntax-highlighting sudo dnf)
# Guard the oh-my-zsh source with a directory existence check.
# If $ZSH is missing (oh-my-zsh not installed, wrong path, or the directory was
# deleted), a bare `source` call here causes a fatal error that halts execution
# of the entire ~/.zshrc. Every alias, function, and setting below this line
# would silently never load — the shell opens but is completely unconfigured.
# With the guard, the shell loads fully and functionally even without oh-my-zsh,
# and you get a clear implicit signal (no theme, no plugins) that it's missing.
if [[ -d "$ZSH" ]]; then
source "$ZSH/oh-my-zsh.sh"
fi
# --- 4. Aliases ---
# Safety
alias cp='cp -i'
alias mv='mv -i'
alias rm='rm -i'
# Directory Listing
alias ls='LC_COLLATE=en_US.UTF-8 ls -h --group-directories-first --color=auto'
alias l='ls -Fail'
alias l.='ls -d .* --color=auto'
alias la='ls -lAh'
alias ll='ls -lh'
alias lsa='ls -lah'
# Navigation
alias -- -='cd -'
alias ..='cd ..'
alias ...='cd ../..'
alias ....='cd ../../..'
alias .....='cd ../../../..'
alias ......='cd ../../../../..'
alias 1='cd -1'
alias 2='cd -2'
alias 3='cd -3'
alias 4='cd -4'
alias 5='cd -5'
alias 6='cd -6'
alias 7='cd -7'
alias 8='cd -8'
alias 9='cd -9'
# Package Management (Fedora / dnf5)
alias autoremove='sudo dnf autoremove'
alias install='sudo dnf install'
alias remove='sudo dnf remove'
alias search='dnf search'
alias update='sudo dnf upgrade'
# Grep & Search
alias grep='grep --color=auto --exclude-dir={.bzr,CVS,.git,.hg,.svn,.idea,.tox,.venv,venv}'
alias egrep='grep -E --color=auto'
alias fgrep='grep -F --color=auto'
alias xzegrep='xzegrep --color=auto'
alias xzfgrep='xzfgrep --color=auto'
alias xzgrep='xzgrep --color=auto'
alias zegrep='zegrep --color=auto'
alias zfgrep='zfgrep --color=auto'
alias zgrep='zgrep --color=auto'
# System Info & Hardware
alias battery='upower -i /org/freedesktop/UPower/devices/battery_macsmc_battery'
alias checkdns='resolvectl status && printf "\n\e[1mAvahi (mDNS)\e[0m\n\e[94m%21s\e[0m %s\n\e[94m%21s\e[0m %s\n" "Current Status:" "$(systemctl is-active avahi-daemon 2>/dev/null)" "Startup:" "$(systemctl is-enabled avahi-daemon 2>/dev/null)"'
alias mydf='df -hT -x squashfs -x tmpfs -x devtmpfs'
alias sysstat='free -h && df -hT / && swapon --show && sysctl vm.swappiness'
# Avahi / mDNS
alias avahioff='sudo systemctl disable --now avahi-daemon'
alias avahion='sudo systemctl enable --now avahi-daemon'
# Networking & Ports
alias ports='sudo ss -tulanp'
# Logging
alias logs='sudo journalctl -xe'
alias logs-f='sudo journalctl -f'
# Systemd
alias sc='sudo systemctl'
alias sc-enable='sudo systemctl enable --now'
alias sc-restart='sudo systemctl restart'
alias sc-start='sudo systemctl start'
alias sc-status='systemctl status'
alias sc-stop='sudo systemctl stop'
# ZFS & VM
alias dropzfs='sudo umount /mnt/zfs'
alias importzfs="ssh root@${ZFS_VM_IP} 'zpool import -af && zpool status'"
alias loginzfs='ssh -i ~/.ssh/<your_ssh_key> root@<your_vm_ip>'
# Dotfiles & Config Editing
alias config='/usr/bin/git --git-dir=$HOME/.dotfiles/ --work-tree=$HOME'
alias eb="kate -b ~/.bashrc"
alias es='sudo visudo'
alias esw='sudo visudo -f /etc/sudoers.d/<your_username>'
alias ez="kate -b ~/.zshrc && source ~/.zshrc && echo 'Zsh config reloaded!'"
alias reload='tput reset && source ~/.zshrc && echo "Zsh config reloaded."'
# Sudo Helpers
alias _='sudo '
alias sudo='sudo '
# Utilities
alias backup-check='sudo btrfs subvolume list /run/media/<your_username>/<your_backup_drive>'
alias dnslog="echo \"--- \$(date) ---\" >> ~/.dnsleak.log && dnsleaktest | tee -a ~/.dnsleak.log"
alias mc='. /usr/libexec/mc/mc-wrapper.sh'
alias md='mkdir -p'
alias rd=rmdir
alias run-help=man
alias vi=vim
alias weather='curl -s "wttr.in/<your_city>?m"'
# Tmux
alias tkill='tmux kill-server'
alias tmux-wipe='rm -f ~/.local/share/tmux/resurrect/*.txt ~/.local/share/tmux/resurrect/last && tmux display-message "History wiped. Press Prefix + Ctrl-S to set your new baseline."'
# Zsh Built-ins & Completion
alias history=omz_history
alias which='alias | /usr/bin/which --tty-only --read-alias --show-tilde --show-dot'
alias which-command=whence
# Suffix Aliases (open by extension)
alias -s log=kate
alias -s txt=kate
alias -s md=kate
alias -s conf=nano
# Global Aliases (inline pipe shortcuts)
alias -g G='| grep --color=auto'
# --- Git Management Aliases ---
alias g=git
alias ga='git add'
alias gaa='git add --all'
alias gam='git am'
alias gama='git am --abort'
alias gamc='git am --continue'
alias gams='git am --skip'
alias gamscp='git am --show-current-patch'
alias gap='git apply'
alias gapa='git add --patch'
alias gapt='git apply --3way'
alias gau='git add --update'
alias gav='git add --verbose'
alias gb='git branch'
alias gbD='git branch --delete --force'
alias gba='git branch --all'
alias gbd='git branch --delete'
alias gbg='LANG=C git branch -vv | grep ": gone\]"'
alias gbgD='LANG=C git branch --no-color -vv | grep ": gone\]" | cut -c 3- | awk '\''{print $1}'\'' | xargs git branch -D'
alias gbgd='LANG=C git branch --no-color -vv | grep ": gone\]" | cut -c 3- | awk '\''{print $1}'\'' | xargs git branch -d'
alias gbl='git blame -w'
alias gbm='git branch --move'
alias gbnm='git branch --no-merged'
alias gbr='git branch --remote'
alias gbs='git bisect'
alias gbsb='git bisect bad'
alias gbsg='git bisect good'
alias gbsn='git bisect new'
alias gbso='git bisect old'
alias gbsr='git bisect reset'
alias gbss='git bisect start'
alias gc='git commit --verbose'
alias 'gc!'='git commit --verbose --amend'
alias gcB='git checkout -B'
alias gca='git commit --verbose --all'
alias 'gca!'='git commit --verbose --all --amend'
alias gcam='git commit --all --message'
alias 'gcan!'='git commit --verbose --all --no-edit --amend'
alias 'gcann!'='git commit --verbose --all --date=now --no-edit --amend'
alias 'gcans!'='git commit --verbose --all --signoff --no-edit --amend'
alias gcas='git commit --all --signoff'
alias gcasm='git commit --all --signoff --message'
alias gcb='git checkout -b'
alias gcd='git checkout $(git_develop_branch)'
alias gcf='git config --list'
alias gcfu='git commit --fixup'
alias gcl='git clone --recurse-submodules'
alias gclean='git clean --interactive -d'
alias gclf='git clone --recursive --shallow-submodules --filter=blob:none --also-filter-submodules'
alias gcm='git checkout $(git_main_branch)'
alias gcmsg='git commit --message'
alias gcn='git commit --verbose --no-edit'
alias 'gcn!'='git commit --verbose --no-edit --amend'
alias gco='git checkout'
alias gcor='git checkout --recurse-submodules'
alias gcount='git shortlog --summary --numbered'
alias gcp='git cherry-pick'
alias gcpa='git cherry-pick --abort'
alias gcpc='git cherry-pick --continue'
alias gcs='git commit --gpg-sign'
alias gcsm='git commit --signoff --message'
alias gcss='git commit --gpg-sign --signoff'
alias gcssm='git commit --gpg-sign --signoff --message'
alias gd='git diff'
alias gdca='git diff --cached'
alias gdct='git describe --tags $(git rev-list --tags --max-count=1)'
alias gdcw='git diff --cached --word-diff'
alias gds='git diff --staged'
alias gdt='git diff-tree --no-commit-id --name-only -r'
alias gdup='git diff @{upstream}'
alias gdw='git diff --word-diff'
alias gf='git fetch'
alias gfa='git fetch --all --tags --prune --jobs=10'
alias gfg='git ls-files | grep'
alias gfo='git fetch origin'
alias gg='git gui citool'
alias gga='git gui citool --amend'
alias ggpull='git pull origin "$(git_current_branch)"'
alias ggpur=ggu
alias ggpush='git push origin "$(git_current_branch)"'
alias ggsup='git branch --set-upstream-to=origin/$(git_current_branch)'
alias ghh='git help'
alias gignore='git update-index --assume-unchanged'
alias gignored='git ls-files -v | grep "^[[:lower:]]"'
alias git-svn-dcommit-push='git svn dcommit && git push github $(git_main_branch):svntrunk'
alias gk='\gitk --all --branches &!'
alias gke='\gitk --all $(git log --walk-reflogs --pretty=%h) &!'
alias gl='git pull'
alias glg='git log --stat'
alias glgg='git log --graph'
alias glgga='git log --graph --decorate --all'
alias glgm='git log --graph --max-count=10'
alias glgp='git log --stat --patch'
alias glo='git log --oneline --decorate'
alias globurl='noglob urlglobber '
alias glod='git log --graph --pretty="%Cred%h%Creset -%C(auto)%d%Creset %s %Cgreen(%ad) %C(bold blue)<%an>%Creset"'
alias glods='git log --graph --pretty="%Cred%h%Creset -%C(auto)%d%Creset %s %Cgreen(%ad) %C(bold blue)<%an>%Creset" --date=short'
alias glog='git log --oneline --decorate --graph'
alias gloga='git log --oneline --decorate --graph --all'
alias glol='git log --graph --pretty="%Cred%h%Creset -%C(auto)%d%Creset %s %Cgreen(%ar) %C(bold blue)<%an>%Creset"'
alias glola='git log --graph --pretty="%Cred%h%Creset -%C(auto)%d%Creset %s %Cgreen(%ar) %C(bold blue)<%an>%Creset" --all'
alias glols='git log --graph --pretty="%Cred%h%Creset -%C(auto)%d%Creset %s %Cgreen(%ar) %C(bold blue)<%an>%Creset" --stat'
alias glp=_git_log_prettily
alias gluc='git pull upstream $(git_current_branch)'
alias glum='git pull upstream $(git_main_branch)'
alias gm='git merge'
alias gma='git merge --abort'
alias gmc='git merge --continue'
alias gmff='git merge --ff-only'
alias gmom='git merge origin/$(git_main_branch)'
alias gms='git merge --squash'
alias gmtl='git mergetool --no-prompt'
alias gmtlvim='git mergetool --no-prompt --tool=vimdiff'
alias gmum='git merge upstream/$(git_main_branch)'
alias gp='git push'
alias gpd='git push --dry-run'
alias gpf='git push --force-with-lease --force-if-includes'
alias 'gpf!'='git push --force'
alias gpoat='git push origin --all && git push origin --tags'
alias gpod='git push origin --delete'
alias gpr='git pull --rebase'
alias gpra='git pull --rebase --autostash'
alias gprav='git pull --rebase --autostash -v'
alias gpristine='git reset --hard && git clean --force -dfx'
alias gprom='git pull --rebase origin $(git_main_branch)'
alias gpromi='git pull --rebase=interactive origin $(git_main_branch)'
alias gprum='git pull --rebase upstream $(git_main_branch)'
alias gprumi='git pull --rebase=interactive upstream $(git_main_branch)'
alias gprv='git pull --rebase -v'
alias gpsup='git push --set-upstream origin $(git_current_branch)'
alias gpsupf='git push --set-upstream origin $(git_current_branch) --force-with-lease --force-if-includes'
alias gpu='git push upstream'
alias gpv='git push --verbose'
alias gr='git remote'
alias gra='git remote add'
alias grb='git rebase'
alias grba='git rebase --abort'
alias grbc='git rebase --continue'
alias grbd='git rebase $(git_develop_branch)'
alias grbi='git rebase --interactive'
alias grbm='git rebase $(git_main_branch)'
alias grbo='git rebase --onto'
alias grbom='git rebase origin/$(git_main_branch)'
alias grbs='git rebase --skip'
alias grbum='git rebase upstream/$(git_main_branch)'
alias grev='git revert'
alias greva='git revert --abort'
alias grevc='git revert --continue'
alias grf='git reflog'
alias grh='git reset'
alias grhh='git reset --hard'
alias grhk='git reset --keep'
alias grhs='git reset --soft'
alias grm='git rm'
alias grmc='git rm --cached'
alias grmv='git remote rename'
alias groh='git reset origin/$(git_current_branch) --hard'
alias grrm='git remote remove'
alias grs='git restore'
alias grset='git remote set-url'
alias grss='git restore --source'
alias grst='git restore --staged'
alias grt='cd "$(git rev-parse --show-toplevel || echo .)"'
alias gru='git reset --'
alias grup='git remote update'
alias grv='git remote --verbose'
alias gsb='git status --short --branch'
alias gsd='git svn dcommit'
alias gsh='git show'
alias gsi='git submodule init'
alias gsps='git show --pretty=short --show-signature'
alias gsr='git svn rebase'
alias gss='git status --short'
alias gst='git status'
alias gsta='git stash push'
alias gstaa='git stash apply'
alias gstall='git stash --all'
alias gstc='git stash clear'
alias gstd='git stash drop'
alias gstl='git stash list'
alias gstp='git stash pop'
alias gsts='git stash show --patch'
alias gstu='git stash push --include-untracked'
alias gsu='git submodule update'
alias gsw='git switch'
alias gswc='git switch --create'
alias gswd='git switch $(git_develop_branch)'
alias gswm='git switch $(git_main_branch)'
alias gta='git tag --annotate'
alias gtl='gtl(){ git tag --sort=-v:refname -n --list "${1}*" }; noglob gtl'
alias gts='git tag --sign'
alias gtv='git tag | sort -V'
alias gunignore='git update-index --no-assume-unchanged'
alias gunwip='git rev-list --max-count=1 --format="%s" HEAD | grep -q "\--wip--" && git reset HEAD~1'
alias gwch='git log --patch --abbrev-commit --pretty=medium --raw'
alias gwip='git add -A; git rm $(git ls-files --deleted) 2> /dev/null; git commit --no-verify --no-gpg-sign --message "--wip-- [skip ci]"'
alias gwipe='git reset --hard && git clean --force -df'
alias gwt='git worktree'
alias gwta='git worktree add'
alias gwtls='git worktree list'
alias gwtmv='git worktree move'
alias gwtrm='git worktree remove'
# --- 5. Fixes & Functions ---
tmux-status() {
local last_save="$HOME/.local/share/tmux/resurrect/last"
if [[ -f "$last_save" ]]; then
local save_time=$(stat -c %y "$last_save" 2>/dev/null || stat -f "%Sm" "$last_save")
echo "✅ Last tmux save: $save_time"
else
echo "❌ No tmux save found in ~/.local/share/tmux/resurrect/"
fi
}
precmd() {
eval "$(resize)" > /dev/null 2>&1
}
if [[ "$XDG_SESSION_TYPE" == "wayland" ]]; then
(sleep 0.1 && stty cols $(tput cols) rows $(tput lines)) &!
fi
if command -v fastfetch &> /dev/null; then
fastfetch 2> /dev/null
fi
purge_ram() {
echo "--- Memory usage BEFORE ---"
free -h
echo "\nSyncing and clearing caches..."
sudo sync
echo 3 | sudo tee /proc/sys/vm/drop_caches > /dev/null
echo "\n--- Memory usage AFTER ---"
free -h
}
resetzfs() {
local SSH_KEY="$HOME/.ssh/id_ed25519"
local -a SSH_OPTS=(-o BatchMode=yes -o ConnectTimeout=3 -o StrictHostKeyChecking=no -i "$SSH_KEY")
# Reset failed systemd state and lazy-unmount
echo "Resetting systemd mount state..."
sudo systemctl reset-failed mnt-zfs.mount mnt-zfs.automount 2>/dev/null || true
sudo umount -l /mnt/zfs 2>/dev/null || true
# Start VM if not running
if ! sudo virsh list --name | grep -q '^<your_vm_name>$'; then
echo "VM is down — starting <your_vm_name>..."
sudo virsh start <your_vm_name> 2>/dev/null || {
echo "ERROR: Failed to start VM. Is the ZFS disk plugged in?"
echo " lsblk | grep tank"
return 1
}
echo "Waiting for SSH (up to 90s)..."
local i
for i in $(seq 1 45); do
ssh "${SSH_OPTS[@]}" root@$ZFS_VM_IP exit 2>/dev/null && break
printf '.'
sleep 2
done
echo ""
ssh "${SSH_OPTS[@]}" root@$ZFS_VM_IP exit 2>/dev/null || {
echo "ERROR: VM started but SSH not ready. Try: ssh root@$ZFS_VM_IP"
return 1
}
echo "VM is up."
else
echo "VM already running."
ssh "${SSH_OPTS[@]}" root@$ZFS_VM_IP exit 2>/dev/null || {
echo "ERROR: VM running but SSH unreachable at $ZFS_VM_IP"
return 1
}
fi
# Check/import ZFS pool
echo "Checking ZFS pool..."
local pool_status
pool_status=$(ssh "${SSH_OPTS[@]}" root@$ZFS_VM_IP 'zpool list -H -o health tank 2>/dev/null || echo MISSING')
if [[ "$pool_status" == "MISSING" ]]; then
echo "Pool not imported — importing..."
ssh "${SSH_OPTS[@]}" root@$ZFS_VM_IP 'zpool import -af && zpool status tank'
elif [[ "$pool_status" != "ONLINE" ]]; then
echo "WARNING: Pool health is $pool_status"
ssh "${SSH_OPTS[@]}" root@$ZFS_VM_IP 'zpool status tank'
else
echo "Pool: ONLINE"
fi
# Restart automount and trigger mount
echo "Restarting automount..."
sudo systemctl daemon-reload
sudo systemctl restart mnt-zfs.automount
echo "Triggering mount..."
if ls /mnt/zfs/ > /dev/null 2>&1; then
df -hT /mnt/zfs
echo "SUCCESS: /mnt/zfs is mounted."
else
echo "ERROR: Mount failed."
sudo journalctl -u mnt-zfs.mount -n 10 --no-pager
return 1
fi
}
# [ ] → [[ ]] for both tests.
# [[ ]] is a zsh built-in conditional operator (not an external command like [ ]).
# Benefits over POSIX [ ]:
# - Handles unset/empty variables safely without "unexpected operator" errors
# (relevant if XTERM_VERSION or TMUX is unset and zsh NO_UNSET is active)
# - No word-splitting or glob expansion on the variable values
# - Cleaner, idiomatic zsh style consistent with the rest of this file
if [[ -n "$XTERM_VERSION" ]] && [[ -z "$TMUX" ]]; then
exec tmux new-session -A -s main
fi
sedit() {
if [[ -z "$1" ]]; then
echo "Usage: sedit <file_path>"
return 1
fi
env SUDO_EDITOR="nano" sudoedit "$1" 2> /dev/null
}
prep-upload() {
if [[ -z "$1" ]]; then
echo "Usage: prep-upload <file>"
return 1
fi
local src="$1"
local filename="${src:t}"
local dest_dir="$HOME/uploads"
local dest_file="$dest_dir/$filename"
[[ -d "$dest_dir" ]] || mkdir -p "$dest_dir"
if [[ -f "$dest_file" ]]; then
if read -q "REPLY?File '$filename' already exists in uploads. Overwrite? (y/n): "; then
echo
else
echo -e "\nAborted."
return 1
fi
fi
sudo cp -f "$src" "$dest_file"
sudo chown <your_username>:<your_username> "$dest_file"
chmod 644 "$dest_file"
echo "File ready at: $dest_file"
}
deploy-upload() {
if [[ -z "$1" || -z "$2" ]]; then
echo "Usage: deploy-upload <filename_in_uploads> <destination_path>"
return 1
fi
local src="$HOME/uploads/$1"
local dest="$2"
if [[ ! -f "$src" ]]; then
echo "Error: File '$1' not found in ~/uploads/"
return 1
fi
echo "Deploying $1 to $dest..."
sudo mv "$src" "$dest"
sudo chown root:root "$dest"
sudo chmod 0440 "$dest"
if [[ "$dest" == *"/etc/sudoers"* ]]; then
echo "Verifying sudoers syntax..."
sudo visudo -c
else
echo "Deployment complete."
fi
}
_deploy_upload_comp() {
local -a files
files=($HOME/uploads/*(:t))
_describe 'files in uploads' files
}
compdef _deploy_upload_comp deploy-upload
expand-alias-space() {
local ignored=" l ls cp mv rm "
if [[ $LBUFFER =~ '(^|[[:space:]])([_0-9a-zA-Z]+)$' ]]; then
local alias_name=$match[2]
if [[ -n $aliases[$alias_name] && ! $ignored =~ " $alias_name " ]]; then
LBUFFER=${LBUFFER%${alias_name}}$aliases[$alias_name]
fi
fi
zle self-insert
}
# Timeshift manual backup with zombie cleanup, comment prompt, and verbose output
timeback() {
echo "Clearing stuck Timeshift processes and lock files..."
sudo killall -9 timeshift 2>/dev/null
sudo killall -9 timeshift-gtk 2>/dev/null
sudo rm -f /run/timeshift.pid 2>/dev/null
echo -n "Would you like to add a comment to this backup? (y/N): "
read -r response
if [[ "$response" =~ ^([yY][eE][sS]|[yY])$ ]]; then
echo -n "Enter your comment: "
read -r comment
echo "Starting Timeshift backup..."
sudo timeshift --create --comments "$comment" --verbose
else
echo "Starting Timeshift backup without comment..."
sudo timeshift --create --verbose
fi
}
# Quickly select the OS for the next boot
setboot() {
echo "Current Boot Configuration:"
sudo asahi-bless
echo "\nTo reboot now, run: 'sudo reboot'"
}
zle -N expand-alias-space
bindkey ' ' expand-alias-space
bindkey -M isearch ' ' self-insert
check_alias_conflicts() {
local input_file="${1:-aliases.txt}"
if [[ ! -f "$input_file" ]]; then
echo "Error: File '$input_file' not found."
return 1
fi
echo "Scanning for aliases that shadow system binaries..."
echo "----------------------------------------------------"
# Loop through the file, splitting at the first '='
while IFS='=' read -r key value; do
# Strip potential quotes or leading/trailing whitespace from the key
local clean_key=$(echo "$key" | tr -d "'\"" | xargs)
[[ -z "$clean_key" || "$clean_key" == \#* ]] && continue
# 'whence -p' checks if the key exists as a command path
local binary_path=$(whence -p "$clean_key")
if [[ -n "$binary_path" ]]; then
echo "⚠️ Conflict: '$clean_key' shadows $binary_path"
fi
done < "$input_file"
echo "----------------------------------------------------"
echo "Scan complete."
}
check_ls_compat() {
local test_flags=("--group-directories-first" "--color=auto")
local unsupported=()
for flag in "${test_flags[@]}"; do
# Try to run ls with the flag on an empty string to check for errors
if ! ls "$flag" /dev/null >/dev/null 2>&1; then
unsupported+=("$flag")
fi
done
if [[ ${#unsupported[@]} -gt 0 ]]; then
echo "❌ Your current 'ls' does NOT support: ${unsupported[*]}"
echo "This usually happens on macOS/BSD or with very old GNU versions."
else
echo "✅ All 'ls' flags are supported on this machine."
fi
}
check_grep_compat() {
# Test if grep supports --exclude-dir by running it on a dummy string
if echo "test" | grep --exclude-dir=. ".+" >/dev/null 2>&1; then
echo "✅ Your 'grep' supports --exclude-dir. Your alias is safe."
else
echo "❌ Your 'grep' does NOT support --exclude-dir."
echo "Consider installing 'grep' via Homebrew (on Mac) or removing that flag."
fi
}
# Kill the alias to prevent parse errors
unalias current_branch 2>/dev/null
current_branch() {
# The logic is called, but send all potential 'deprecated' noise to /dev/null
if (( $+functions[git_current_branch] )); then
git_current_branch 2>/dev/null
else
git rev-parse --abbrev-ref HEAD 2>/dev/null
fi
}
# Detect the clipboard tool and create a global alias 'C'
if (( $+commands[wl-copy] )); then
alias -g C='| wl-copy'
elif (( $+commands[xclip] )); then
alias -g C='| xclip -selection clipboard'
elif (( $+commands[pbcopy] )); then
alias -g C='| pbcopy'
fi