├── .editorconfig ├── .gitignore ├── LICENSE ├── README.md ├── bin └── zephyr ├── lib └── bootstrap.zsh ├── makefile ├── plugins ├── color │ ├── README.md │ └── color.plugin.zsh ├── completion │ └── completion.plugin.zsh ├── compstyle │ └── compstyle.plugin.zsh ├── confd │ └── confd.plugin.zsh ├── directory │ ├── README.md │ └── directory.plugin.zsh ├── editor │ └── editor.plugin.zsh ├── environment │ └── environment.plugin.zsh ├── helper │ ├── README.md │ └── helper.plugin.zsh ├── history │ └── history.plugin.zsh ├── homebrew │ ├── README.md │ └── homebrew.plugin.zsh ├── macos │ ├── README.md │ ├── functions │ │ ├── _manp │ │ ├── cdf │ │ ├── flushdns │ │ ├── hidefiles │ │ ├── lmk │ │ ├── mand │ │ ├── manp │ │ ├── ofd │ │ ├── peek │ │ ├── pfd │ │ ├── pfs │ │ ├── pushdf │ │ ├── rmdsstore │ │ ├── showfiles │ │ └── trash │ └── macos.plugin.zsh ├── prompt │ ├── prompt.plugin.zsh │ └── themes │ │ ├── hydro.toml │ │ ├── prezto.toml │ │ └── zephyr.toml ├── utility │ └── utility.plugin.zsh └── zfunctions │ ├── README.md │ └── zfunctions.plugin.zsh ├── runcoms ├── zshenv.zsh ├── zshrc.zsh └── zstyles.zsh ├── tests ├── __init__.zsh ├── runtests ├── test_color.md ├── test_completion.md ├── test_confd.md ├── test_directory.md ├── test_editor.md ├── test_environment.md ├── test_helper.md ├── test_history.md ├── test_homebrew.md ├── test_macos.md ├── test_prompt.md ├── test_utility.md └── test_zfunctions.md ├── zephyr.plugin.zsh └── zephyr.zsh /.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 | indent_style = space 13 | trim_trailing_whitespace = false 14 | 15 | [.git*] 16 | indent_style = tab 17 | indent_size = 4 18 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | ~* 2 | *.zwc 3 | *.zwc.old 4 | .external/ 5 | .prompts/ 6 | contribs/ 7 | prompts/*/ 8 | !prompts/functions 9 | .cache/ 10 | .foo/ 11 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2009-2011 Robby Russell and contributors 4 | Copyright (c) 2011-2017 Sorin Ionescu and contributors 5 | Copyright (c) 2018-2019 Kaleb Elwert and contributors 6 | Copyright (c) 2022- Matt McElheny and contributors 7 | 8 | Permission is hereby granted, free of charge, to any person obtaining a copy 9 | of this software and associated documentation files (the "Software"), to deal 10 | in the Software without restriction, including without limitation the rights 11 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 12 | copies of the Software, and to permit persons to whom the Software is 13 | furnished to do so, subject to the following conditions: 14 | 15 | The above copyright notice and this permission notice shall be included in all 16 | copies or substantial portions of the Software. 17 | 18 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 19 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 20 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 21 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 22 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 23 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 24 | SOFTWARE. 25 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # :wind_face: Zephyr 2 | 3 | > A Zsh framework as nice as a cool summer breeze 4 | 5 | Zsh is a wonderful shell, but out-of-the-box it needs a boost. That's where Zephyr comes 6 | in. 7 | 8 | Zephyr combines some of the best parts from [Prezto][prezto] and other Zsh frameworks, 9 | removes bloat and dependencies, and prioritizes speed and simplicity. 10 | 11 | Zephyr can be thought of as a fast, lightweight set of independent Zsh features, and is 12 | designed to be one of the first things you load to build your ideal Zsh config. 13 | 14 | Combine Zephyr with a [plugin manager][antidote] and some [awesome 15 | plugins](https://github.com/unixorn/awesome-zsh-plugins) and you'll have a powerful Zsh 16 | setup that rivals anything out there. 17 | 18 | ## Project goals 19 | 20 | Zephyr allows you to take an _a la carte_ approach to building your ideal Zsh 21 | configuration. Other Zsh frameworks are meant to be used wholesale and are not truly 22 | modular. Zephyr is different - each of its plugins works independently, and are designed 23 | to pair well with a modern Zsh plugin manager like [antidote]. Zephyr can be used in 24 | whole or in part, and plays nice with other popular plugins. Zephyr brings together core 25 | Zsh functionality that typically is not available elsewhere as standalone plugins - 26 | while favoring a build-your-own composable Zsh config. 27 | 28 | ## Prompt 29 | 30 | Zephyr comes with an (optional) [Starship][starship] prompt config. 31 | 32 | ![Zephyr Prompt][terminal-img] 33 | 34 | ## Install 35 | 36 | ### Using a Plugin manager 37 | 38 | If your plugin manager supports using sub-plugins, you can load Zephyr that way as well. 39 | 40 | [Antidote][antidote] is one such plugin manager. You can load only the parts of Zephyr you need like so: 41 | 42 | ```shell 43 | # .zsh_plugins.txt 44 | # pick only the plugins you want and remove the rest 45 | mattmc3/zephyr path:plugins/color 46 | mattmc3/zephyr path:plugins/completion 47 | mattmc3/zephyr path:plugins/compstyle 48 | mattmc3/zephyr path:plugins/confd 49 | mattmc3/zephyr path:plugins/directory 50 | mattmc3/zephyr path:plugins/editor 51 | mattmc3/zephyr path:plugins/environment 52 | mattmc3/zephyr path:plugins/history 53 | mattmc3/zephyr path:plugins/homebrew 54 | mattmc3/zephyr path:plugins/macos 55 | mattmc3/zephyr path:plugins/prompt 56 | mattmc3/zephyr path:plugins/utility 57 | mattmc3/zephyr path:plugins/zfunctions 58 | ``` 59 | 60 | ### Manually 61 | 62 | Add the following snippet to your `.zshrc`: 63 | 64 | ```zsh 65 | # Clone Zephyr. 66 | [[ -d ${ZDOTDIR:-~}/.zephyr ]] || 67 | git clone --depth=1 https://github.com/mattmc3/zephyr ${ZDOTDIR:-~}/.zephyr 68 | 69 | # Use zstyle to specify which plugins you want. Order matters. 70 | zephyr_plugins=( 71 | zfunctions 72 | directory 73 | editor 74 | history 75 | ) 76 | zstyle ':zephyr:load' plugins $zephyr_plugins 77 | 78 | # Source Zephyr. 79 | source ${ZDOTDIR:-~}/.zephyr/zephyr.zsh 80 | ``` 81 | 82 | ## Plugins 83 | 84 | - **color** - Make terminal things more colorful 85 | - **completion** - Load and initialize the built-in zsh completion system 86 | - **compstyle** - Load and initialize a completion style system 87 | - **confd** - Source a Fish-like `conf.d` directory 88 | - **directory** - Set options and aliases related to the dirstack and filesystem 89 | - **editor** - Override and fill in the gaps of the default keybinds 90 | - **environment** - Define common environment variables 91 | - **history** - Load and initialize the built-in zsh history system 92 | - **homebrew** - Functionality for users of Homebrew 93 | - **macos** - Functionality for macOS users 94 | - **prompt** - Load and initialize the built-in zsh prompt system 95 | - **utility** - Common shell utilities, aimed at making cross platform work less painful 96 | - **zfunctions** - Lazy load a Fish-like functions directory 97 | 98 | ## Why don't you include... 99 | 100 | _Q: Why don't you include programming language plugins (eg: Python, Ruby)?_ \ 101 | **A:** These kinds of plugins can be very opinionated, and are in need of lots of upkeep 102 | from maintainers that use those languages. Language plugins are already available via 103 | Oh-My-Zsh and Prezto, and can always be installed with [a plugin manager that supports 104 | subplugins][antidote]. 105 | 106 | _Q: Why don't you also include popular plugins the way Prezto does (eg: 107 | zsh-autosuggestions, zsh-history-substring-search)?_ \ 108 | **A:** These kinds of utilities are already 109 | available as standalone plugins. Zephyr aims to include only core Zsh functionality that 110 | you can't already easily get via a [plugin manager][antidote], with a few exceptions for 111 | convenience. I have experimented with including submodules similar to Prezto, but was 112 | not happy with the result. Simpler is better. 113 | 114 | ## Credits 115 | 116 | Zephyr is a derivative work of the following great projects: 117 | 118 | - [Prezto][prezto] - [MIT License][prezto-license] 119 | - [zsh-utils][zsh-utils] - [MIT License][zsh-utils-license] 120 | - [Oh-My-Zsh][ohmyzsh] - [MIT License][ohmyzsh-license] 121 | 122 | [antidote]: https://antidote.sh 123 | [ohmyzsh]: https://github.com/ohmyzsh/ohmyzsh 124 | [ohmyzsh-license]: https://github.com/ohmyzsh/ohmyzsh/blob/master/LICENSE.txt 125 | [prezto]: https://github.com/sorin-ionescu/prezto 126 | [prezto-license]: https://github.com/sorin-ionescu/prezto/blob/master/LICENSE 127 | [zsh-utils]: https://github.com/belak/zsh-utils 128 | [zsh-utils-license]: https://github.com/belak/zsh-utils/blob/main/LICENSE 129 | [terminal-img]: https://raw.githubusercontent.com/mattmc3/zephyr/resources/img/terminal.png 130 | [starship]: https://starship.rs 131 | -------------------------------------------------------------------------------- /bin/zephyr: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | ##? usage: zephyr 3 | # To check, run: shellcheck -e SC3043 -e SC2016 ./zephyr 4 | 5 | # Zsh can be POSIX too... with help. 6 | [ -n "$ZSH_VERSION" ] && setopt POSIX_ARGZERO 7 | 8 | # THIS_SCRIPT="$(realpath "$0")" 9 | ZEPHYR_HOME="$(realpath "$0"/../..)" 10 | 11 | # POSIX test for function existance. 12 | is_function() { 13 | [ "$#" -eq 1 ] || return 1 14 | type "$1" | sed "s/$1//" | grep -qwi function 15 | } 16 | 17 | ##? commands: 18 | ##? help Display this help 19 | zephyr_help() { 20 | # echo "$0" 21 | grep "^##?" "$0" | cut -c 5- 22 | } 23 | 24 | contains() {( 25 | while getopts "i" opt; do 26 | case "$opt" in 27 | i) o_index=1 ;; 28 | *) return 1 ;; 29 | esac 30 | done 31 | shift $(( OPTIND - 1 )) 32 | 33 | if [ "$#" -eq 0 ]; then 34 | echo >&2 "contains: key not specified" 35 | return 1 36 | fi 37 | 38 | key="$1"; shift 39 | index=0 40 | for val in "$@"; do 41 | index=$(( index + 1 )) 42 | if [ "$val" = "$key" ]; then 43 | [ -n "$o_index" ] && echo $index 44 | return 0 45 | fi 46 | done 47 | return 1 48 | )} 49 | 50 | print_start_region() { 51 | echo "#region $1" 52 | echo "#" 53 | } 54 | 55 | print_end_region() { 56 | echo "#" 57 | echo "#endregion" 58 | } 59 | 60 | ##? bulid1 Build the .zephyr1 file 61 | zephyr_build1() { 62 | local filter_regions squish_newlines anon_func_wrapper noop 63 | local tmpfile zephyr1_file plugin plugin_file 64 | tmpfile=$ZEPHYR_HOME/lib/.zephyr1.tmp 65 | zephyr1_file="$ZEPHYR_HOME/lib/.zephyr1" 66 | 67 | noop='{print $0}' 68 | 69 | filter_regions=' 70 | BEGIN { skip=0 } 71 | /^\#region/ { skip=1; next } 72 | /^\#endregion/ { skip=0; next } 73 | skip==0 { print } 74 | ' 75 | 76 | squish_newlines=' 77 | BEGIN { nl=0 } 78 | NF==0 { nl+=1 } 79 | NF>0 { nl=0 } 80 | nl<2 { print } 81 | ' 82 | 83 | anon_func_wrapper=' 84 | BEGIN { print ""; print "() {" } 85 | NF==0 { print $0; next } 86 | { print " " $0 } 87 | END { print "}"; print "" } 88 | ' 89 | 90 | { 91 | echo "#!/bin/zsh" 92 | echo "# .zshrc1" 93 | echo "# > First things first - start your .zshrc off right with Zephyr lite" 94 | echo "# Project Home: https://github.com/mattmc3/zephyr" 95 | echo 96 | 97 | print_start_region "bootstrap" 98 | awk "$filter_regions" "$ZEPHYR_HOME/lib/bootstrap.zsh" 99 | print_end_region 100 | print_start_region "helper" 101 | awk "$filter_regions" "$ZEPHYR_HOME/plugins/helper/helper.plugin.zsh" 102 | print_end_region 103 | } > "$tmpfile" 104 | 105 | for plugin in \ 106 | environment homebrew history directory color editor utility zfunctions \ 107 | prompt compstyle completion confd 108 | do 109 | plugin_file="$ZEPHYR_HOME/plugins/${plugin}/${plugin}.plugin.zsh" 110 | { 111 | print_start_region "$plugin" 112 | outfilter=$noop 113 | if contains "$plugin" color compstyle directory editor history homebrew utility zfunctions; then 114 | outfilter="$anon_func_wrapper" 115 | fi 116 | awk "$filter_regions" "$plugin_file" | tac | sed -e '/./,$!d' | tac | sed -e '/./,$!d' | awk "$outfilter" 117 | print_end_region 118 | } >> "$tmpfile" 119 | done 120 | 121 | { 122 | awk "$squish_newlines" "$tmpfile" 123 | echo 124 | echo "# vim: ft=zsh sw=2 ts=2 et" 125 | } > "$zephyr1_file" 126 | 127 | # Cleanup 128 | rm -f -- "$tmpfile" 129 | } 130 | 131 | # main zephyr command 132 | zephyr() { 133 | local subcmd 134 | if [ "$#" -eq 0 ]; then 135 | echo >&2 "zephyr: expecting a subcommand." 136 | echo 137 | zephyr_help 138 | return 1 139 | fi 140 | 141 | subcmd="$1" 142 | if [ "$subcmd" = "-h" ] || [ "$subcmd" = "--help" ]; then 143 | # Support -h/--help flags 144 | subcmd="help" 145 | else 146 | # Make kebab-case-subcommands work. 147 | subcmd=$(printf '%s' "$subcmd" | tr '-' '_') 148 | fi 149 | 150 | # Call the subcommand if it exists. 151 | if is_function "zephyr_${subcmd}"; then 152 | shift 153 | "zephyr_${subcmd}" "$@" 154 | else 155 | echo >&2 "zephyr: subcommand not found '$subcmd'." 156 | return 1 157 | fi 158 | } 159 | zephyr "$@" 160 | 161 | # vim: set sw=2 sts=2 ts=8 et: 162 | -------------------------------------------------------------------------------- /lib/bootstrap.zsh: -------------------------------------------------------------------------------- 1 | #region HEADER 2 | # 3 | # bootstrap: Ensure Zephyr is properly boostrapped. 4 | # 5 | 6 | # Set ZEPHYR_HOME. 7 | 0=${(%):-%N} 8 | : ${ZEPHYR_HOME:=${0:a:h:h}} 9 | #endregion 10 | 11 | # Set critical Zsh options. 12 | setopt extended_glob interactive_comments 13 | 14 | # Set Zsh locations. 15 | typeset -gx __zsh_{config,cache,user_data}_dir 16 | : ${__zsh_config_dir:=${ZDOTDIR:-${XDG_CONFIG_HOME:-$HOME/.config}/zsh}} 17 | : ${__zsh_user_data_dir:=${XDG_DATA_HOME:-$HOME/.local/share}/zsh} 18 | : ${__zsh_cache_dir:=${XDG_CACHE_HOME:-$HOME/.cache}/zsh} 19 | mkdir -p $__zsh_config_dir $__zsh_user_data_dir $__zsh_cache_dir 20 | 21 | # There's not really a post_zshrc event, so we're going to fake one by adding a 22 | # function called run_post_zshrc to the precmd event. That function only runs once, 23 | # and then unregisters itself. If the user wants to (or needs to because it doesn't 24 | # play well with a plugin), they can run it themselves manually at the very end of 25 | # their .zshrc, and then it unregisters the precmd event. 26 | 27 | # Define a variable to hold actions run during the post_zshrc event. 28 | typeset -ga post_zshrc_hook 29 | 30 | # Add our new event. 31 | function run_post_zshrc { 32 | # Run anything attached to the post_zshrc hook 33 | local fn 34 | for fn in $post_zshrc_hook; do 35 | # Uncomment to debug: 36 | # echo "post_zshrc is about to run: ${=fn}" 37 | "${=fn}" 38 | done 39 | 40 | # Now delete the precmd hook and self-remove this function and its list var so 41 | # that it only runs once, and doesn't keep running on every future precmd event. 42 | add-zsh-hook -d precmd run_post_zshrc 43 | unfunction -- run_post_zshrc 44 | unset -- post_zshrc_hook 45 | } 46 | 47 | # Attach run_post_zshrc to built-in precmd. 48 | autoload -U add-zsh-hook 49 | add-zsh-hook precmd run_post_zshrc 50 | 51 | #region LOAD HELPERS 52 | zstyle -t ':zephyr:plugin:helper' loaded \ 53 | || source $ZEPHYR_HOME/plugins/helper/helper.plugin.zsh 54 | #endregion 55 | 56 | #region MARK LOADED 57 | zstyle ":zephyr:lib:bootstrap" loaded 'yes' 58 | #endregion 59 | -------------------------------------------------------------------------------- /makefile: -------------------------------------------------------------------------------- 1 | ##? zephyr - A Zsh framework as nice as a cool summer breeze 2 | ##? 3 | ##? Usage: make 4 | ##? 5 | ##? Commands: 6 | 7 | .DEFAULT_GOAL := help 8 | all : build help test submodules 9 | .PHONY : all 10 | 11 | ##? build run build tasks 12 | build: 13 | ./bin/build_external 14 | 15 | ##? test run cli tests 16 | test: 17 | ./tests/runtests 18 | 19 | ##? submodules update all submodules 20 | submodules: 21 | git submodule update --recursive --remote 22 | 23 | ##? help show this message 24 | help: 25 | @grep "^##?" makefile | cut -c 5- 26 | -------------------------------------------------------------------------------- /plugins/color/README.md: -------------------------------------------------------------------------------- 1 | # Color 2 | 3 | > Make the terminal more colorful 4 | 5 | ## Features 6 | 7 | This plugin adds the following features: 8 | 9 | | feature | description | 10 | | --------------------------- | ------------------------------------------------------- | 11 | | autoload `colors` | Includes Zsh built in [colors][colors] | 12 | | colorize man pages | Running man now shows docs in color | 13 | | colorize `ls` | Uses `dircolors` if found to set `LSCOLORS`/`LS_COLORS` | 14 | | add color flags to commands | Add colors for `grep`, `ls`, and `diff` commands | 15 | | colorize completions | Add zstyles for list-colors | 16 | 17 | ## Aliases 18 | 19 | This plugin adds/modifies the following aliases: 20 | 21 | | alias | description | 22 | | ---------- | ----------------------------------------- | 23 | | `diff` | Adds `--color` flag | 24 | | `grep` | Adds `--color=auto` flag | 25 | | `ls` | Adds `--color=auto` flag | 26 | | `colormap` | Show a colormap with terminal color codes | 27 | 28 | ## Variables 29 | 30 | This plugin sets the following variables: 31 | 32 | | variable | description | 33 | | ----------------- | ----------------------------- | 34 | | `LESS_TERMCAP_md` | start less bold style | 35 | | `LESS_TERMCAP_mb` | start less blink style | 36 | | `LESS_TERMCAP_so` | start less standout style | 37 | | `LESS_TERMCAP_us` | start less underline style | 38 | | `LESS_TERMCAP_se` | end less standout style | 39 | | `LESS_TERMCAP_ue` | end less underline style | 40 | | `LESS_TERMCAP_me` | end less bold/blink style | 41 | | `LS_COLORS` | ls colors for GNU systems | 42 | | `LSCOLORS` | ls colors for BSD systems | 43 | | `CLICOLOR` | Enable colors for BSD systems | 44 | 45 | ## Customizations 46 | 47 | This plugin allows for the following customizations: 48 | 49 | To cache the results of the `dircolors` call, you can set: 50 | 51 | `zstyle ':zephyr:plugin:color' 'use-cache' 'yes'` 52 | 53 | To always use caching to speed up expensive calls, you can set: 54 | 55 | `zstyle ':zephyr:plugin:*' 'use-cache' 'yes'` 56 | 57 | [colors]: https://zsh.sourceforge.io/Doc/Release/User-Contributions.html#index-colors 58 | -------------------------------------------------------------------------------- /plugins/color/color.plugin.zsh: -------------------------------------------------------------------------------- 1 | #region HEADER 2 | # 3 | # color: Make the terminal more colorful. 4 | # 5 | #endregion 6 | 7 | # Return if requirements are not met. 8 | [[ "$TERM" != 'dumb' ]] || return 1 9 | ! zstyle -t ":zephyr:plugin:color" skip || return 0 10 | 11 | # Built-in zsh colors. 12 | autoload -Uz colors && colors 13 | 14 | # Colorize man pages. 15 | export LESS_TERMCAP_md=${LESS_TERMCAP_md:-$fg_bold[blue]} # start bold 16 | export LESS_TERMCAP_mb=${LESS_TERMCAP_mb:-$fg_bold[blue]} # start blink 17 | export LESS_TERMCAP_so=${LESS_TERMCAP_so:-$'\e[00;47;30m'} # start standout: white bg, black fg 18 | export LESS_TERMCAP_us=${LESS_TERMCAP_us:-$'\e[04;35m'} # start underline: underline magenta 19 | export LESS_TERMCAP_se=${LESS_TERMCAP_se:-$reset_color} # end standout 20 | export LESS_TERMCAP_ue=${LESS_TERMCAP_ue:-$reset_color} # end underline 21 | export LESS_TERMCAP_me=${LESS_TERMCAP_me:-$reset_color} # end bold/blink 22 | 23 | # Set LS_COLORS using (g)dircolors if found. 24 | if [[ -z "$LS_COLORS" ]]; then 25 | _dircolors_cmds=( 26 | $commands[dircolors](N) $commands[gdircolors](N) 27 | ) 28 | if (( $#_dircolors_cmds )); then 29 | if zstyle -t ':zephyr:plugin:color' 'use-cache'; then 30 | cached-eval "${_dircolors_cmds[1]:t}" "$_dircolors_cmds[1]" --sh 31 | else 32 | source <("$_dircolors_cmds[1]" --sh) 33 | fi 34 | fi 35 | unset _dircolors_cmds 36 | 37 | # Pick a reasonable default for LS_COLORS if it hasn't been set by this point. 38 | export LS_COLORS="${LS_COLORS:-di=34:ln=35:so=32:pi=33:ex=31:bd=1;36:cd=1;33:su=30;41:sg=30;46:tw=30;42:ow=30;43}" 39 | fi 40 | 41 | # Missing dircolors is a good indicator of a BSD system. Set LSCOLORS for macOS/BSD. 42 | if (( ! $+commands[dircolors] )); then 43 | # For BSD systems, set LSCOLORS. 44 | export CLICOLOR=${CLICOLOR:-1} 45 | export LSCOLORS="${LSCOLORS:-exfxcxdxbxGxDxabagacad}" 46 | fi 47 | 48 | # Set aliases. 49 | if ! zstyle -t ':zephyr:plugin:color:alias' skip; then 50 | # Print a simple colormap. 51 | alias colormap='for i in {0..255}; do print -Pn "%K{$i} %k%F{$i}${(l:3::0:)i}%f " ${${(M)$((i%6)):#3}:+"\n"}; done' 52 | 53 | # Set colors for grep. 54 | alias grep="${aliases[grep]:-grep} --color=auto" 55 | 56 | # Set colors for ls. 57 | alias ls="${aliases[ls]:-ls} --color=auto" 58 | if (( $+commands[gls] )); then 59 | alias gls="${aliases[gls]:-gls} --color=auto" 60 | fi 61 | 62 | # Set colors for diff. 63 | if command diff --color /dev/null{,} &>/dev/null; then 64 | alias diff="${aliases[diff]:-diff} --color" 65 | fi 66 | fi 67 | 68 | # Colorize completions. 69 | zstyle ':completion:*:default' list-colors ${(s.:.)LS_COLORS} 70 | 71 | #region MARK LOADED 72 | zstyle ':zephyr:plugin:color' loaded 'yes' 73 | #endregion 74 | -------------------------------------------------------------------------------- /plugins/completion/completion.plugin.zsh: -------------------------------------------------------------------------------- 1 | #region HEADER 2 | # 3 | # completion: Set up zsh completions. 4 | # 5 | 6 | # References: 7 | # - https://github.com/sorin-ionescu/prezto/blob/master/modules/completion/init.zsh#L31-L44 8 | # - https://github.com/sorin-ionescu/prezto/blob/master/runcoms/zlogin#L9-L15 9 | # - http://zsh.sourceforge.net/Doc/Release/Completion-System.html#Use-of-compinit 10 | # - https://gist.github.com/ctechols/ca1035271ad134841284#gistcomment-2894219 11 | # - https://htr3n.github.io/2018/07/faster-zsh/ 12 | 13 | 0=${(%):-%N} 14 | zstyle -t ':zephyr:lib:bootstrap' loaded || source ${0:a:h:h:h}/lib/bootstrap.zsh 15 | zstyle -t ':zephyr:plugin:compstyle' loaded || source $ZEPHYR_HOME/plugins/compstyle/compstyle.plugin.zsh 16 | #endregion 17 | 18 | # Return if requirements are not met. 19 | [[ "$TERM" != 'dumb' ]] || return 1 20 | ! zstyle -t ":zephyr:plugin:completion" skip || return 0 21 | 22 | # Set completion options. 23 | setopt always_to_end # Move cursor to the end of a completed word. 24 | setopt auto_list # Automatically list choices on ambiguous completion. 25 | setopt auto_menu # Show completion menu on a successive tab press. 26 | setopt auto_param_slash # If completed parameter is a directory, add a trailing slash. 27 | setopt complete_in_word # Complete from both ends of a word. 28 | setopt path_dirs # Perform path search even on command names with slashes. 29 | setopt NO_flow_control # Disable start/stop characters in shell editor. 30 | setopt NO_menu_complete # Do not autoselect the first completion entry. 31 | 32 | # Allow Fish-like user contributed completions. 33 | fpath=($__zsh_config_dir/completions(-/FN) $fpath) 34 | 35 | function run_compinit { 36 | emulate -L zsh 37 | setopt local_options extended_glob 38 | 39 | # Use ZSH_COMPDUMP for the completion file. 40 | typeset -g ZSH_COMPDUMP 41 | if [[ -z "$ZSH_COMPDUMP" ]]; then 42 | if zstyle -T ':zephyr:plugin:completion' use-xdg-basedirs; then 43 | ZSH_COMPDUMP=$__zsh_cache_dir/zcompdump 44 | else 45 | ZSH_COMPDUMP=$HOME/.zcompdump 46 | fi 47 | fi 48 | 49 | # Make sure ZSH_COMPDUMP's directory exists and doesnt' have a leading tilde. 50 | ZSH_COMPDUMP="${~ZSH_COMPDUMP}" 51 | [[ -d $ZSH_COMPDUMP:h ]] || mkdir -p $ZSH_COMPDUMP:h 52 | 53 | # `run_compinit -f` forces a cache reset. 54 | if [[ "$1" == (-f|--force) ]]; then 55 | shift 56 | [[ -r "$ZSH_COMPDUMP" ]] && rm -rf -- "$ZSH_COMPDUMP" 57 | fi 58 | 59 | # compinit flags: https://zsh.sourceforge.io/Doc/Release/Completion-System.html#Use-of-compinit 60 | # -C : Omit the check for new completion functions 61 | # -i : Ignore insecure directories in fpath 62 | # -u : Allow insecure directories in fpath 63 | # -d : Specify zcompdump file 64 | local -a compinit_flags=(-i) 65 | if zstyle -t ':zephyr:plugin:completion' 'disable-compfix'; then 66 | compinit_flags=(-u) 67 | fi 68 | compinit_flags+=(-d "$ZSH_COMPDUMP") 69 | 70 | # Initialize completions 71 | autoload -Uz compinit 72 | if zstyle -t ':zephyr:plugin:completion' 'use-cache'; then 73 | # Load and initialize the completion system ignoring insecure directories with a 74 | # cache time of 20 hours, so it should almost always regenerate the first time a 75 | # shell is opened each day. 76 | local zcompdump_cache=($ZSH_COMPDUMP(Nmh-20)) 77 | if (( $#zcompdump_cache )); then 78 | compinit -C $compinit_flags 79 | else 80 | compinit $compinit_flags 81 | touch "$ZSH_COMPDUMP" # Ensure timestamp updates to reset the cache timeout. 82 | fi 83 | else 84 | compinit $compinit_flags 85 | fi 86 | 87 | # Compile ZSH_COMPDUMP, if modified, in background to increase startup speed. 88 | { 89 | if [[ -s "$ZSH_COMPDUMP" && (! -s "${ZSH_COMPDUMP}.zwc" || "$ZSH_COMPDUMP" -nt "${ZSH_COMPDUMP}.zwc") ]]; then 90 | if command mkdir "${ZSH_COMPDUMP}.zwc.lock" 2>/dev/null; then 91 | zcompile "$ZSH_COMPDUMP" 92 | command rmdir "${ZSH_COMPDUMP}.zwc.lock" 2>/dev/null 93 | fi 94 | fi 95 | } &! 96 | } 97 | 98 | # Let's talk about compinit for a second... 99 | # compinit works by finding _completion files in your fpath. That means fpath needs to 100 | # be fully populated prior to calling it. But sometimes you need to call compdef before 101 | # fpath is done being populated (eg: plugins do this). compinit has big chicken-and-egg 102 | # problems. This code handles all those completion use-cases by wrapping compinit, 103 | # queueing any calls to compdef, and hooking the real call to compinit to Zephyr's 104 | # custom post_zshrc event. 105 | 106 | # Define compinit placeholder functions (compdef) so we can queue up calls. 107 | # That way when the real compinit is called, we can execute the queue. 108 | typeset -gHa __compdef_queue=() 109 | function compdef { 110 | (( $# )) || return 111 | local compdef_args=("${@[@]}") 112 | __compdef_queue+=("$(typeset -p compdef_args)") 113 | } 114 | 115 | # Wrap compinit temporarily so that when the real compinit call happens, the 116 | # queue of compdef calls is processed. 117 | function compinit { 118 | unfunction compinit compdef &>/dev/null 119 | autoload -Uz compinit && compinit "$@" 120 | 121 | # Apply all the queued compdefs. 122 | local typedef_compdef_args 123 | for typedef_compdef_args in $__compdef_queue; do 124 | eval $typedef_compdef_args 125 | compdef "$compdef_args[@]" 126 | done 127 | unset __compdef_queue 128 | 129 | # We can run compinit early, and if we did we no longer need a post_zshrc hook. 130 | post_zshrc_hook=(${post_zshrc_hook:#run_compinit}) 131 | } 132 | 133 | # Set the completion style 134 | zstyle -s ':zephyr:plugin:completion' compstyle 'zcompstyle' || zcompstyle=zephyr 135 | if (( $+functions[compstyle_${zcompstyle}_setup] )); then 136 | compstyle_${zcompstyle}_setup 137 | elif [[ "$zcompstyle" != none ]]; then 138 | compstyleinit 139 | compstyle ${zcompstyle} 140 | fi 141 | unset zcompstyle 142 | 143 | # Allow the user to bypass the compinit deferral and run it immediately. Otherwise, we 144 | # hook run_compinit to the custom post_zshrc event. 145 | if zstyle -t ':zephyr:plugin:completion' immediate; then 146 | run_compinit || return 1 147 | else 148 | post_zshrc_hook+=(run_compinit) 149 | fi 150 | 151 | #region MARK LOADED 152 | zstyle ':zephyr:plugin:completion' loaded 'yes' 153 | #endregion 154 | -------------------------------------------------------------------------------- /plugins/compstyle/compstyle.plugin.zsh: -------------------------------------------------------------------------------- 1 | #region HEADER 2 | # 3 | # completion: Set up system for Zsh completion styles similar to prompt system. 4 | # 5 | 6 | # References: 7 | # - https://github.com/zsh-users/zsh/blob/master/Functions/Prompts/promptinit 8 | 9 | 0=${(%):-%N} 10 | zstyle -t ':zephyr:lib:bootstrap' loaded || source ${0:a:h:h:h}/lib/bootstrap.zsh 11 | zstyle -t ':zephyr:plugin:compstyle' loaded && return 1 12 | #endregion 13 | 14 | # Return if requirements are not met. 15 | [[ "$TERM" != 'dumb' ]] || return 1 16 | ! zstyle -t ":zephyr:plugin:compstyle" skip || return 0 17 | 18 | function compstyle_zephyr_help { 19 | echo "A composite of the grml, prezto, and ohmyzsh completions." 20 | echo "You can invoke it with the following command:" 21 | echo 22 | echo " compstyle zephyr" 23 | echo 24 | echo "More information available at: https://github.com/mattmc3/zephyr" 25 | } 26 | 27 | function compstyle_zephyr_setup { 28 | # Pre-reqs. 29 | : ${__zsh_cache_dir:=${XDG_CACHE_HOME:-$HOME/.cache}/zsh} 30 | [[ -d $__zsh_cache_dir ]] || mkdir -p $__zsh_cache_dir 31 | 32 | # Standard style used by default for 'list-colors' 33 | LS_COLORS=${LS_COLORS:-'di=34:ln=35:so=32:pi=33:ex=31:bd=36;01:cd=33;01:su=31;40;07:sg=36;40;07:tw=32;40;07:ow=33;40;07:'} 34 | 35 | # Defaults. 36 | zstyle ':completion:*:default' list-colors ${(s.:.)LS_COLORS} 37 | zstyle ':completion:*:default' list-prompt '%S%M matches%s' 38 | 39 | # Use caching to make completion for commands such as dpkg and apt usable. 40 | zstyle ':completion::complete:*' use-cache on 41 | zstyle ':completion::complete:*' cache-path "$__zsh_cache_dir/zcompcache" 42 | 43 | # Case-insensitive (all), partial-word, and then substring completion. 44 | if zstyle -t ':zephyr:plugin:compstyle:*' case-sensitive; then 45 | zstyle ':completion:*' matcher-list 'r:|=*' 'l:|=* r:|=*' 46 | setopt case_glob 47 | else 48 | zstyle ':completion:*' matcher-list 'm:{a-zA-Z}={A-Za-z}' 'r:|=*' 'l:|=* r:|=*' 49 | unsetopt case_glob 50 | fi 51 | 52 | # Group matches and describe. 53 | zstyle ':completion:*:*:*:*:*' menu select 54 | zstyle ':completion:*:matches' group 'yes' 55 | zstyle ':completion:*:options' description 'yes' 56 | zstyle ':completion:*:options' auto-description '%d' 57 | zstyle ':completion:*:corrections' format ' %F{red}-- %d (errors: %e) --%f' 58 | zstyle ':completion:*:descriptions' format ' %F{purple}-- %d --%f' 59 | zstyle ':completion:*:messages' format ' %F{green} -- %d --%f' 60 | zstyle ':completion:*:warnings' format ' %F{yellow}-- no matches found --%f' 61 | zstyle ':completion:*' format ' %F{blue}-- %d --%f' 62 | zstyle ':completion:*' group-name '' 63 | zstyle ':completion:*' verbose yes 64 | 65 | # Fuzzy match mistyped completions. 66 | zstyle ':completion:*' completer _complete _match _approximate 67 | zstyle ':completion:*:match:*' original only 68 | zstyle ':completion:*:approximate:*' max-errors 1 numeric 69 | 70 | # Increase the number of errors based on the length of the typed word. But make 71 | # sure to cap (at 7) the max-errors to avoid hanging. 72 | zstyle -e ':completion:*:approximate:*' max-errors 'reply=($((($#PREFIX+$#SUFFIX)/3>7?7:($#PREFIX+$#SUFFIX)/3))numeric)' 73 | 74 | # Don't complete unavailable commands. 75 | zstyle ':completion:*:functions' ignored-patterns '(_*|pre(cmd|exec))' 76 | 77 | # Array completion element sorting. 78 | zstyle ':completion:*:*:-subscript-:*' tag-order indexes parameters 79 | 80 | # Directories 81 | zstyle ':completion:*:*:cd:*' tag-order local-directories directory-stack path-directories 82 | zstyle ':completion:*:*:cd:*:directory-stack' menu yes select 83 | zstyle ':completion:*:-tilde-:*' group-order 'named-directories' 'path-directories' 'users' 'expand' 84 | zstyle ':completion:*' squeeze-slashes true 85 | zstyle ':completion:*' special-dirs .. 86 | 87 | # History 88 | zstyle ':completion:*:history-words' stop yes 89 | zstyle ':completion:*:history-words' remove-all-dups yes 90 | zstyle ':completion:*:history-words' list false 91 | zstyle ':completion:*:history-words' menu yes 92 | 93 | # Environment Variables 94 | zstyle ':completion::*:(-command-|export):*' fake-parameters ${${${_comps[(I)-value-*]#*,}%%,*}:#-*-} 95 | 96 | # Populate hostname completion. But allow ignoring custom entries from static 97 | # */etc/hosts* which might be uninteresting. 98 | zstyle -a ':zephyr:plugin:compstyle:*:hosts' etc-host-ignores '_etc_host_ignores' 99 | 100 | zstyle -e ':completion:*:hosts' hosts 'reply=( 101 | ${=${=${=${${(f)"$(cat {/etc/ssh/ssh_,~/.ssh/}known_hosts(|2)(N) 2> /dev/null)"}%%[#| ]*}//\]:[0-9]*/ }//,/ }//\[/ } 102 | ${=${(f)"$(cat /etc/hosts(|)(N) <<(ypcat hosts 2> /dev/null))"}%%(\#${_etc_host_ignores:+|${(j:|:)~_etc_host_ignores}})*} 103 | ${=${${${${(@M)${(f)"$(cat ~/.ssh/config 2> /dev/null)"}:#Host *}#Host }:#*\**}:#*\?*}} 104 | )' 105 | 106 | # Don't complete uninteresting users... 107 | zstyle ':completion:*:*:*:users' ignored-patterns \ 108 | adm amanda apache avahi beaglidx bin cacti canna clamav daemon \ 109 | dbus distcache dovecot fax ftp games gdm gkrellmd gopher \ 110 | hacluster haldaemon halt hsqldb ident junkbust ldap lp mail \ 111 | mailman mailnull mldonkey mysql nagios \ 112 | named netdump news nfsnobody nobody nscd ntp nut nx openvpn \ 113 | operator pcap postfix postgres privoxy pulse pvm quagga radvd \ 114 | rpc rpcuser rpm shutdown squid sshd sync uucp vcsa xfs '_*' 115 | 116 | # ... unless we really want to. 117 | zstyle '*' single-ignored show 118 | 119 | # Ignore multiple entries. 120 | zstyle ':completion:*:(rm|kill|diff):*' ignore-line other 121 | zstyle ':completion:*:rm:*' file-patterns '*:all-files' 122 | 123 | # Kill 124 | zstyle ':completion:*:*:*:*:processes' command 'ps -u $LOGNAME -o pid,user,command -w' 125 | zstyle ':completion:*:*:kill:*:processes' list-colors '=(#b) #([0-9]#) ([0-9a-z-]#)*=01;36=0=01' 126 | zstyle ':completion:*:*:kill:*' menu yes select 127 | zstyle ':completion:*:*:kill:*' force-list always 128 | zstyle ':completion:*:*:kill:*' insert-ids single 129 | 130 | # Man 131 | zstyle ':completion:*:manuals' separate-sections true 132 | zstyle ':completion:*:manuals.(^1*)' insert-sections true 133 | zstyle ':completion:*:man:*' menu yes select 134 | 135 | # Media Players 136 | zstyle ':completion:*:*:mpg123:*' file-patterns '*.(mp3|MP3):mp3\ files *(-/):directories' 137 | zstyle ':completion:*:*:mpg321:*' file-patterns '*.(mp3|MP3):mp3\ files *(-/):directories' 138 | zstyle ':completion:*:*:ogg123:*' file-patterns '*.(ogg|OGG|flac):ogg\ files *(-/):directories' 139 | zstyle ':completion:*:*:mocp:*' file-patterns '*.(wav|WAV|mp3|MP3|ogg|OGG|flac):ogg\ files *(-/):directories' 140 | 141 | # Mutt 142 | if [[ -s "$HOME/.mutt/aliases" ]]; then 143 | zstyle ':completion:*:*:mutt:*' menu yes select 144 | zstyle ':completion:*:mutt:*' users ${${${(f)"$(<"$HOME/.mutt/aliases")"}#alias[[:space:]]}%%[[:space:]]*} 145 | fi 146 | 147 | # SSH/SCP/RSYNC 148 | zstyle ':completion:*:(ssh|scp|rsync):*' tag-order 'hosts:-host:host hosts:-domain:domain hosts:-ipaddr:ip\ address *' 149 | zstyle ':completion:*:(scp|rsync):*' group-order users files all-files hosts-domain hosts-host hosts-ipaddr 150 | zstyle ':completion:*:ssh:*' group-order users hosts-domain hosts-host users hosts-ipaddr 151 | zstyle ':completion:*:(ssh|scp|rsync):*:hosts-host' ignored-patterns '*(.|:)*' loopback ip6-loopback localhost ip6-localhost broadcasthost 152 | zstyle ':completion:*:(ssh|scp|rsync):*:hosts-domain' ignored-patterns '<->.<->.<->.<->' '^[-[:alnum:]]##(.[-[:alnum:]]##)##' '*@*' 153 | zstyle ':completion:*:(ssh|scp|rsync):*:hosts-ipaddr' ignored-patterns '^(<->.<->.<->.<->|(|::)([[:xdigit:].]##:(#c,2))##(|%*))' '127.0.0.<->' '255.255.255.255' '::1' 'fe80::*' 154 | } 155 | 156 | # Load with `autoload -Uz compstyleinit; compstyleinit'. 157 | # Type `compstyle -h' for help. 158 | function compstyleinit { 159 | typeset -gaU completion_styles 160 | typeset -ga completion_style 161 | completion_styles=(zephyr) 162 | 163 | function compstyleinit { 164 | emulate -L zsh; setopt extendedglob 165 | 166 | local name setupfn 167 | local -a match 168 | 169 | # Autoload all compstyle_*_setup functions in fpath. 170 | for setupfn in $^fpath/compstyle_*_setup(N); do 171 | if [[ $setupfn == */compstyle_(#b)(*)_setup ]]; then 172 | name="$match[1]" 173 | if [[ -r "$setupfn" ]]; then 174 | completion_styles=($completion_styles $name) 175 | autoload -Uz compstyle_${name}_setup 176 | else 177 | print "Cannot read '$setupfn' file containing completion styles." 178 | fi 179 | else 180 | print "Unexpect compstyle setup function '$setupfn'." 181 | fi 182 | done 183 | } 184 | 185 | function _compstyle_usage { 186 | emulate -L zsh; setopt extended_glob 187 | local -a usage=( 188 | 'Usage: compstyle [-l] [-h [