diff options
| author | Craig Jennings <c@cjennings.net> | 2026-01-24 18:52:34 -0600 |
|---|---|---|
| committer | Craig Jennings <c@cjennings.net> | 2026-01-24 18:52:34 -0600 |
| commit | 7d0f90da66985b402c6a25eb3eca8cc9e6060ced (patch) | |
| tree | 94a4fefdccc5cc1750a7466b3764b44bf1b8d0b0 /dotfiles/system/.profile.d | |
| download | archsetup-7d0f90da66985b402c6a25eb3eca8cc9e6060ced.tar.gz archsetup-7d0f90da66985b402c6a25eb3eca8cc9e6060ced.zip | |
fix(testing): remove obsolete --skip-slow-packages option
This flag was removed from archsetup but remained in test scripts.
Diffstat (limited to 'dotfiles/system/.profile.d')
| -rwxr-xr-x | dotfiles/system/.profile.d/arch-linux-downgrade.sh | 50 | ||||
| -rw-r--r-- | dotfiles/system/.profile.d/auto-tmux-session.sh | 12 | ||||
| -rw-r--r-- | dotfiles/system/.profile.d/chronographic.sh | 120 | ||||
| -rw-r--r-- | dotfiles/system/.profile.d/compress.sh | 75 | ||||
| -rw-r--r-- | dotfiles/system/.profile.d/dd.sh | 19 | ||||
| -rw-r--r-- | dotfiles/system/.profile.d/display.sh | 14 | ||||
| -rw-r--r-- | dotfiles/system/.profile.d/emacs.sh | 33 | ||||
| -rw-r--r-- | dotfiles/system/.profile.d/extract.sh | 27 | ||||
| -rw-r--r-- | dotfiles/system/.profile.d/framework.sh | 10 | ||||
| -rw-r--r-- | dotfiles/system/.profile.d/freebsd.sh | 10 | ||||
| -rw-r--r-- | dotfiles/system/.profile.d/fzf.sh | 123 | ||||
| -rw-r--r-- | dotfiles/system/.profile.d/git.sh | 24 | ||||
| -rw-r--r-- | dotfiles/system/.profile.d/media.sh | 41 | ||||
| -rwxr-xr-x | dotfiles/system/.profile.d/zoxide.sh | 11 |
14 files changed, 569 insertions, 0 deletions
diff --git a/dotfiles/system/.profile.d/arch-linux-downgrade.sh b/dotfiles/system/.profile.d/arch-linux-downgrade.sh new file mode 100755 index 0000000..d97a2dc --- /dev/null +++ b/dotfiles/system/.profile.d/arch-linux-downgrade.sh @@ -0,0 +1,50 @@ +#!/bin/sh + +# arch-linux-downgrade.sh +# Craig Jennings <c@cjennings.net> +# Downgrade an explicitly installed Arch package, chosen via fzf. + +# Config: +# export DG_HELPER=pacman # or yay, paru, etc. Must support -Qe, -Qi, -Si +# export DG_FZF_OPTS="..." # optional extra fzf flags + +dg() { + emulate -L zsh + set -u + set -o pipefail + + local helper="${DG_HELPER:-pacman}" + + # Check dependencies + for cmd in "$helper" fzf sudo downgrade awk sort; do + if ! command -v "${cmd%% *}" >/dev/null 2>&1; then + print -u2 -- "Missing dependency: $cmd" + return 1 + fi + done + + # List explicitly installed packages + local selection + selection="$( + "$helper" -Qe 2>/dev/null \ + | fzf --no-multi \ + --prompt="Pick package to downgrade > " \ + --height=80% \ + --reverse \ + --delimiter=' ' \ + --preview-window=right:60%:wrap \ + --preview "$helper -Qi {1} 2>/dev/null || $helper -Si {1}" \ + ${DG_FZF_OPTS:-} + )" + + # If fzf or pacman fails, just return + [[ $? -ne 0 || -z "$selection" ]] && return 0 + + local pkg + pkg="$(print -r -- "$selection" | head -n1 | awk '{print $1}')" + + if ! sudo downgrade "$pkg"; then + print -u2 -- "Downgrade failed for $pkg" + return 1 + fi +} diff --git a/dotfiles/system/.profile.d/auto-tmux-session.sh b/dotfiles/system/.profile.d/auto-tmux-session.sh new file mode 100644 index 0000000..2f17085 --- /dev/null +++ b/dotfiles/system/.profile.d/auto-tmux-session.sh @@ -0,0 +1,12 @@ +#!/bin/sh + +# auto-tmux-session.sh +# Craig Jennings <c@cjennings.net> +# if TRAMP (ssh dumb terminal), simplify prompt, and start tmux. + +# start tmux when logging in via ssh +if [[ -z "$TMUX" ]] && [ "$SSH_CONNECTION" != "" ]; then + export TERM="xterm-mono" + # if dumb terminal (i.e., tramp), then set a simple prompt, otherwise set monochrome TERM and start tmux + tmux attach-session -t "$USER" || tmux new-session -s "$USER" +fi diff --git a/dotfiles/system/.profile.d/chronographic.sh b/dotfiles/system/.profile.d/chronographic.sh new file mode 100644 index 0000000..41c1860 --- /dev/null +++ b/dotfiles/system/.profile.d/chronographic.sh @@ -0,0 +1,120 @@ +#!/bin/sh + +# chronographic.sh +# Craig Jennings <c@cjennings.net> +# quick and dirty terminal clock, timer, alarm and stopwatch functions + +alias beep='paplay $BEEP' +export BEEP="/usr/share/sounds/freedesktop/stereo/bell.oga" + +## +## CLOCK +## + +clock() { + while true; do tput clear; echo ""; date +" %l : %M %p" | figlet -f roman -w 200 ; sleep 1; done +} + +## +## TIMER +## + +timer() { + # Ensure we have at least two arguments + if [ "$#" -lt 2 ]; then + echo "Pass the time and a notification. Example: timer 1h30m Parking expiring" + return 1 + fi + message="${@:2}" + start_time=$(date +"%H:%M:%S %p") + printf "\nStarting %s timer at $start_time\n" "$1" + snore "$1" && paplay "$BEEP" && notify-send "Timer" "$message" && echo "" +} + +## +## ALARM +## + +alarm() { + # Ensure we have two or more arguments + if [ "$#" -lt 2 ]; then + echo "Pass both the time and a message. Example: alarm 1:45pm Time to eat!" + return 1 + fi + + # Validate the first argument is a valid time + ! date -d "$1" >/dev/null 2>&1 && echo "Invalid time: $1" && return 1 + + # silently schedule the command using 'at' command + echo "paplay \$BEEP && notify-send \"Alarm\" \"$@\"" | at "$1" >> /dev/null 2>&1 + echo "" + echo "Alarm '${@:2}' is queued for $1." + echo "To see all alarms, issue the command: 'atq'" + echo "To remove an alarm, issue the command: 'atrm' and the number of entry from atq" + echo "" +} + +## +## STOPWATCH FUNCTIONS +## + +sw_start_time=0 +sw_started=0 + +swreset() { + sw_start_time=0 + sw_started=0 + echo "Stopwatch reset" +} + +swshow() { + if [ "$sw_started" = 0 ] ; then + echo "Error: Stopwatch not started" >&2 && return 1 + fi + + current_time=$(date +%s) + elapsed_time=$((current_time - sw_start_time)) + + if (( elapsed_time < 60 )); then + # Display elapsed time in seconds + echo "Elapsed time: $elapsed_time seconds" + elif (( elapsed_time < 3600 )); then + # Display elapsed time in minutes and seconds + minutes=$((elapsed_time / 60)) + seconds=$((elapsed_time % 60)) + echo "Elapsed time: $minutes minutes, $seconds seconds" + else + # Display elapsed time in hours, minutes, and seconds + hours=$((elapsed_time / 3600)) + minutes=$(((elapsed_time / 60) % 60)) + seconds=$((elapsed_time % 60)) + echo "Elapsed time: $hours hours, $minutes minutes, and $seconds seconds" + fi +} + +swstop() { + swshow + swreset +} + +swstart() { + if [ "$sw_started" = 1 ] ; then + printf "Stopwatch is already started. Reset? (y/n): " + read -r answer + if [ "$answer" = "y" -o "$answer" = "Y" ]; then + swreset + # continue on to start the new timer + elif [ "$answer" = "n" -o "$answer" = "N" ]; then + echo "Stopwatch not reset." + swshow + # return to avoid restarting the timer + return + else + echo "Error: Invalid input. Exiting." >&2 && return 1 + fi + fi + + sw_started=1 + sw_start_time=$(date +%s) + printf "Stopwatch started at %s\n\n" "$(date +"%H:%M:%S %p")" +} diff --git a/dotfiles/system/.profile.d/compress.sh b/dotfiles/system/.profile.d/compress.sh new file mode 100644 index 0000000..0a9a7db --- /dev/null +++ b/dotfiles/system/.profile.d/compress.sh @@ -0,0 +1,75 @@ +#!/bin/sh +# Craig Jennings <c@cjennings.net> +# convenience compression function + +compress () { + if [ $# -ne 2 ]; then + echo "Usage: compress <format> <file_or_directory>" + echo "Formats: tar.bz2, tar.gz, bz2, tar, tbz2, tgz, zip, gz, Z" + return 1 + fi + + format="$1" + target="$2" + + if [ ! -e "$target" ]; then + echo "Error: '$target' does not exist" + return 1 + fi + + basename=$(basename "$target") + + # Determine output filename first + case "$format" in + tar.bz2|tbz2) output="${basename}.tar.bz2" ;; + tar.gz|tgz) output="${basename}.tar.gz" ;; + bz2) output="${target}.bz2" ;; + gz) output="${target}.gz" ;; + tar) output="${basename}.tar" ;; + zip) output="${basename}.zip" ;; + Z) output="${target}.Z" ;; + *) + echo "Error: Unknown format '$format'" + return 1 + ;; + esac + + # Check if output file already exists + if [ -e "$output" ]; then + printf "Warning: '%s' already exists. Overwrite? (y/N): " "$output" + read -r response + case "$response" in + [yY]|[yY][eE][sS]) + rm -f "$output" + ;; + *) + echo "Aborted." + return 1 + ;; + esac + fi + + # perform the compression + case "$format" in + tar.bz2|tbz2) tar -cjf "$output" "$target" ;; + tar.gz|tgz) tar -czf "$output" "$target" ;; + bz2) + [ -d "$target" ] && echo "Error: bz2 only works on files" && return 1 + bzip2 -k "$target" + ;; + gz) + [ -d "$target" ] && echo "Error: gz only works on files" && return 1 + gzip -k "$target" + ;; + tar) tar -cf "$output" "$target" ;; + zip) + [ -d "$target" ] && zip -r "$output" "$target" || zip "$output" "$target" + ;; + Z) + [ -d "$target" ] && echo "Error: Z only works on files" && return 1 + compress -c "$target" > "$output" + ;; + esac + + [ $? -eq 0 ] && echo "✓ Created $output" || echo "✗ Compression failed" +} diff --git a/dotfiles/system/.profile.d/dd.sh b/dotfiles/system/.profile.d/dd.sh new file mode 100644 index 0000000..5390a65 --- /dev/null +++ b/dotfiles/system/.profile.d/dd.sh @@ -0,0 +1,19 @@ +#!/bin/sh + +# dd.sh +# Craig Jennings <c@cjennings.net> +# takes input and output files as arguments +# prints parameters needed for dd + + +dd_with_bs() { + OUT_DIR=$(dirname "$2") + if [ ! -e "$1" -o ! -e "$OUT_DIR" ]; then + echo "$1 or $OUT_DIR doesn't exist" + return 1 + fi + IN_BS=$(stat -c "%o" "$1") + OUT_BS=$(stat -c "%o" "$OUT_DIR") + + echo dd \"if=$1\" \"of=$2\" \"ibs=$IN_BS\" \"obs=$OUT_BS\" +} diff --git a/dotfiles/system/.profile.d/display.sh b/dotfiles/system/.profile.d/display.sh new file mode 100644 index 0000000..df5a57c --- /dev/null +++ b/dotfiles/system/.profile.d/display.sh @@ -0,0 +1,14 @@ +#!/bin/sh +# display.sh +# Craig Jennings <c@cjennings.net> +# UI Appearance settings, sourced by .profile + +# Theme +export GTK_THEME=Adwaita:dark +# export GTK_THEME=Adwaita + + +XDG_CURRENT_DESKTOP=GNOME +# export QT_QPA_PLATFORMTHEME=qt5ct +export QT_QPA_PLATFORMTHEME=qt6ct +export QT_SCALE_FACTOR=1 diff --git a/dotfiles/system/.profile.d/emacs.sh b/dotfiles/system/.profile.d/emacs.sh new file mode 100644 index 0000000..c70d928 --- /dev/null +++ b/dotfiles/system/.profile.d/emacs.sh @@ -0,0 +1,33 @@ +#!/bin/sh + +# emacs.sh +# Craig Jennings <c@cjennings.net> +# Emacs specific settings, sourced by .profile + +### INFO FILES +export INFOPATH="$HOME/.config/emacs/info:/usr/share/info:/usr/local/share/info" + +### WORKAROUND +# https://unix.stackexchange.com/questions/230238/x-applications-warn-couldnt-connect-to-accessibility-bus-on-stderr +# emacs/gtk interaction bug workaround +export NO_AT_BRIDGE=1 + +# WAKE UTILITY +# useful when emacs or elisp doesn't timeout. +alias emacswake='for i in `seq 1 500`; do killall -s USR2 emacs; done' # wake emacs from a freeze + +### VTERM +# Vterm uses some features (e.g., directory-tracking and prompt-tracking or message passing) that require shell-side configurations. +# This functions enables the shell to send information to vterm via properly escaped sequences. + +vterm_printf(){ + if [ -n "$TMUX" ] && ([ "${TERM%%-*}" = "tmux" ] || [ "${TERM%%-*}" = "screen" ] ); then + # Tell tmux to pass the escape sequences through + printf "\ePtmux;\e\e]%s\007\e\\" "$1" + elif [ "${TERM%%-*}" = "screen" ]; then + # GNU screen (screen, screen-256color, screen-256color-bce) + printf "\eP\e]%s\007\e\\" "$1" + else + printf "\e]%s\e\\" "$1" + fi +} diff --git a/dotfiles/system/.profile.d/extract.sh b/dotfiles/system/.profile.d/extract.sh new file mode 100644 index 0000000..5fce587 --- /dev/null +++ b/dotfiles/system/.profile.d/extract.sh @@ -0,0 +1,27 @@ +#!/bin/sh + +# extract.sh +# Craig Jennings <c@cjennings.net> +# convenience extraction function + +## EXTRACT + +extract () { + if [ -f "$1" ] ; then + case "$1" in + *.tar.bz2) tar xjf "$1" ;; + *.tar.gz) tar xzf "$1" ;; + *.bz2) bunzip2 "$1" ;; + *.rar) rar x "$1" ;; + *.gz) gunzip "$1" ;; + *.tar) tar xf "$1" ;; + *.tbz2) tar xjf "$1" ;; + *.tgz) tar xzf "$1" ;; + *.zip) unzip "$1" ;; + *.Z) uncompress "$1" ;; + *) echo "$1 cannot be extracted via extract()" ;; + esac + else + echo "$1 is not a valid file" + fi +} diff --git a/dotfiles/system/.profile.d/framework.sh b/dotfiles/system/.profile.d/framework.sh new file mode 100644 index 0000000..2b8895e --- /dev/null +++ b/dotfiles/system/.profile.d/framework.sh @@ -0,0 +1,10 @@ +#!/bin/sh + +# framework.sh +# Craig Jennings <c@cjennings.net> +# settings for Framework 13 specific issues + +# HiDPI scale settings for Framework 13 Laptop +export GDK_DPI_SCALE=1 # text scaling only. +export GDK_SCALE=1 # this is an integer, 1 or 2 etc +export QT_AUTO_SCREEN_SCALE_FACTOR=1 diff --git a/dotfiles/system/.profile.d/freebsd.sh b/dotfiles/system/.profile.d/freebsd.sh new file mode 100644 index 0000000..8d12031 --- /dev/null +++ b/dotfiles/system/.profile.d/freebsd.sh @@ -0,0 +1,10 @@ +#!/bin/sh + +# freebsd.sh +# Craig Jennings <c@cjennings.net> +# Settings FreeBSD specific, sourced by .profile + +# make delete do the right thing for freebsd +if echo "$(uname)" | grep -q "FreeBSD"; then + bindkey "\e[3~" delete-char +fi diff --git a/dotfiles/system/.profile.d/fzf.sh b/dotfiles/system/.profile.d/fzf.sh new file mode 100644 index 0000000..5fab752 --- /dev/null +++ b/dotfiles/system/.profile.d/fzf.sh @@ -0,0 +1,123 @@ +#!/bin/sh + +# fzf.sh +# Craig Jennings <c@cjennings.net> +# fuzzy find settings and utilities, sourced by .profile + +# otherwise ** doesn't expand +source /usr/share/fzf/completion.zsh + +### SETTINGS +export FZF_DEFAULT_OPTS='--height=70%' +export FZF_DEFAULT_COMMAND='rg --files' +export FZF_CTRL_T_COMMAND="$FZF_DEFAULT_COMMAND" +export FZF_DEFAULT_COMMAND='rg --files --no-ignore-vcs --hidden' + +# Directory paths for convenience functions +IF_GAMES_DIR="$HOME/sync/org/text.games" +BOOKS_DIR="$HOME/sync/books" + +### NAVIGATION + +# cdff - change directory find file +# change to the directory where the file resides. +cdff() { + + file=$(fzf +m -q "$1") + dir=$(dirname "$file") + cd "$dir" || exit +} + +# CD to a directory with fzf +cdd () { + destdir=$(find "${1:-.}" -path '*/\.*' -prune \ + -o -type d -print 2> /dev/null | fzf +m) && + cd "$destdir" +} + +### SYSTEM ADMIN + +# Kill a process with fzf +kp () { + pid=$(ps -ef | sed 1d | eval "fzf ${FZF_DEFAULT_OPTS} -m --header='[kill:process]'" | awk '{print $2}') + + if [ "x$pid" != "x" ] + then + echo "$pid" | xargs kill -${1:-9} + kp + fi +} + +# list available packages, show info in preview, and install selection +yinstall() { + yay -Slq | fzf --multi --preview 'yay -Si {1}' | xargs -ro yay -S --noconfirm +} + + +yinstall-skipverify() { + yay -Slq | fzf --multi --preview 'yay -Si {1}' | xargs -ro yay -S --noconfirm --mflags --skipinteg +} + +# list installed packages, show info in preview, and remove selection +yrm() { + yay -Qq | fzf --multi --preview 'yay -Qi {1}' | xargs -ro yay -Rns +} + +# find-in-file - usage: fif <searchTerm> +fif() { + if [ ! "$#" -gt 0 ]; then echo "Need a string to search for!"; return 1; fi + rg --files-with-matches --no-messages "$1" | fzf --preview "highlight -O ansi -l {} 2> /dev/null | rg --colors 'match:bg:yellow' --ignore-case --pretty --context 10 '$1' || rg --ignore-case --pretty --context 10 '$1' {}" +} + +### CONVENIENCE + +# Find an epub book in the library and open it in epr terminal reader. +# previously: find ~/books \( -iname \*.epub -o -iname \*.pdf -o -iname \*.djvu \) | fzf | xargs emacs +bk() { + bkfile=$(find "$BOOKS_DIR" -iname "*.epub" -print | fzf) + if [ -n "$bkfile" ]; then + epr "$bkfile" + fi +} + +# Find an interactive fiction game and open it in frotz. +# Supports Z-machine files (.z1-.z8, .zblorb, .blorb) +tg() { + gamefile=$(find "$IF_GAMES_DIR" -type f \( -iname "*.z[1-8]" -o -iname "*.zblorb" -o -iname "*.blorb" \) -print | fzf) + if [ -n "$gamefile" ]; then + frotz "$gamefile" + fi +} + + + +# close wireguard connection first if already running, then +# run wireguard, selecting the configuration file. +wgup() { + # Check if wireguard is running + output=$(sudo wg) + if [[ -n "$output" ]]; then + # Shutdown all wg interfaces if WireGuard is currently running. + for iface in $(sudo wg show interfaces); do + sudo wg-quick down "${iface}" + done + fi + # Get the list of config files + wgfile=$(sudo find /etc/wireguard/ -iname "*.conf" -exec basename -s .conf {} \; | fzf) + + if [ -n "$wgfile" ]; then + sudo wg-quick up $wgfile + sudo wg + fi +} +wgdown() { + # Check if wireguard is running + output=$(sudo wg) + if [[ -n "$output" ]]; then + # Shutdown all wg interfaces if WireGuard is currently running. + for iface in $(sudo wg show interfaces); do + sudo wg-quick down "${iface}" + done + fi +} +alias wg=wgup diff --git a/dotfiles/system/.profile.d/git.sh b/dotfiles/system/.profile.d/git.sh new file mode 100644 index 0000000..7332ba1 --- /dev/null +++ b/dotfiles/system/.profile.d/git.sh @@ -0,0 +1,24 @@ +#!/bin/sh + +# git.sh +# Craig Jennings <c@cjennings.net> +# git settings and convenience aliases, sourced by .profile + +alias gitlog="git log --graph --pretty=format:'%Cred%h%Creset %an: %s - %Creset %C(yellow)%d%Creset %Cgreen(%cr)%Creset' --abbrev-commit --date=relative" +alias gitstatus='git status -sb ' +alias gitcom='git commit -m ' +alias gitpp='git pull --prune ' # clean up any orphaned git objects +alias gittagbydate="git for-each-ref --sort=creatordate --format '%(refname) %(creatordate)' refs/tags" + +gitsp() { + git stash && git pull && git stash pop +} + +gitck() { + git checkout "$(git branch --all | fzf| tr -d '[:space:]')" +} + +gitdiff() { + preview="git diff $@ --color=always -- {-1}" + git diff "$@" --name-only | fzf -m --ansi --preview "$preview" +} diff --git a/dotfiles/system/.profile.d/media.sh b/dotfiles/system/.profile.d/media.sh new file mode 100644 index 0000000..3add213 --- /dev/null +++ b/dotfiles/system/.profile.d/media.sh @@ -0,0 +1,41 @@ +#!/bin/sh + +# media.sh +# Craig Jennings <c@cjennings.net> +# utilities for working with media (music, video, books, etc.) + + +### TERMINAL MPV ALIASES +alias play='mpv --no-video' +alias shuffle='mpv --no-video --shuffle ' + + +### YOUTUBE AND TIDAL +# Leverage task spooler to download url targets serially in the background. +# example : % stdl "https://youtu.be/gv-3Y7CcUUo" +# note that zshell urls must be quoted; not so for bash. + +# tidal-dl +alias tdl="tidal-dl -l" +alias ttdl="tsp tidal-dl -l" + +# youtube-dl +alias yt="yt-dlp --ignore-config --no-playlist --add-metadata -i -o '%(channel)s-%(title)s.%(ext)s'" +alias tyt="tsp yt-dlp --ignore-config --no-playlist --add-metadata -i -o '%(channel)s-%(title)s.%(ext)s'" + +alias ytp="yt-dlp --ignore-config --yes-playlist --add-metadata -i -o '%(channel)s-%(playlist_title)s-%(playlist_index)s-%(title)s.%(ext)s'" +alias tytp="tsp yt-dlp --ignore-config --yes-playlist --add-metadata -i -o '%(channel)s-%(playlist_title)s-%(playlist_index)s-%(title)s.%(ext)s'" + +alias yta="yt-dlp --ignore-config --no-playlist -x -f bestaudio/best -o '%(artist)s-%(title)s.%(ext)s'" +alias tyta="tsp yt-dlp --ignore-config --no-playlist -x -f bestaudio/best -o '%(artist)s-%(title)s.%(ext)s'" + +alias ytap="yt-dlp --ignore-config --yes-playlist -x -f bestaudio/best -o '%(playlist_index)s-%(artist)s-%(title)s.%(ext)s'" +alias tytap="tsp yt-dlp --ignore-config --yes-playlist -x -f bestaudio/best -o '%(playlist_index)s-%(artist)s-%(title)s.%(ext)s'" + + +### SOUND FILE CONVERSION +# converts audible aax to other formats. Requires AAXtoMP3 script in dotfiles. + +alias aax2flac='AAXtoMP3 -f ' +alias aax2mp3='AAXtoMP3 -c -e:mp3 ' +alias aax2opus='AAXtoMP3 --opus -t . -c ' diff --git a/dotfiles/system/.profile.d/zoxide.sh b/dotfiles/system/.profile.d/zoxide.sh new file mode 100755 index 0000000..8bbb86b --- /dev/null +++ b/dotfiles/system/.profile.d/zoxide.sh @@ -0,0 +1,11 @@ +#!/bin/sh + +# zoxide.sh +# Craig Jennings <c@cjennings.net> +# zoxide initialization, sourced by .profile + +# Initialize zoxide for zsh +eval "$(zoxide init zsh)" + +# Alias cd to use zoxide +# alias cd="z" |
