├── .docs ├── completions.md ├── readme.md ├── zdotdir.md ├── zsh-cheatsheet.md ├── zsh-optparse.md ├── zsh-setopts.md └── zsh-string.md ├── .editorconfig ├── .gitignore ├── .zaliases ├── .zplugins ├── .zshenv ├── .zshrc ├── .zstyles ├── LICENSE ├── README.md ├── completions ├── _g ├── _git ├── _starship └── git-completion.bash ├── conf.d ├── __init__.zsh ├── archive │ ├── homebrew.zsh │ └── magic-enter.zsh ├── gpg.zsh ├── iwd.zsh ├── ruby.zsh ├── terminal.zsh ├── zoxide.zsh └── zsh-syntax-highlighting.zsh ├── functions ├── allexts ├── bak ├── clone ├── noext ├── optdiff ├── post-autosuggestions ├── post-history-substring-search ├── prj ├── repo ├── rmzwc ├── substenv ├── tailf ├── touchf ├── update_completions ├── weather ├── zcompiledir └── zephyr2lib ├── lib ├── antidote.zsh ├── archive │ ├── instant-zsh.zsh │ └── transient-prompt.zsh └── history.zsh ├── plugins ├── git │ └── git.plugin.zsh ├── golang │ └── golang.plugin.zsh ├── hooks │ └── zsh-hooks.plugin.zsh ├── otp │ ├── functions │ │ └── otp │ └── otp.plugin.zsh ├── p10k-instaprompt │ └── p10k-instaprompt.plugin.zsh ├── python │ ├── functions │ │ ├── _venv │ │ ├── _workon │ │ ├── juno │ │ ├── pipup │ │ ├── pyclean │ │ ├── venv │ │ └── workon │ └── python.plugin.zsh ├── starship-ftl │ ├── functions │ │ └── prompt_starship_setup │ └── starship-ftl.plugin.zsh └── xdg │ └── xdg.plugin.zsh └── themes ├── lean.p10k.zsh ├── mmc.p10k.zsh ├── mmc.toml ├── prompt_omz_setup ├── prompt_p10k_setup ├── pure.p10k.zsh └── zephyr.toml /.docs/completions.md: -------------------------------------------------------------------------------- 1 | # Completions 2 | 3 | Add user contributed completions to this directory. 4 | 5 | Read more about how Zsh completions work in this [how-to][1] article. 6 | 7 | 8 | [1]: https://github.com/zsh-users/zsh-completions/blob/master/zsh-completions-howto.org 9 | -------------------------------------------------------------------------------- /.docs/readme.md: -------------------------------------------------------------------------------- 1 | # Zsh reference 2 | 3 | I can't always remember all the Zsh goodies, so here's all the wonderful stuff I have 4 | learned and references to things other's have provided. 5 | 6 | ## Bare Zsh 7 | 8 | Zsh can be run without RCs using the following command: 9 | 10 | ```zsh 11 | zsh -dfi 12 | ``` 13 | 14 | When run this way, be careful - all exported environment variables are still set. 15 | 16 | If you want to run a totally clean environment, you can with with `env -i`. 17 | 18 | ``` 19 | env -i zsh -dfi 20 | ``` 21 | 22 | ## $0 23 | 24 | `${BASH_SOURCE[0]` is `${(%):-%x}}` in Zsh 25 | 26 | For example: 27 | 28 | ```zsh 29 | # $ZDOTDIR/functions/foo 30 | #functon foo { 31 | 32 | # prints foo 33 | echo $0 34 | 35 | # prints $ZDOTDIR/functions/foo 36 | echo ${(%):-%x} 37 | 38 | #} 39 | ``` 40 | 41 | From `man zshmisc`: 42 | 43 | ```text 44 | %N The name of the script, sourced file, or shell function that zsh is currently executing, 45 | whichever was started most recently. If there is none, this is equivalent to the parameter 46 | $0. An integer may follow the '%' to specify a number of trailing path components to show; 47 | zero means the full path. A negative integer specifies leading components. 48 | 49 | %x The name of the file containing the source code currently being executed. This behaves as %N 50 | except that function and eval command names are not shown, instead the file where they were 51 | defined. 52 | ``` 53 | 54 | - [See here](https://stackoverflow.com/questions/9901210/bash-source0-equivalent-in-zsh) 55 | - or run `man zshmisc`. 56 | 57 | ## String functions 58 | 59 | If you want to replace '~' with '$HOME' in a variable, you can do this: 60 | 61 | ```zsh 62 | mydir='~/path/to/my/dir' 63 | mydir=${mydir:s/~/$HOME} 64 | echo $mydir 65 | ``` 66 | 67 | ## Globbing 68 | 69 | [Glob qualifiers][zsh-glob-qualifiers] are options tacked onto a wildcard pattern that 70 | filter or modify the match. Some examples: 71 | 72 | ```zsh 73 | cd $ZDOTDIR 74 | ``` 75 | 76 | Show directories with `/`: 77 | 78 | ```zsh 79 | $ echo *(/) 80 | plugins zshrc.d zfunctions 81 | ``` 82 | 83 | Show regular files with `.`: 84 | 85 | ```zsh 86 | $ echo *(.) 87 | .zshenv .zshrc 88 | ``` 89 | 90 | Show symlinks with `@`: 91 | 92 | ```zsh 93 | $ echo *(@) 94 | .zsh_history 95 | ``` 96 | 97 | Toggle qualifiers to work with symlinks `-`: 98 | 99 | ```zsh 100 | $ echo *(.-) 101 | .zshenv .zsh_history .zshrc 102 | ``` 103 | 104 | Exclude files with `^`: 105 | 106 | ```zsh 107 | $ # exclude dotfiles 108 | $ echo ^.* 109 | README.md 110 | ``` 111 | 112 | Null glob, or "don't error on zero results": 113 | 114 | ```zsh 115 | $ mkdir empty && cd empty 116 | $ echo * 117 | zsh: no matches found: * 118 | $ echo *(N) 119 | ``` 120 | 121 | Files over/unsder a certain size with `L[+|-]n`: 122 | 123 | ```zsh 124 | $ # files over 1k 125 | $ echo *(Lk+1) 126 | LICENSE README.md 127 | ``` 128 | 129 | ## Expansion Modifiers 130 | 131 | [Expansion modifiers][zsh-modifiers] change the path stored in a variable. 132 | 133 | Set a file path in a variable to play with (assumes OMZ installed): 134 | 135 | ```zsh 136 | cd $ZSH 137 | filepath=./plugins/extract/extract.plugin.zsh 138 | ``` 139 | 140 | `:a` will expand a relative filepath to an absolute one 141 | 142 | ```zsh 143 | $ echo $filepath 144 | ./plugins/extract/extract.plugin.zsh 145 | $ echo ${filepath:a} 146 | $ZSH/plugins/extract/extract.plugin.zsh 147 | ``` 148 | 149 | `:h` will remove the trailing pathname component, shortening the path by one directory 150 | level. This is the 'head' of the pathname, which works like `dirname`. 151 | 152 | ```zsh 153 | $ echo ${filepath:h} 154 | ./plugins/extract 155 | ``` 156 | 157 | `:r` will remove the file extension leaving the 'root' name. 158 | 159 | ```zsh 160 | $ echo ${filepath:r} 161 | ./plugins/extract/extract.plugin 162 | ``` 163 | 164 | `:t` will remove all leading path components leaving the final part, or 'tail'. This 165 | works like `basename`. 166 | 167 | ```zsh 168 | $ echo ${filepath:t} 169 | extract.plugin.zsh 170 | ``` 171 | 172 | `:u` will convert the variable to UPPERCASE. Conversely, `:l` will convert back to 173 | lowercase. 174 | 175 | ```zsh 176 | $ echo ${filepath:u} 177 | ./PLUGINS/EXTRACT/EXTRACT.PLUGIN.ZSH 178 | $ echo ${filepath:u:l} 179 | ./plugins/extract/extract.plugin 180 | ``` 181 | 182 | [zsh-modifiers]: http://zsh.sourceforge.net/Doc/Release/Expansion.html#Modifiers 183 | [filename-generation]: http://zsh.sourceforge.net/Doc/Release/Expansion.html#Filename-Generation 184 | [zsh-glob-qualifiers]: http://zsh.sourceforge.net/Doc/Release/Expansion.html#Glob-Qualifiers 185 | [glob-filter-stackexchange]: https://unix.stackexchange.com/questions/31504/how-do-i-filter-a-glob-in-zsh 186 | -------------------------------------------------------------------------------- /.docs/zdotdir.md: -------------------------------------------------------------------------------- 1 | # ZDOTDIR 2 | 3 | > A simple guide to moving your Zsh files out of your `$HOME` 4 | 5 | This guide shows you how to move your Zsh files out of your home directory into a dedicated Zsh config directory. 6 | 7 | ## Pick a path 8 | 9 | Assuming you want to put your Zsh config in `~/.config/zsh`, run the following from an interactive Zsh session: 10 | 11 | ```zsh 12 | export ZDOTDIR=~/.config/zsh 13 | mkdir -p $ZDOTDIR 14 | ``` 15 | 16 | These commands will set the `ZDOTDIR` variable to your new Zsh home, and then ensure that the directory is properly created. 17 | 18 | ## Move your Zsh dotfiles 19 | 20 | ```zsh 21 | zdotfiles=( 22 | .zlog{in,out} 23 | .zprofile 24 | .zsh{env,rc,_history} 25 | ) 26 | for file in $zdotfiles 27 | do 28 | [[ -f ~/$file ]] && echo mv ~/$file $ZDOTDIR 29 | done 30 | ``` 31 | -------------------------------------------------------------------------------- /.docs/zsh-cheatsheet.md: -------------------------------------------------------------------------------- 1 | # Zsh CheatSheet 2 | 3 | [Source](https://gist.github.com/ClementNerma/1dd94cb0f1884b9c20d1ba0037bdcde2) 4 | 5 | This is a cheat sheet for how to perform various actions to Zsh, which can be tricky to find on the web as the syntax is not intuitive and it is generally not very well-documented. 6 | 7 | ## Strings 8 | 9 | | Description | Syntax | 10 | |--------------------------------------------------|-------------------------------------| 11 | | Get the length of a string | `${#VARNAME}` | 12 | | Get a single character | `${VARNAME[index]}` | 13 | | Get the string from a specific index | `${VARNAME[index,-1]}` | 14 | | Get a substring | `${VARNAME[from,to]}` | 15 | | Replace the first occurrence in a string | `${VARNAME/toreplace/replacement}` | 16 | | Replace all occurrences in a string | `${VARNAME//toreplace/replacement}` | 17 | | Cut a string after a model | `${VARNAME%%model*}` | 18 | | Check if a string starts by a specific substring | `if [[ $VARNAME = "startstr"* ]]` | 19 | | Check if a string contains a substring | `if [[ $VARNAME = *"substring"* ]]` | 20 | | Check if a string ends by a specific substring | `if [[ $VARNAME = *"substring" ]]` | 21 | 22 | ## Paths 23 | 24 | See [modifiers](https://zsh.sourceforge.io/Doc/Release/Expansion.html#Modifiers) 25 | 26 | | Description | Syntax | 27 | |--------------------------------------------------|-----------------| 28 | | Convert to an absolute path | `${RELPATH:a}` | 29 | | Convert to an absolute path and resolve symlinks | `${RELPATH:A}` | 30 | | Convert command to full path (via `$PATH`) | `${COMMAND:c}` | 31 | | Get the file extension | `${FILEPATH:e}` | 32 | | Remove the end of the path (head) | `${FILEPATH:h}` | 33 | | Convert to lowercase | `${STR:l}` | 34 | | Convert to UPPERCASE | `${STR:u}` | 35 | | Remove the file extension (root) | `${FILEPATH:r}` | 36 | | Remove all but the final part of the path (tail) | `${FILEPATH:t}` | 37 | 38 | ## Arrays 39 | 40 | | Description | Syntax | 41 | |-------------------------------------------------------------------|----------------------------------| 42 | | Create an array | `VARNAME=()` | 43 | | Create an array with initial values | `VARNAME=(value1 value2 value3)` | 44 | | Push to an array | `VARNAME+=(value)` | 45 | | Access an array's element | `VARNAME[index]` | 46 | | Get an array's length | `${#VARNAME}` | 47 | | Iterate over an array's values | `for value in $VARNAME;` | 48 | | Get index of a value in an array (`0` if not found) | `${VARNAME[(Ie)value]}` | 49 | | Get index of a value in an array (`${#VARNAME} + 1` if not found) | `${VARNAME[(ie)value]}` | 50 | | Get an array slice _after_ the specified index | `${VARNAME:index}` | 51 | | Get an array slice _after_ the specified index | `${VARNAME:index:length}` | 52 | | Check if a value is contained in an array | `if (( $VARNAME[(Ie)value] ));` | 53 | | Check if an array is empty | `if [[ -z $VARNAME ]]` | 54 | | Check if an array is not empty | `if [[ ! -z $VARNAME ]]` | 55 | | Remove an element from an array | `VARNAME[index]=()` | 56 | 57 | ## Associative arrays (= maps / dictionaries) 58 | 59 | Associate arrays are the equivalent of hash maps or dictionaries in many other programming languages: unlike arrays, they can use string keys, and these don't necessary have an order. 60 | 61 | | Description | Syntax | 62 | |-------------------------------------------------|------------------------------------------------------| 63 | | Create an associative array | `typeset -A VARNAME=()` | 64 | | Create an associative array with initial values | `typeset -A VARNAME=( [key1]=value1 [key2]=value2 )` | 65 | | Add a new key to the array | `VARNAME[key]=value` | 66 | | Access the array's elements | `$VARNAME[key]` | 67 | | Remove a key from the array | `unset 'VARNAME[key]'` | 68 | | Get the array's number of elements | `${#VARNAME}` | 69 | | Iterate over the array's values | `for value in $VARNAME;` | 70 | | Iterate over the array's keys | `for key in ${(k)VARNAME};` | 71 | | Iterate over the array's key-value pairs | `for key value in ${(kv)VARNAME};` | 72 | 73 | ## Arithmetics 74 | 75 | | Description | Syntax | 76 | |----------------------------------------------------------------------------------------|-------------------| 77 | | Compute a mathematical expression (variables don't need to be prefixed with `$` in it) | `$((expression))` | 78 | 79 | ## Variables 80 | 81 | | Description | Syntax | 82 | |---------------------------------------------------------------|--------------------| 83 | | Get the value of a variable whose name is in another variable | `${(P)NAMEVAR}` | 84 | | Get the list of all defined variables, as an array | `${(k)parameters}` | 85 | | Delete a variable | `unset VARNAME` | 86 | 87 | ## Functions 88 | 89 | | Description | Syntax | 90 | |-------------------------------------------------------------------|--------------------------------| 91 | | Declare a local variable (not accessible outside the function) | `local varname=...` | 92 | | Get the original executable name | `$0` | 93 | | Get a parameter | `$1` (second is `$2`, etc.) | 94 | | Expand all parameters | `$*` | 95 | | Expand all parameters but keep them quoted if needed | `$@` (tip: it's an array!) | 96 | | Get the number of parameters (so not counting `$0`) | `$#` | 97 | | Remove the first parameter from `$@` | `shift` | 98 | | Remove the last parameter from `$@` | `shift -p` | 99 | | Exit the function with a status code (behaves like for a command) | `return 1` (or any other code) | 100 | | Get the list of all functions, as an array | `${(k)functions}` | 101 | | Delete a function | `unset -f func_name` | 102 | 103 | ## Aliases 104 | 105 | | Description | Syntax | 106 | |--------------------------------------------------|-------------------------------------------| 107 | | Display the list of all defined aliases | `alias` | 108 | | Get the list of all defined aliases, as an array | `${(k)aliases}` | 109 | | Define an alias | `alias name="command arg1 arg2 arg3 ..."` | 110 | | Remove an alias | `unalias name` | 111 | | Get the arguments, with escaped spaces | `${@:q}` | 112 | 113 | ## Conditionals 114 | 115 | [A word on conditionals](#a-word-on-conditionals) 116 | 117 | Syntaxes: 118 | 119 | ```zsh 120 | # 1) 121 | if expression 122 | then 123 | # instructions 124 | fi 125 | 126 | # 2) 127 | if expression; then 128 | # instructions 129 | fi 130 | 131 | # 3) 132 | if expression; then ...; fi 133 | 134 | # 4) 135 | if expression; then 136 | # instructions 137 | else 138 | # instructions 139 | fi 140 | 141 | # 5) 142 | if expression; then 143 | # instructions 144 | elif expression; then 145 | # instructions 146 | else 147 | # instructions 148 | fi 149 | ``` 150 | 151 | | Description | Syntax | 152 | |-----------------------------------------------------------------|------------------------------| 153 | | Check if a string is empty or not defined | `if [[ -z $VARNAME ]];` | 154 | | Check if a string is defined and not empty | `if [[ -n $VARNAME ]];` | 155 | | Check if a file exists | `if [[ -f "filepath" ]];` | 156 | | Check if a directory exists | `if [[ -d "dirpath" ]]; ` | 157 | | Check if a symbolic link exists | `if [[ -L "symlinkpath" ]];` | 158 | | Check if a shell option is set | `if [[ -o OPTION_NAME ]];` | 159 | | Check if two values are equal | `if [[ $VAR1 = $VAR2 ]];` | 160 | | Check if two values are different | `if [[ $VAR1 != $VAR2 ]];` | 161 | | Check if a number is greater than another | `if (( $VAR1 > $VAR2 ));` | 162 | | Check if a number is smaller than another | `if (( $VAR1 < $VAR2 ));` | 163 | | Check if a command exits successfully (exit code `0`) | `if command arg1 arg2 ...` | 164 | | Check if a command doesn't exit successfully (exit code != `0`) | `if ! command arg1 arg2 ...` | 165 | 166 | Note that the `$` symbol preceding variables' names in arithmetic expression (`((...))`) are purely optional, so you can perfectly write `if (( VAR1 < VAR2 ));` for instance. 167 | 168 | You can read all dash `-` options in Zsh's manual, as there are many different ones: http://zsh.sourceforge.net/Doc/Release/Conditional-Expressions.html 169 | 170 | ## Loops 171 | 172 | Syntaxes: 173 | 174 | ```zsh 175 | # 1) 176 | for itervarname in iterable 177 | do 178 | # instructions 179 | done 180 | 181 | # 2) 182 | for itervarname in iterable; do 183 | # instructions 184 | done 185 | 186 | # 3) 187 | for itervaname in iterable; do ...; done 188 | ``` 189 | 190 | | Description | Syntax | 191 | |--------------------------------------------------------------------------|----------------------------| 192 | | Iterate over a range (inclusive) | `for i in {from..to};` | 193 | | Iterate over a list of filesystem items | `for i in globpattern;` | 194 | | Iterate over a list of filesystem items, fail silently if no match found | `for i in globpattern(N);` | 195 | 196 | ## Examples cheat sheet 197 | 198 | Return a value from within a function: 199 | 200 | ```zsh 201 | function add() { 202 | local sum=$(($1 + $2)) 203 | echo $sum 204 | } 205 | 206 | function add_twice() { 207 | local sum=$(add $1 $2) # get the callee's STDOUT 208 | local sum_twice=$(add $sum $sum) 209 | echo $sum_twice 210 | } 211 | 212 | echo $(add 2 3) # 5 213 | echo $(add_twice 2 3) # 10 214 | ``` 215 | 216 | ## A word on conditionals 217 | 218 | Conditionals use expressions, such as in `if [[ -z $VARNAME ]];` the expression is `[[ -z $VARNAME ]]`. These can also be used in `while` loops, as well as be used outside of blocks: 219 | 220 | ```zsh 221 | [[ -z $VARNAME ]] && echo "VARNAME is not defined or empty!" 222 | [[ -f $FILEPATH ]] && echo "File exists!" 223 | ``` 224 | 225 | This works because conditional expressions (`[[ ... ]]` and `(( ... ))`) don't actually return a value; they behave like commands and as such set the status code to `0` if the condition is true, or `1` else. 226 | 227 | If we want to display the message only if the condition is falsey: 228 | 229 | ```zsh 230 | [[ -z $VARNAME ]] || echo "VARNAME is not empty!" 231 | [[ -f $FILEPATH ]] || echo "File does not exist!" 232 | ``` 233 | -------------------------------------------------------------------------------- /.docs/zsh-optparse.md: -------------------------------------------------------------------------------- 1 | # Parsing Zsh options 2 | 3 | ## Manually 4 | 5 | ```zsh 6 | # Manual opt parsing example 7 | # 8 | # Features: 9 | # - supports short and long flags (ie: -v|--verbose) 10 | # - supports short and long key/value options (ie: -f | --filename ) 11 | # - supports short and long key/value options with equals assignment (ie: -f= | --filename=) 12 | # - does NOT support short option chaining (ie: -vh) 13 | # - everything after -- is positional even if it looks like an option (ie: -f) 14 | # - once we hit an arg that isn't an option flag, everything after that is considered positional 15 | function optparsing_demo() { 16 | local positional=() 17 | local flag_verbose=false 18 | local filename=myfile 19 | 20 | local usage=( 21 | "optparsing_demo [-h|--help]" 22 | "optparsing_demo [-v|--verbose] [-f|--filename=] []" 23 | ) 24 | opterr() { echo >&2 "optparsing_demo: Unknown option '$1'" } 25 | 26 | while (( $# )); do 27 | case $1 in 28 | --) shift; positional+=("$@"); break ;; 29 | -h|--help) printf "%s\n" $usage && return ;; 30 | -v|--verbose) flag_verbose=true ;; 31 | -f|--filename) shift; filename=$1 ;; 32 | -f=*|--filename=*) filename="${1#*=}" ;; 33 | -*) opterr $1 && return 2 ;; 34 | *) positional+=("$@"); break ;; 35 | esac 36 | shift 37 | done 38 | 39 | echo "--verbose: $flag_verbose" 40 | echo "--filename: $filename" 41 | echo "positional: $positional" 42 | } 43 | ``` 44 | 45 | ## With zparseopts 46 | 47 | ```zsh 48 | # zparseopts 49 | # 50 | # Resources: 51 | # - https://xpmo.gitlab.io/post/using-zparseopts/ 52 | # - https://zsh.sourceforge.io/Doc/Release/Zsh-Modules.html#index-zparseopts 53 | # 54 | # Features: 55 | # - supports short and long flags (ie: -v|--verbose) 56 | # - supports short and long key/value options (ie: -f | --filename ) 57 | # - does NOT support short and long key/value options with equals assignment (ie: -f= | --filename=) 58 | # - supports short option chaining (ie: -vh) 59 | # - everything after -- is positional even if it looks like an option (ie: -f) 60 | # - once we hit an arg that isn't an option flag, everything after that is considered positional 61 | function zparseopts_demo() { 62 | local flag_help flag_verbose 63 | local arg_filename=(myfile) # set a default 64 | local usage=( 65 | "zparseopts_demo [-h|--help]" 66 | "zparseopts_demo [-v|--verbose] [-f|--filename=] []" 67 | ) 68 | 69 | # -D pulls parsed flags out of $@ 70 | # -E allows flags/args and positionals to be mixed, which we don't want in this example 71 | # -F says fail if we find a flag that wasn't defined 72 | # -M allows us to map option aliases (ie: h=flag_help -help=h) 73 | # -K allows us to set default values without zparseopts overwriting them 74 | # Remember that the first dash is automatically handled, so long options are -opt, not --opt 75 | zmodload zsh/zutil 76 | zparseopts -D -F -K -- \ 77 | {h,-help}=flag_help \ 78 | {v,-verbose}=flag_verbose \ 79 | {f,-filename}:=arg_filename || 80 | return 1 81 | 82 | [[ -z "$flag_help" ]] || { print -l $usage && return } 83 | if (( $#flag_verbose )); then 84 | print "verbose mode" 85 | fi 86 | 87 | echo "--verbose: $flag_verbose" 88 | echo "--filename: $arg_filename[-1]" 89 | echo "positional: $@" 90 | } 91 | ``` 92 | 93 | ## Here are some examples of the manual parsing function in action... 94 | 95 | Call with no args 96 | 97 | ```zsh 98 | $ optparsing_demo 99 | --verbose: false 100 | --filename: myfile 101 | positional: 102 | ``` 103 | 104 | Call with both short and long options, as well as positional args 105 | 106 | ```zsh 107 | $ optparsing_demo --verbose -f test.txt foo 108 | --verbose: true 109 | --filename: test.txt 110 | positional: foo 111 | ``` 112 | 113 | Call with -- to pass positionals that look like flags 114 | 115 | ```zsh 116 | $ optparsing_demo --filename=test.txt -- -v --verbose -f --filename are acceptable options 117 | --verbose: false 118 | --filename: test.txt 119 | positional: -v --verbose -f --filename are acceptable options 120 | ``` 121 | 122 | Called incorrectly with positionals before intended opts 123 | 124 | ```zsh 125 | $ optparsing_demo do not put positionals before opts --verbose --filename=mynewfile 126 | --verbose: false 127 | --filename: myfile 128 | positional: do not put positionals before opts --verbose --filename=mynewfile 129 | ``` 130 | 131 | This method of opt parsing does not support flag chaining like getopt does 132 | 133 | ```zsh 134 | $ optparsing_demo -vh 135 | optparsing_demo: Unknown option '-vh' 136 | ``` 137 | 138 | --- 139 | 140 | ## Here are some examples of the zparseopt version in action... 141 | 142 | Call with no args 143 | 144 | ```zsh 145 | $ zparseopts_demo 146 | --verbose: 147 | --filename: myfile 148 | positional: 149 | ``` 150 | 151 | Call with both short and long options, as well as positional args 152 | 153 | ```zsh 154 | $ zparseopts_demo --verbose -f test.txt foo 155 | --verbose: --verbose 156 | --filename: test.txt 157 | positional: foo 158 | ``` 159 | 160 | Call with -- to pass positionals that look like flags 161 | 162 | ```zsh 163 | $ zparseopts_demo --filename test.txt -- -v --verbose -f --filename are acceptable options 164 | --verbose: 165 | --filename: test.txt 166 | positional: -v --verbose -f --filename are acceptable options 167 | ``` 168 | 169 | Called incorrectly with positionals before intended opts. If you want this, 170 | zparseopts supports it with the -E flag. 171 | 172 | ```zsh 173 | $ zparseopts_demo do not put positionals before opts --verbose --filename=mynewfile 174 | --verbose: 175 | --filename: myfile 176 | positional: do not put positionals before opts --verbose --filename=mynewfile 177 | ``` 178 | 179 | This method of opt parsing does supports flag chaining like getopt does 180 | 181 | ```zsh 182 | $ zparseopts_demo -vh 183 | zparseopts_demo [-h|--help] 184 | zparseopts_demo [-v|--verbose] [-f|--filename=] [] 185 | ``` 186 | -------------------------------------------------------------------------------- /.docs/zsh-setopts.md: -------------------------------------------------------------------------------- 1 | # Zsh Options 2 | 3 | Set options with `setopt`, unset with `unsetopt`. Options can take a `NO_` prefix as 4 | well (eg: `setopt NO_BEEP` is the same as `unsetopt BEEP`). You can view set options via 5 | the `set -o` command. You can see only enabled options with `set -o | grep 'on$'`. 6 | 7 | Asterisk (\*) indicates the option is on by default for native zsh. 8 | 9 | ## Changing Directories 10 | 11 | [16.2.1 Changing Directories][16.2.1] 12 | 13 | | Option | Short Description | 14 | |-------------------|---------------------------------------------| 15 | | AUTO_CD | If a command is dir name, `cd` to it | 16 | | AUTO_PUSHD | `cd` pushes to directory stack | 17 | | CDABLE_VARS | `cd var` works if `$var` is directory | 18 | | CD_SILENT | Don't print the dir after `cd` | 19 | | CHASE_DOTS | Resolve symlinks when `..` in `cd` | 20 | | CHASE_LINKS | Resolve symlinks in `cd` | 21 | | POSIX_CD | Change behavior of `cd`, `chdir`, & `pushd` | 22 | | PUSHD_IGNORE_DUPS | Don’t push duplicate dirs onto stack | 23 | | PUSHD_MINUS | Reverse meanings of `–` and `+` in `pushd` | 24 | | PUSHD_SILENT | Don't print the dir stack after `pushd` | 25 | | PUSHD_TO_HOME | `pushd` with no argument goes to `~` | 26 | 27 | ## Completion 28 | 29 | [16.2.2 Completion][16.2.2] 30 | 31 | | Option | Short Description | 32 | |----------------------|------------------------------------| 33 | | ALWAYS_LAST_PROMPT\* | Completion lists after prompt | 34 | | ALWAYS_TO_END | On completion go to end of word | 35 | | AUTO_LIST\* | List ambiguous completions | 36 | | AUTO_MENU\* | Menu complete after two tabs | 37 | | AUTO_NAME_DIRS | Variables always can be %~ abbrevs | 38 | | AUTO_PARAM_KEYS\* | Magic completion for parameters | 39 | | AUTO_PARAM_SLASH\* | `$dirname` completes with `/` | 40 | | AUTO_REMOVE_SLASH\* | Trailing `/` in completion removed | 41 | | BASH_AUTO_LIST | List completions on second tab | 42 | | COMPLETE_ALIASES | Completion uses unexpanded aliases | 43 | | COMPLETE_IN_WORD | Completion works inside words | 44 | | GLOB_COMPLETE | Patterns are active in completion | 45 | | HASH_LIST_ALL\* | Store all on first completion | 46 | | LIST_AMBIGUOUS\* | List completions when ambiguous | 47 | | LIST_BEEP\* | Beep on ambiguous completion | 48 | | LIST_PACKED | More compact completion lists | 49 | | LIST_ROWS_FIRST | List completions across | 50 | | LIST_TYPES\* | File types listed in completion | 51 | | MENU_COMPLETE | Cycle through ambiguous matches | 52 | | REC_EXACT | Exact completion matches are used | 53 | 54 | ## Expansion and Globbing 55 | 56 | [16.2.3 Expansion and Globbing][16.2.3] 57 | 58 | | Option | Short Description | 59 | |---------------------|------------------------------------------------| 60 | | BAD_PATTERN\* | Errors on pattern syntax; else literal | 61 | | BARE_GLOB_QUAL\* | Glob qualifiers with bare parens | 62 | | BRACE_CCL | `X{ab}` expands to `Xa` `Xb` | 63 | | CASE_GLOB\* | Make globbing case-sensitive | 64 | | CASE_MATCH | Make regex case-sensitive | 65 | | CASE_PATHS | Make paths case-sensitive | 66 | | CSH_NULL_GLOB | One glob must succeed, failed globs ignored | 67 | | EQUALS\* | Expand `=cmd` to `/path/to/cmd` | 68 | | EXTENDED_GLOB | Expand globbing syntax | 69 | | FORCE_FLOAT | Treat numbers as floats when doing arithmetic | 70 | | GLOB\* | Enable globbing | 71 | | GLOB_ASSIGN | `var=*` expands, assigns array | 72 | | GLOB_DOTS | Patterns may match leading dots | 73 | | GLOB_STAR_SHORT | Allow `**`,`***` shorthand for `**/*`,`***/*` | 74 | | GLOB_SUBST | Substituted characters may glob | 75 | | HIST_SUBST_PATTERN | History modifiers match by pattern, not string | 76 | | IGNORE_BRACES | Don’t use `{a,b}` expansions | 77 | | IGNORE_CLOSE_BRACES | Do not perform brace expansion | 78 | | KSH_GLOB | Globbing matches KornShell | 79 | | MAGIC_EQUAL_SUBST | Special expansion after all `=` | 80 | | MARK_DIRS | Append `/` to globbed directories | 81 | | MULTIBYTE | Respect multibyte characters in strings | 82 | | NOMATCH\* | Error if glob fails to match | 83 | | NULL_GLOB | Failed globs are removed from line | 84 | | NUMERIC_GLOB_SORT | Numbers in globs sorted numerically | 85 | | RC_EXPAND_PARAM | `X$array` gives `Xelt1` `Xelt2` etc. | 86 | | REMATCH_PCRE | Use Perl-compatible regex syntax for `=~` | 87 | | SH_GLOB | Disables non-extended zsh globs | 88 | | UNSET\* | Unset variables OK, treat as empty | 89 | | WARN_CREATE_GLOBAL | Warn when a function makes a global var | 90 | | WARN_NESTED_VAR | Warn when a nested function var violates scope | 91 | 92 | ## History 93 | 94 | [16.2.4 History][16.2.4] 95 | 96 | | Option | Short Description | 97 | |-------------------------|--------------------------------------------------| 98 | | APPEND_HISTORY\* | History appends to existing file | 99 | | BANG_HIST\* | `!` style history allowed | 100 | | EXTENDED_HISTORY | Timestamps saved to history file | 101 | | HIST_ALLOW_CLOBBER | On clobber error, up arrow to retry | 102 | | HIST_BEEP\* | Beep when going beyond history | 103 | | HIST_EXPIRE_DUPS_FIRST | Duplicate history entries lost first | 104 | | HIST_FCNTL_LOCK | Use `fcntl` for histfile locking | 105 | | HIST_FIND_NO_DUPS | History search finds once only | 106 | | HIST_IGNORE_ALL_DUPS | Remove earlier dups and store recent | 107 | | HIST_IGNORE_DUPS | Do not write history if dupe exists | 108 | | HIST_IGNORE_SPACE | Don’t store lines starting with space | 109 | | HIST_LEX_WORDS | Use lexer to detect quoted whitespace | 110 | | HIST_NO_FUNCTIONS | Don’t store shell functions | 111 | | HIST_NO_STORE | Don’t store `history` and `fc` | 112 | | HIST_REDUCE_BLANKS | Trim multiple insignificant blanks | 113 | | HIST_SAVE_BY_COPY\* | histfile is written as copy instead of in situ | 114 | | HIST_SAVE_NO_DUPS | Remove duplicates when saving | 115 | | HIST_VERIFY | Show `!` history line for editing | 116 | | INC_APPEND_HISTORY | Save history line by line | 117 | | INC_APPEND_HISTORY_TIME | Save history after command completes with timing | 118 | | SHARE_HISTORY | Save and restore history per line | 119 | 120 | ## Initialization 121 | 122 | [16.2.5 Initialization][16.2.5] 123 | 124 | | Option | Short Description | 125 | |-----------------|-------------------------------------| 126 | | ALL_EXPORT | Export all variables to environment | 127 | | GLOBAL_EXPORT\* | Exported variables not made local | 128 | | GLOBAL_RCS\* | Execute `/etc/z*` files | 129 | | RCS\* | Run startup files | 130 | 131 | ## I/O 132 | 133 | [16.2.6 Input/Output][16.2.6] 134 | 135 | | Option | Short Description | 136 | |----------------------|------------------------------------------| 137 | | ALIASES\* | Expand aliases | 138 | | CLOBBER\* | Allow redirections to overwrite | 139 | | CORRECT | Correct spelling of commands | 140 | | CORRECT_ALL | Correct spelling of all arguments | 141 | | DVORAK | Dvorak keyboard for correction | 142 | | FLOW_CONTROL\* | Use `^S/^Q` style flow control | 143 | | HASH_CMDS\* | Store command location for speed | 144 | | HASH_DIRS\* | Store for all commands in dir | 145 | | IGNORE_EOF | Ignore `^D` (`stty eof` char) | 146 | | INTERACTIVE_COMMENTS | `#` on interactive line for comment | 147 | | MAIL_WARNING | Warn if mail file timestamp changed | 148 | | PATH_DIRS | `dir/cmd` can be found in `$PATH` | 149 | | PRINT_EIGHT_BIT | Print all 8-bit characters directly | 150 | | PRINT_EXIT_VALUE | Return status printed unless zero | 151 | | RC_QUOTES | `''` inside single quotes gives `'` | 152 | | RM_STAR_SILENT | Don’t warn on `rm *` | 153 | | RM_STAR_WAIT | Wait before asking if `rm *` is OK | 154 | | SHORT_LOOPS\* | `for words; list` works | 155 | | SUN_KEYBOARD_HACK | Unmatched `` ` `` at end of line ignored | 156 | 157 | ## Job Control 158 | 159 | [16.2.7 Job Control][16.2.7] 160 | 161 | | Option | Short Description | 162 | |----------------|------------------------------------| 163 | | AUTO_CONTINUE | Jobs are continued when `disown`ed | 164 | | AUTO_RESUME | `cmd` can resume job `%cmd` | 165 | | BG_NICE\* | Background jobs at lower priority | 166 | | CHECK_JOBS\* | Check jobs before exiting shell | 167 | | HUP\* | Send SIGHUP to proceses on exit | 168 | | LONG_LIST_JOBS | More verbose listing of jobs | 169 | | MONITOR | Shell has job control enabled | 170 | | NOTIFY\* | Asynchronous job control messages | 171 | 172 | ## Prompting 173 | 174 | [16.2.8 Prompting][16.2.8] 175 | 176 | | Option | Short Description | 177 | |-------------------|------------------------------------| 178 | | PROMPT_BANG | Special treatment of `!` in prompt | 179 | | PROMPT_CR\* | Prompt always at start of line | 180 | | PROMPT_PERCENT\* | `%` escapes expanded in prompts | 181 | | PROMPT_SUBST | `$` expansion etc. in prompts | 182 | | TRANSIENT_RPROMPT | Right prompt goes away after edit | 183 | 184 | ## Scripts and Functions 185 | 186 | [16.2.9 Scripts and Functions][16.2.9] 187 | 188 | | Option | Short Description | 189 | |--------------------|---------------------------------------| 190 | | C_BASES | Output hexadecimal with `0x` | 191 | | ERR_EXIT | Exit shell on non-zero status | 192 | | ERR_RETURN | Return from function instead | 193 | | EVAL_LINE_NO\* | `$LINENO` counts inside `eval` code | 194 | | EXEC\* | Execute commands | 195 | | FUNCTION_ARGZER0\* | `$0` in function is its name | 196 | | LOCAL_OPTIONS | Options reset on function return | 197 | | LOCAL_TRAPS | Traps reset on function return | 198 | | MULTIOS\* | Multiple redirections are special | 199 | | OCTAL_ZEROES | Leading zeros in integers force octal | 200 | | TYPESET_SILENT | Silent on `typeset foo` | 201 | | VERBOSE | Output commands to be executed | 202 | | XTRACE | Show trace of execution with `$PS4` | 203 | 204 | ## Shell Emulation 205 | 206 | [16.2.10 Shell Emulation][16.2.10] 207 | 208 | | Option | Short Description | 209 | |--------------------|--------------------------------------| 210 | | BSD_ECHO | No echo escapes unless `-e` given | 211 | | CSH_JUNKIE_HISTORY | Single `!` for previous command | 212 | | CSH_JUNKIE_LOOPS | `list; end` for `do...done` | 213 | | CSH_JUNKIE_QUOTES | No newlines in quotes | 214 | | CSH_NULLCMD | Redirections with no commands fail | 215 | | KSH_ARRAYS | Indexing etc. for arrays like ksh | 216 | | KSH_AUTOLOAD | Function file includes function name | 217 | | KSH_OPTION_PRINT | Show all options plus on or off | 218 | | KSH_TYPESET | No word splitting in`typeset` etc. | 219 | | POSIX_BUILTINS | Illogical command behaviour | 220 | | SH_FILE_EXPANSION | `~` etc. expansion done early | 221 | | SH_NULL_CMD | Commandless redirections like `sh` | 222 | | SH_OPTION_LETTERS | Single letter options are like `sh` | 223 | | SH_WORD_SPLIT | Split non-array variables yuckily | 224 | | TRAPS_ASYNC | Traps may run when `wait`ing | 225 | 226 | ## Shell State 227 | 228 | [16.2.11 Shell State][16.2.11] 229 | 230 | | Option | Short Description | 231 | |----------------|------------------------------------| 232 | | INTERACTIVE | Shell is interactive | 233 | | LOGIN | Shell is login shell | 234 | | PRIVILEGED | Special behaviour on setuid/setgid | 235 | | RESTRICTED | Shell has restricted capabilities | 236 | | SHIN_STDIN | Shell input comes from stdin | 237 | | SINGLE_COMMAND | Execute one command then exit | 238 | 239 | ## ZLE 240 | 241 | [16.2.11 Zle][16.2.12] 242 | 243 | | Option | Short Description | 244 | |-----------------|-------------------------------------------| 245 | | BEEP\* | Beep on errors | 246 | | COMBINING_CHARS | Display diacritics properly | 247 | | EMACS | Use Emacs editing. Prefer `bindkey -e` | 248 | | OVERSTRIKE | Start line editor in overstrike mode | 249 | | SINGLE_LINE_ZLE | Line editing on single line (bad tty) | 250 | | VI | Use vi modal editing. Prefer `bindkey -v` | 251 | | ZLE | Line editor used to input lines | 252 | 253 | 254 | [16.2.1]: https://zsh.sourceforge.io/Doc/Release/Options.html#Changing-Directories 255 | [16.2.2]: https://zsh.sourceforge.io/Doc/Release/Options.html#Completion-4 256 | [16.2.3]: https://zsh.sourceforge.io/Doc/Release/Options.html#Expansion-and-Globbing 257 | [16.2.4]: https://zsh.sourceforge.io/Doc/Release/Options.html#History 258 | [16.2.5]: https://zsh.sourceforge.io/Doc/Release/Options.html#Initialisation 259 | [16.2.6]: https://zsh.sourceforge.io/Doc/Release/Options.html#Input_002fOutput 260 | [16.2.7]: https://zsh.sourceforge.io/Doc/Release/Options.html#Job-Control 261 | [16.2.8]: https://zsh.sourceforge.io/Doc/Release/Options.html#Prompting 262 | [16.2.9]: https://zsh.sourceforge.io/Doc/Release/Options.html#Scripts-and-Functions 263 | [16.2.10]: https://zsh.sourceforge.io/Doc/Release/Options.html#Shell-Emulation 264 | [16.2.11]: https://zsh.sourceforge.io/Doc/Release/Options.html#Shell-State 265 | [16.2.12]: https://zsh.sourceforge.io/Doc/Release/Options.html#Zle 266 | -------------------------------------------------------------------------------- /.docs/zsh-string.md: -------------------------------------------------------------------------------- 1 | # zsh-strings 2 | 3 | Fish has a utility for [string maniplulation][string]. 4 | 5 | This is how you can do the same things with vanilla Zsh. 6 | 7 | References: 8 | - [Zsh regex][3] 9 | - [String modifiers][1] 10 | - [String expansion][2] 11 | 12 | ## Length 13 | 14 | Get the length of a string with `#`. 15 | This is similar to `string length` in [fish][length]. 16 | 17 | ```zsh 18 | $ str="abcdefghijklmnopqrstuvwxyz" 19 | $ echo ${#str} 20 | 26 21 | ``` 22 | 23 | ## Pad/Trim 24 | 25 | Left pad a string with the [l expansion flag][2]. 26 | Right pad a string with the [r expansion flag][2]. 27 | This is similar to `string pad` in [fish][pad]. 28 | 29 | ```zsh 30 | $ str="abc" 31 | $ echo ${(l(10)(-))str} 32 | -------abc 33 | $ echo ${(r(10)(ABC))str} 34 | abcABCABCA 35 | ``` 36 | 37 | The docs can be confusing. They show the syntax as `l:expr::string1::string2:`, which 38 | uses colons instead of the more readable parens. Don't be confused by the double colon, 39 | which is really just the closing/opening combo `)(`. If you choose to follow the docs, 40 | the syntax looks like this: 41 | 42 | ```zsh 43 | $ str="abc" 44 | $ echo ${(r:10::-:)str} 45 | abc------- 46 | ``` 47 | 48 | Trim requires the use of `sed`. This is similar to `string trim` in [fish][trim]. 49 | 50 | ```zsh 51 | $ str=" \t\t\t abc \t\t\t " 52 | $ echo "$str" | sed -e 's/^[[:space:]]*//' -e 's/[[:space:]]*$//' 53 | abc 54 | ``` 55 | 56 | ## Substring 57 | 58 | Get a substing from string with comma indexing `[start,end]`. 59 | This is similar to `string sub` in [fish][sub]. 60 | 61 | ```zsh 62 | $ str="abcdefghijklmnopqrstuvwxyz" 63 | $ echo ${str[3,6]} 64 | cdef 65 | ``` 66 | 67 | You can also use the `${var:offset:length}` syntax: 68 | 69 | ```zsh 70 | $ str="abcdefghijklmnopqrstuvwxyz" 71 | $ echo ${str:3:6} 72 | defghi 73 | $ echo ${str:(-4)} 74 | wxyz 75 | ``` 76 | 77 | ## Repeat 78 | 79 | Repeat a string by using `printf`. 80 | This is similar to `string repeat` in [fish][repeat]. 81 | 82 | ```zsh 83 | $ str="abc" 84 | $ abc3=$(printf "$str%.0s" {1..3}) 85 | $ echo $abc3 86 | abcabcabc 87 | ``` 88 | 89 | ## Escape/Unescape 90 | 91 | Escape (quote) strings with the [q modifier][1]. 92 | This is similar to `string escape` in [fish][escape]. 93 | 94 | ```zsh 95 | $ str="3 tabs \t\t\t." 96 | $ echo "${str:q}" 97 | 3\ tabs\ \t\t\t. 98 | ``` 99 | 100 | Unescape (unquote) strings with the [Q modifier][1]. 101 | This is similar to `string unescape` in [fish][unescape]. 102 | 103 | ```zsh 104 | $ str="3 backticks \`\`\`." 105 | $ esc="${str:q}" 106 | $ echo $esc 107 | 3\ backticks\ \`\`\`. 108 | $ echo "${esc:Q}" 109 | 3 backticks ```. 110 | ``` 111 | 112 | ## Join/Split 113 | 114 | Join strings with the [j expansion flag][2]. 115 | This is similar to `string join` in [fish][join]. 116 | 117 | ```zsh 118 | $ words=(abc def ghi) 119 | $ sep=: 120 | $ echo ${(pj.$sep.)words} 121 | abc:def:ghi 122 | ``` 123 | 124 | A common join seperator is the null character. 125 | This is similar to `string join0` in [fish][join0]. 126 | 127 | ```zsh 128 | $ words=(abc def ghi) 129 | $ sep="\x00" 130 | $ echo ${${(pj.$sep.)words}:q} 131 | abc\x00def\x00ghi 132 | ``` 133 | 134 | Split strings with the [s expansion flag][2]. 135 | This is similar to `string split` in [fish][split]. 136 | 137 | - `@`: Preserves empty elements. _"In double quotes, array elements are put into separate words"_. 138 | - `p`: Use print syntax. _"Recognize the same escape sequences as the print."_ 139 | - `s`: Split. _"Force field splitting at the separator string."_ 140 | 141 | ```zsh 142 | $ str="a:b::c" 143 | $ sep=: 144 | $ printf '%s\n' "${(@ps.$sep.)str}" 145 | a 146 | b 147 | 148 | c 149 | ``` 150 | 151 | A common split seperator is the null character. 152 | This is similar to `string split0` in [fish][split0]. 153 | 154 | ```zsh 155 | $ str="abc\x00def\x00ghi" 156 | $ sep="\x00" 157 | $ arr=(${(ps.$sep.)str}) 158 | $ printf '%s\n' $arr 159 | abc 160 | def 161 | ghi 162 | ``` 163 | 164 | ## Upper/Lower 165 | 166 | Convert a string to uppercase with the [u modifier][1]. 167 | This is similar to `string upper` in [fish][upper]. 168 | 169 | ```zsh 170 | $ str="AbCdEfGhIjKlMnOpQrStUvWxYz" 171 | $ echo "${str:u}" 172 | ABCDEFGHIJKLMNOPQRSTUVWXYZ 173 | ``` 174 | 175 | Convert a string to lowercase with the [l modifier][1]. 176 | This is similar to `string lower` in [fish][lower]. 177 | 178 | ```zsh 179 | $ str="AbCdEfGhIjKlMnOpQrStUvWxYz" 180 | $ echo "${str:l}" 181 | abcdefghijklmnopqrstuvwxyz 182 | ``` 183 | 184 | ## Match/Replace 185 | 186 | ```zsh 187 | str="The following are zip codes: 78884 90210 99513" 188 | setopt REMATCH_PCRE 189 | if [[ $str =~ '\d{5}' ]]; then 190 | echo "contains zip codes" 191 | else 192 | echo "no zip codes found" 193 | fi 194 | ``` 195 | 196 | ```zsh 197 | str="https://gist.github.com/mattmc3/110eca74a876154c842423471b8e5cbb" 198 | zmodload zsh/pcre 199 | pattern='^(ftp|https?)://' 200 | pcre_compile -smx $pattern 201 | pcre_match -b -- $str 202 | if [[ $? -ne 0 ]]; then 203 | echo "no match..." 204 | else 205 | echo "match found. (match: $MATCH, position: $ZPCRE_OP)" 206 | fi 207 | ``` 208 | 209 | ## TODO 210 | 211 | Collect, replace, trim. 212 | 213 | [1]: https://zsh.sourceforge.io/Doc/Release/Expansion.html#Modifiers 214 | [2]: https://zsh.sourceforge.io/Doc/Release/Expansion.html#Parameter-Expansion-Flags 215 | [3]: https://zsh.sourceforge.io/Doc/Release/Zsh-Modules.html#The-zsh_002fpcre-Module 216 | [collect]: https://fishshell.com/docs/current/cmds/string-collect.html 217 | [escape]: https://fishshell.com/docs/current/cmds/string-escape.html 218 | [join]: https://fishshell.com/docs/current/cmds/string-join.html 219 | [join0]: https://fishshell.com/docs/current/cmds/string-join0.html 220 | [length]: https://fishshell.com/docs/current/cmds/string-length.html 221 | [lower]: https://fishshell.com/docs/current/cmds/string-lower.html 222 | [match]: https://fishshell.com/docs/current/cmds/string-match.html 223 | [pad]: https://fishshell.com/docs/current/cmds/string-pad.html 224 | [repeat]: https://fishshell.com/docs/current/cmds/string-repeat.html 225 | [replace]: https://fishshell.com/docs/current/cmds/string-replace.html 226 | [split]: https://fishshell.com/docs/current/cmds/string-split.html 227 | [split0]: https://fishshell.com/docs/current/cmds/string-split0.html 228 | [string]: https://fishshell.com/docs/current/cmds/string.html 229 | [sub]: https://fishshell.com/docs/current/cmds/string-sub.html 230 | [trim]: https://fishshell.com/docs/current/cmds/string-trim.html 231 | [unescape]: https://fishshell.com/docs/current/cmds/string-unescape.html 232 | [upper]: https://fishshell.com/docs/current/cmds/string-upper.html 233 | -------------------------------------------------------------------------------- /.editorconfig: -------------------------------------------------------------------------------- 1 | root = true 2 | 3 | [*] 4 | charset = utf-8 5 | end_of_line = lf 6 | insert_final_newline = true 7 | trim_trailing_whitespace = true 8 | indent_style = space 9 | indent_size = 2 10 | 11 | [*.md] 12 | trim_trailing_whitespace = false 13 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | .antidote 2 | .antidote/ 3 | .cache/ 4 | .external/ 5 | .plugins/ 6 | .unplugged/ 7 | .zcompcache/ 8 | .zcompdump* 9 | .zdirs 10 | .zhistory 11 | .zplugins/ 12 | .zplugins/ 13 | .zsh_history 14 | .zsh_plugins.zsh 15 | .zsh_sessions/ 16 | *.cache 17 | *.bak 18 | *.local 19 | *.local.zsh 20 | *.zwc 21 | *.zwc.old 22 | .zplugins.zsh 23 | ~* 24 | .zephyr/ 25 | .zlocal 26 | .kickstart/ 27 | -------------------------------------------------------------------------------- /.zaliases: -------------------------------------------------------------------------------- 1 | # 2 | # aliases - Zsh and bash aliases 3 | # 4 | 5 | # References 6 | # - https://medium.com/@webprolific/getting-started-with-dotfiles-43c3602fd789#.vh7hhm6th 7 | # - https://github.com/webpro/dotfiles/blob/master/system/.alias 8 | # - https://github.com/mathiasbynens/dotfiles/blob/master/.aliases 9 | # - https://github.com/ohmyzsh/ohmyzsh/blob/master/plugins/common-aliases/common-aliases.plugin.zsh 10 | # 11 | 12 | # single character shortcuts - be sparing! 13 | alias _=sudo 14 | alias l=ls 15 | alias g=git 16 | 17 | # mask built-ins with better defaults 18 | alias ping='ping -c 5' 19 | alias vi=vim 20 | alias nv=nvim 21 | alias grep="${aliases[grep]:-grep} --exclude-dir={.git,.vscode}" 22 | 23 | # directories 24 | alias secrets="cd ${XDG_DATA_HOME:-~/.local/share}/secrets" 25 | 26 | # more ways to ls 27 | alias ll='ls -lh' 28 | alias la='ls -lAh' 29 | alias lsa="ls -aG" 30 | alias ldot='ls -ld .*' 31 | 32 | # fix typos 33 | alias get=git 34 | alias quit='exit' 35 | alias cd..='cd ..' 36 | alias zz='exit' 37 | 38 | # tar 39 | alias tarls="tar -tvf" 40 | alias untar="tar -xf" 41 | 42 | # date/time 43 | alias timestamp="date '+%Y-%m-%d %H:%M:%S'" 44 | alias datestamp="date '+%Y-%m-%d'" 45 | alias isodate="date +%Y-%m-%dT%H:%M:%S%z" 46 | alias utc="date -u +%Y-%m-%dT%H:%M:%SZ" 47 | alias unixepoch="date +%s" 48 | 49 | # find 50 | alias fd='find . -type d -name' 51 | alias ff='find . -type f -name' 52 | 53 | # homebrew 54 | #alias brewup="brew update && brew upgrade && brew cleanup" 55 | #alias brewinfo="brew leaves | xargs brew desc --eval-all" 56 | 57 | # disk usage 58 | alias biggest='du -s ./* | sort -nr | awk '\''{print $2}'\'' | xargs du -sh' 59 | alias dux='du -x --max-depth=1 | sort -n' 60 | alias dud='du -d 1 -h' 61 | alias duf='du -sh *' 62 | 63 | # url encode/decode 64 | alias urldecode='python3 -c "import sys, urllib.parse as ul; \ 65 | print(ul.unquote_plus(sys.argv[1]))"' 66 | alias urlencode='python3 -c "import sys, urllib.parse as ul; \ 67 | print (ul.quote_plus(sys.argv[1]))"' 68 | 69 | # misc 70 | alias please=sudo 71 | alias zshrc='${EDITOR:-vim} "${ZDOTDIR:-$HOME}"/.zshrc' 72 | alias zbench='for i in {1..10}; do /usr/bin/time zsh -lic exit; done' 73 | alias cls="clear && printf '\e[3J'" 74 | 75 | # print things 76 | alias print-fpath='for fp in $fpath; do echo $fp; done; unset fp' 77 | alias print-path='echo $PATH | tr ":" "\n"' 78 | alias print-functions='print -l ${(k)functions[(I)[^_]*]} | sort' 79 | 80 | # auto-orient images based on exif tags 81 | alias autorotate="jhead -autorot" 82 | 83 | # dotfiles 84 | : ${DOTFILES:=$HOME/.dotfiles} 85 | alias dotf='cd "$DOTFILES"' 86 | alias dotfed='cd "$DOTFILES" && ${VISUAL:-${EDITOR:-vim}} .' 87 | alias dotfl="cd \$DOTFILES/local" 88 | alias fdot='cd ${XDG_CONFIG_HOME:-~/.config}/fish' 89 | alias fconf=fdot 90 | alias zdot='cd $ZDOTDIR' 91 | 92 | # java 93 | alias setjavahome="export JAVA_HOME=\`/usr/libexec/java_home\`" 94 | 95 | # todo-txt 96 | alias t="todo.sh" 97 | alias todos="$VISUAL $HOME/Desktop/todo.txt" 98 | 99 | # vim: ft=zsh sw=2 ts=2 et 100 | -------------------------------------------------------------------------------- /.zplugins: -------------------------------------------------------------------------------- 1 | # 2 | # .zplugins.txt - antidote plugins file 3 | # 4 | 5 | # 6 | # Init 7 | # 8 | 9 | $ZSH_CUSTOM/plugins/p10k-instaprompt conditional:is-theme-p10k 10 | $ZSH_CUSTOM/plugins/starship-ftl conditional:is-theme-starship 11 | mattmc3/zephyr path:plugins/environment 12 | mattmc3/zephyr path:plugins/homebrew 13 | $ZSH_CUSTOM/plugins/xdg 14 | 15 | # 16 | # Completions 17 | # 18 | 19 | mattmc3/ez-compinit 20 | zsh-users/zsh-completions kind:fpath path:src 21 | 22 | # 23 | # Prompts 24 | # 25 | 26 | mattmc3/zephyr path:plugins/prompt 27 | $ZDOTDIR/themes kind:fpath 28 | romkatv/powerlevel10k kind:fpath 29 | # sindresorhus/pure kind:fpath 30 | # miekg/lean kind:fpath 31 | 32 | # 33 | # Custom 34 | # 35 | 36 | $ZSH_CUSTOM/plugins/git 37 | $ZSH_CUSTOM/plugins/golang 38 | $ZSH_CUSTOM/plugins/otp 39 | $ZSH_CUSTOM/plugins/python 40 | 41 | # 42 | # Utils 43 | # 44 | 45 | mattmc3/zephyr path:plugins/color 46 | mattmc3/zephyr path:plugins/directory 47 | mattmc3/zephyr path:plugins/history 48 | mattmc3/zephyr path:plugins/utility 49 | romkatv/zsh-bench kind:path 50 | ohmyzsh/ohmyzsh path:plugins/extract 51 | mattmc3/zman 52 | 53 | # 54 | # Editor 55 | # 56 | 57 | mattmc3/zephyr path:plugins/editor 58 | jeffreytse/zsh-vi-mode 59 | romkatv/zsh-no-ps2 60 | 61 | # 62 | # macOS 63 | # 64 | 65 | mattmc3/zephyr path:plugins/macos conditional:is-macos 66 | ohmyzsh/ohmyzsh path:plugins/iterm2 conditional:is-macos 67 | 68 | # 69 | # Fish-like 70 | # 71 | 72 | mattmc3/zephyr path:plugins/zfunctions 73 | mattmc3/zephyr path:plugins/confd 74 | #zdharma-continuum/fast-syntax-highlighting 75 | zsh-users/zsh-syntax-highlighting 76 | zsh-users/zsh-autosuggestions post:post-autosuggestions 77 | zsh-users/zsh-history-substring-search post:post-history-substring-search 78 | 79 | # vi: ft=properties 80 | -------------------------------------------------------------------------------- /.zshenv: -------------------------------------------------------------------------------- 1 | #!/bin/zsh 2 | # 3 | # .zshenv: Zsh environment file, loaded always. 4 | # 5 | 6 | export ZDOTDIR=${ZDOTDIR:-$HOME/.config/zsh} 7 | 8 | # XDG 9 | export XDG_CONFIG_HOME=${XDG_CONFIG_HOME:-$HOME/.config} 10 | export XDG_CACHE_HOME=${XDG_CACHE_HOME:-$HOME/.cache} 11 | export XDG_DATA_HOME=${XDG_DATA_HOME:-$HOME/.local/share} 12 | export XDG_STATE_HOME=${XDG_STATE_HOME:-$HOME/.local/state} 13 | export XDG_RUNTIME_DIR=${XDG_RUNTIME_DIR:-$HOME/.xdg} 14 | export XDG_PROJECTS_DIR=${XDG_PROJECTS_DIR:-$HOME/Projects} 15 | 16 | # Fish-like dirs 17 | : ${__zsh_config_dir:=${ZDOTDIR:-${XDG_CONFIG_HOME:-$HOME/.config}/zsh}} 18 | : ${__zsh_user_data_dir:=${XDG_DATA_HOME:-$HOME/.local/share}/zsh} 19 | : ${__zsh_cache_dir:=${XDG_CACHE_HOME:-$HOME/.cache}/zsh} 20 | 21 | # Ensure Zsh directories exist. 22 | () { 23 | local zdir 24 | for zdir in $@; do 25 | [[ -d "${(P)zdir}" ]] || mkdir -p -- "${(P)zdir}" 26 | done 27 | } __zsh_{config,user_data,cache}_dir XDG_{CONFIG,CACHE,DATA,STATE}_HOME XDG_{RUNTIME,PROJECTS}_DIR 28 | 29 | # Make Terminal.app behave. 30 | if [[ "$OSTYPE" == darwin* ]]; then 31 | export SHELL_SESSIONS_DISABLE=1 32 | fi 33 | -------------------------------------------------------------------------------- /.zshrc: -------------------------------------------------------------------------------- 1 | #!/bin/zsh 2 | # 3 | # .zshrc - Run on interactive Zsh session. 4 | # 5 | 6 | # 7 | # Profiling 8 | # 9 | 10 | [[ "$ZPROFRC" -ne 1 ]] || zmodload zsh/zprof 11 | alias zprofrc="ZPROFRC=1 zsh" 12 | 13 | # 14 | # Zstyles 15 | # 16 | 17 | # Load .zstyles file with customizations. 18 | [[ -r ${ZDOTDIR:-$HOME}/.zstyles ]] && source ${ZDOTDIR:-$HOME}/.zstyles 19 | 20 | # 21 | # Theme 22 | # 23 | 24 | # Set prompt theme 25 | typeset -ga ZSH_THEME 26 | zstyle -a ':zephyr:plugin:prompt' theme ZSH_THEME || 27 | ZSH_THEME=(p10k mmc) 28 | 29 | # Set helpers for antidote. 30 | is-theme-p10k() { [[ "$ZSH_THEME" == (p10k|powerlevel10k)* ]] } 31 | is-theme-starship() { [[ "$ZSH_THEME" == starship* ]] } 32 | 33 | # 34 | # Libs 35 | # 36 | 37 | # Load things from lib. 38 | for zlib in $ZDOTDIR/lib/*.zsh; source $zlib 39 | unset zlib 40 | 41 | # 42 | # Aliases 43 | # 44 | 45 | [[ -r ${ZDOTDIR:-$HOME}/.zaliases ]] && source ${ZDOTDIR:-$HOME}/.zaliases 46 | 47 | # 48 | # Completions 49 | # 50 | 51 | # Uncomment to manually initialize completion system, or let Zephyr 52 | # do it automatically in the zshrc-post hook. 53 | # ZSH_COMPDUMP=${XDG_CACHE_HOME:-$HOME/.cache}/zsh/compdump 54 | # [[ -d $ZSH_COMPDUMP:h ]] || mkdir -p $ZSH_COMPDUMP:h 55 | # autoload -Uz compinit && compinit -i -d $ZSH_COMPDUMP 56 | 57 | # 58 | # Prompt 59 | # 60 | 61 | # Uncomment to manually set your prompt, or let Zephyr do it automatically in the 62 | # zshrc-post hook. Note that some prompts like powerlevel10k may not work well 63 | # with post_zshrc. 64 | setopt prompt_subst transient_rprompt 65 | autoload -Uz promptinit && promptinit 66 | prompt "$ZSH_THEME[@]" 67 | 68 | # 69 | # Wrap up 70 | # 71 | 72 | # Never start in the root file system. Looking at you, Zed. 73 | [[ "$PWD" != "/" ]] || cd 74 | 75 | # Manually call post_zshrc to bypass the hook 76 | (( $+functions[run_post_zshrc] )) && run_post_zshrc 77 | 78 | # Finish profiling by calling zprof. 79 | [[ "$ZPROFRC" -eq 1 ]] && zprof 80 | [[ -v ZPROFRC ]] && unset ZPROFRC 81 | 82 | # Always return success 83 | true 84 | -------------------------------------------------------------------------------- /.zstyles: -------------------------------------------------------------------------------- 1 | #!/bin/zsh 2 | # 3 | # .zstyles - zstyle settings for features/plugins that need them. 4 | # 5 | 6 | # 7 | # Antidote 8 | # 9 | 10 | : ${ANTIDOTE_HOME:=${XDG_CACHE_HOME:-~/.cache}/repos} 11 | 12 | # Keep all 3 for different test scenarios. 13 | antidote_repo=$ANTIDOTE_HOME/mattmc3/antidote 14 | # antidote_repo=~/Projects/mattmc3/antidote 15 | # antidote_repo=${HOMEBREW_PREFIX:-/opt/homebrew}/opt/antidote/share/antidote 16 | 17 | zstyle ':antidote:home' path $ANTIDOTE_HOME 18 | zstyle ':antidote:repo' path $antidote_repo 19 | zstyle ':antidote:bundle' use-friendly-names 'yes' 20 | zstyle ':antidote:plugin:*' defer-options '-p' 21 | zstyle ':antidote:*' zcompile 'yes' 22 | 23 | # 24 | # Zephyr features 25 | # 26 | 27 | # Use caching. 28 | zstyle ':zephyr:plugin:*' 'use-cache' yes 29 | 30 | # 31 | # Editor 32 | # 33 | 34 | # Set the key mapping style to 'emacs' or 'vi'. 35 | zstyle ':zephyr:plugin:editor' key-bindings 'vi' 36 | 37 | # Auto convert .... to ../.. 38 | zstyle ':zephyr:plugin:editor' dot-expansion 'yes' 39 | 40 | # Use ^z to return background processes to foreground. 41 | zstyle ':zephyr:plugin:editor' symmetric-ctrl-z 'yes' 42 | 43 | # Expand aliases to their actual command like Fish abbreviations. 44 | zstyle ':zephyr:plugin:editor' glob-alias 'yes' 45 | noexpand=( 46 | ls 47 | grep 48 | gpg 49 | vi 50 | z 51 | 0 1 2 3 4 5 6 7 8 9 52 | ) 53 | zstyle ':zephyr:plugin:editor:glob-alias' noexpand $noexpand 54 | 55 | # Set the default (magic) command when hitting enter on an empty prompt. 56 | zstyle ':zephyr:plugin:editor' magic-enter 'yes' 57 | # zstyle ':zephyr:plugin:editor:magic-enter' command 'ls -lh .' 58 | # zstyle ':zephyr:plugin:editor:magic-enter' git-command 'git status -u .' 59 | 60 | # Editor style 61 | zstyle -s ':zephyr:plugin:editor' key-bindings 'vi' 62 | 63 | # From compinit docs: 64 | # To avoid these tests and make all files found be used without asking, use the 65 | # option -u, and to make compinit silently ignore all insecure files and directories 66 | # use the option -i. This security check is skipped entirely when the -C option is 67 | # given, provided the dumpfile exists. 68 | zstyle ':zephyr:plugin:completion' 'disable-compfix' yes 69 | zstyle ':zephyr:plugin:completion' compstyle 'zephyr' 70 | 71 | # 72 | # Prompt 73 | # 74 | 75 | # Set prompt 76 | zstyle ':zephyr:plugin:prompt' theme p10k mmc 77 | 78 | # 79 | # Completions 80 | # 81 | 82 | zstyle ':plugin:ez-compinit' 'compstyle' 'zshzoo' 83 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2019-2025 mattmc3 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # zdotdir 2 | 3 | My `$ZDOTDIR` [dotfiles] directory, which contains my zsh configuration. 4 | 5 | ## My Terminal 6 | 7 | ![My Terminal][zdotdir_gif] 8 | 9 | ## My setup 10 | 11 | I like my Zsh to behave like [Fish][fish], so there's a lot of features that will be very familiar to other Fish users. 12 | 13 | - A functions directory for my custom functions 14 | - A completions directory for my custom functions 15 | - A conf.d directory so that .zshrc isn't a cluttered mess 16 | - A plugins directory similar to [oh-my-zsh] for adding/removing shell features 17 | 18 | ## Installation 19 | 20 | Since this is my personal `$ZDOTDIR`, this installation procedure is mostly for my personal use. 21 | 22 | It's a good idea to backup existing files first: 23 | 24 | ```zsh 25 | setopt extended_glob 26 | zfiles=( 27 | ${ZDOTDIR:-~}/.zsh*(.N) 28 | ${ZDOTDIR:-~}/.zlog*(.N) 29 | ${ZDOTDIR:-~}/.zprofile(.N) 30 | ) 31 | mkdir -p ~/.bak 32 | for zfile in $zfiles; do 33 | cp $zfile ~/.bak 34 | done 35 | unset zfile zfiles 36 | ``` 37 | 38 | Install this dotfiles repo to your `$ZDOTDIR`: 39 | 40 | ```zsh 41 | # set the amazing ZDOTDIR variable 42 | export ZDOTDIR=~/.config/zsh 43 | 44 | # clone this repo 45 | git clone --recursive git@github.com:mattmc3/zdotdir.git $ZDOTDIR 46 | 47 | # change the root .zshenv file to use ZDOTDIR 48 | cat << 'EOF' >| ~/.zshenv 49 | export ZDOTDIR=~/.config/zsh 50 | [[ -f $ZDOTDIR/.zshenv ]] && . $ZDOTDIR/.zshenv 51 | EOF 52 | 53 | # load zsh 54 | zsh 55 | ``` 56 | 57 | ## Performance 58 | 59 | A snappy shell is very important. I regularly run [zsh-bench](https://github.com/romkatv/zsh-bench) to make sure my shell feels snappy. 60 | 61 | The latest benchmark run shows that we load a new shell pretty fast. 62 | 63 | ```zsh 64 | % # MacBook Air (M3, 2024): starship prompt 65 | % zsh-bench 66 | ==> benchmarking login shell of user matt ... 67 | creates_tty=0 68 | has_compsys=1 69 | has_syntax_highlighting=1 70 | has_autosuggestions=1 71 | has_git_prompt=1 72 | first_prompt_lag_ms=130.800 73 | first_command_lag_ms=139.313 74 | command_lag_ms=126.693 75 | input_lag_ms=11.314 76 | exit_time_ms=65.501 77 | 78 | % # MacBook Air (M3, 2024): p10k prompt 79 | ==> benchmarking login shell of user matt ... 80 | creates_tty=0 81 | has_compsys=1 82 | has_syntax_highlighting=1 83 | has_autosuggestions=1 84 | has_git_prompt=1 85 | first_prompt_lag_ms=13.365 86 | first_command_lag_ms=125.555 87 | command_lag_ms=47.757 88 | input_lag_ms=8.953 89 | exit_time_ms=70.038 90 | ``` 91 | 92 | If you prefer a naive, completely meaningless Zsh 'exit' benchmark, I include that too for legacy reasons. 93 | 94 | ```zsh 95 | % # MacBook Air (M3, 2024) 96 | % for i in {1..10}; do; /usr/bin/time zsh -lic exit; done 97 | 0.09 real 0.03 user 0.02 sys 98 | 0.07 real 0.02 user 0.01 sys 99 | 0.06 real 0.02 user 0.01 sys 100 | 0.07 real 0.02 user 0.01 sys 101 | 0.07 real 0.02 user 0.01 sys 102 | 0.06 real 0.02 user 0.01 sys 103 | 0.07 real 0.02 user 0.01 sys 104 | 0.07 real 0.02 user 0.01 sys 105 | 0.06 real 0.02 user 0.01 sys 106 | 0.07 real 0.02 user 0.01 sys 107 | ``` 108 | 109 | ## Look-and-feel 110 | 111 | ### Fonts 112 | 113 | Install [nerd fonts][nerd-fonts] via homebrew: 114 | 115 | ```zsh 116 | brew tap homebrew/cask-fonts 117 | brew install --cask font-meslo-lg-nerd-font 118 | brew install --cask font-fira-code-nerd-font 119 | brew install --cask font-hack-nerd-font 120 | brew install --cask font-inconsolata-nerd-font 121 | brew install --cask font-sauce-code-pro-nerd-font 122 | ``` 123 | 124 | ### Color schemes 125 | 126 | iTerm2 has some awesome [color schemes][iterm2-colors]. You can use them for more than 127 | just iTerm2. 128 | 129 | I use Space Gray: 130 | 131 |

