#!/bin/zsh # Blake's ZSH config file ### Basic shell configuration >>> ### Environment variables >>> { # Intelligently set $EDITOR if command -v nvim > /dev/null;then export EDITOR=nvim elif command -v vim > /dev/null;then export EDITOR=vim elif command -v vi > /dev/null;then export EDITOR=vi fi export PATH="$PATH:${XDG_DATA_HOME:-$HOME/.local/bin}" export SYSTEMD_EDITOR="$EDITOR" export LSCOLORS="Gxfxcxdxbxegedabagacad" export ZSH_CACHE_DIR="${XDG_CACHE_HOME:-$HOME/.cache}/zsh" export ZINIT_HOME_DIR="$HOME/.local/share/zinit" WORKING_DIR_SAVE_FILE="${XDG_CACHE_HOME:-$HOME/.cache}/zsh/last-working-dir" # make the dir for the file if needed ! test -d "$(dirname "$WORKING_DIR_SAVE_FILE")" && mkdir -p "$(dirname "$WORKING_DIR_SAVE_FILE")" # (I know this shouldn't go here, but I needed it to happen early) # change cursor to beam by default echo -ne '\e[5 q' # Plugin setting >>> { # ZSH Vi Mode ZVM_VI_HIGHLIGHT_FOREGROUND=#BBC2CF ZVM_VI_HIGHLIGHT_BACKGROUND=#515860 # ZVM_VI_HIGHLIGHT_EXTRASTYLE=bold,underline # bold and underline # OMZ Completion COMPLETION_WAITING_DOTS=true } # <<< # optionally source an external environment variable file [ -f "${XDG_CONFIG_HOME:-$HOME/.config}/shell/envrc" ] && source "${XDG_CONFIG_HOME:-$HOME/.config}/shell/envrc" } # <<< ### Aliases >>> { ## Short hand programs (ex: sc = shellcheck) >>> # use nvim rather than vim if the command exists alias \ vim='nvim' \ vimdiff='nvim -d' alias \ vv="$EDITOR" \ e="$EDITOR" \ sedit='sudoedit' \ # I do this too much by accident smh my head alias :q='exit' \ q='exit' \ alias sc=shellcheck # rmdir is long alias \ rmd='rmdir' \ rd='rmdir' \ alias \ mkd="mkdir -p" \ g=git \ sctl='sudo systemctl' \ # <<< ## Program improvements (ex: ls = ls -h) >>> alias sudo='sudo ' # allow using aliases in sudo commands alias df='df -h' # Human-readable sizes alias free='free -m' # Show sizes in MB alias bc='bc -ql' # Make bc usable for fast math [ -z "$VIMRUNTIME" ] && alias glow='glow -p' # force Glow to preview with `less` if not in vim # I hate it when I get ghost script instead of git status. this will be removed alias gs="echo 'you don'\''t really want ghost script, do you?'" # tell make to use all cpu cores alias make='make -j$(nproc)' # Colors alias \ ls='ls -hN --color=auto --group-directories-first' \ grep='grep --color=auto' \ diff='diff --color=auto' \ pacman='pacman --color=auto' \ paru='paru --color=auto --sudoloop --newsonupgrade --pgpfetch --upgrademenu --bottomup --fm vim --skipreview' \ command -v lsd > /dev/null && alias \ ls=lsd \ lsd='lsd --group-dirs=first' \ # <<< ## Mini short-hand scripts (ex: glone = git clone) >>> # dotfile management alias dot='git --git-dir="$HOME/git/dotfiles" --work-tree="$HOME"' alias d='git --git-dir="$HOME/git/dotfiles" --work-tree="$HOME"' # duplicate for auto-complete # quicker shutdown alias sdn='shutdown now' # open a new session called 0, but if there is already a session called 0, connect to it alias tm='tmux new -As0' # List available X displays. Useful for finding what display to export when connected over ssh. alias lsx='ls /tmp/.X11-unix | tr "X" ":"' # Make ydotool actually usable for short things alias ydotool='(sudo ydotoold &) && sleep 0.05 && sudo ydotool' # Update zinit and plugins alias zup='zinit self-update && zinit update --parallel' # Edit config files alias \ nvc='(cd ~/.config/nvim/lua/blake && nvim ../../init.lua)' \ zrc='$EDITOR ~/.zshrc' \ fstab='sudoedit /etc/fstab' \ hst='$EDITOR $HISTFILE' \ # Git cLONE alias glone="git clone" # Docker alias \ logs='docker-compose logs --tail=200 -f' \ dupd='docker-compose up -d' \ ddwn='docker-compose down' \ dc='docker-compose' \ occ='docker exec -it -u www-data nextcloud php occ' \ # file copying with a progress bar alias cpv="rsync -ah --info=progress2" # lists all open ports, along with some other info alias ls-ports='netstat -tulpn' # list all disks and their mount points alias mnt="mount | awk -F' ' '{ printf \"%s\t%s\n\",\$1,\$3; }' | column -t | grep -E '^/dev/' | sort" # backs up list of packages alias packback='comm -23 <(paru -Qqett | sort) <(paru -Qqg base -g base-devel | sort | uniq) > ~/pkglist.txt' # thoroughly reset the terminal alias rce='reset && clear && exec zsh' # find pretty much any file, quickly alias fds='fd --hidden --exclude /run' # smart plug things SMART_PLUG_IP='192.168.1.250' alias light='tplink_smartplug.py -t $SMART_PLUG_IP -c' # Common ls aliases alias \ l=ls \ la='ls -ah' \ ll='ls -lh' \ lla='ls -lah' \ # <<< # optionally source an external alias file [ -f "${XDG_CONFIG_HOME:-$HOME/.config}/shell/aliasrc" ] && source "${XDG_CONFIG_HOME:-$HOME/.config}/shell/aliasrc" } # # TODO: remove all aliases that refrence programs which do not exist >>> # alias fdsa=not_an_alias # test alias # alias what='which ' # this will return 0 if something we give it cannot be executed # validate_alias() { # what "$1" # } # # what fdsa # # may need to use xargs # for ALIAS in $(alias | cut -d = -f 1);do # assumes you don't have = signs in your alias's names # echo "validating alias $ALIAS" # what "$ALIAS" && # unalias "$ALIAS" && # echo "alias $ALIAS was removed" # done # alias q=exit # # <<< # <<< ### Functions >>> { # cd search: cd to a directory, given part of its name # (also can take arguments for an `fd` commnd) # (also can cd to a file if `-t f` is passed) cds() { if ! [ -z "$1" ];then DIR="$(fd --max-results=1 -t d $@)" if [ -f "$DIR" ];then cd "$(dirname "$DIR")" && pwd else cd "$DIR" && pwd fi else echo "$0: no arguments provided" return 1 fi } # cd find (interactive): cd to the containing dir of a file, or inside a folder, given part of its name # Basically, an interactive version of what's above # can take an `fd` command # requires that `fzy` is installed cdf() { DIR="$(fd $@ | fzy)" if [ -f "$DIR" ];then cd "$(dirname "$DIR")" && pwd else cd "$DIR" && pwd fi } # cd all: opens a new shell in each of the directories below the one you're in, so # you can execute commands in them until you type 'exit' # If I use this enough, I may make something that can do more # Ideas for what it could do in the future: # - somehow record typed commands so they can be automatically repeated like a macro # - maybe get the length of the histfile before and after, executing the last X number of commands # - Maybe just add an argument that takes a command and executes it in all dirs # (although that wouldn't be as good as recording actions bc it's easy to do # that by just writing a for loop) cda() { for DIR in *; do (cd "$DIR" && zsh) done } # edit file: Uses fzy to locate a file, and opens it in your favorite text editor # Takes arguments for `fd` ef() { "$EDITOR" "$(fd $@ | fzy)" } # toggles whether a file or group of files is executable chx() { for FILE in "$@";do if [ -x "$FILE" ];then chmod -x "$FILE" && echo -e "$FILE: -x" elif ! [ -x "$FILE" ];then chmod +x "$FILE" && echo -e "$FILE: +x" else echo "error: file $FILE does not exist" >&2 fi done } launch() { $@ > /dev/null 2>&1 & disown } # a simple way to manage your todo list # Usage: # todo -- pull latest repo version and edit ~/todo # todo [any git command] -- manage todo for easy syncing, assuming ~/todo is # a symlink that points to a file in a git repo # # Suggested use: make a git repo for holding your todo list, then make # a symlink called 'todo' that points to your todo list in your home directory # todo() { todo_dir="$(dirname "$(realpath ~/todo)")" todo_file="$(realpath ~/todo)" if [ -z "$@" ];then ( # subshell to protect against directory changes cd "$todo_dir" # pull the latest commits git rev-parse && git pull # open the file "$EDITOR" "$todo_file" # commit and push the file if it's in a git repo and the file has changed if git rev-parse && ! git diff --exit-code "$todo_file"; then git commit "$todo_file" -m 'todo' && git push fi ) elif [ "$@" = "cd" ]; then cd "$todo_dir" else git -C "$todo_dir" $@ fi } # Simple extraction script. Taken from manjaro's .bashrc ex() { if [ -f $1 ] ; then case $1 in *.tar.bz2) tar xjf $1 ;; *.tar.gz) tar xzf $1 ;; *.bz2) bunzip2 $1 ;; *.rar) unrar x $1 ;; *.gz) gunzip $1 ;; *.tar) tar xf $1 ;; *.tbz2) tar xjf $1 ;; *.tgz) tar xzf $1 ;; *.zip) unzip $1 ;; *.Z) uncompress $1;; *.7z) 7z x $1 ;; *) echo "'$1' cannot be extracted via ex()" ;; esac else echo "'$1' is not a valid file" fi } # TODO: encode the url to fix things like spaces using something like https://stackoverflow.com/a/10660730/11162605 # usage: sitepath # usage: sitepath # usage: sitepath # usage: sitepath -- you can search with 'fd' if you put in a command sitepath() { # account for if there is no urlencode command URLENCODE=urlencode if ! command -v urlencode > /dev/null 2>&1;then URLENCODE=cat fi # If there is no input, make the input the current directory [ -z ${1+x} ] && 1="$(pwd)" FILEPATH="$(([ -e "$1" ] && readlink -f "$1") || fd $@ /home/blake/docker/blakenorth.net/site)" # change all file paths into urls echo "$FILEPATH" | grep -o 'site.*' | sed 's+^site+https://blakenorth.net+g' | $URLENCODE # if you need this, I am using dead10ck/urlencode (cargo install urlencode) } # for sending error messages from functions and whatnot error() { ERROR_CODE="$?" >&2 echo "An error occurred within a function in the .zshrc on line number ${1}" return $ERROR_CODE } # prcolors(): Display all colors in a few different ways >>> # TODO: change this to make it not just a few scripts smashed together prcolors() { [ -z "$1" ] && 1=0 if [ $1 -eq '1' ];then # Taken from manjaro's bashrc >>> local fgc bgc vals seq0 printf "Color escapes are %s\n" '\e[${value};...;${value}m' printf "Values 30..37 are \e[33mforeground colors\e[m\n" printf "Values 40..47 are \e[43mbackground colors\e[m\n" printf "Value 1 gives a \e[1mbold-faced look\e[m\n\n" # foreground colors for fgc in {30..37}; do # background colors for bgc in {40..47}; do fgc=${fgc#37} # white bgc=${bgc#40} # black vals="${fgc:+$fgc;}${bgc}" vals=${vals%%;} seq0="${vals:+\e[${vals}m}" printf " %-9s" "${seq0:-(default)}" printf " ${seq0}TEXT\e[m" printf " \e[${vals:+${vals+$vals;}}1mBOLD\e[m" done echo; echo done # <<< elif [ $1 -eq '2' ];then # from base16shell >>> ansi_mappings=( Red Green Yellow Blue Magenta Cyan White Black Bright_Red Bright_Green Bright_Yellow Bright_Blue Bright_Magenta Bright_Cyan Bright_White Bright_Black ) colors=( base00 base08 base0B base0A base0D base0E base0C base05 base03 base08 base0B base0A base0D base0E base0C base07 base09 base0F base01 base02 base04 base06 ) for padded_value in `seq -w 0 21`; do color_variable="color${padded_value}" eval current_color=\$${color_variable} current_color=$(echo ${current_color//\//} | tr '[:lower:]' '[:upper:]') # get rid of slashes, and uppercase non_padded_value=$((10#$padded_value)) base16_color_name=${colors[$non_padded_value]} current_color_label=${current_color:-unknown} ansi_label=${ansi_mappings[$non_padded_value]} block=$(printf "\x1b[48;5;${non_padded_value}m___________________________") foreground=$(printf "\x1b[38;5;${non_padded_value}m$color_variable") printf "%s %s %s %-30s %s\x1b[0m\n" $foreground $base16_color_name $current_color_label ${ansi_label:-""} $block done; #if [ $# -eq 1 ]; then # printf "To restore current theme, source ~/.base16_theme or reopen your terminal\n" #fi # <<< elif [ $1 -eq '3' ];then # Similar to above, but does 256-bit colors. >>> # Taken from this: https://github.com/romkatv/powerlevel10k#set-colors-through-Powerlevel10k-configuration-parameters for i in {0..255}; do print -Pn "%K{$i} %k%F{$i}${(l:3::0:)i}%f " ${${(M)$((i%6)):#3}:+$'\n'} done # <<< else cat <<-EOF Usage: prcolors 1: Manjaro bashrc -- for checking text readability 2: base26shell -- for seeing the 16 set terminal colors 3: 256 -- for testing 256 color output EOF fi } # <<< # shellcheck disable=SC2016 mkcd() { mkdir -p "$1" || error $LINENO cd "$1" || error $LINENO } # shellcheck disable=SC2086 random-mac() { interfaces=(enp5s0 wlp4s0) for interface in "${interfaces[@]}";do echo " Changing interface: $interface" sudo ip link set dev $interface down sudo macchanger -r $interface sudo ip link set dev $interface up done } # Git cLONE cD gloned() { git clone "$1" || return $? if ! cd "$(echo "$1" | sed 's/\.git//g' | rev | cut -d '/' -f 1 | rev)";then echo 'Error: Could not `cd` into the repo' return 1 fi echo # ls --color=auto } # believe it or not, zsh makes for a fine calculator calc() { echo $(($*)) } # Makes a swapfile at /swapfile of a given size (ex: mkswp 4G) mkswp() { sudo fallocate -l "$1" /swapfile && sudo chmod 600 /swapfile sudo mkswap /swapfile && sudo swapon /swapfile } # Deletes the swapfile created by mkswp() rmswp() { sudo swapoff -v /swapfile sudo rm /swapfile } # optionally source an external function file [ -f "${XDG_CONFIG_HOME:-$HOME/.config}/shell/fnrc" ] && source "${XDG_CONFIG_HOME:-$HOME/.config}/shell/fnrc" } # <<< # <<< ### Plugins >>> { # plugin config >>> # vim-mode cursor # syntax: "[color] [blinking] [style]" see: https://github.com/softmoth/zsh-vim-mode#mode-in-prompt MODE_CURSOR_VIINS="blinking bar" MODE_CURSOR_REPLACE="steady bar" MODE_CURSOR_VICMD="steady block" MODE_CURSOR_SEARCH="blinking underline" MODE_CURSOR_VISUAL="steady block" MODE_CURSOR_VLINE="steady block" # <<< # Load zinit >>> { # Install zinit if not installed if [[ ! -f "$ZINIT_HOME_DIR/bin/zinit.zsh" ]]; then print -P "%F{33}▓▒░ %F{220}Installing %F{33}DHARMA%F{220} Initiative Plugin Manager (%F{33}zdharma-continuum/zinit%F{220})…%f" command mkdir -p "$ZINIT_HOME_DIR" && command chmod g-rwX "$ZINIT_HOME_DIR" command git clone https://github.com/zdharma-continuum/zinit "$ZINIT_HOME_DIR/bin" && \ print -P "%F{33}▓▒░ %F{34}Installation successful.%f%b" || \ print -P "%F{160}▓▒░ The clone has failed.%f%b" fi # Source zinit source "$ZINIT_HOME_DIR/bin/zinit.zsh" autoload -Uz _zinit (( ${+_comps} )) && _comps[zinit]=_zinit if [[ -r "${XDG_CACHE_HOME:-$HOME/.cache}/p10k-instant-prompt-${(%):-%n}.zsh" ]]; then source "${XDG_CACHE_HOME:-$HOME/.cache}/p10k-instant-prompt-${(%):-%n}.zsh" fi # Load a few important annexes, without Turbo # (this is currently required for annexes) zinit light-mode for \ zdharma-continuum/z-a-rust \ zdharma-continuum/z-a-as-monitor \ zdharma-continuum/z-a-patch-dl \ zdharma-continuum/z-a-bin-gem-node } # <<< # Plugins to install >>> { alias zinit='ice wait"!0" depth"1";zinit' # turbo mode and git clone depth zinit snippet OMZ::lib/history.zsh # Some better completion options zinit snippet OMZ::lib/completion.zsh # Quality of life zinit load "zsh-users/zsh-autosuggestions" zinit load "zdharma-continuum/fast-syntax-highlighting" zinit load "jeffreytse/zsh-vi-mode" zinit load "zsh-users/zsh-history-substring-search" zinit load "zsh-users/zsh-completions" ## Themes # terminal colors if [[ -f ~/.config/shell/colors.sh ]];then source ~/.config/shell/colors.sh else zinit snippet 'https://github.com/chriskempson/base16-shell/blob/master/scripts/base16-onedark.sh' # onedark shell colors fi zinit load "romkatv/powerlevel10k" zinit ice atclone"dircolors -b ./src/dir_colors > colors.zsh" \ atpull'%atclone' pick"colors.zsh" nocompile'!' \ atload'zstyle ":completion:*" list-colors “${(s.:.)LS_COLORS}”' zinit light arcticicestudio/nord-dircolors [[ -f ~/.p10k.zsh ]] && source ~/.p10k.zsh unalias zinit } # <<< } # <<< ### General ZSH configuration >>> # This section is (mostly) From manjaro's "manjaro-zsh-config" (/usr/share/zsh/manjaro-zsh-config) [ -z "$HISTFILE" ] && HISTFILE="$HOME/.zsh_history" ## ZSH Options >>> { # setopt correct # Auto correct mistakes setopt extendedglob # Extended globbing. Allows using regular expressions with * [ -z "$TERMUX_VERSION" ] && setopt nocaseglob # Case insensitive globbing (and fix for termux) setopt rcexpandparam # Array expension with parameters setopt checkjobs # Warn about running processes when exiting setopt numericglobsort # Sort filenames numerically when it makes sense setopt nobeep # Most important option setopt appendhistory # Immediately append history instead of overwriting setopt inc_append_history # save commands are added to the history immediately, otherwise only when shell exits. setopt histfindnodups # If a new command is a duplicate, remove the older one setopt histignorealldups # If a new command is a duplicate, remove the older one setopt autocd # if only directory path is entered, cd there. setopt interactive_comments # allow typing comments in line setopt no_rm_star_silent # Ensure the user wants to execute 'rm *' setopt rm_star_wait # Wait before accepting 'rm *' or 'rm /path/*' setopt short_loops # allow things like 'if [ 1=1 ] { echo "okay"}' < https://zsh.sourceforge.io/Doc/Release/Shell-Grammar.html#Alternate-Forms-For-Complex-Commands setopt pipe_fail # When a pipe fails, show the non-0 exit code for the exit code } # <<< ## ZSH Completion Options >>> { # Mine # zstyle ':completion:*' completer _expand _complete _ignored _prefix # zstyle ':completion:*' expand prefix suffix # zstyle ':completion:*' file-sort access # zstyle ':completion:*' ignore-parents parent pwd directory # zstyle ':completion:*' list-colors ${(s.:.)LS_COLORS} # zstyle ':completion:*' list-prompt %SAt %p: Hit TAB for more, or the character to insert%s # zstyle ':completion:*' matcher-list '' 'm:{[:lower:]}={[:upper:]}' 'm:{[:lower:][:upper:]}={[:upper:][:lower:]}' 'r:|[._-]=** r:|=**' # zstyle ':completion:*' menu select=long # zstyle ':completion:*' select-prompt %SScrolling active: current selection at %p%s # zstyle :compinstall filename '/home/blake/.zshrc' # Manjaro's zstyle ':completion:*' matcher-list 'm:{a-zA-Z}={A-Za-z}' # Case insensitive tab completion zstyle ':completion:*' list-colors "${(s.:.)LS_COLORS}" # Colored completion (different colors for dirs/files/etc) zstyle ':completion:*' rehash true # automatically find new executables in path # Speed up completions zstyle ':completion:*' accept-exact '*(N)' zstyle ':completion:*' use-cache on zstyle ':completion:*' cache-path $ZSH_CACHE_DIR WORDCHARS=${WORDCHARS//\/[&.;]} # Don't consider certain characters part of the word # just gonna sneak this in here, too unalias zi zpl zini zplg which-command run-help } # <<< ## Keybindings >>> bindkey -v # Enable Vi mode bindkey '^[[7~' beginning-of-line # Home key bindkey '^[[H' beginning-of-line # Home key if [[ "${terminfo[khome]}" != "" ]]; then bindkey "${terminfo[khome]}" beginning-of-line # [Home] - Go to beginning of line fi bindkey '^[[8~' end-of-line # End key bindkey '^[[F' end-of-line # End key if [[ "${terminfo[kend]}" != "" ]]; then bindkey "${terminfo[kend]}" end-of-line # [End] - Go to end of line fi bindkey '^[[2~' overwrite-mode # Insert key bindkey '^[[3~' delete-char # Delete key bindkey '^[[C' forward-char # Right key bindkey '^[[D' backward-char # Left key bindkey '^[[5~' history-beginning-search-backward # Page up key bindkey '^[[6~' history-beginning-search-forward # Page down key # Navigate words with ctrl+arrow keys bindkey '^[Oc' forward-word # bindkey '^[Od' backward-word # bindkey '^[[1;5D' backward-word # bindkey '^[[1;5C' forward-word # # Delete words with ctrl+bksp/del bindkey '^H' backward-kill-word # delete previous word with ctrl+backspace bindkey '^[[3;5~' kill-word # delete next word with ctrl+delete bindkey '^[[Z' undo # Shift+tab undo last action # bind UP and DOWN arrow keys to history substring search zmodload zsh/terminfo # bindkey "$terminfo[kcuu1]" history-substring-search-up # bindkey "$terminfo[kcud1]" history-substring-search-down bindkey '^[[A' history-substring-search-up bindkey '^[[B' history-substring-search-down bindkey -M vicmd 'k' history-substring-search-up bindkey -M vicmd 'j' history-substring-search-down # <<< # Colors and compinit >>> export LESS_TERMCAP_mb=$'\E[01;32m' export LESS_TERMCAP_md=$'\E[01;32m' export LESS_TERMCAP_me=$'\E[0m' export LESS_TERMCAP_se=$'\E[0m' export LESS_TERMCAP_so=$'\E[01;47;34m' export LESS_TERMCAP_ue=$'\E[0m' export LESS_TERMCAP_us=$'\E[01;36m' export LESS=-R autoload -U compinit colors zcalc compinit -d colors # <<< ### Various manjaro ZSH functions >>> # Set terminal window and tab/icon title >>> # usage: title short_tab_title [long_window_title] # See: http://www.faqs.org/docs/Linux-mini/Xterm-Title.html#ss3.1 # Fully supports screen and probably most modern xterm and rxvt # (In screen, only short_tab_title is used) function title { emulate -L zsh setopt prompt_subst [[ "$EMACS" == *term* ]] && return # if $2 is unset use $1 as default # if it is set and empty, leave it as is : ${2=$1} case "$TERM" in xterm*|putty*|rxvt*|konsole*|ansi|mlterm*|alacritty|st*) print -Pn "\e]2;${2:q}\a" # set window name print -Pn "\e]1;${1:q}\a" # set tab name ;; screen*|tmux*) print -Pn "\ek${1:q}\e\\" # set screen hardstatus ;; *) # Try to use terminfo to set the title # If the feature is available set title if [[ -n "$terminfo[fsl]" ]] && [[ -n "$terminfo[tsl]" ]]; then echoti tsl print -Pn "$1" echoti fsl fi ;; esac } # <<< ZSH_THEME_TERM_TAB_TITLE_IDLE="%15<..<%~%<<" # 15 char left truncated PWD ZSH_THEME_TERM_TITLE_IDLE="%n@%m:%~" # Runs before showing the prompt >>> function mzc_termsupport_precmd { [[ "${DISABLE_AUTO_TITLE:-}" == true ]] && return title $ZSH_THEME_TERM_TAB_TITLE_IDLE $ZSH_THEME_TERM_TITLE_IDLE } # <<< # Runs before executing the command >>> function mzc_termsupport_preexec { [[ "${DISABLE_AUTO_TITLE:-}" == true ]] && return emulate -L zsh # split command into array of arguments local -a cmdargs cmdargs=("${(z)2}") # " <- syntax highlighting fix # if running fg, extract the command from the job description if [[ "${cmdargs[1]}" = fg ]]; then # get the job id from the first argument passed to the fg command local job_id jobspec="${cmdargs[2]#%}" # logic based on jobs arguments: # http://zsh.sourceforge.net/Doc/Release/Jobs-_0026-Signals.html#Jobs # https://www.zsh.org/mla/users/2007/msg00704.html case "$jobspec" in <->) # %number argument: # use the same passed as an argument job_id=${jobspec} ;; ""|%|+) # empty, %% or %+ argument: # use the current job, which appears with a + in $jobstates: # suspended:+:5071=suspended (tty output) job_id=${(k)jobstates[(r)*:+:*]} ;; -) # %- argument: # use the previous job, which appears with a - in $jobstates: # suspended:-:6493=suspended (signal) job_id=${(k)jobstates[(r)*:-:*]} ;; [?]*) # %?string argument: # use $jobtexts to match for a job whose command *contains* job_id=${(k)jobtexts[(r)*${(Q)jobspec}*]} ;; *) # %string argument: # use $jobtexts to match for a job whose command *starts with* job_id=${(k)jobtexts[(r)${(Q)jobspec}*]} ;; esac # override preexec function arguments with job command if [[ -n "${jobtexts[$job_id]}" ]]; then 1="${jobtexts[$job_id]}" 2="${jobtexts[$job_id]}" fi fi # cmd name only, or if this is sudo or ssh, the next cmd local CMD=${1[(wr)^(*=*|sudo|ssh|mosh|rake|-*)]:gs/%/%%} local LINE="${2:gs/%/%%}" title '$CMD' '%100>...>$LINE%<<' } # <<< autoload -U add-zsh-hook add-zsh-hook precmd mzc_termsupport_precmd add-zsh-hook preexec mzc_termsupport_preexec # <<< # auto save and load working dir (allow `cd -` on start) >>> # Load the last working directory load_working_dir() { # load the directory (and do validation to make sure it's actually a directory) if test -f "$WORKING_DIR_SAVE_FILE"; then local PREVIOUS_WORKING_DIR="$(cat "$WORKING_DIR_SAVE_FILE")" if test -d "$(cat "$WORKING_DIR_SAVE_FILE")"; then cd "$PREVIOUS_WORKING_DIR" || error $LINENO else echo "Invalid saved working directory ($PREVIOUS_WORKING_DIR)" > /dev/null return 1 fi else echo "Invalid working directory save file ($WORKING_DIR_SAVE_FILE)" > /dev/null return 1 fi } save_working_dir() { pwd > "$WORKING_DIR_SAVE_FILE" } autoload -U add-zsh-hook add-zsh-hook chpwd save_working_dir load_working_dir && cd - > /dev/null # Case insensitive globbing (fix for termux) [ -n "$TERMUX_VERSION" ] && setopt nocaseglob # <<< # <<< # Optionally source the user's customized .zshrc [ -f "${XDG_CONFIG_HOME:-$HOME/.config}/shell/zshrc.local" ] && source "${XDG_CONFIG_HOME:-$HOME/.config}/shell/zshrc.local" || true # vim:fdm=marker:fmr=>>>,<<<:et:ft=sh:sw=3