switch to zsh

This commit is contained in:
2026-03-26 07:35:16 +01:00
parent d14538742a
commit b09c760ffc
23 changed files with 591 additions and 17 deletions
+1 -1
View File
@@ -12,7 +12,7 @@ keybind = ctrl+shift+h=write_screen_file:copy
keybind = ctrl+shift+j=text:ghostty-capture\n
keybind = ctrl+enter=unbind
command = exec fish
command = exec /bin/zsh
confirm-close-surface = false
@@ -14,8 +14,8 @@ mouse_map ctrl+shift+right press ungrabbed combine : mouse_select_command_output
# disable the stupid notification
confirm_os_window_close 0
# set shell to fish
shell fish
# set shell to zsh
shell /bin/zsh
# hide_window_decorations yes
window_padding_width 10
@@ -45,4 +45,4 @@ map ctrl+minus change_font_size all -1
map ctrl+kp_subtract change_font_size all -1
map ctrl+0 change_font_size all 0
map ctrl+kp_0 change_font_size all 0
map ctrl+kp_0 change_font_size all 0
@@ -14,8 +14,8 @@ mouse_map ctrl+shift+right press ungrabbed combine : mouse_select_command_output
# disable the stupid notification
confirm_os_window_close 0
# set shell to fish
shell fish
# set shell to zsh
shell /bin/zsh
# hide_window_decorations yes
window_padding_width 10
@@ -18,7 +18,7 @@ UProgressExpand {
onClicked: (mouse) => {
WriteClipboard.write(displayText);
SendNotification.show("Copied to clipboard", displayText);
SendNotification.show("Copied to clipboard", displayText, true);
}
onRightClicked: {
@@ -6,11 +6,17 @@ pragma Singleton
Singleton {
id: root
function show(title, message, icon = "", urgency = "normal") {
function show(title, message, nohistory = false, icon = "", urgency = "normal") {
const cmds = ["notify-send", "-u", urgency, "-a", "quickshell"];
if (icon)
Quickshell.execDetached(["notify-send", "-u", urgency, "-i", icon, title, message, "-a", "quickshell"]);
else
Quickshell.execDetached(["notify-send", "-u", urgency, title, message, "-a", "quickshell"]);
cmds.push("-i", icon);
if (nohistory) {
cmds.push("--hint", "int:transient:1");
cmds.push("--expire-time", "3000");
}
cmds.push(title, message);
Quickshell.execDetached(cmds);
}
}
+4 -4
View File
@@ -26,10 +26,10 @@ prepend_path() {
[ -f "$HOME/.profile" ] && . "$HOME/.profile"
# Better than nothing
export XDG_CONFIG_HOME="$HOME/.config"
export XDG_DATA_HOME="$HOME/.local/share"
export XDG_STATE_HOME="$HOME/.local/state"
export XDG_CACHE_HOME="$HOME/.cache"
export XDG_CONFIG_HOME=${XDG_CONFIG_HOME:-$HOME/.config}
export XDG_DATA_HOME=${XDG_DATA_HOME:-$HOME/.local/share}
export XDG_STATE_HOME=${XDG_STATE_HOME:-$HOME/.local/state}
export XDG_CACHE_HOME=${XDG_CACHE_HOME:-$HOME/.cache}
# Better than nothing
if [[ -z "$LANG" ]]; then
+3
View File
@@ -0,0 +1,3 @@
# antidote generated/cache files
.zsh_plugins.zsh
.antidote/
+13
View File
@@ -0,0 +1,13 @@
# Syntax highlighting
zsh-users/zsh-syntax-highlighting
# Catppuccin Mocha theme for syntax highlighting
catppuccin/zsh-syntax-highlighting path:themes/catppuccin_mocha-zsh-syntax-highlighting.zsh
# Fish-like autosuggestions
zsh-users/zsh-autosuggestions
# Additional completions
zsh-users/zsh-completions
# Long command done notification — handled by conf.d/10-done.zsh
@@ -0,0 +1,12 @@
*
!.gitignore
!01-options.zsh
!02-completions.zsh
!03-plugins.zsh
!10-done.zsh
!10-env.zsh
!10-oops.zsh
!10-sshs.zsh
!50-prompt.zsh
!60-alias.zsh
!60-fetch.zsh
@@ -0,0 +1,23 @@
# History
HISTFILE="${XDG_DATA_HOME:-$HOME/.local/share}/zsh/history"
HISTSIZE=100000
SAVEHIST=100000
setopt APPEND_HISTORY SHARE_HISTORY
setopt HIST_IGNORE_DUPS HIST_SAVE_NO_DUPS HIST_FIND_NO_DUPS
setopt HIST_IGNORE_SPACE HIST_REDUCE_BLANKS INC_APPEND_HISTORY
setopt HIST_VERIFY
# Shell options
setopt AUTO_CD EXTENDED_GLOB NOTIFY INTERACTIVE_COMMENTS
bindkey -e
# Allow word-based navigation and deletion to work on paths
WORDCHARS=${WORDCHARS//\//}
# Rookie keybindings :)
bindkey '^[[1;5D' backward-word # C-Left
bindkey '^[[1;5C' forward-word # C-Right
bindkey '^H' backward-kill-word # C-Backspace
@@ -0,0 +1,16 @@
fpath=(~/.zfunc $fpath)
# Cache compinit: only regenerate dump once daily
autoload -Uz compinit
if [[ -n ${ZDOTDIR:-$HOME}/.zcompdump(#qN.mh+24) ]]; then
compinit
else
compinit -C
fi
zstyle ':completion:*' matcher-list 'm:{a-z}={A-Z}'
zstyle ':completion:*' menu select
zstyle ':completion:*' squeeze-slashes true
zstyle ':completion:*' list-colors "${(s.:.)LS_COLORS}"
zstyle ':completion:*:descriptions' format '%F{cyan}-- %d --%f'
zstyle ':completion:*:warnings' format '%F{red}-- no matches --%f'
@@ -0,0 +1,20 @@
_uy_antidote_dir="${XDG_DATA_HOME:-$HOME/.local/share}/antidote"
# Find antidote: system package → user-local clone → auto-bootstrap
if [[ -f /usr/share/zsh-antidote/antidote.zsh ]]; then
source /usr/share/zsh-antidote/antidote.zsh
elif [[ -f "$_uy_antidote_dir/antidote.zsh" ]]; then
source "$_uy_antidote_dir/antidote.zsh"
elif (( $+commands[git] )); then
git clone --depth=1 https://github.com/mattmc3/antidote.git "$_uy_antidote_dir"
source "$_uy_antidote_dir/antidote.zsh"
fi
if (( $+functions[antidote] )); then
_uy_zsh_plugins="${XDG_CONFIG_HOME:-$HOME/.config}/zsh/.zsh_plugins.txt"
if [[ -f "$_uy_zsh_plugins" ]]; then
antidote load "$_uy_zsh_plugins"
fi
fi
unset _uy_antidote_dir _uy_zsh_plugins
@@ -0,0 +1,67 @@
# Long command done notification for Niri (Wayland)
# Sends notify-send when a command takes longer than $uy_done_min_cmd_duration
# seconds and the terminal window is not focused.
(( $+commands[notify-send] )) && [[ -n "$NIRI_SOCKET" ]] || return
zmodload zsh/datetime
: ${uy_done_min_cmd_duration:=10}
: ${uy_done_exclude:='^(nvim|helix|hx|vim|vi|nano|less|more|man|ssh|top|htop|btop)$'}
uy_done_get_focused_window_id() {
(( $+commands[jq] )) || return
niri msg --json focused-window 2>/dev/null | jq -r '.id // empty'
}
uy_done_preexec() {
uy_done_cmd="$1"
uy_done_start=$EPOCHSECONDS
uy_done_window_id=$(uy_done_get_focused_window_id)
}
uy_done_precmd() {
local exit_status=$?
[[ -n "$uy_done_start" ]] || return
local elapsed=$(( EPOCHSECONDS - uy_done_start ))
unset uy_done_start
(( elapsed >= uy_done_min_cmd_duration )) || return
# skip excluded commands
local cmd_name="${uy_done_cmd%% *}"
[[ "$cmd_name" =~ $uy_done_exclude ]] && return
# skip if window is still focused
local current_id
current_id=$(uy_done_get_focused_window_id)
[[ -n "$uy_done_window_id" && "$uy_done_window_id" = "$current_id" ]] && return
# humanize duration
local title duration="" urgency=low
local minutes=$(( elapsed / 60 )) seconds=$(( elapsed % 60 ))
local hours=$(( elapsed / 3600 ))
(( hours > 0 )) && duration+="${hours}h "
(( minutes > 0 )) && duration+="$(( minutes % 60 ))m "
duration+="${seconds}s"
local wd="${PWD/#$HOME/~}"
if (( exit_status == 0 )); then
title="Done in $duration"
else
title="Failed ($exit_status) after $duration"
urgency=critical
fi
notify-send \
--hint=int:transient:1 \
--urgency="$urgency" \
--icon=utilities-terminal \
--app-name=zsh \
"$title" "$wd/ $uy_done_cmd"
}
autoload -Uz add-zsh-hook
add-zsh-hook preexec uy_done_preexec
add-zsh-hook precmd uy_done_precmd
@@ -0,0 +1,31 @@
# MANPAGER
if (( $+commands[bat] )); then
export MANPAGER="sh -c 'col -bx | bat -l man -p'"
export MANROFFOPT=-c
fi
# Editor
for _uy_app in nvim helix vim vi nano; do
if (( $+commands[$_uy_app] )); then
export EDITOR=$_uy_app
export VISUAL=$_uy_app
break
fi
done
unset _uy_app
if (( $+commands[helix] )) && ! (( $+commands[hx] )); then
alias hx=helix
fi
# GPG
if (( $+commands[gpg] )); then
export GPG_TTY=$(tty)
fi
# Catppuccin Mocha — autosuggestions color
ZSH_AUTOSUGGEST_HIGHLIGHT_STYLE="fg=#6c7086"
@@ -0,0 +1,29 @@
_oops_confirm() {
if [[ ! -f "$HISTFILE" ]]; then
print -P "%F{red}Failed to locate history file: $HISTFILE%f"
return 1
fi
local last_line=$(tail -n 1 "$HISTFILE")
if [[ -z "$last_line" ]]; then
print -P "%F{yellow}History file is empty, nothing to clean. %f"
return 0
fi
print -P "About to permanently delete the last command from history:"
print -P "%F{red} $last_line%f"
local reply
echo -n "Proceed? [Y/n] "
read -r reply
if [[ -z "$reply" || "$reply" == [yY]* ]]; then
sed -i '$d' "$HISTFILE"
print -P "%F{green}Command removed from history.%f"
else
print -P "%F{yellow}Operation cancelled.%f"
fi
}
alias oops=' _oops_confirm'
@@ -0,0 +1,19 @@
# ssh with encrypted private keys
# $uy_ssh_keys should be set in a device-specific file or left empty for defaults
if [[ "${UY_ENABLE_GPG_AGENT_SSH:-0}" = "1" ]] &&
(( $+commands[gpg-init] )) && (( $+commands[gpgconf] )); then
: # GPG agent handles SSH — nothing to do
elif [[ "${UY_USING_SSH_AGENT:-0}" = "1" ]]; then
sshs() {
if ! ssh-add -l &>/dev/null; then
if [[ -n "${uy_ssh_keys[*]}" ]]; then
ssh-add "${uy_ssh_keys[@]}"
else
ssh-add
fi
fi
ssh "$@"
}
fi
@@ -0,0 +1,7 @@
# Fallback prompt (if oh-my-posh is not available)
PROMPT='%F{blue}%n@%m%f %F{cyan}%~%f > '
# oh-my-posh
if [[ -f "$HOME/.config/posh_theme.omp.json" ]] && (( $+commands[oh-my-posh] )); then
eval "$(oh-my-posh init zsh --config "$HOME/.config/posh_theme.omp.json")"
fi
@@ -0,0 +1,187 @@
# fzf
if (( $+commands[fzf] )); then
source <(fzf --zsh)
# auto copy fzf's output
if (( $+commands[wl-copy] )); then
alias fzf="fzf --bind 'enter:execute-silent(echo {+} | wl-copy --trim-newline)+accept'"
fi
# fzh: history
alias fzh="history -1 0 | fzf"
# fz: fuzzy find a file and preview
if (( $+commands[bat] )); then
alias fz="fzf --preview 'bat --style=numbers --color=always {}'"
else
alias fz="fzf --preview 'cat -n {}'"
fi
# fe: fuzzy find a file and edit using $EDITOR
fe() {
local file
file=$(fz "$@")
[[ -n "$file" ]] && $EDITOR "$file"
}
# fkill: fuzzy find a process and kill with SIGKILL
fkill() {
local pids
pids=$(ps -ef | sed 1d | fzf -m --preview 'pstree -p $(echo {} | awk "{print \$2}")' | awk '{print $2}')
[[ -n "$pids" ]] && kill -9 ${=pids}
}
if (( $+commands[yay] )); then
# fyq: fuzzy yay query
alias fyq="yay -Qq | fzf --preview 'yay -Qi {}'"
# fyi: fuzzy yay install
fyi() {
local pkg
pkg=$(yay -Sl | awk '{print $1"/"$2}' | fzf -m --preview 'yay -Si {}' "$@")
[[ -n "$pkg" ]] && yay -S ${=pkg}
}
# fyr: fuzzy yay remove
fyr() {
local pkg
pkg=$(yay -Qq | fzf -m --preview 'yay -Qi {}' "$@")
[[ -n "$pkg" ]] && yay -Rn ${=pkg}
}
fi
fi
# cd (zoxide)
if (( $+commands[zoxide] )); then
eval "$(zoxide init zsh)"
alias cd=z
fi
# ls
if (( $+commands[eza] )); then
alias ll="eza -lh --group-directories-first --icons=auto"
alias la="eza -lh --group-directories-first --icons=auto --all"
alias lt="eza --tree --level=2 --long --icons --git"
else
alias ls="ls --color=auto"
alias ll="ls -lh --group-directories-first --color=auto"
alias la="ls -lah --group-directories-first --color=auto"
fi
# directories
alias ..='cd ..'
alias ...='cd ../..'
alias ....='cd ../../..'
# colorize
alias grep="grep --color=auto"
alias dir="dir --color=auto"
alias vdir="vdir --color=auto"
alias fgrep="fgrep --color=auto"
alias egrep="egrep --color=auto"
# copy
copy() {
if [[ $# -eq 2 && -d "$1" ]]; then
command cp -r "${1%/}" "$2"
else
command cp "$@"
fi
}
# wget
if (( $+commands[wget] )); then
alias wget="wget -c "
fi
# pacman
if (( $+commands[expac] )); then
alias big="expac -H M '%m\t%n' | sort -h | nl"
fi
# clock
if (( $+commands[tty-clock] )); then
alias clock="tty-clock -c -C 4"
fi
# journalctl
alias jctl="journalctl -p 3 -xb"
# nohup
nh() {
nohup "$@" >/dev/null 2>&1 &
disown
}
# ffmpeg
alias ffmpeg="ffmpeg -hide_banner -nostdin"
alias ffprobe="ffprobe -hide_banner"
# git
if (( $+commands[git] )); then
gcp() {
git add -A || return 1
if [[ $# -eq 0 ]]; then
git commit -m "👐 foo: too lazy to come up with a helpful commit message :)" || return 1
else
git commit -m "$*" || return 1
fi
git push
}
if (( $+commands[wl-paste] )); then
# Get a git repo URL from clipboard, prompting if invalid
uy_git_repo_from_clipboard() {
local repo
repo=$(wl-paste)
if [[ ! "$repo" =~ '^(http|https|git|ssh)://|^git@' ]]; then
echo "Error: Clipboard does not contain a valid git repository URL." >&2
echo "Error: Clipboard content: $repo" >&2
read "repo?Enter a valid git repository URL: "
if [[ ! "$repo" =~ '^(http|https|git|ssh)://|^git@' ]]; then
echo "Error: Invalid git repository URL." >&2
return 1
fi
fi
print -r -- "$repo"
}
gc() {
local repo
repo=$(uy_git_repo_from_clipboard) || return 1
git clone "$repo"
}
pingo() {
cd "$HOME/Repositories/PGdP" || return 1
local repo
repo=$(uy_git_repo_from_clipboard) || return 1
local dir_name="${repo:t:r}"
if [[ ! -d "$dir_name" ]]; then
git clone "$repo" || return 1
fi
local app="$1"
if [[ -n "$app" ]] && (( $+commands[$app] )); then
echo "Opening project with $app"
nohup "$app" "$dir_name" >/dev/null 2>&1 &
disown
else
echo "Opening method missing or invalid"
cd "$dir_name"
fi
}
fi
fi
@@ -0,0 +1,54 @@
# Detect logo capability
if [[ -z "$uy_fetch_logo_type" ]]; then
if (( $+commands[kgp-query] )) && kgp-query 2>/dev/null; then
uy_fetch_logo_type=kitty
elif (( $+commands[sixel-query] )) && sixel-query 2>/dev/null; then
uy_fetch_logo_type=sixel
elif (( $+commands[kgp-query] )) || (( $+commands[sixel-query] )); then
uy_fetch_logo_type=logo
else
uy_fetch_logo_type=auto
fi
fi
: ${uy_fetch_color:="38;2;137;180;250"}
# Build fastfetch args (arrays to handle paths with spaces safely)
case "$uy_fetch_logo_type" in
symbols)
uy_fetch_args=(--logo-type raw --logo-width 42 --logo "$HOME/.config/fastfetch/logo_ros/42x.symbols" --color "$uy_fetch_color")
uy_fetch_args_brief=(--logo-type raw --logo-width 28 --logo "$HOME/.config/fastfetch/logo_ros/28x.symbols" --color "$uy_fetch_color")
;;
logo)
uy_fetch_args=(--logo-type builtin)
uy_fetch_args_brief=(--logo-type small)
;;
sixel)
uy_fetch_args=(--logo-type raw --logo-width 42 --logo "$HOME/.config/fastfetch/logo_ros/42x.sixel" --color "$uy_fetch_color")
uy_fetch_args_brief=(--logo-type raw --logo-width 28 --logo "$HOME/.config/fastfetch/logo_ros/28x.sixel" --color "$uy_fetch_color")
;;
*) # kitty, auto, etc.
uy_fetch_args=(--logo-type "$uy_fetch_logo_type" --logo-width 42 --logo "$HOME/.config/fastfetch/logo_ros/ros.png" --color "$uy_fetch_color")
uy_fetch_args_brief=(--logo-type "$uy_fetch_logo_type" --logo-width 28 --logo "$HOME/.config/fastfetch/logo_ros/ros.png" --color "$uy_fetch_color")
;;
esac
# Functions
if (( $+commands[fastfetch] )); then
ff() { fastfetch -c "$HOME/.config/fastfetch/config.jsonc" "${uy_fetch_args[@]}" "$@"; }
if [[ -f "$HOME/.config/fastfetch/brief.jsonc" ]]; then
ffb() { fastfetch -c "$HOME/.config/fastfetch/brief.jsonc" "${uy_fetch_args_brief[@]}" "$@"; }
else
ffb() { ff "$@"; }
fi
fi
# Auto-fetch on startup
if [[ -z "$uy_no_fetch" ]] && (( $+functions[ffb] )); then
ffb
fi
+79
View File
@@ -0,0 +1,79 @@
#!/bin/zsh
# Login shell only — runs once per session (like .bash_profile)
# Path helpers (needed before sourcing .profile)
append_path() {
[[ -z "$1" ]] && return
[[ -d "$1" ]] || return
case ":$PATH:" in
*:"$1":*) ;;
*)
PATH="${PATH:+$PATH:}$1"
;;
esac
}
prepend_path() {
[[ -z "$1" ]] && return
[[ -d "$1" ]] || return
case ":$PATH:" in
*:"$1":*) ;;
*)
PATH="$1${PATH:+:$PATH}"
;;
esac
}
# XDG, better than not set
export XDG_CONFIG_HOME=${XDG_CONFIG_HOME:-$HOME/.config}
export XDG_DATA_HOME=${XDG_DATA_HOME:-$HOME/.local/share}
export XDG_STATE_HOME=${XDG_STATE_HOME:-$HOME/.local/state}
export XDG_CACHE_HOME=${XDG_CACHE_HOME:-$HOME/.cache}
# Locale, better than not set
if [[ -z "$LANG" ]]; then
export LANG="en_US.UTF-8"
fi
# .profile is not included in the repo (private / per-device)
[[ -f "$HOME/.profile" ]] && . "$HOME/.profile"
# Paths
[[ -f "$HOME/.cargo/env" ]] && source "$HOME/.cargo/env"
prepend_path "$HOME/go/bin"
prepend_path "$HOME/.local/bin"
prepend_path "$HOME/.local/scripts"
prepend_path "$HOME/.local/share/fnm"
export PATH
# fnm
if (( $+commands[fnm] )); then
eval "$(fnm env --shell zsh)"
fi
# GPG agent for SSH
if (( $+commands[gpgconf] )) && (( $+commands[gpg-connect-agent] )) &&
[[ -x "$HOME/.local/scripts/gpg-init" ]] &&
[[ "${UY_ENABLE_GPG_AGENT_SSH:-0}" = "1" ]]; then
eval "$($HOME/.local/scripts/gpg-init 2>/dev/null)" &>/dev/null
fi
# SSH agent
if (( $+commands[ssh-add] )) && (( $+commands[ssh-agent] )) &&
{ [[ -z "$SSH_AUTH_SOCK" ]] ||
{ ssh-add -l &>/dev/null; [[ $? -eq 2 ]]; } } &&
[[ -x "$HOME/.local/scripts/ssh-init" ]]; then
unset SSH_AUTH_SOCK
eval "$($HOME/.local/scripts/ssh-init 2>/dev/null)" &>/dev/null
export UY_USING_SSH_AGENT=1
fi
unfunction append_path
unfunction prepend_path
+8
View File
@@ -0,0 +1,8 @@
#!/bin/zsh
[[ $- != *i* ]] && return
for _f in "${XDG_CONFIG_HOME:-$HOME/.config}"/zsh/conf.d/*.zsh(N); do
source "$_f"
done
unset _f
+1 -1
View File
@@ -13,7 +13,7 @@ config.hide_tab_bar_if_only_one_tab = true
config.window_background_opacity = 0.95
config.default_prog = { "/usr/bin/fish" }
config.default_prog = { "/usr/bin/zsh" }
config.window_close_confirmation = "NeverPrompt"