132 | space gray 133 |

134 | 135 | ## Resources 136 | 137 | - [fish][fish] 138 | - [antidote][antidote] 139 | - [zephyr][zephyr] 140 | - [zshzoo][zshzoo] 141 | - [zsh_unplugged][zsh_unplugged] 142 | - [prezto][prezto] 143 | - [oh-my-zsh][oh-my-zsh] 144 | - [supercharge your terminal with zsh][supercharge-zsh] 145 | - [awesome zsh][awesome-zsh-plugins] 146 | 147 | [antidote]: https://github.com/mattmc3/antidote 148 | [awesome-zsh-plugins]: https://github.com/unixorn/awesome-zsh-plugins 149 | [fish]: https://fishshell.com 150 | [dotfiles]: https://dotfiles.github.io/ 151 | [homebrew]: https://brew.sh 152 | [iterm2-colors]: https://github.com/mbadolato/iTerm2-Color-Schemes 153 | [nerd-fonts]: https://github.com/ryanoasis/nerd-fonts 154 | [oh-my-zsh]: https://github.com/ohmyzsh/ohmyzsh 155 | [prezto]: https://github.com/sorin-ionescu/prezto 156 | [starship-toml]: https://github.com/mattmc3/zdotdir/blob/main/prompt/starship.toml 157 | [starship]: https://starship.rs 158 | [supercharge-zsh]: https://blog.callstack.io/supercharge-your-terminal-with-zsh-8b369d689770 159 | [zdotdir_gif]: https://raw.githubusercontent.com/mattmc3/zdotdir/resources/img/zdotdir.gif 160 | [zephyr]: https://github.com/zshzoo/zephyr 161 | [zsh_unplugged]: https://github.com/mattmc3/zsh_unplugged 162 | [zshzoo]: https://github.com/zshzoo/zshzoo 163 | -------------------------------------------------------------------------------- /completions/_g: -------------------------------------------------------------------------------- 1 | #compdef g=git 2 | 3 | # vim: ft=zsh sw=2 ts=2 et 4 | -------------------------------------------------------------------------------- /completions/_git: -------------------------------------------------------------------------------- 1 | #compdef git gitk 2 | 3 | # zsh completion wrapper for git 4 | # 5 | # Copyright (c) 2012-2020 Felipe Contreras 6 | # 7 | # The recommended way to install this script is to make a copy of it as a 8 | # file named '_git' inside any directory in your fpath. 9 | # 10 | # For example, create a directory '~/.zsh/', copy this file to '~/.zsh/_git', 11 | # and then add the following to your ~/.zshrc file: 12 | # 13 | # fpath=(~/.zsh $fpath) 14 | # 15 | # You need git's bash completion script installed. By default bash-completion's 16 | # location will be used (e.g. pkg-config --variable=completionsdir bash-completion). 17 | # 18 | # If your bash completion script is somewhere else, you can specify the 19 | # location in your ~/.zshrc: 20 | # 21 | # zstyle ':completion:*:*:git:*' script ~/.git-completion.bash 22 | # 23 | 24 | zstyle -T ':completion:*:*:git:*' tag-order && \ 25 | zstyle ':completion:*:*:git:*' tag-order 'common-commands' 26 | 27 | zstyle -s ":completion:*:*:git:*" script script 28 | if [ -z "$script" ]; then 29 | local -a locations 30 | local e bash_completion 31 | 32 | bash_completion=$(pkg-config --variable=completionsdir bash-completion 2>/dev/null) || 33 | bash_completion='/usr/share/bash-completion/completions/' 34 | 35 | locations=( 36 | "$(dirname ${funcsourcetrace[1]%:*})"/git-completion.bash 37 | "$HOME/.local/share/bash-completion/completions/git" 38 | "$bash_completion/git" 39 | '/etc/bash_completion.d/git' # old debian 40 | ) 41 | for e in $locations; do 42 | test -f $e && script="$e" && break 43 | done 44 | fi 45 | 46 | local old_complete="$functions[complete]" 47 | functions[complete]=: 48 | GIT_SOURCING_ZSH_COMPLETION=y . "$script" 49 | functions[complete]="$old_complete" 50 | 51 | __gitcomp () 52 | { 53 | emulate -L zsh 54 | 55 | local cur_="${3-$cur}" 56 | 57 | case "$cur_" in 58 | --*=) 59 | ;; 60 | --no-*) 61 | local c IFS=$' \t\n' 62 | local -a array 63 | for c in ${=1}; do 64 | if [[ $c == "--" ]]; then 65 | continue 66 | fi 67 | c="$c${4-}" 68 | case $c in 69 | --*=|*.) ;; 70 | *) c="$c " ;; 71 | esac 72 | array+=("$c") 73 | done 74 | compset -P '*[=:]' 75 | compadd -Q -S '' -p "${2-}" -a -- array && _ret=0 76 | ;; 77 | *) 78 | local c IFS=$' \t\n' 79 | local -a array 80 | for c in ${=1}; do 81 | if [[ $c == "--" ]]; then 82 | c="--no-...${4-}" 83 | array+=("$c ") 84 | break 85 | fi 86 | c="$c${4-}" 87 | case $c in 88 | --*=|*.) ;; 89 | *) c="$c " ;; 90 | esac 91 | array+=("$c") 92 | done 93 | compset -P '*[=:]' 94 | compadd -Q -S '' -p "${2-}" -a -- array && _ret=0 95 | ;; 96 | esac 97 | } 98 | 99 | __gitcomp_direct () 100 | { 101 | emulate -L zsh 102 | 103 | compset -P '*[=:]' 104 | compadd -Q -S '' -- ${(f)1} && _ret=0 105 | } 106 | 107 | __gitcomp_nl () 108 | { 109 | emulate -L zsh 110 | 111 | compset -P '*[=:]' 112 | compadd -Q -S "${4- }" -p "${2-}" -- ${(f)1} && _ret=0 113 | } 114 | 115 | __gitcomp_file () 116 | { 117 | emulate -L zsh 118 | 119 | compset -P '*[=:]' 120 | compadd -f -p "${2-}" -- ${(f)1} && _ret=0 121 | } 122 | 123 | __gitcomp_direct_append () 124 | { 125 | __gitcomp_direct "$@" 126 | } 127 | 128 | __gitcomp_nl_append () 129 | { 130 | __gitcomp_nl "$@" 131 | } 132 | 133 | __gitcomp_file_direct () 134 | { 135 | __gitcomp_file "$1" "" 136 | } 137 | 138 | _git_zsh () 139 | { 140 | __gitcomp "v1.1" 141 | } 142 | 143 | __git_complete_command () 144 | { 145 | emulate -L zsh 146 | 147 | local command="$1" 148 | local completion_func="_git_${command//-/_}" 149 | if (( $+functions[$completion_func] )); then 150 | emulate ksh -c $completion_func 151 | return 0 152 | else 153 | return 1 154 | fi 155 | } 156 | 157 | __git_zsh_bash_func () 158 | { 159 | emulate -L ksh 160 | 161 | local command=$1 162 | 163 | __git_complete_command "$command" && return 164 | 165 | local expansion=$(__git_aliased_command "$command") 166 | if [ -n "$expansion" ]; then 167 | words[1]=$expansion 168 | __git_complete_command "$expansion" 169 | fi 170 | } 171 | 172 | __git_zsh_cmd_common () 173 | { 174 | local -a list 175 | list=( 176 | add:'add file contents to the index' 177 | bisect:'find by binary search the change that introduced a bug' 178 | branch:'list, create, or delete branches' 179 | checkout:'checkout a branch or paths to the working tree' 180 | clone:'clone a repository into a new directory' 181 | commit:'record changes to the repository' 182 | diff:'show changes between commits, commit and working tree, etc' 183 | fetch:'download objects and refs from another repository' 184 | grep:'print lines matching a pattern' 185 | init:'create an empty Git repository or reinitialize an existing one' 186 | log:'show commit logs' 187 | merge:'join two or more development histories together' 188 | mv:'move or rename a file, a directory, or a symlink' 189 | pull:'fetch from and merge with another repository or a local branch' 190 | push:'update remote refs along with associated objects' 191 | rebase:'forward-port local commits to the updated upstream head' 192 | reset:'reset current HEAD to the specified state' 193 | restore:'restore working tree files' 194 | rm:'remove files from the working tree and from the index' 195 | show:'show various types of objects' 196 | status:'show the working tree status' 197 | switch:'switch branches' 198 | tag:'create, list, delete or verify a tag object signed with GPG') 199 | _describe -t common-commands 'common commands' list && _ret=0 200 | } 201 | 202 | __git_zsh_cmd_alias () 203 | { 204 | local -a list 205 | list=(${${(0)"$(git config -z --get-regexp '^alias\.*')"}#alias.}) 206 | list=(${(f)"$(printf "%s:alias for '%s'\n" ${(f@)list})"}) 207 | _describe -t alias-commands 'aliases' list && _ret=0 208 | } 209 | 210 | __git_zsh_cmd_all () 211 | { 212 | local -a list 213 | emulate ksh -c __git_compute_all_commands 214 | list=( ${=__git_all_commands} ) 215 | _describe -t all-commands 'all commands' list && _ret=0 216 | } 217 | 218 | __git_zsh_main () 219 | { 220 | local curcontext="$curcontext" state state_descr line 221 | typeset -A opt_args 222 | local -a orig_words 223 | 224 | orig_words=( ${words[@]} ) 225 | 226 | _arguments -C \ 227 | '(-p --paginate --no-pager)'{-p,--paginate}'[pipe all output into ''less'']' \ 228 | '(-p --paginate)--no-pager[do not pipe git output into a pager]' \ 229 | '--git-dir=-[set the path to the repository]: :_directories' \ 230 | '--bare[treat the repository as a bare repository]' \ 231 | '(- :)--version[prints the git suite version]' \ 232 | '--exec-path=-[path to where your core git programs are installed]:: :_directories' \ 233 | '--html-path[print the path where git''s HTML documentation is installed]' \ 234 | '--info-path[print the path where the Info files are installed]' \ 235 | '--man-path[print the manpath (see `man(1)`) for the man pages]' \ 236 | '--work-tree=-[set the path to the working tree]: :_directories' \ 237 | '--namespace=-[set the git namespace]' \ 238 | '--no-replace-objects[do not use replacement refs to replace git objects]' \ 239 | '(- :)--help[prints the synopsis and a list of the most commonly used commands]: :->arg' \ 240 | '(-): :->command' \ 241 | '(-)*:: :->arg' && return 242 | 243 | case $state in 244 | (command) 245 | _tags common-commands alias-commands all-commands 246 | while _tags; do 247 | _requested common-commands && __git_zsh_cmd_common 248 | _requested alias-commands && __git_zsh_cmd_alias 249 | _requested all-commands && __git_zsh_cmd_all 250 | let _ret || break 251 | done 252 | ;; 253 | (arg) 254 | local command="${words[1]}" __git_dir __git_cmd_idx=1 255 | 256 | if (( $+opt_args[--bare] )); then 257 | __git_dir='.' 258 | else 259 | __git_dir=${opt_args[--git-dir]} 260 | fi 261 | 262 | (( $+opt_args[--help] )) && command='help' 263 | 264 | words=( ${orig_words[@]} ) 265 | 266 | __git_zsh_bash_func $command 267 | ;; 268 | esac 269 | } 270 | 271 | _git () 272 | { 273 | local _ret=1 274 | local cur cword prev 275 | local __git_repo_path 276 | 277 | cur=${words[CURRENT]} 278 | prev=${words[CURRENT-1]} 279 | let cword=CURRENT-1 280 | 281 | if (( $+functions[__${service}_zsh_main] )); then 282 | __${service}_zsh_main 283 | elif (( $+functions[__${service}_main] )); then 284 | emulate ksh -c __${service}_main 285 | elif (( $+functions[_${service}] )); then 286 | emulate ksh -c _${service} 287 | elif (( $+functions[_${service//-/_}] )); then 288 | emulate ksh -c _${service//-/_} 289 | fi 290 | 291 | let _ret && _default && _ret=0 292 | return _ret 293 | } 294 | 295 | _git 296 | -------------------------------------------------------------------------------- /completions/_starship: -------------------------------------------------------------------------------- 1 | #compdef starship 2 | 3 | autoload -U is-at-least 4 | 5 | _starship() { 6 | typeset -A opt_args 7 | typeset -a _arguments_options 8 | local ret=1 9 | 10 | if is-at-least 5.2; then 11 | _arguments_options=(-s -S -C) 12 | else 13 | _arguments_options=(-s -C) 14 | fi 15 | 16 | local context curcontext="$curcontext" state line 17 | _arguments "${_arguments_options[@]}" : \ 18 | '-h[Print help]' \ 19 | '--help[Print help]' \ 20 | '-V[Print version]' \ 21 | '--version[Print version]' \ 22 | ":: :_starship_commands" \ 23 | "*::: :->starship" \ 24 | && ret=0 25 | case $state in 26 | (starship) 27 | words=($line[1] "${words[@]}") 28 | (( CURRENT += 1 )) 29 | curcontext="${curcontext%:*:*}:starship-command-$line[1]:" 30 | case $line[1] in 31 | (bug-report) 32 | _arguments "${_arguments_options[@]}" : \ 33 | '-h[Print help]' \ 34 | '--help[Print help]' \ 35 | && ret=0 36 | ;; 37 | (completions) 38 | _arguments "${_arguments_options[@]}" : \ 39 | '-h[Print help]' \ 40 | '--help[Print help]' \ 41 | ':shell:(bash elvish fish powershell zsh)' \ 42 | && ret=0 43 | ;; 44 | (config) 45 | _arguments "${_arguments_options[@]}" : \ 46 | '-h[Print help]' \ 47 | '--help[Print help]' \ 48 | '::name -- Configuration key to edit:' \ 49 | '::value -- Value to place into that key:' \ 50 | && ret=0 51 | ;; 52 | (explain) 53 | _arguments "${_arguments_options[@]}" : \ 54 | '-s+[The status code of the previously run command as an unsigned or signed 32bit integer]:STATUS_CODE: ' \ 55 | '--status=[The status code of the previously run command as an unsigned or signed 32bit integer]:STATUS_CODE: ' \ 56 | '*--pipestatus=[Bash, Fish and Zsh support returning codes for each process in a pipeline]:PIPESTATUS: ' \ 57 | '-w+[The width of the current interactive terminal]:TERMINAL_WIDTH: ' \ 58 | '--terminal-width=[The width of the current interactive terminal]:TERMINAL_WIDTH: ' \ 59 | '-p+[The path that the prompt should render for]:PATH:_files' \ 60 | '--path=[The path that the prompt should render for]:PATH:_files' \ 61 | '-P+[The logical path that the prompt should render for. This path should be a virtual/logical representation of the PATH argument]:LOGICAL_PATH:_files' \ 62 | '--logical-path=[The logical path that the prompt should render for. This path should be a virtual/logical representation of the PATH argument]:LOGICAL_PATH:_files' \ 63 | '-d+[The execution duration of the last command, in milliseconds]:CMD_DURATION: ' \ 64 | '--cmd-duration=[The execution duration of the last command, in milliseconds]:CMD_DURATION: ' \ 65 | '-k+[The keymap of fish/zsh/cmd]:KEYMAP: ' \ 66 | '--keymap=[The keymap of fish/zsh/cmd]:KEYMAP: ' \ 67 | '-j+[The number of currently running jobs]:JOBS: ' \ 68 | '--jobs=[The number of currently running jobs]:JOBS: ' \ 69 | '-h[Print help]' \ 70 | '--help[Print help]' \ 71 | && ret=0 72 | ;; 73 | (init) 74 | _arguments "${_arguments_options[@]}" : \ 75 | '--print-full-init[]' \ 76 | '-h[Print help]' \ 77 | '--help[Print help]' \ 78 | ':shell:' \ 79 | && ret=0 80 | ;; 81 | (module) 82 | _arguments "${_arguments_options[@]}" : \ 83 | '-s+[The status code of the previously run command as an unsigned or signed 32bit integer]:STATUS_CODE: ' \ 84 | '--status=[The status code of the previously run command as an unsigned or signed 32bit integer]:STATUS_CODE: ' \ 85 | '*--pipestatus=[Bash, Fish and Zsh support returning codes for each process in a pipeline]:PIPESTATUS: ' \ 86 | '-w+[The width of the current interactive terminal]:TERMINAL_WIDTH: ' \ 87 | '--terminal-width=[The width of the current interactive terminal]:TERMINAL_WIDTH: ' \ 88 | '-p+[The path that the prompt should render for]:PATH:_files' \ 89 | '--path=[The path that the prompt should render for]:PATH:_files' \ 90 | '-P+[The logical path that the prompt should render for. This path should be a virtual/logical representation of the PATH argument]:LOGICAL_PATH:_files' \ 91 | '--logical-path=[The logical path that the prompt should render for. This path should be a virtual/logical representation of the PATH argument]:LOGICAL_PATH:_files' \ 92 | '-d+[The execution duration of the last command, in milliseconds]:CMD_DURATION: ' \ 93 | '--cmd-duration=[The execution duration of the last command, in milliseconds]:CMD_DURATION: ' \ 94 | '-k+[The keymap of fish/zsh/cmd]:KEYMAP: ' \ 95 | '--keymap=[The keymap of fish/zsh/cmd]:KEYMAP: ' \ 96 | '-j+[The number of currently running jobs]:JOBS: ' \ 97 | '--jobs=[The number of currently running jobs]:JOBS: ' \ 98 | '-l[List out all supported modules]' \ 99 | '--list[List out all supported modules]' \ 100 | '-h[Print help]' \ 101 | '--help[Print help]' \ 102 | '::name -- The name of the module to be printed:' \ 103 | && ret=0 104 | ;; 105 | (preset) 106 | _arguments "${_arguments_options[@]}" : \ 107 | '(-l --list)-o+[Output the preset to a file instead of stdout]:OUTPUT:_files' \ 108 | '(-l --list)--output=[Output the preset to a file instead of stdout]:OUTPUT:_files' \ 109 | '-l[List out all preset names]' \ 110 | '--list[List out all preset names]' \ 111 | '-h[Print help]' \ 112 | '--help[Print help]' \ 113 | '::name -- The name of preset to be printed:(bracketed-segments gruvbox-rainbow jetpack nerd-font-symbols no-empty-icons no-nerd-font no-runtime-versions pastel-powerline plain-text-symbols pure-preset tokyo-night)' \ 114 | && ret=0 115 | ;; 116 | (print-config) 117 | _arguments "${_arguments_options[@]}" : \ 118 | '-d[Print the default instead of the computed config]' \ 119 | '--default[Print the default instead of the computed config]' \ 120 | '-h[Print help]' \ 121 | '--help[Print help]' \ 122 | '*::name -- Configuration keys to print:' \ 123 | && ret=0 124 | ;; 125 | (prompt) 126 | _arguments "${_arguments_options[@]}" : \ 127 | '(--right)--profile=[Print the prompt with the specified profile name (instead of the standard left prompt)]:PROFILE: ' \ 128 | '-s+[The status code of the previously run command as an unsigned or signed 32bit integer]:STATUS_CODE: ' \ 129 | '--status=[The status code of the previously run command as an unsigned or signed 32bit integer]:STATUS_CODE: ' \ 130 | '*--pipestatus=[Bash, Fish and Zsh support returning codes for each process in a pipeline]:PIPESTATUS: ' \ 131 | '-w+[The width of the current interactive terminal]:TERMINAL_WIDTH: ' \ 132 | '--terminal-width=[The width of the current interactive terminal]:TERMINAL_WIDTH: ' \ 133 | '-p+[The path that the prompt should render for]:PATH:_files' \ 134 | '--path=[The path that the prompt should render for]:PATH:_files' \ 135 | '-P+[The logical path that the prompt should render for. This path should be a virtual/logical representation of the PATH argument]:LOGICAL_PATH:_files' \ 136 | '--logical-path=[The logical path that the prompt should render for. This path should be a virtual/logical representation of the PATH argument]:LOGICAL_PATH:_files' \ 137 | '-d+[The execution duration of the last command, in milliseconds]:CMD_DURATION: ' \ 138 | '--cmd-duration=[The execution duration of the last command, in milliseconds]:CMD_DURATION: ' \ 139 | '-k+[The keymap of fish/zsh/cmd]:KEYMAP: ' \ 140 | '--keymap=[The keymap of fish/zsh/cmd]:KEYMAP: ' \ 141 | '-j+[The number of currently running jobs]:JOBS: ' \ 142 | '--jobs=[The number of currently running jobs]:JOBS: ' \ 143 | '--right[Print the right prompt (instead of the standard left prompt)]' \ 144 | '(--right --profile)--continuation[Print the continuation prompt (instead of the standard left prompt)]' \ 145 | '-h[Print help]' \ 146 | '--help[Print help]' \ 147 | && ret=0 148 | ;; 149 | (session) 150 | _arguments "${_arguments_options[@]}" : \ 151 | '-h[Print help]' \ 152 | '--help[Print help]' \ 153 | && ret=0 154 | ;; 155 | (time) 156 | _arguments "${_arguments_options[@]}" : \ 157 | '-h[Print help]' \ 158 | '--help[Print help]' \ 159 | && ret=0 160 | ;; 161 | (timings) 162 | _arguments "${_arguments_options[@]}" : \ 163 | '-s+[The status code of the previously run command as an unsigned or signed 32bit integer]:STATUS_CODE: ' \ 164 | '--status=[The status code of the previously run command as an unsigned or signed 32bit integer]:STATUS_CODE: ' \ 165 | '*--pipestatus=[Bash, Fish and Zsh support returning codes for each process in a pipeline]:PIPESTATUS: ' \ 166 | '-w+[The width of the current interactive terminal]:TERMINAL_WIDTH: ' \ 167 | '--terminal-width=[The width of the current interactive terminal]:TERMINAL_WIDTH: ' \ 168 | '-p+[The path that the prompt should render for]:PATH:_files' \ 169 | '--path=[The path that the prompt should render for]:PATH:_files' \ 170 | '-P+[The logical path that the prompt should render for. This path should be a virtual/logical representation of the PATH argument]:LOGICAL_PATH:_files' \ 171 | '--logical-path=[The logical path that the prompt should render for. This path should be a virtual/logical representation of the PATH argument]:LOGICAL_PATH:_files' \ 172 | '-d+[The execution duration of the last command, in milliseconds]:CMD_DURATION: ' \ 173 | '--cmd-duration=[The execution duration of the last command, in milliseconds]:CMD_DURATION: ' \ 174 | '-k+[The keymap of fish/zsh/cmd]:KEYMAP: ' \ 175 | '--keymap=[The keymap of fish/zsh/cmd]:KEYMAP: ' \ 176 | '-j+[The number of currently running jobs]:JOBS: ' \ 177 | '--jobs=[The number of currently running jobs]:JOBS: ' \ 178 | '-h[Print help]' \ 179 | '--help[Print help]' \ 180 | && ret=0 181 | ;; 182 | (toggle) 183 | _arguments "${_arguments_options[@]}" : \ 184 | '-h[Print help]' \ 185 | '--help[Print help]' \ 186 | ':name -- The name of the module to be toggled:' \ 187 | '::value -- The key of the config to be toggled:' \ 188 | && ret=0 189 | ;; 190 | (help) 191 | _arguments "${_arguments_options[@]}" : \ 192 | ":: :_starship__help_commands" \ 193 | "*::: :->help" \ 194 | && ret=0 195 | 196 | case $state in 197 | (help) 198 | words=($line[1] "${words[@]}") 199 | (( CURRENT += 1 )) 200 | curcontext="${curcontext%:*:*}:starship-help-command-$line[1]:" 201 | case $line[1] in 202 | (bug-report) 203 | _arguments "${_arguments_options[@]}" : \ 204 | && ret=0 205 | ;; 206 | (completions) 207 | _arguments "${_arguments_options[@]}" : \ 208 | && ret=0 209 | ;; 210 | (config) 211 | _arguments "${_arguments_options[@]}" : \ 212 | && ret=0 213 | ;; 214 | (explain) 215 | _arguments "${_arguments_options[@]}" : \ 216 | && ret=0 217 | ;; 218 | (init) 219 | _arguments "${_arguments_options[@]}" : \ 220 | && ret=0 221 | ;; 222 | (module) 223 | _arguments "${_arguments_options[@]}" : \ 224 | && ret=0 225 | ;; 226 | (preset) 227 | _arguments "${_arguments_options[@]}" : \ 228 | && ret=0 229 | ;; 230 | (print-config) 231 | _arguments "${_arguments_options[@]}" : \ 232 | && ret=0 233 | ;; 234 | (prompt) 235 | _arguments "${_arguments_options[@]}" : \ 236 | && ret=0 237 | ;; 238 | (session) 239 | _arguments "${_arguments_options[@]}" : \ 240 | && ret=0 241 | ;; 242 | (time) 243 | _arguments "${_arguments_options[@]}" : \ 244 | && ret=0 245 | ;; 246 | (timings) 247 | _arguments "${_arguments_options[@]}" : \ 248 | && ret=0 249 | ;; 250 | (toggle) 251 | _arguments "${_arguments_options[@]}" : \ 252 | && ret=0 253 | ;; 254 | (help) 255 | _arguments "${_arguments_options[@]}" : \ 256 | && ret=0 257 | ;; 258 | esac 259 | ;; 260 | esac 261 | ;; 262 | esac 263 | ;; 264 | esac 265 | } 266 | 267 | (( $+functions[_starship_commands] )) || 268 | _starship_commands() { 269 | local commands; commands=( 270 | 'bug-report:Create a pre-populated GitHub issue with information about your configuration' \ 271 | 'completions:Generate starship shell completions for your shell to stdout' \ 272 | 'config:Edit the starship configuration' \ 273 | 'explain:Explains the currently showing modules' \ 274 | 'init:Prints the shell function used to execute starship' \ 275 | 'module:Prints a specific prompt module' \ 276 | 'preset:Prints a preset config' \ 277 | 'print-config:Prints the computed starship configuration' \ 278 | 'prompt:Prints the full starship prompt' \ 279 | 'session:Generate random session key' \ 280 | 'time:Prints time in milliseconds' \ 281 | 'timings:Prints timings of all active modules' \ 282 | 'toggle:Toggle a given starship module' \ 283 | 'help:Print this message or the help of the given subcommand(s)' \ 284 | ) 285 | _describe -t commands 'starship commands' commands "$@" 286 | } 287 | (( $+functions[_starship__bug-report_commands] )) || 288 | _starship__bug-report_commands() { 289 | local commands; commands=() 290 | _describe -t commands 'starship bug-report commands' commands "$@" 291 | } 292 | (( $+functions[_starship__completions_commands] )) || 293 | _starship__completions_commands() { 294 | local commands; commands=() 295 | _describe -t commands 'starship completions commands' commands "$@" 296 | } 297 | (( $+functions[_starship__config_commands] )) || 298 | _starship__config_commands() { 299 | local commands; commands=() 300 | _describe -t commands 'starship config commands' commands "$@" 301 | } 302 | (( $+functions[_starship__explain_commands] )) || 303 | _starship__explain_commands() { 304 | local commands; commands=() 305 | _describe -t commands 'starship explain commands' commands "$@" 306 | } 307 | (( $+functions[_starship__help_commands] )) || 308 | _starship__help_commands() { 309 | local commands; commands=( 310 | 'bug-report:Create a pre-populated GitHub issue with information about your configuration' \ 311 | 'completions:Generate starship shell completions for your shell to stdout' \ 312 | 'config:Edit the starship configuration' \ 313 | 'explain:Explains the currently showing modules' \ 314 | 'init:Prints the shell function used to execute starship' \ 315 | 'module:Prints a specific prompt module' \ 316 | 'preset:Prints a preset config' \ 317 | 'print-config:Prints the computed starship configuration' \ 318 | 'prompt:Prints the full starship prompt' \ 319 | 'session:Generate random session key' \ 320 | 'time:Prints time in milliseconds' \ 321 | 'timings:Prints timings of all active modules' \ 322 | 'toggle:Toggle a given starship module' \ 323 | 'help:Print this message or the help of the given subcommand(s)' \ 324 | ) 325 | _describe -t commands 'starship help commands' commands "$@" 326 | } 327 | (( $+functions[_starship__help__bug-report_commands] )) || 328 | _starship__help__bug-report_commands() { 329 | local commands; commands=() 330 | _describe -t commands 'starship help bug-report commands' commands "$@" 331 | } 332 | (( $+functions[_starship__help__completions_commands] )) || 333 | _starship__help__completions_commands() { 334 | local commands; commands=() 335 | _describe -t commands 'starship help completions commands' commands "$@" 336 | } 337 | (( $+functions[_starship__help__config_commands] )) || 338 | _starship__help__config_commands() { 339 | local commands; commands=() 340 | _describe -t commands 'starship help config commands' commands "$@" 341 | } 342 | (( $+functions[_starship__help__explain_commands] )) || 343 | _starship__help__explain_commands() { 344 | local commands; commands=() 345 | _describe -t commands 'starship help explain commands' commands "$@" 346 | } 347 | (( $+functions[_starship__help__help_commands] )) || 348 | _starship__help__help_commands() { 349 | local commands; commands=() 350 | _describe -t commands 'starship help help commands' commands "$@" 351 | } 352 | (( $+functions[_starship__help__init_commands] )) || 353 | _starship__help__init_commands() { 354 | local commands; commands=() 355 | _describe -t commands 'starship help init commands' commands "$@" 356 | } 357 | (( $+functions[_starship__help__module_commands] )) || 358 | _starship__help__module_commands() { 359 | local commands; commands=() 360 | _describe -t commands 'starship help module commands' commands "$@" 361 | } 362 | (( $+functions[_starship__help__preset_commands] )) || 363 | _starship__help__preset_commands() { 364 | local commands; commands=() 365 | _describe -t commands 'starship help preset commands' commands "$@" 366 | } 367 | (( $+functions[_starship__help__print-config_commands] )) || 368 | _starship__help__print-config_commands() { 369 | local commands; commands=() 370 | _describe -t commands 'starship help print-config commands' commands "$@" 371 | } 372 | (( $+functions[_starship__help__prompt_commands] )) || 373 | _starship__help__prompt_commands() { 374 | local commands; commands=() 375 | _describe -t commands 'starship help prompt commands' commands "$@" 376 | } 377 | (( $+functions[_starship__help__session_commands] )) || 378 | _starship__help__session_commands() { 379 | local commands; commands=() 380 | _describe -t commands 'starship help session commands' commands "$@" 381 | } 382 | (( $+functions[_starship__help__time_commands] )) || 383 | _starship__help__time_commands() { 384 | local commands; commands=() 385 | _describe -t commands 'starship help time commands' commands "$@" 386 | } 387 | (( $+functions[_starship__help__timings_commands] )) || 388 | _starship__help__timings_commands() { 389 | local commands; commands=() 390 | _describe -t commands 'starship help timings commands' commands "$@" 391 | } 392 | (( $+functions[_starship__help__toggle_commands] )) || 393 | _starship__help__toggle_commands() { 394 | local commands; commands=() 395 | _describe -t commands 'starship help toggle commands' commands "$@" 396 | } 397 | (( $+functions[_starship__init_commands] )) || 398 | _starship__init_commands() { 399 | local commands; commands=() 400 | _describe -t commands 'starship init commands' commands "$@" 401 | } 402 | (( $+functions[_starship__module_commands] )) || 403 | _starship__module_commands() { 404 | local commands; commands=() 405 | _describe -t commands 'starship module commands' commands "$@" 406 | } 407 | (( $+functions[_starship__preset_commands] )) || 408 | _starship__preset_commands() { 409 | local commands; commands=() 410 | _describe -t commands 'starship preset commands' commands "$@" 411 | } 412 | (( $+functions[_starship__print-config_commands] )) || 413 | _starship__print-config_commands() { 414 | local commands; commands=() 415 | _describe -t commands 'starship print-config commands' commands "$@" 416 | } 417 | (( $+functions[_starship__prompt_commands] )) || 418 | _starship__prompt_commands() { 419 | local commands; commands=() 420 | _describe -t commands 'starship prompt commands' commands "$@" 421 | } 422 | (( $+functions[_starship__session_commands] )) || 423 | _starship__session_commands() { 424 | local commands; commands=() 425 | _describe -t commands 'starship session commands' commands "$@" 426 | } 427 | (( $+functions[_starship__time_commands] )) || 428 | _starship__time_commands() { 429 | local commands; commands=() 430 | _describe -t commands 'starship time commands' commands "$@" 431 | } 432 | (( $+functions[_starship__timings_commands] )) || 433 | _starship__timings_commands() { 434 | local commands; commands=() 435 | _describe -t commands 'starship timings commands' commands "$@" 436 | } 437 | (( $+functions[_starship__toggle_commands] )) || 438 | _starship__toggle_commands() { 439 | local commands; commands=() 440 | _describe -t commands 'starship toggle commands' commands "$@" 441 | } 442 | 443 | if [ "$funcstack[1]" = "_starship" ]; then 444 | _starship "$@" 445 | else 446 | compdef _starship starship 447 | fi 448 | -------------------------------------------------------------------------------- /conf.d/__init__.zsh: -------------------------------------------------------------------------------- 1 | # 2 | # __init__: This runs prior to any other conf.d contents. 3 | # 4 | 5 | # Apps 6 | export EDITOR=nvim 7 | export VISUAL=code 8 | export PAGER=less 9 | 10 | # Set the list of directories that cd searches. 11 | cdpath=( 12 | $XDG_PROJECTS_DIR(N/) 13 | $XDG_PROJECTS_DIR/mattmc3(N/) 14 | $cdpath 15 | ) 16 | 17 | # Set the list of directories that Zsh searches for programs. 18 | path=( 19 | # core 20 | $prepath 21 | $path 22 | 23 | # emacs 24 | $HOME/.emacs.d/bin(N) 25 | $XDG_CONFIG_HOME/emacs/bin(N) 26 | 27 | # keg only brew apps 28 | $HOMEBREW_PREFIX/opt/curl/bin(N) 29 | $HOMEBREW_PREFIX/opt/go/libexec/bin(N) 30 | $HOMEBREW_PREFIX/share/npm/bin(N) 31 | $HOMEBREW_PREFIX/opt/ruby/bin(N) 32 | $HOMEBREW_PREFIX/lib/ruby/gems/*/bin(N) 33 | $HOME/.gem/ruby/*/bin(N) 34 | ) 35 | -------------------------------------------------------------------------------- /conf.d/archive/homebrew.zsh: -------------------------------------------------------------------------------- 1 | (( $+commands[brew] )) || return 1 2 | 3 | if [[ -z "$HOMEBREW_PREFIX" ]]; then 4 | source <(brew shellenv) 5 | fi 6 | brew_owner=$(stat -f "%Su" $HOMEBREW_PREFIX) 7 | if [[ $(whoami) != $brew_owner ]]; then 8 | alias brew="sudo -Hu '$brew_owner' brew" 9 | fi 10 | unset brew_owner 11 | -------------------------------------------------------------------------------- /conf.d/archive/magic-enter.zsh: -------------------------------------------------------------------------------- 1 | # 2 | # magic-enter: Configure ohmyzsh/ohmyzsh/plugins/magic-enter 3 | # 4 | 5 | # Set the default commands to run when none is given 6 | MAGIC_ENTER_GIT_COMMAND='git status -sb' 7 | MAGIC_ENTER_OTHER_COMMAND='ls' 8 | -------------------------------------------------------------------------------- /conf.d/gpg.zsh: -------------------------------------------------------------------------------- 1 | # 2 | # gpg: Customize GNUPG 3 | # 4 | 5 | export GNUPGHOME=${GNUPGHOME:=${XDG_DATA_HOME:-$HOME/.local/share}/gnupg} 6 | [[ -e $GNUPGHOME:h ]] || mkdir -p $GNUPGHOME:h 7 | alias gpg="${aliases[gpg]:-gpg} --homedir \"$GNUPGHOME\"" 8 | -------------------------------------------------------------------------------- /conf.d/iwd.zsh: -------------------------------------------------------------------------------- 1 | # 2 | # iwd: Save off the initial working directory 3 | # 4 | 5 | : ${IWD:=$PWD} 6 | alias iwd='cd $IWD' 7 | -------------------------------------------------------------------------------- /conf.d/ruby.zsh: -------------------------------------------------------------------------------- 1 | # Ruby is keg-only 2 | [[ -d "${HOMBREW_PREFIX:-/opt/homebrew}" ]] || return 3 | 4 | : ${HOMBREW_PREFIX:=/opt/homebrew} 5 | path=( 6 | $HOMBREW_PREFIX/opt/ruby/bin(N) 7 | $HOMEBREW_PREFIX/lib/ruby/gems/*/bin(N) 8 | $HOME/.gem/ruby/*/bin(N) 9 | $path 10 | ) 11 | -------------------------------------------------------------------------------- /conf.d/terminal.zsh: -------------------------------------------------------------------------------- 1 | # Emit an OSC 1337 sequence to set vars your terminal app (WezTerm) can use. 2 | function set_terminal_var() { 3 | hash base64 2>/dev/null || return 1 4 | local val 5 | val="$(echo -n "$2" | base64)" 6 | 7 | # https://github.com/tmux/tmux/wiki/FAQ#what-is-the-passthrough-escape-sequence-and-how-do-i-use-it 8 | # Note that you ALSO need to add "set -g allow-passthrough on" to your tmux.conf 9 | if [[ -n "${TMUX}" ]] ; then 10 | printf "\033Ptmux;\033\033]1337;SetUserVar=%s=%s\007\033\\" "$1" "$val" 11 | else 12 | printf "\033]1337;SetUserVar=%s=%s\007" "$1" "$val" 13 | fi 14 | } 15 | set_terminal_var "TERM_CURRENT_SHELL" "zsh ${ZSH_PATCHLEVEL:-$ZSH_VERSION}" 16 | -------------------------------------------------------------------------------- /conf.d/zoxide.zsh: -------------------------------------------------------------------------------- 1 | # 2 | # zoxide: Configure zoxide. 3 | # 4 | 5 | # https://github.com/ajeetdsouza/zoxide 6 | if (( $+commands[zoxide] )); then 7 | cached-eval 'zoxide-init-zsh' zoxide init zsh 8 | fi 9 | -------------------------------------------------------------------------------- /conf.d/zsh-syntax-highlighting.zsh: -------------------------------------------------------------------------------- 1 | # 2 | # zsh-syntax-highlighting: Snippet to config zsh-users/zsh-syntax-highlighting 3 | # 4 | 5 | # See available highlighters here: 6 | # - https://github.com/zsh-users/zsh-syntax-highlighting/blob/master/docs/highlighters/main.md 7 | 8 | # Check if using zsh-users/zsh-syntax-highlighting 9 | [[ -v ZSH_HIGHLIGHT_STYLES ]] || return 1 10 | 11 | ZSH_HIGHLIGHT_HIGHLIGHTERS=( 12 | main 13 | brackets 14 | regexp 15 | pattern 16 | line 17 | cursor 18 | root 19 | ) 20 | 21 | # Highlight subcommands (the second word) in yellow. 22 | ZSH_HIGHLIGHT_STYLES[subcommand]='fg=yellow' 23 | 24 | # Whenever the buffer is modified, evaluate whether there's a subcommand. 25 | _zsh_highlight_highlighter_subcommand_predicate() { 26 | _zsh_highlight_buffer_modified 27 | } 28 | 29 | _zsh_highlight_highlighter_subcommand_paint() { 30 | # Short-circuit check to ensure there are multiple words. 31 | local -a words=(${=BUFFER}) 32 | (( $#words > 1 )) || return 33 | 34 | # Find the second word 35 | local startpos=0 pos=0 state=start char= 36 | for char in ${(s..)BUFFER}; do 37 | case $state in 38 | start) 39 | if [[ "$char" == [[:alnum:]] ]]; then 40 | state=cmd 41 | elif [[ "$char" == '#' ]]; then 42 | state=comment 43 | break 44 | fi 45 | ;; 46 | cmd) 47 | if [[ "$char" == [[:space:]] ]]; then 48 | state=whitespace 49 | fi 50 | ;; 51 | whitespace) 52 | if [[ "$char" == [[:alnum:]] ]]; then 53 | startpos=$pos 54 | state=subcmd 55 | elif [[ "$char" != [[:space:]] ]]; then 56 | # If the next word begins with a non-space, non-alnum char 57 | # (eg: punctuation), then it's likely a --flag, $var, ~/path, 58 | # or something else - not a proper subcommand 59 | state=none 60 | break 61 | fi 62 | ;; 63 | subcmd) 64 | if [[ "$char" == [[:space:]] ]]; then 65 | break 66 | elif [[ "$char" != [[:alnum:]] ]] && [[ "$char" != (-|_) ]]; then 67 | state=none 68 | break 69 | fi 70 | ;; 71 | esac 72 | (( ++pos )) 73 | done 74 | 75 | if [[ "$state" == subcmd ]] && (( $startpos < $pos )); then 76 | _zsh_highlight_add_highlight $startpos $pos 'subcommand' 77 | fi 78 | } 79 | 80 | # Add custom subcommand highlighter 81 | ZSH_HIGHLIGHT_HIGHLIGHTERS+=(subcommand) 82 | 83 | # Highlight command flags (-f|--flag). 84 | ZSH_HIGHLIGHT_STYLES[single-hyphen-option]=fg=cyan 85 | ZSH_HIGHLIGHT_STYLES[double-hyphen-option]=fg=cyan 86 | 87 | # A directory name in command position when the AUTO_CD option is set 88 | ZSH_HIGHLIGHT_STYLES[autodirectory]="fg=blue,bold,underline" 89 | 90 | ZSH_HIGHLIGHT_STYLES[path]=fg=magenta 91 | ZSH_HIGHLIGHT_STYLES[default]=fg=blue 92 | 93 | # Make rm -rf a bit more obvious. 94 | typeset -A ZSH_HIGHLIGHT_PATTERNS 95 | ZSH_HIGHLIGHT_PATTERNS[rm*-rf*]="fg=white,bold,bg=red" 96 | -------------------------------------------------------------------------------- /functions/allexts: -------------------------------------------------------------------------------- 1 | #!/bin/zsh 2 | ##? Show all extensions in current folder structure. 3 | 4 | find . -not \( -path '*/.git/*' -prune \) -type f -name '*.*' | sed 's|.*\.|\.|' | sort | uniq -c 5 | -------------------------------------------------------------------------------- /functions/bak: -------------------------------------------------------------------------------- 1 | #!/bin/zsh 2 | local now f 3 | now=$(date +"%Y%m%d-%H%M%S") 4 | for f in "$@"; do 5 | if [[ ! -e "$f" ]]; then 6 | echo "file not found: $f" >&2 7 | continue 8 | fi 9 | cp -R "$f" "$f".$now.bak 10 | done 11 | -------------------------------------------------------------------------------- /functions/clone: -------------------------------------------------------------------------------- 1 | #!/bin/zsh 2 | ##? clone - clone a git repo 3 | if [[ -z "$1" ]]; then 4 | echo "What git repo do you want?" >&2 5 | return 1 6 | fi 7 | local user repo 8 | if [[ "$1" = */* ]]; then 9 | user=${1%/*} 10 | repo=${1##*/} 11 | else 12 | user=mattmc3 13 | repo=$1 14 | fi 15 | 16 | local giturl="github.com" 17 | local dest=${XDG_PROJECTS_HOME:-~/Projects}/$user/$repo 18 | 19 | if [[ ! -d $dest ]]; then 20 | git clone --recurse-submodules "git@${giturl}:${user}/${repo}.git" "$dest" 21 | else 22 | echo "No need to clone, that directory already exists." 23 | echo "Taking you there." 24 | fi 25 | cd $dest 26 | -------------------------------------------------------------------------------- /functions/noext: -------------------------------------------------------------------------------- 1 | #!/bin/zsh 2 | ##? noext - Find files with no file extension 3 | 4 | # for fun, rename with: noext -exec mv '{}' '{}.sql' \; 5 | find . -not \( -path '*/.git/*' -prune \) -type f ! -name '*.*' 6 | -------------------------------------------------------------------------------- /functions/optdiff: -------------------------------------------------------------------------------- 1 | #!/bin/zsh 2 | ##? optdiff - show a diff between set options and Zsh defaults 3 | 4 | tmp1=$(mktemp) 5 | tmp2=$(mktemp) 6 | zsh -df -c "set -o" >| $tmp1 7 | set -o >| $tmp2 8 | diff --changed-group-format='%<' --unchanged-group-format='' $tmp2 $tmp1 9 | rm $tmp1 $tmp2 10 | -------------------------------------------------------------------------------- /functions/post-autosuggestions: -------------------------------------------------------------------------------- 1 | #!/bin/zsh 2 | # https://github.com/zsh-users/zsh-autosuggestions 3 | 4 | # Set highlight color, default 'fg=8'. 5 | ZSH_AUTOSUGGEST_HIGHLIGHT_STYLE='fg=242' 6 | 7 | # Set key bindings. 8 | if [[ -n "$key_info" ]]; then 9 | # vi 10 | bindkey -M viins "$key_info[Control]F" vi-forward-word 11 | bindkey -M viins "$key_info[Control]E" vi-add-eol 12 | fi 13 | -------------------------------------------------------------------------------- /functions/post-history-substring-search: -------------------------------------------------------------------------------- 1 | #!/bin/zsh 2 | # https://github.com/zsh-users/zsh-history-substring-search 3 | 4 | for keymap in 'emacs' 'viins'; do 5 | bindkey -M "$keymap" "$terminfo[kcuu1]" history-substring-search-up 6 | bindkey -M "$keymap" "$terminfo[kcud1]" history-substring-search-down 7 | done 8 | 9 | # Vi 10 | bindkey -M vicmd "k" history-substring-search-up 11 | bindkey -M vicmd "j" history-substring-search-down 12 | 13 | # Emacs 14 | if [[ -n "$key_info" ]]; then 15 | bindkey -M emacs "$key_info[Control]P" history-substring-search-up 16 | bindkey -M emacs "$key_info[Control]N" history-substring-search-down 17 | fi 18 | -------------------------------------------------------------------------------- /functions/prj: -------------------------------------------------------------------------------- 1 | #!/bin/zsh 2 | ##? prj - project jumper 3 | if ! command -v fzf >/dev/null; then 4 | echo "fzf command not found" >&2 5 | return 1 6 | fi 7 | 8 | local query=() 9 | local project_dir=${XDG_PROJECTS_DIR:-$HOME/Projects} 10 | local usage=( 11 | "prj [-h|--help]" 12 | "prj [-d|--directory=] []" 13 | ) 14 | opterr() { echo >&2 "prj: Unknown option '$1'" } 15 | 16 | while (( $# )); do 17 | case $1 in 18 | --) shift; query+=("$@"); break ;; 19 | -h|--help) printf "%s\n" $usage && return ;; 20 | -d|--directory) shift; project_dir=$1 ;; 21 | -d=*|--directory=*) project_dir="${1#*=}" ;; 22 | -*) opterr $1 && return 2 ;; 23 | *) query+=("$@"); break ;; 24 | esac 25 | shift 26 | done 27 | 28 | if [[ $project_dir = '~/'* ]]; then 29 | project_dir=${project_dir:s/~/$HOME} 30 | fi 31 | 32 | if [[ ! -d $project_dir ]]; then 33 | echo >&2 "prj: Project home directory not found '$project_dir'" 34 | return 1 35 | fi 36 | 37 | local projects=( 38 | $project_dir/*/.git/.. 39 | $project_dir/*/*/.git/.. 40 | ) 41 | 42 | # absolute path with project dir prefix stripped 43 | projects=(${${projects:a}#*$project_dir/}) 44 | 45 | # fzf a project 46 | local selection=$(printf "%s\n" ${projects[@]} | fzf --layout=reverse-list --query=$query) 47 | 48 | # cd to the selected project 49 | if [[ -n $selection ]] && [[ -d $project_dir/$selection ]]; then 50 | cd $project_dir/$selection 51 | fi 52 | -------------------------------------------------------------------------------- /functions/repo: -------------------------------------------------------------------------------- 1 | #!/bin/zsh 2 | ##? repo - Deal with git repos 3 | 4 | function __repo_help { 5 | echo "repo - Deal with git repos" 6 | echo "" 7 | echo "commands:" 8 | echo " help print this help" 9 | echo " home print repo home" 10 | echo " ls print repo list" 11 | echo " rm remove repo" 12 | echo " in install repo" 13 | echo " up update repos" 14 | echo "" 15 | echo "examples:" 16 | echo " repo in $newsha)" 26 | fi 27 | } 28 | 29 | function __repo_clone { 30 | local repo=$1 31 | local repodir=$REPO_HOME/$repo 32 | if [ -d $repodir ]; then 33 | echo "Found $repo..." 34 | return 35 | fi 36 | 37 | echo "Cloning $repo..." 38 | command git clone --quiet --depth 1 --recursive --shallow-submodules \ 39 | https://github.com/$repo $repodir 40 | 41 | local init=$repodir/${repo:t}.plugin.zsh 42 | if [[ ! -e $init ]]; then 43 | local -a initfiles=($repodir/*.{plugin.zsh,zsh-theme,zsh,sh}(N)) 44 | (( $#initfiles )) && ln -sf $initfiles[1] $init 45 | fi 46 | if [[ $repo == sorin-ionescu/prezto ]]; then 47 | for init in $repodir/modules/*/init.zsh; do 48 | ln -sf $init $init:h/${init:h:t}.plugin.zsh 49 | done 50 | fi 51 | echo "Cloned $repo." 52 | } 53 | 54 | function repo { 55 | emulate -L zsh 56 | setopt local_options extended_glob no_monitor 57 | 58 | (( $# )) || { 59 | echo >&2 "repo: Expecting command argument." 60 | return 1 61 | } 62 | 63 | local repo err=1 64 | local cmd=$1; shift 65 | : ${REPO_HOME:=${XDG_CACHE_HOME:-$HOME/.cache}/repos} 66 | 67 | # piped/redirected input 68 | if ! [ -t 0 ]; then 69 | local -a args=($@) 70 | local data 71 | while IFS= read -r data || [ -n "$data" ]; do 72 | data=${data%\#*} 73 | args+=($data) 74 | done 75 | set -- $args 76 | fi 77 | 78 | case "$cmd" in 79 | help|-h|--help) 80 | __repo_help 81 | ;; 82 | home) 83 | echo $REPO_HOME 84 | ;; 85 | ls|list) 86 | err=1 87 | for repo in $REPO_HOME/*/*/.git(/N); do 88 | echo ${repo:h:h:t}/${repo:h:t} 89 | err=0 90 | done 91 | return $err 92 | ;; 93 | up|update) 94 | echo "Checking for updates..." 95 | for repo in $(repo ls); do 96 | echo "$repo..." 97 | __repo_update $repo & 98 | done 99 | wait 100 | echo "Updates complete." 101 | ;; 102 | in|install) 103 | for repo in $@; do 104 | __repo_clone $repo & 105 | done 106 | wait 107 | ;; 108 | rm|del) 109 | local err=0 110 | for repo in $@; do 111 | if ! [[ "$REPO_HOME" =~ $HOME/* ]]; then 112 | echo >&2 "repo: \$REPO_HOME not set correctly '$REPO_HOME'." 113 | return 2 114 | elif ! [[ -d $REPO_HOME/$repo ]]; then 115 | echo "Repo not found '$repo'." 116 | err=1 117 | else 118 | command rm -rf -- $REPO_HOME/$repo 119 | fi 120 | done 121 | return $err 122 | ;; 123 | *) 124 | echo >&2 "repo: Unknown command '"$cmd"'" 125 | return 1 126 | ;; 127 | esac 128 | } 129 | repo "$@" 130 | -------------------------------------------------------------------------------- /functions/rmzwc: -------------------------------------------------------------------------------- 1 | #!/bin/zsh 2 | if [[ "$1" == "--help" ]] || [[ "$1" == "-h" ]]; then 3 | echo "rmzwc" 4 | echo " removes zcompiled files" 5 | echo "options:" 6 | echo " -q Quiet" 7 | echo " --dry-run Dry run" 8 | echo " -h --help Show help screen" 9 | return 0 10 | fi 11 | 12 | findprint="-print" 13 | finddel="-delete" 14 | if [[ "$1" == '-q' ]]; then 15 | findprint="" 16 | elif [[ "$1" == "--dry-run" ]]; then 17 | finddel="" 18 | fi 19 | 20 | if [[ -d "${ZDOTDIR}" ]]; then 21 | find "${ZDOTDIR:A}" -type f \( -name "*.zwc" -o -name "*.zwc.old" \) $findprint $finddel 22 | fi 23 | find "$HOME" -maxdepth 1 -type f \( -name "*.zwc" -o -name "*.zwc.old" \) $findprint $finddel 24 | find . -maxdepth 1 -type f \( -name "*.zwc" -o -name "*.zwc.old" \) $findprint $finddel 25 | unset findargs 26 | -------------------------------------------------------------------------------- /functions/substenv: -------------------------------------------------------------------------------- 1 | #!/bin/zsh 2 | ##? substenv - substitutes string parts with environment variables 3 | #function substenv { 4 | if (( $# == 0 )); then 5 | subenv ZDOTDIR | subenv HOME 6 | else 7 | local sedexp="s|${(P)1}|\$$1|g" 8 | shift 9 | sed "$sedexp" "$@" 10 | fi 11 | #} 12 | -------------------------------------------------------------------------------- /functions/tailf: -------------------------------------------------------------------------------- 1 | #!/bin/zsh 2 | local nl 3 | tail -f $2 | while read j; do 4 | print -n "$nl$j" 5 | nl="\n" 6 | done 7 | -------------------------------------------------------------------------------- /functions/touchf: -------------------------------------------------------------------------------- 1 | #!/bin/zsh 2 | ##? touchf - makes any dirs recursively and then touches a file if it doesn't exist 3 | if [[ -n "$1" ]] && [[ ! -f "$1" ]]; then 4 | mkdir -p "$1:h" && touch "$1" 5 | fi 6 | -------------------------------------------------------------------------------- /functions/update_completions: -------------------------------------------------------------------------------- 1 | function update_completions { 2 | emulate -L zsh; setopt local_options 3 | : ${__zsh_config_dir:=${ZDOTDIR:-${XDG_CONFIG_HOME:-$HOME/.config}/zsh}} 4 | local destdir=$__zsh_config_dir/completions 5 | mkdir -p $destdir 6 | 7 | echo "Getting git completions..." 8 | curl -fsSL -o $destdir/git-completion.bash https://raw.githubusercontent.com/git/git/master/contrib/completion/git-completion.bash 9 | curl -fsSL -o $destdir/_git https://raw.githubusercontent.com/git/git/master/contrib/completion/git-completion.zsh 10 | 11 | echo "Generating starship completions..." 12 | local _starship=$destdir/_starship 13 | starship completions zsh >| $_starship 14 | } 15 | update_completions "$@" 16 | -------------------------------------------------------------------------------- /functions/weather: -------------------------------------------------------------------------------- 1 | #!/bin/zsh 2 | # What is the weather? 3 | curl "http://wttr.in/$1" 4 | -------------------------------------------------------------------------------- /functions/zcompiledir: -------------------------------------------------------------------------------- 1 | #!/bin/zsh 2 | emulate -L zsh; setopt localoptions extendedglob globdots globstarshort nullglob rcquotes 3 | autoload -U zrecompile 4 | 5 | local f 6 | local flag_clean=false 7 | [[ "$1" == "-c" ]] && flag_clean=true && shift 8 | if [[ -z "$1" ]] || [[ ! -d "$1" ]]; then 9 | echo "Bad or missing directory $1" && return 1 10 | fi 11 | 12 | if [[ $flag_clean == true ]]; then 13 | for f in "$1"/**/*.zwc(.N) "$1"/**/*.zwc.old(.N); do 14 | echo "removing $f" && command rm -f "$f" 15 | done 16 | else 17 | for f in "$1"/**/*.zsh{,-theme}; do 18 | echo "compiling $f" && zrecompile -pq "$f" 19 | done 20 | fi 21 | -------------------------------------------------------------------------------- /functions/zephyr2lib: -------------------------------------------------------------------------------- 1 | # Move zephyr files into lib directory 2 | : ${ZEPHYR_HOME:=$HOME/Projects/mattmc3/zephyr} 3 | 4 | # rm -- $ZDOTDIR/lib/*.zsh 5 | cp -f $ZEPHYR_HOME/plugins/helper/helper.plugin.zsh $ZDOTDIR/lib/archive/__init__.zsh 6 | for plugin in $ZEPHYR_HOME/plugins/*(/); do 7 | plugin=${plugin:t} 8 | if [[ $plugin == macos ]] || [[ $plugin == helper ]]; then 9 | continue 10 | fi 11 | cp -f $ZEPHYR_HOME/plugins/${plugin}/${plugin}.plugin.zsh $ZDOTDIR/lib/archive/${plugin}.zsh.tmp 12 | done 13 | 14 | filter_bootstap=' 15 | BEGIN { skip=0 } 16 | /# Bootstrap/ { skip = 4 } 17 | skip>0 { skip--; next } 18 | skip==0 { print } 19 | ' 20 | filter_last3='NR>n{print A[NR%n]} {A[NR%n]=$0}' 21 | 22 | for file in $ZDOTDIR/lib/archive/*.zsh.tmp; do 23 | cat $file | awk $filter_bootstap | awk -v n=3 $filter_last3 >| ${file:r} 24 | rm -- $file 25 | done 26 | -------------------------------------------------------------------------------- /lib/antidote.zsh: -------------------------------------------------------------------------------- 1 | # 2 | # antidote: The fastest Zsh plugin manager. 3 | # 4 | 5 | # Setup antidote. 6 | export ZSH_CUSTOM=${ZSH_CUSTOM:-$ZDOTDIR} 7 | export ANTIDOTE_HOME=${ANTIDOTE_HOME:-${XDG_CACHE_HOME:-$HOME/.cache}/repos} 8 | zstyle -s ':antidote:repo' path antidote_path \ 9 | || antidote_path=$ANTIDOTE_HOME/mattmc3/antidote 10 | 11 | # Clone antidote if missing. 12 | [[ -d $antidote_path ]] \ 13 | || git clone --depth 1 --quiet https://github.com/mattmc3/antidote $antidote_path 14 | 15 | # Lazy-load antidote from its functions directory. 16 | fpath=($antidote_path/functions $fpath) 17 | autoload -Uz antidote 18 | 19 | # Generate static file in a subshell whenever .zplugins is updated. 20 | zplugins=${ZDOTDIR:-~}/.zplugins 21 | if [[ ! ${zplugins}.zsh -nt ${zplugins} ]] || [[ ! -e $ANTIDOTE_HOME/.lastupdated ]]; then 22 | antidote bundle <${zplugins} >|${zplugins}.zsh 23 | date +%Y-%m-%dT%H:%M:%S%z >| $ANTIDOTE_HOME/.lastupdated 24 | fi 25 | 26 | # Source the static file. 27 | source ${zplugins}.zsh 28 | -------------------------------------------------------------------------------- /lib/archive/instant-zsh.zsh: -------------------------------------------------------------------------------- 1 | # Make zsh start INSTANTLY with this one weird trick. 2 | # 3 | # https://asciinema.org/a/274255 4 | # 5 | # HOW TO USE 6 | # 7 | # 1. Download this script. 8 | # 9 | # curl -fsSL -o ~/instant-zsh.zsh https://gist.github.com/romkatv/8b318a610dc302bdbe1487bb1847ad99/raw 10 | # 11 | # 2. Add this at the top of your ~/.zshrc. 12 | # 13 | # source ~/instant-zsh.zsh 14 | # instant-zsh-pre '%n@%m %~%# ' 15 | # 16 | # Adjust the argument of instant-zsh-pre to be similar to your real prompt. 17 | # For example, if you are using Powerlevel10k with lean style, this works well: 18 | # 19 | # instant-zsh-pre "%B%39F${${(V)${(%):-%~}//\%/%%}//\//%b%31F/%B%39F}%b%f"$'\n'"%76F❯%f " 20 | # 21 | # If you override PROMPT_EOL_MARK in your zsh config files, move the definition 22 | # above the instant-zsh-pre call. 23 | # 24 | # 3. Add this at the bottom of your ~/.zshrc. 25 | # 26 | # instant-zsh-post 27 | # 28 | # 4. Optional: Compile instant-zsh.zsh for faster loading. 29 | # 30 | # zcompile ~/instant-zsh.zsh 31 | # 32 | # HOW IT WORKS 33 | # 34 | # This doesn't actually make your zsh start instantly, hence the reference to the 35 | # "one weird trick" advertisement. It does, however, make it feel like zsh is loading 36 | # faster. Or, put it another way, your original zsh wasn't so slow to load, but you 37 | # thought it was slow. Now you see that it was pretty fast all along. 38 | # 39 | # Here's how it work. To make your zsh "start instantly" all you need to do is print 40 | # your prompt immediately when zsh starts, before doing anything else. At the top of 41 | # ~/.zshrc is a good place for this. If your prompt takes a long time to initialize, 42 | # print something that looks close enough. Then, while the rest of ~/.zshrc is evaluated 43 | # and precmd hooks are run, all keyboard input simply gets buffered. Once initialization 44 | # is complete, clear the screen and allow the real prompt be printed where the "loading" 45 | # prompt was before. With the real prompt in place, all buffered keyboard input is 46 | # processed by zle. 47 | # 48 | # It's a bit gimmicky but it does reduce the perceived ZSH startup latency by a lot. 49 | # To make it more interesting, add `sleep 1` at the bottom of zsh and try opening a new 50 | # tab in your terminal. It's still instant! 51 | 52 | # Usage: instant-zsh-pre loading-prompt 53 | # 54 | # Prints the specified prompt after percent expansion (but not single word shell 55 | # expansions). The prompt is replaced inplace once the real prompt is initialized. 56 | # 57 | # For best results, set loading-prompt to something that looks similar 58 | # (or, ideally, identical) to the real prompt. 59 | # 60 | # Must be called at the very top of ~/.zshrc. Must be paired with instant-zsh-post. 61 | # 62 | # If you want to override PROMPT_EOL_MARK, do it before calling instant-zsh-pre. 63 | function instant-zsh-pre() { 64 | zmodload zsh/terminfo 65 | 66 | # Do nothing if terminal is lacking required capabilities. 67 | (( ${+terminfo[cuu]} && ${+terminfo[ed]} && ${+terminfo[sc]} && ${+terminfo[rc]} )) || return 0 68 | 69 | unsetopt localoptions prompt_cr prompt_sp 70 | 71 | () { 72 | emulate -L zsh 73 | 74 | # Emulate prompt_cr and prompt_sp. 75 | local eol_mark=${PROMPT_EOL_MARK-"%B%S%#%s%b"} 76 | local -i fill=COLUMNS 77 | 78 | () { 79 | local COLUMNS=1024 80 | local -i x y=$#1 m 81 | if (( y )); then 82 | while (( ${${(%):-$1%$y(l.1.0)}[-1]} )); do 83 | echo $y 84 | x=y 85 | (( y *= 2 )); 86 | done 87 | local xy 88 | while (( y > x + 1 )); do 89 | m=$(( x + (y - x) / 2 )) 90 | typeset ${${(%):-$1%$m(l.x.y)}[-1]}=$m 91 | done 92 | fi 93 | (( fill -= x )) 94 | } $eol_mark 95 | 96 | print -r ${(%):-$eol_mark${(pl.$fill.. .)}$'\r'%b%k%f%E}$'\n\n\n\n\n\n\n\n\n' 97 | echoti cuu 10 98 | print -rn -- ${terminfo[sc]}${(%)1} 99 | 100 | _clear-loading-prompt() { 101 | unsetopt localoptions 102 | setopt prompt_cr prompt_sp 103 | () { 104 | emulate -L zsh 105 | # Clear the loading prompt. The real prompt is about to get printed. 106 | print -rn -- $terminfo[rc]$terminfo[sgr0]$terminfo[ed] 107 | unfunction _clear-loading-prompt 108 | precmd_functions=(${(@)precmd_functions:#_clear-loading-prompt}) 109 | } 110 | } 111 | precmd_functions=($precmd_functions _clear-loading-prompt) 112 | } "$@" 113 | } 114 | 115 | # Must be called at the very bottom of ~/.zshrc. Must be paired with 116 | # instant-zsh-pre. 117 | function instant-zsh-post() { 118 | emulate -L zsh 119 | if (( ${+precmd_functions} && ${+precmd_functions[(I)_clear-loading-prompt]} )); then 120 | # Move _clear-loading-prompt to the end so that the loading prompt doesn't get 121 | # erased too soon. This assumes that the real prompt is set during the first 122 | # `precmd` or even earlier. 123 | precmd_functions=(${(@)precmd_functions:#_clear-loading-prompt} _clear-loading-prompt) 124 | fi 125 | } 126 | -------------------------------------------------------------------------------- /lib/archive/transient-prompt.zsh: -------------------------------------------------------------------------------- 1 | # https://www.zsh.org/mla/users/2019/msg00633.html 2 | # https://github.com/romkatv/powerlevel10k/issues/888#issuecomment-657969840 3 | # https://github.com/starship/starship/issues/888 4 | 5 | # Add transient prompt to Zsh 6 | if [[ ${ZSH_THEME:-powerlevel10k} == (p10k|powerlevel10k) ]]; then 7 | typeset -g POWERLEVEL9K_TRANSIENT_PROMPT 8 | : ${POWERLEVEL9K_TRANSIENT_PROMPT:=same-dir} 9 | return 10 | fi 11 | 12 | zle-line-init() { 13 | emulate -L zsh 14 | 15 | [[ $CONTEXT == start ]] || return 0 16 | 17 | while true; do 18 | zle .recursive-edit 19 | local -i ret=$? 20 | [[ $ret == 0 && $KEYS == $'\4' ]] || break 21 | [[ -o ignore_eof ]] || exit 0 22 | done 23 | 24 | local saved_prompt=$PROMPT 25 | local saved_rprompt=$RPROMPT 26 | PROMPT="%F{magenta}%# " 27 | RPROMPT='' 28 | zle .reset-prompt 29 | PROMPT=$saved_prompt 30 | RPROMPT=$saved_rprompt 31 | 32 | if (( ret )); then 33 | zle .send-break 34 | else 35 | zle .accept-line 36 | fi 37 | return ret 38 | } 39 | zle -N zle-line-init 40 | -------------------------------------------------------------------------------- /lib/history.zsh: -------------------------------------------------------------------------------- 1 | # 2 | # history: Set history options and define history aliases. 3 | # 4 | 5 | # References: 6 | # - https://github.com/sorin-ionescu/prezto/tree/master/modules/history 7 | # - https://github.com/ohmyzsh/ohmyzsh/blob/master/lib/history.zsh 8 | # - https://zsh.sourceforge.io/Doc/Release/Options.html#History 9 | 10 | # Set history options. 11 | setopt bang_hist # Treat the '!' character specially during expansion. 12 | setopt extended_history # Write the history file in the ':start:elapsed;command' format. 13 | setopt hist_expire_dups_first # Expire a duplicate event first when trimming history. 14 | setopt hist_find_no_dups # Do not display a previously found event. 15 | setopt hist_ignore_all_dups # Delete an old recorded event if a new event is a duplicate. 16 | setopt hist_ignore_dups # Do not record an event that was just recorded again. 17 | setopt hist_ignore_space # Do not record an event starting with a space. 18 | setopt hist_reduce_blanks # Remove extra blanks from commands added to the history list. 19 | setopt hist_save_no_dups # Do not write a duplicate event to the history file. 20 | setopt hist_verify # Do not execute immediately upon history expansion. 21 | setopt inc_append_history # Write to the history file immediately, not when the shell exits. 22 | setopt share_history # Share history between all sessions. 23 | setopt NO_hist_beep # Don't beep when accessing non-existent history. 24 | 25 | # Set history vars. 26 | HISTFILE="${XDG_DATA_HOME:-$HOME/.local/share}/zsh/zsh_history" 27 | mkdir -p "${HISTFILE:h}" # ensure directory exists 28 | SAVEHIST=100000 # history file entries 29 | HISTSIZE=20000 # session entries 30 | 31 | # Set history aliases. 32 | alias hist='fc -liL' 33 | alias history-stat="history 0 | awk '{print \$2}' | sort | uniq -c | sort -n -r | head" 34 | -------------------------------------------------------------------------------- /plugins/git/git.plugin.zsh: -------------------------------------------------------------------------------- 1 | # 2 | # git 3 | # 4 | 5 | # References 6 | # - https://www.oliverspryn.com/blog/adding-git-completion-to-zsh 7 | 8 | function update_git_completions { 9 | # Download the git scripts 10 | local giturl=https://raw.githubusercontent.com/git/git/master/contrib/completion 11 | local dest=${1:-${XDG_DATA_HOME:-~/.local/share}/zsh/completions} 12 | [[ -d $dest ]] || mkdir -p $dest 13 | curl -fsSL $giturl/git-completion.bash -o $dest/git-completion.bash 14 | curl -fsSL $giturl/git-completion.zsh -o $dest/_git 15 | } 16 | 17 | # Add completions 18 | fpath=(${XDG_DATA_HOME:-~/.local/share}/zsh/completions $fpath) 19 | [[ -f ${fpath[1]}/_git ]] || update_git_completions 20 | zstyle ':completion:*:*:git:*' script ${fpath[1]}/git-completion.bash 21 | 22 | # Aliases 23 | alias gad="git add" 24 | alias gbn="git rev-parse --abbrev-ref HEAD" 25 | alias gcd1="git clone --depth 1 https://github.com/" 26 | alias gcl="git clean" 27 | alias gclone="git clone git@github.com:mattmc3/" 28 | alias gcmt="git commit -am " 29 | alias gco="git checkout" 30 | alias gcob="git checkout -b " 31 | alias gcod="git checkout develop" 32 | alias gcom="git checkout main" 33 | alias get="git" 34 | alias glg="git log" 35 | alias glog="git log --graph --pretty='%Cred%h%Creset -%C(auto)%d%Creset %s %Cgreen(%ad) %C(bold blue)<%an>%Creset' --date=short" 36 | alias gpll="git pull" 37 | alias gpristine="git reset --hard && git clean -fdx" 38 | alias gpsh="git push" 39 | alias gpsuo="git push --set-upstream origin (git rev-parse --abbrev-ref HEAD)" 40 | alias grv="git remote -v" 41 | alias gsh="git stash" 42 | alias gst="git status -sb" 43 | 44 | -------------------------------------------------------------------------------- /plugins/golang/golang.plugin.zsh: -------------------------------------------------------------------------------- 1 | # 2 | # golang 3 | # 4 | 5 | # export GLOBALGOPATH=$XDG_PROJECTS_DIR/golang 6 | 7 | path+=($HOME/go/bin(N)) 8 | 9 | alias gob="go build" 10 | alias goc="go clean" 11 | alias god="go doc" 12 | alias gof="go fmt" 13 | alias gofa="go fmt ./..." 14 | alias gog="go get" 15 | alias goi="go install" 16 | alias gol="go list" 17 | alias gop="cd \$GOPATH" 18 | alias gopb="cd \$GOPATH/bin" 19 | alias gops="cd \$GOPATH/src" 20 | alias gor="go run" 21 | alias got="go test" 22 | alias gov="go vet" 23 | -------------------------------------------------------------------------------- /plugins/hooks/zsh-hooks.plugin.zsh: -------------------------------------------------------------------------------- 1 | # SOURCE: https://github.com/zsh-hooks/zsh-hooks 2 | # LICENSE: https://github.com/zsh-hooks/zsh-hooks/blob/master/LICENCE 3 | 4 | # Add to HOOK the given FUNCTION. 5 | # 6 | # With -d, remove the function from the hook instead; delete the hook 7 | # variable if it is empty. 8 | # 9 | # -D behaves like -d, but pattern characters are active in the 10 | # function name, so any matching function will be deleted from the hook. 11 | # 12 | # Without -d, the FUNCTION is marked for autoload; -U is passed down to 13 | # autoload if that is given, as are -z and -k. (This is harmless if the 14 | # function is actually defined inline.) 15 | 16 | 17 | hooks-add-hook(){ 18 | 19 | emulate -L zsh 20 | 21 | local opt 22 | local -a autoopts 23 | integer del list help 24 | 25 | while getopts "dDhLUzk" opt; do 26 | case "$opt" in 27 | (d) del=1 ;; 28 | (D) del=2 ;; 29 | (h) help=1 ;; 30 | (L) list=1 ;; 31 | ([Uzk]) autoopts+=("-$opt") ;; 32 | (*) return 1 ;; 33 | esac 34 | done 35 | shift $(( OPTIND - 1 )) 36 | 37 | if (( list )); then 38 | if [[ -z "$1" ]]; then 39 | printf '%s: What hook do you want listed?\n' "${funcstack[@]}" >&2 40 | return 1 41 | fi 42 | typeset -mp $@ 43 | return $? 44 | elif (( help || $# != 2 )); then 45 | print -u$(( 2 - help )) $usage 46 | return $(( 1 - help )) 47 | fi 48 | 49 | local hook="${1}" 50 | local fn="$2" 51 | 52 | if (( del )); then 53 | # delete, if hook is set 54 | if (( ${(P)+hook} )); then 55 | if (( del == 2 )); then 56 | set -A $hook ${(P)hook:#${~fn}} 57 | else 58 | set -A $hook ${(P)hook:#$fn} 59 | fi 60 | # unset if no remaining entries --- this can give better 61 | # performance in some cases 62 | if (( ! ${(P)#hook} )); then 63 | unset $hook 64 | fi 65 | fi 66 | else 67 | if (( ${(P)+hook} )); then 68 | if (( ${${(P)hook}[(I)$fn]} == 0 )); then 69 | set -A $hook ${(P)hook} $fn 70 | fi 71 | else 72 | set -A $hook $fn 73 | fi 74 | autoload $autoopts -- $fn 75 | fi 76 | 77 | } 78 | 79 | hooks-run-hook(){ 80 | local f 81 | for f in ${(P)1}; do 82 | $f ${@:2} # send given args to the func 83 | done 84 | } 85 | 86 | hooks-define-hook(){ 87 | typeset -ag "$1" 88 | } 89 | 90 | -hooks-define-zle-hook(){ 91 | local hname 92 | hname="${1//-/_}" # substitute all `-` with `_` 93 | eval " 94 | hooks-define-hook ${hname}_hook 95 | ${1}(){ 96 | ZSH_CUR_KEYMAP=\$KEYMAP 97 | hooks-run-hook ${hname}_hook 98 | } 99 | zle -N ${1} 100 | " 101 | } 102 | 103 | # Add the special widgets defined at: 104 | # https://zsh.sourceforge.io/Doc/Release/Zsh-Line-Editor.html#Special-Widgets 105 | -hooks-define-zle-hook zle-isearch-exit 106 | -hooks-define-zle-hook zle-isearch-update 107 | -hooks-define-zle-hook zle-line-pre-redraw 108 | -hooks-define-zle-hook zle-line-init 109 | -hooks-define-zle-hook zle-line-finish 110 | # this one causes a double-free error for zaw using the ag source 111 | # because it does some funny stuff with the history. Anyway, 112 | # since as far as I know nobody uses or wants to use this hook, 113 | # I'll comment it out until such a time as this issue is fixed... 114 | #-hooks-define-zle-hook zle-history-line-set 115 | -hooks-define-zle-hook zle-keymap-select 116 | 117 | # load the official hooks as well 118 | autoload -U add-zsh-hook 119 | -------------------------------------------------------------------------------- /plugins/otp/functions/otp: -------------------------------------------------------------------------------- 1 | #!/bin/zsh 2 | 3 | #function otp { 4 | # set otp home 5 | zstyle -s ':zdotdir:plugin:otp' home 'SECRETS_HOME' || 6 | SECRETS_HOME="${XDG_DATA_HOME:-$HOME/.local/share}/secrets" 7 | [[ -d $SECRETS_HOME ]] || mkdir -p $SECRETS_HOME 8 | 9 | if ! command -v oathtool > /dev/null 2>&1; then 10 | echo >&2 "otp: 'oathtool' not found. Install oathtool or oath-toolkit, depending on your OS." 11 | return 1 12 | fi 13 | 14 | if ! command -v gpg > /dev/null 2>&1; then 15 | echo >&2 "otp: 'gpg' not found. Install, and create a key with 'gpg --gen-key' if you don't already have one." 16 | return 1 17 | fi 18 | 19 | source $SECRETS_HOME/bin/gpg_key_ids.zsh 20 | local recp recipients=() 21 | for recp in ${(v)gpg_key_ids}; do 22 | recipients+=("--recipient=$recp") 23 | done 24 | 25 | local -a flag_help flag_add flag_list 26 | local usage=( 27 | "usage: otp [-h | --help] [-l | --list] [-a | --add] " 28 | ) 29 | zmodload zsh/zutil 30 | zparseopts -D -F -K -- \ 31 | {h,-help}=flag_help \ 32 | {l,-list}=flag_list \ 33 | {a,-add}=flag_add || { 34 | print -u 2 "Run 'opt -h' for usage." 35 | return 1 36 | } 37 | 38 | if (( $#flag_help )); then 39 | print -l $usage 40 | return 41 | elif (( $#flag_list )); then 42 | local file 43 | for file in $SECRETS_HOME/otp/*.otp.asc; do 44 | print $file:t:r:r 45 | done 46 | elif [[ -z "$1" ]]; then 47 | print -u 2 "otp: Expecting argument. Run 'opt -h' for usage." 48 | return 1 49 | elif (( $#flag_add )); then 50 | echo "The 'otp' utility works by using gpg to encrypt your OTP key." 51 | echo "First, enter the email address associated your GPG private key. You can add multiple." 52 | echo "When done, press enter to end with an empty line." 53 | echo "Next, you will paste your OTP secret key, followed by ^D to end the GPG message." 54 | rm -f $SECRETS_HOME/otp/$1.otp.asc 55 | gpg ${=recipients} --armor --encrypt --output $SECRETS_HOME/otp/$1.otp.asc /dev/stdin 56 | elif [[ ! -f $SECRETS_HOME/otp/$1.otp.asc ]]; then 57 | echo "otp: missing key '$1'. Run 'otp --add ' to add a new one-time password." 58 | return 1 59 | else 60 | totpkey=$(gpg --quiet --decrypt $SECRETS_HOME/otp/$1.otp.asc) 61 | oathtool --totp --b $totpkey | tee /dev/stderr | pbcopy 62 | fi 63 | #} 64 | -------------------------------------------------------------------------------- /plugins/otp/otp.plugin.zsh: -------------------------------------------------------------------------------- 1 | # 2 | # otp - One-time passwords (multi-factor authentication from the command line) 3 | # 4 | 5 | # 6 | # References 7 | # 8 | 9 | # https://github.com/ohmyzsh/ohmyzsh/tree/master/plugins/otp 10 | 11 | # 12 | # Variables 13 | # 14 | 15 | zstyle -s ':zdotdir:plugin:otp' home 'SECRETS_HOME' || 16 | SECRETS_HOME="${XDG_DATA_HOME:-$HOME/.local/share}/secrets" 17 | 18 | [[ -d $SECRETS_HOME ]] || 19 | git clone git@github.com:mattmc3/secrets $SECRETS_HOME 20 | 21 | # 22 | # Functions 23 | # 24 | 25 | # Load plugin functions. 26 | 0=${(%):-%N} 27 | fpath=(${0:A:h}/functions $fpath) 28 | autoload -Uz ${0:A:h}/functions/*(.:t) 29 | 30 | # 31 | # Completions 32 | # 33 | 34 | function __otp_keys { 35 | reply=($(find $SECRETS_HOME/otp -name \*.otp.asc | xargs basename -s .otp.asc)) 36 | } 37 | 38 | compctl -K __otp_keys otp 39 | 40 | # 41 | # Wrap up 42 | # 43 | 44 | zstyle ":zdotdir:plugin:otp" loaded 'yes' 45 | -------------------------------------------------------------------------------- /plugins/p10k-instaprompt/p10k-instaprompt.plugin.zsh: -------------------------------------------------------------------------------- 1 | # Run this early so we can P10k instant prompt if we need it. 2 | [[ "$ZSH_THEME" == (p10k|powerlevel10k)* ]] || return 1 3 | if [[ -r "${XDG_CACHE_HOME:-$HOME/.cache}/p10k-instant-prompt-${(%):-%n}.zsh" ]]; then 4 | source "${XDG_CACHE_HOME:-$HOME/.cache}/p10k-instant-prompt-${(%):-%n}.zsh" 5 | fi 6 | -------------------------------------------------------------------------------- /plugins/python/functions/_venv: -------------------------------------------------------------------------------- 1 | #compdef venv 2 | 3 | _arguments '-l[list]' '-h[help]' '-p[print venv path]' '-r[remove venv]' '--home[set venv home]' 4 | _values 'venvs' $(venv -l) 5 | 6 | # vim: ft=zsh sw=2 ts=2 et 7 | -------------------------------------------------------------------------------- /plugins/python/functions/_workon: -------------------------------------------------------------------------------- 1 | #compdef workon 2 | 3 | _values 'venvs' $(venv -l) 4 | 5 | # vim: ft=zsh sw=2 ts=2 et 6 | -------------------------------------------------------------------------------- /plugins/python/functions/juno: -------------------------------------------------------------------------------- 1 | #!/bin/zsh 2 | ##? Open a Jupyter notebook. 3 | 4 | if ! venv -p juno 2>/dev/null; then 5 | venv juno 6 | pip install --upgrade pip 7 | pip install jupyterlab 8 | pip install pandas 9 | fi 10 | 11 | local jupyter_prj=$HOME/Projects/mattmc3/jupyter 12 | if [[ ! -d $jupyter_prj ]]; then 13 | git clone git@github.com:mattmc3/jupyter $jupyter_prj 14 | fi 15 | 16 | jupyter lab ${1:-$jupyter_prj} 17 | -------------------------------------------------------------------------------- /plugins/python/functions/pipup: -------------------------------------------------------------------------------- 1 | #!/bin/zsh 2 | pip list --outdated | cut -d ' ' -f1 | xargs -n1 pip install -U 3 | -------------------------------------------------------------------------------- /plugins/python/functions/pyclean: -------------------------------------------------------------------------------- 1 | #!/bin/zsh 2 | ##? Clean common python cache files. 3 | 4 | find "${@:-.}" -type f -name "*.py[co]" -delete 5 | find "${@:-.}" -type d -name "__pycache__" -delete 6 | find "${@:-.}" -depth -type d -name ".mypy_cache" -exec rm -r "{}" + 7 | find "${@:-.}" -depth -type d -name ".pytest_cache" -exec rm -r "{}" + 8 | -------------------------------------------------------------------------------- /plugins/python/functions/venv: -------------------------------------------------------------------------------- 1 | #!/bin/zsh 2 | ##? venv - Manage Python venvs. 3 | 4 | local workon_home 5 | local -a usage o_list o_remove o_path 6 | workon_home=${WORKON_HOME:-${XDG_DATA_HOME:-$HOME/.local/share}/venvs} 7 | usage=( 8 | "usage: venv [--home=] [-r|--remove] [-p|--path] " 9 | " venv [-h|--help] [-l|--list]" 10 | ) 11 | 12 | # Parse arguments 13 | while (( $# )); do 14 | case $1 in 15 | --) 16 | shift 17 | break 18 | ;; 19 | -h|--help) 20 | printf "%s\n" $usage 21 | return 22 | ;; 23 | -l|--list) 24 | o_list+=($1) 25 | ;; 26 | -r|--remove) 27 | o_remove+=($1) 28 | ;; 29 | -p|--path) 30 | o_path+=($1) 31 | ;; 32 | --home) 33 | shift 34 | workon_home=$1 35 | ;; 36 | --home=*) 37 | workon_home=("${1#*=}") 38 | ;; 39 | -*) 40 | echo >&2 "workon: Unknown option '$1'." 41 | return 2 42 | ;; 43 | *) 44 | break 45 | ;; 46 | esac 47 | shift 48 | done 49 | 50 | [[ -d "$workon_home" ]] || mkdir -p "$workon_home" 51 | 52 | # --list 53 | if (( $#o_list )); then 54 | local venv 55 | for venv in $workon_home/*(-/FN); do 56 | echo ${venv:t} 57 | done 58 | return 59 | fi 60 | 61 | # Expecting 62 | if (( $# == 0 )); then 63 | echo >&2 "usage: venv " 64 | return 1 65 | fi 66 | 67 | # --path 68 | if (( $#o_path )); then 69 | if [[ ! -d "$workon_home/$1" ]]; then 70 | echo >&2 "venv: venv not found '$1'." 71 | return 1 72 | fi 73 | echo "$workon_home/$1" 74 | return 75 | fi 76 | 77 | # --remove 78 | if (( $#o_remove )); then 79 | if [[ ! -d "$workon_home/$1" ]]; then 80 | echo >&2 "venv: venv not found '$1'." 81 | return 1 82 | fi 83 | rm -rf -- "$workon_home/$1" 84 | return 85 | fi 86 | 87 | # Make venv if missing and activate 88 | if [[ ! -d "$workon_home/$1" ]]; then 89 | python3 -m venv "$workon_home/$1" || return 1 90 | fi 91 | source "$workon_home/$1/bin/activate" 92 | -------------------------------------------------------------------------------- /plugins/python/functions/workon: -------------------------------------------------------------------------------- 1 | #!/bin/zsh 2 | ##? Work on (activate) a Python venv. 3 | 4 | venv -- "$@" 5 | -------------------------------------------------------------------------------- /plugins/python/python.plugin.zsh: -------------------------------------------------------------------------------- 1 | # 2 | # python 3 | # 4 | 5 | # Load plugin functions. 6 | fpath=(${0:A:h}/functions $fpath) 7 | autoload -U $fpath[1]/*(.:t) 8 | 9 | # workon 10 | export WORKON_HOME="$XDG_DATA_HOME/venvs" 11 | [[ -d "$WORKON_HOME" ]] || mkdir -p "$WORKON_HOME" 12 | 13 | # python aliases 14 | alias py2='python2' 15 | alias py3='python3' 16 | alias py='python3' 17 | alias pip2update="pip2 list --outdated | cut -d ' ' -f1 | xargs -n1 pip2 install -U" 18 | alias pip3update="pip3 list --outdated | cut -d ' ' -f1 | xargs -n1 pip3 install -U" 19 | alias pipup="pip3 list --outdated | cut -d ' ' -f1 | xargs -n1 pip3 install -U" 20 | alias pyfind='find . -name "*.py"' 21 | alias pygrep='grep --include="*.py"' 22 | alias pyva="source .venv/bin/activate" 23 | 24 | # jupyter 25 | export JUPYTER_CONFIG_DIR="${JUPYTER_CONFIG_DIR:-$XDG_CONFIG_HOME/jupyter}" 26 | -------------------------------------------------------------------------------- /plugins/starship-ftl/functions/prompt_starship_setup: -------------------------------------------------------------------------------- 1 | #!/bin/zsh 2 | # When loaded through the prompt command, these prompt_* options will be enabled 3 | prompt_opts=(cr percent sp subst) 4 | 5 | local -a cmds=( 6 | $commands[starship](N) 7 | /opt/homebrew/bin/starship(N) 8 | /usr/local/bin/starship(N) 9 | ) 10 | local starship=$cmds[1] 11 | 12 | if [[ -n "$1" ]]; then 13 | local -a configs=( 14 | $__zsh_config_dir/themes/$1.toml(N) 15 | ${XDG_CONFIG_HOME:-$HOME/.config}/starship/$1.toml(N) 16 | ) 17 | (( $#configs )) && export STARSHIP_CONFIG=$configs[1] 18 | fi 19 | 20 | # Initialize starship. 21 | if zstyle -t ':zephyr:plugin:prompt' 'use-cache'; then 22 | cached-eval 'starship-init-zsh' $starship init zsh 23 | else 24 | source <($starship init zsh) 25 | fi 26 | -------------------------------------------------------------------------------- /plugins/starship-ftl/starship-ftl.plugin.zsh: -------------------------------------------------------------------------------- 1 | # Starship faster-than-light 2 | 3 | zstyle ':zephyr:plugin:prompt' skip yes 4 | 5 | # Load plugin functions. 6 | 0=${(%):-%N} 7 | fpath=(${0:A:h}/functions $fpath) 8 | autoload -Uz ${0:A:h}/functions/*(.:t) 9 | -------------------------------------------------------------------------------- /plugins/xdg/xdg.plugin.zsh: -------------------------------------------------------------------------------- 1 | # 2 | # xdg - don't pollute home 3 | # 4 | 5 | # XDG basedirs 6 | 7 | export XDG_CONFIG_HOME=~/.config 8 | export XDG_CACHE_HOME=~/.cache 9 | export XDG_DATA_HOME=~/.local/share 10 | export XDG_STATE_HOME=~/.local/state 11 | export XDG_RUNTIME_DIR=~/.xdg 12 | export XDG_PROJECTS_DIR=~/Projects 13 | 14 | for _xdgdir in XDG_{CONFIG,CACHE,DATA,STATE}_HOME XDG_RUNTIME_DIR; do 15 | [[ -e ${(P)_xdgdir} ]] || mkdir -p ${(P)_xdgdir} 16 | done 17 | unset _xdgdir 18 | 19 | # 20 | # Shell utils 21 | # 22 | 23 | # less 24 | export LESSKEY="${LESSKEY:-$XDG_CONFIG_HOME/less/lesskey}" 25 | export LESSHISTFILE="${LESSHISTFILE:-$XDG_CACHE_HOME/less/history}" 26 | 27 | # readline 28 | export INPUTRC="${INPUTRC:-$XDG_CONFIG_HOME/readline/inputrc}" 29 | 30 | # screen 31 | export SCREENRC="${SCREENRC:-$XDG_CONFIG_HOME/screen/screenrc}" 32 | 33 | # tmux 34 | export TMUX_CONFIG="${TMUX_CONFIG:-$XDG_CONFIG_HOME/tmux/tmux.conf}" 35 | alias tmux="${aliases[tmux]:-tmux} -f \"\$TMUX_CONFIG\"" 36 | 37 | # wget 38 | export WGETRC="${WGETRC:-$XDG_CONFIG_HOME/wget/wgetrc}" 39 | alias wget="${aliases[wget]:-wget} --hsts-file=\$XDG_CACHE_HOME/wget/wget-hsts" 40 | 41 | # 42 | # Dev tools 43 | # 44 | 45 | # gpg 46 | export GNUPGHOME="${GNUPGHOME:-$XDG_DATA_HOME/gnupg}" 47 | alias gpg="${aliases[gpg]:-gpg} --homedir \"\$GNUPGHOME\"" 48 | 49 | # groovy 50 | if [[ "$OSTYPE" == darwin* ]]; then 51 | export GROOVY_HOME=$HOMEBREW_PREFIX/opt/groovy/libexec # per homebrew 52 | export GROOVY_TURN_OFF_JAVA_WARNINGS="true" 53 | fi 54 | 55 | # jupyter 56 | export JUPYTER_CONFIG_DIR="${JUPYTER_CONFIG_DIR:-$XDG_CONFIG_HOME/jupyter}" 57 | 58 | # node 59 | path+=( 60 | /{opt/homebrew,usr/local}/share/npm/bin(N) 61 | ) 62 | export NPM_CONFIG_USERCONFIG="${NPM_CONFIG_USERCONFIG:-$XDG_CONFIG_HOME/npm/npmrc}" 63 | export NODE_REPL_HISTORY="${NODE_REPL_HISTORY:-$XDG_DATA_HOME/nodejs/repl_history}" 64 | 65 | # nuget 66 | export NUGET_PACKAGES="${NUGET_PACKAGES:-$XDG_CACHE_HOME/NuGetPackages}" 67 | 68 | # postgres 69 | export PSQLRC="${PSQLRC:-$XDG_CONFIG_HOME/pg/psqlrc}" 70 | export PSQL_HISTORY="${PSQL_HISTORY:-$XDG_CACHE_HOME/pg/psql_history}" 71 | export PGPASSFILE="${PGPASSFILE:-$XDG_CONFIG_HOME/pg/pgpass}" 72 | export PGSERVICEFILE="${PGSERVICEFILE:-$XDG_CONFIG_HOME/pg/pg_service.conf}" 73 | 74 | # ruby bundler 75 | export BUNDLE_USER_CONFIG="${BUNDLE_USER_CONFIG:-$XDG_CONFIG_HOME/bundle}" 76 | export BUNDLE_USER_CACHE="${BUNDLE_USER_CACHE:-$XDG_CACHE_HOME/bundle}" 77 | export BUNDLE_USER_PLUGIN="${BUNDLE_USER_PLUGIN:-$XDG_DATA_HOME/bundle}" 78 | 79 | # ruby gems 80 | export GEM_HOME="${GEM_HOME:-$XDG_DATA_HOME/gem}" 81 | export GEM_SPEC_CACHE="${GEM_SPEC_CACHE:-$XDG_CACHE_HOME/gem}" 82 | 83 | # rust 84 | export CARGO_HOME="${CARGO_HOME:-$XDG_DATA_HOME/cargo}" 85 | export RUSTUP_HOME="${RUSTUP_HOME:-$XDG_DATA_HOME/rustup}" 86 | -------------------------------------------------------------------------------- /themes/mmc.toml: -------------------------------------------------------------------------------- 1 | # 2 | # mmc - My default prompt theme 3 | # 4 | 5 | add_newline = false 6 | 7 | # A minimal left prompt 8 | format = """$python$directory$character""" 9 | 10 | # Move the rest of the prompt to the right 11 | right_format = """$status$cmd_duration$git_branch${custom.git_status_dirty}$git_status""" 12 | 13 | # Timeout for commands executed by starship (in milliseconds) 14 | command_timeout=2000 15 | 16 | # Set the palette. 17 | palette = "wombat" 18 | 19 | # Define custom colors 20 | [palettes.tokyo_night] 21 | black = '#15161e' 22 | blue = '#7aa2f7' 23 | cyan = '#7dcfff' 24 | green = '#9ece6a' 25 | purple = '#bb9af7' 26 | red = '#f7768e' 27 | white = '#a9b1d6' 28 | yellow = '#e0af68' 29 | 30 | [palettes.tokyo_night_256] 31 | black = '16' 32 | blue = '111' 33 | cyan = '117' 34 | green = '149' 35 | purple = '141' 36 | red = '210' 37 | white = '146' 38 | yellow = '179' 39 | 40 | [palettes.wombat] 41 | black = '#000000' 42 | blue = '#5da9f6' 43 | cyan = '#82fff7' 44 | green = '#b1e969' 45 | purple = '#e86aff' 46 | red = '#ff615a' 47 | white = '#dedacf' 48 | yellow = '#ebd99c' 49 | 50 | [palettes.wombat_256] 51 | black = '0' 52 | blue = '75' 53 | cyan = '123' 54 | green = '149' 55 | purple = '171' 56 | red = '203' 57 | white = '188' 58 | yellow = '223' 59 | 60 | [character] 61 | format = "$symbol " 62 | success_symbol = "[❯](purple)[❯](cyan)" 63 | error_symbol = "[❯](yellow)[❯](red)" 64 | vicmd_symbol = "[❮](purple)[❮](cyan)" 65 | 66 | [python] 67 | format = '[(\($virtualenv\) )]($style)' 68 | style = 'white' 69 | 70 | [directory] 71 | style = "blue" 72 | truncation_length = 1 73 | truncation_symbol = "" 74 | fish_style_pwd_dir_length = 1 75 | 76 | # Right prompt uses left space padding. 77 | [git_branch] 78 | format = ' [$branch]($style)' 79 | style = 'green' 80 | 81 | [git_status] 82 | format = '( [\[$ahead_behind$stashed\]]($style))' 83 | style = "cyan" 84 | stashed = "≡" 85 | ahead = "⇡${count}" 86 | behind = "⇣${count}" 87 | diverged = "⇕⇡${ahead_count}⇣${behind_count}" 88 | 89 | [custom.git_status_dirty] 90 | when = 'test -n "$(git status --porcelain 2>/dev/null)"' 91 | symbol = "•" 92 | style = "purple" 93 | format="[$symbol]($style)" 94 | shell = ["sh"] 95 | 96 | [shell] 97 | format = '[$indicator]($style)' 98 | fish_indicator = '🐟' # 󰈺 🐟 🐠 99 | powershell_indicator = '_' 100 | pwsh_indicator = '>_' 101 | zsh_indicator = '󠀥%' 102 | bash_indicator = '󠀥$' 103 | style = 'cyan bold' 104 | disabled = true 105 | 106 | [cmd_duration] 107 | format = ' [$duration]($style)' 108 | 109 | [line_break] 110 | disabled = true 111 | 112 | [status] 113 | disabled = false 114 | pipestatus = true 115 | format = '[$symbol$int]($style)' 116 | symbol = '✘' 117 | pipestatus_format = '\[$pipestatus\]($style)' 118 | -------------------------------------------------------------------------------- /themes/prompt_omz_setup: -------------------------------------------------------------------------------- 1 | #!/bin/zsh 2 | 3 | # Be sure OMZ's requirements are set up. 4 | [[ -n "$ZSH" ]] || ZSH="$(antidote path ohmyzsh/ohmyzsh)" 5 | 6 | # Use the 'getantidote/use-omz' plugin to lazy-load whatever you need from OMZ! 7 | # If you don't, you will need to load all the $ZSH/lib prerequisites yourself, and 8 | # may need to uncomment this line: 9 | # source $ZSH/lib/*.zsh 10 | 11 | # Now, load whatever OMZ theme. 12 | [[ -n "$ZSH_THEME" ]] || ZSH_THEME="${1:-robbyrussell}" 13 | source $ZSH/themes/${ZSH_THEME}.zsh-theme 14 | -------------------------------------------------------------------------------- /themes/prompt_p10k_setup: -------------------------------------------------------------------------------- 1 | #!/bin/zsh 2 | if [[ -n "$1" ]]; then 3 | local -a configs=($__zsh_config_dir/themes/$1.p10k.zsh(N)) 4 | (( $#configs )) && source $configs[1] 5 | fi 6 | source ${ANTIDOTE_HOME:-$HOME/.cache/repos}/romkatv/powerlevel10k/powerlevel10k.zsh-theme 7 | -------------------------------------------------------------------------------- /themes/pure.p10k.zsh: -------------------------------------------------------------------------------- 1 | # Generated by Powerlevel10k configuration wizard on 2023-06-26 at 19:34 EDT. 2 | # Based on romkatv/powerlevel10k/config/p10k-pure.zsh, checksum 35142. 3 | # Wizard options: nerdfont-v3 + powerline, large icons, pure, original, 2 lines, sparse, 4 | # instant_prompt=verbose. 5 | # Type `p10k configure` to generate another config. 6 | # 7 | # Config file for Powerlevel10k with the style of Pure (https://github.com/sindresorhus/pure). 8 | # 9 | # Differences from Pure: 10 | # 11 | # - Git: 12 | # - `@c4d3ec2c` instead of something like `v1.4.0~11` when in detached HEAD state. 13 | # - No automatic `git fetch` (the same as in Pure with `PURE_GIT_PULL=0`). 14 | # 15 | # Apart from the differences listed above, the replication of Pure prompt is exact. This includes 16 | # even the questionable parts. For example, just like in Pure, there is no indication of Git status 17 | # being stale; prompt symbol is the same in command, visual and overwrite vi modes; when prompt 18 | # doesn't fit on one line, it wraps around with no attempt to shorten it. 19 | # 20 | # If you like the general style of Pure but not particularly attached to all its quirks, type 21 | # `p10k configure` and pick "Lean" style. This will give you slick minimalist prompt while taking 22 | # advantage of Powerlevel10k features that aren't present in Pure. 23 | 24 | # Temporarily change options. 25 | 'builtin' 'local' '-a' 'p10k_config_opts' 26 | [[ ! -o 'aliases' ]] || p10k_config_opts+=('aliases') 27 | [[ ! -o 'sh_glob' ]] || p10k_config_opts+=('sh_glob') 28 | [[ ! -o 'no_brace_expand' ]] || p10k_config_opts+=('no_brace_expand') 29 | 'builtin' 'setopt' 'no_aliases' 'no_sh_glob' 'brace_expand' 30 | 31 | () { 32 | emulate -L zsh -o extended_glob 33 | 34 | # Unset all configuration options. 35 | unset -m '(POWERLEVEL9K_*|DEFAULT_USER)~POWERLEVEL9K_GITSTATUS_DIR' 36 | 37 | # Zsh >= 5.1 is required. 38 | [[ $ZSH_VERSION == (5.<1->*|<6->.*) ]] || return 39 | 40 | # Prompt colors. 41 | local grey='242' 42 | local red='1' 43 | local yellow='3' 44 | local blue='4' 45 | local magenta='5' 46 | local cyan='6' 47 | local white='7' 48 | 49 | # Left prompt segments. 50 | typeset -g POWERLEVEL9K_LEFT_PROMPT_ELEMENTS=( 51 | # =========================[ Line #1 ]========================= 52 | context # user@host 53 | dir # current directory 54 | vcs # git status 55 | command_execution_time # previous command duration 56 | # =========================[ Line #2 ]========================= 57 | newline # \n 58 | virtualenv # python virtual environment 59 | prompt_char # prompt symbol 60 | ) 61 | 62 | # Right prompt segments. 63 | typeset -g POWERLEVEL9K_RIGHT_PROMPT_ELEMENTS=( 64 | # =========================[ Line #1 ]========================= 65 | # command_execution_time # previous command duration 66 | # virtualenv # python virtual environment 67 | # context # user@host 68 | # time # current time 69 | # =========================[ Line #2 ]========================= 70 | newline # \n 71 | ) 72 | 73 | # Basic style options that define the overall prompt look. 74 | typeset -g POWERLEVEL9K_BACKGROUND= # transparent background 75 | typeset -g POWERLEVEL9K_{LEFT,RIGHT}_{LEFT,RIGHT}_WHITESPACE= # no surrounding whitespace 76 | typeset -g POWERLEVEL9K_{LEFT,RIGHT}_SUBSEGMENT_SEPARATOR=' ' # separate segments with a space 77 | typeset -g POWERLEVEL9K_{LEFT,RIGHT}_SEGMENT_SEPARATOR= # no end-of-line symbol 78 | typeset -g POWERLEVEL9K_VISUAL_IDENTIFIER_EXPANSION= # no segment icons 79 | 80 | # Add an empty line before each prompt except the first. This doesn't emulate the bug 81 | # in Pure that makes prompt drift down whenever you use the Alt-C binding from fzf or similar. 82 | typeset -g POWERLEVEL9K_PROMPT_ADD_NEWLINE=true 83 | 84 | # Magenta prompt symbol if the last command succeeded. 85 | typeset -g POWERLEVEL9K_PROMPT_CHAR_OK_{VIINS,VICMD,VIVIS}_FOREGROUND=$magenta 86 | # Red prompt symbol if the last command failed. 87 | typeset -g POWERLEVEL9K_PROMPT_CHAR_ERROR_{VIINS,VICMD,VIVIS}_FOREGROUND=$red 88 | # Default prompt symbol. 89 | typeset -g POWERLEVEL9K_PROMPT_CHAR_{OK,ERROR}_VIINS_CONTENT_EXPANSION='❯' 90 | # Prompt symbol in command vi mode. 91 | typeset -g POWERLEVEL9K_PROMPT_CHAR_{OK,ERROR}_VICMD_CONTENT_EXPANSION='❮' 92 | # Prompt symbol in visual vi mode is the same as in command mode. 93 | typeset -g POWERLEVEL9K_PROMPT_CHAR_{OK,ERROR}_VIVIS_CONTENT_EXPANSION='❮' 94 | # Prompt symbol in overwrite vi mode is the same as in command mode. 95 | typeset -g POWERLEVEL9K_PROMPT_CHAR_OVERWRITE_STATE=false 96 | 97 | # Grey Python Virtual Environment. 98 | typeset -g POWERLEVEL9K_VIRTUALENV_FOREGROUND=$grey 99 | # Don't show Python version. 100 | typeset -g POWERLEVEL9K_VIRTUALENV_SHOW_PYTHON_VERSION=false 101 | typeset -g POWERLEVEL9K_VIRTUALENV_{LEFT,RIGHT}_DELIMITER= 102 | 103 | # Blue current directory. 104 | typeset -g POWERLEVEL9K_DIR_FOREGROUND=$blue 105 | 106 | # Context format when root: user@host. The first part white, the rest grey. 107 | typeset -g POWERLEVEL9K_CONTEXT_ROOT_TEMPLATE="%F{$white}%n%f%F{$grey}@%m%f" 108 | # Context format when not root: user@host. The whole thing grey. 109 | typeset -g POWERLEVEL9K_CONTEXT_TEMPLATE="%F{$grey}%n@%m%f" 110 | # Don't show context unless root or in SSH. 111 | typeset -g POWERLEVEL9K_CONTEXT_{DEFAULT,SUDO}_CONTENT_EXPANSION= 112 | 113 | # Show previous command duration only if it's >= 5s. 114 | typeset -g POWERLEVEL9K_COMMAND_EXECUTION_TIME_THRESHOLD=5 115 | # Don't show fractional seconds. Thus, 7s rather than 7.3s. 116 | typeset -g POWERLEVEL9K_COMMAND_EXECUTION_TIME_PRECISION=0 117 | # Duration format: 1d 2h 3m 4s. 118 | typeset -g POWERLEVEL9K_COMMAND_EXECUTION_TIME_FORMAT='d h m s' 119 | # Yellow previous command duration. 120 | typeset -g POWERLEVEL9K_COMMAND_EXECUTION_TIME_FOREGROUND=$yellow 121 | 122 | # Grey Git prompt. This makes stale prompts indistinguishable from up-to-date ones. 123 | typeset -g POWERLEVEL9K_VCS_FOREGROUND=$grey 124 | 125 | # Disable async loading indicator to make directories that aren't Git repositories 126 | # indistinguishable from large Git repositories without known state. 127 | typeset -g POWERLEVEL9K_VCS_LOADING_TEXT= 128 | 129 | # Don't wait for Git status even for a millisecond, so that prompt always updates 130 | # asynchronously when Git state changes. 131 | typeset -g POWERLEVEL9K_VCS_MAX_SYNC_LATENCY_SECONDS=0 132 | 133 | # Cyan ahead/behind arrows. 134 | typeset -g POWERLEVEL9K_VCS_{INCOMING,OUTGOING}_CHANGESFORMAT_FOREGROUND=$cyan 135 | # Don't show remote branch, current tag or stashes. 136 | typeset -g POWERLEVEL9K_VCS_GIT_HOOKS=(vcs-detect-changes git-untracked git-aheadbehind) 137 | # Don't show the branch icon. 138 | typeset -g POWERLEVEL9K_VCS_BRANCH_ICON= 139 | # When in detached HEAD state, show @commit where branch normally goes. 140 | typeset -g POWERLEVEL9K_VCS_COMMIT_ICON='@' 141 | # Don't show staged, unstaged, untracked indicators. 142 | typeset -g POWERLEVEL9K_VCS_{STAGED,UNSTAGED,UNTRACKED}_ICON= 143 | # Show '*' when there are staged, unstaged or untracked files. 144 | typeset -g POWERLEVEL9K_VCS_DIRTY_ICON='*' 145 | # Show '⇣' if local branch is behind remote. 146 | typeset -g POWERLEVEL9K_VCS_INCOMING_CHANGES_ICON=':⇣' 147 | # Show '⇡' if local branch is ahead of remote. 148 | typeset -g POWERLEVEL9K_VCS_OUTGOING_CHANGES_ICON=':⇡' 149 | # Don't show the number of commits next to the ahead/behind arrows. 150 | typeset -g POWERLEVEL9K_VCS_{COMMITS_AHEAD,COMMITS_BEHIND}_MAX_NUM=1 151 | # Remove space between '⇣' and '⇡' and all trailing spaces. 152 | typeset -g POWERLEVEL9K_VCS_CONTENT_EXPANSION='${${${P9K_CONTENT/⇣* :⇡/⇣⇡}// }//:/ }' 153 | 154 | # Grey current time. 155 | typeset -g POWERLEVEL9K_TIME_FOREGROUND=$grey 156 | # Format for the current time: 09:51:02. See `man 3 strftime`. 157 | typeset -g POWERLEVEL9K_TIME_FORMAT='%D{%H:%M:%S}' 158 | # If set to true, time will update when you hit enter. This way prompts for the past 159 | # commands will contain the start times of their commands rather than the end times of 160 | # their preceding commands. 161 | typeset -g POWERLEVEL9K_TIME_UPDATE_ON_COMMAND=false 162 | 163 | # Transient prompt works similarly to the builtin transient_rprompt option. It trims down prompt 164 | # when accepting a command line. Supported values: 165 | # 166 | # - off: Don't change prompt when accepting a command line. 167 | # - always: Trim down prompt when accepting a command line. 168 | # - same-dir: Trim down prompt when accepting a command line unless this is the first command 169 | # typed after changing current working directory. 170 | typeset -g POWERLEVEL9K_TRANSIENT_PROMPT=off 171 | 172 | # Instant prompt mode. 173 | # 174 | # - off: Disable instant prompt. Choose this if you've tried instant prompt and found 175 | # it incompatible with your zsh configuration files. 176 | # - quiet: Enable instant prompt and don't print warnings when detecting console output 177 | # during zsh initialization. Choose this if you've read and understood 178 | # https://github.com/romkatv/powerlevel10k/blob/master/README.md#instant-prompt. 179 | # - verbose: Enable instant prompt and print a warning when detecting console output during 180 | # zsh initialization. Choose this if you've never tried instant prompt, haven't 181 | # seen the warning, or if you are unsure what this all means. 182 | typeset -g POWERLEVEL9K_INSTANT_PROMPT=verbose 183 | 184 | # Hot reload allows you to change POWERLEVEL9K options after Powerlevel10k has been initialized. 185 | # For example, you can type POWERLEVEL9K_BACKGROUND=red and see your prompt turn red. Hot reload 186 | # can slow down prompt by 1-2 milliseconds, so it's better to keep it turned off unless you 187 | # really need it. 188 | typeset -g POWERLEVEL9K_DISABLE_HOT_RELOAD=true 189 | 190 | # If p10k is already loaded, reload configuration. 191 | # This works even with POWERLEVEL9K_DISABLE_HOT_RELOAD=true. 192 | (( ! $+functions[p10k] )) || p10k reload 193 | } 194 | 195 | # Tell `p10k configure` which file it should overwrite. 196 | typeset -g POWERLEVEL9K_CONFIG_FILE=${${(%):-%x}:a} 197 | 198 | (( ${#p10k_config_opts} )) && setopt ${p10k_config_opts[@]} 199 | 'builtin' 'unset' 'p10k_config_opts' 200 | -------------------------------------------------------------------------------- /themes/zephyr.toml: -------------------------------------------------------------------------------- 1 | # 2 | # zephyr.toml - Zephyr default prompt theme 3 | # 4 | 5 | add_newline = false 6 | 7 | # A minimal left prompt 8 | format = """$python$directory$character""" 9 | 10 | # move the rest of the prompt to the right 11 | #right_format = """$status$git_branch${custom.git_status_dirty}$git_status""" 12 | right_format = """$status$cmd_duration$git_branch${custom.git_status_dirty}$git_status""" 13 | 14 | palette="wombat" 15 | 16 | # Define custom colors 17 | [palettes.tokyo_night] 18 | black = '#15161e' 19 | blue = '#7aa2f7' 20 | cyan = '#7dcfff' 21 | green = '#9ece6a' 22 | purple = '#bb9af7' 23 | red = '#f7768e' 24 | white = '#a9b1d6' 25 | yellow = '#e0af68' 26 | 27 | [palettes.tokyo_night_256] 28 | black = '16' 29 | blue = '111' 30 | cyan = '117' 31 | green = '149' 32 | purple = '141' 33 | red = '210' 34 | white = '146' 35 | yellow = '179' 36 | 37 | [palettes.wombat] 38 | black = '#000000' 39 | blue = '#5da9f6' 40 | cyan = '#82fff7' 41 | green = '#b1e969' 42 | purple = '#e86aff' 43 | red = '#ff615a' 44 | white = '#dedacf' 45 | yellow = '#ebd99c' 46 | 47 | [palettes.wombat_256] 48 | black = '0' 49 | blue = '75' 50 | cyan = '123' 51 | green = '149' 52 | purple = '171' 53 | red = '203' 54 | white = '188' 55 | yellow = '223' 56 | 57 | [character] 58 | success_symbol = "[❯](purple)[❯](cyan)" 59 | error_symbol = "[❯](yellow)[❯](red)" 60 | vicmd_symbol = "[❮](purple)[❮](cyan)" 61 | 62 | [python] 63 | format = '[(\($virtualenv\) )]($style)' 64 | style = 'white' 65 | 66 | [directory] 67 | style = "blue" 68 | truncation_length = 1 69 | truncation_symbol = "" 70 | fish_style_pwd_dir_length = 1 71 | 72 | # right prompt uses left space padding 73 | [git_branch] 74 | format = ' [$branch]($style)' 75 | style = 'green' 76 | 77 | [git_status] 78 | format = '( [\[$ahead_behind$stashed\]]($style))' 79 | style = "cyan" 80 | stashed = "≡" 81 | ahead = "⇡${count}" 82 | behind = "⇣${count}" 83 | 84 | [custom.git_status_dirty] 85 | when = 'test -n "$(git status --porcelain 2>/dev/null)"' 86 | symbol = "•" 87 | style = "white" 88 | format="[$symbol]($style)" 89 | shell = ["sh"] 90 | 91 | [cmd_duration] 92 | format = ' [$duration]($style)' 93 | 94 | [line_break] 95 | disabled = true 96 | 97 | [status] 98 | disabled = false 99 | symbol = ' ✘' 100 | --------------------------------------------------------------------------------