Skip to content

Latest commit

 

History

History

zsh

A modern, backwards-compatible replacement for bash that offers essentially a superset of bash's features.

why zsh

zsh offers useful features such as complex scripting features, smart tab-completion, advanced globbing support and plugin support while preserving backwards compatibility. Additionally, in my anecdotal experience, zsh has greater support in the open source community.

alternatives considered

My reasons to not use bash are the inverse of why I use zsh (e.g. lack of advanced globbing, lack of useful scripting features, worse (in my experience) plugin support, etc.).

In a sign of zsh's mainstreamness Apple is switching to zsh for its default shell in the next macOS version (as of 10/03/2019). That alone is not necessarily a reason to use it (especially since a factor in Apple's decision here is licensing related as opposed to end user satisfaction) but for anyone unsure about switching to zsh it may offer some surety of it's maturity/viability.

fish seems nice, especially its sane scripting syntax. For me, however, its improvements over zsh don't outweigh its lack of backwards compatibility.

nu seems fascinating. I may even jump to it at some point in the future but it's not mature enough for me at the moment to want to make it my daily driver.

skimmable list of files

  • alias.zsh - define generic aliases
  • completion.zsh - initialize completion
  • dynamic_env_vars.zsh - set environment variables whose value requires dynamism (dependencies)
  • functions.zsh - autoload all functions (executable files) defined in $DOTFILES/functions
  • keymap.zsh - enable vim mode for zsh line editor (zle) and define related keymappings
  • local.zsh - local (computer-specific) overrides (gitignored & sourced only if it exists)
  • manydots.zsh - add a zle widget to facilitate specifying relative directories multiple levels above the current directory (transforms ... -> ../..)
  • path.zsh - configure $PATH
  • plugins.zsh - enable and configure plugins. Managed by zinit.
  • prompt.zsh - configure prompt appearance (currently powerlevel10k)
  • secrets.zsh - store secrets such as API tokens (gitignored & sourced only if it exists)
  • zle-fsh-theme-overlay.ini - an overlay to customize syntax highlighting
  • zshenv - define environment variables, loaded before any other file in this folder (this file defines $DOTFILES)
  • zshrc - source every *.zsh throughout this repo ($DOTFILES/**/*.zsh) to set up config

each file in more detail

Define generic aliases.

Topic-specific aliases (for example aliases for tmux) should go in the corresponding topic folder (e.g. $DOTFILES/tmux/alias.zsh).

Notable aliases:

  • srczsh - source $HOME/.zshrc, reload zshrc
  • zshn - zsh -f, launch shell w/o config
  • rr - git rev-parse --show-toplevel, gives the absolute path to the root of the current repo
  • e - $EDITOR, provides a generic command to edit a file regardless of the backing program
  • f - rg. Similar to e, provides a generic command regardless of backing program.
  • t - trash, a utility to move files/folders to the trash (instead of deleting permanently) on macOS for recoverability

Initialize the asdf version manager.

Initialize completion. Uses a cache with a refresh every 20 hours to speed up shell load.

Sets dynamic environment variables. LESSOPEN depends on the highlight command while $GIT_PAGER, BAT_THEME & EDITOR all depend on settings values in $DOTFILES/.files-settings.

Autoload all functions (executable files) defined in any directory named functions throughout this repo ($DOTFILES/**/functions).

Turn on vim mode for zle and define related keymappings.

Add keymappings to support text objects supported by vim. Each of the following can be used with i or a (e.g. i<character> or a<character>): ', ", `, {, (, [, <.

Add keymappings to recreate behavior of vim-surround (that link provides usage examples).

Additional notable keymappings:

  • insert mode
    • jk to escape insert mode
  • normal mode
    • start/end of line movement
      • ' moves to end of line (same behavior as $)
      • " moves to start of line (same behavior as 0)
    • v to edit the current command in $EDITOR. Quitting the opened editor dumps the edited command to the command line for execution.

Apply local (computer-specific) config (not secrets, for better hygiene those should be in $DOTFILES/secrets.zsh).

This file is not checked in to version control (ignored in $DOTFILES/.gitignore) and sourced only if it exists.

Add a zle widget to facilitate specifying relative directories multiple levels above the current directory.

Each . typed past .. increases the level. For example, cd ... becomes cd ../... Typing . again gives you cd ../../...

Enable and configure $PATH.

Uses zsh's handy mapping of $path array -> $PATH string concatened with ;. Ensures $path array contains each entry only once (like a set) with typeset -u path

Enable and configure plugins.

Managed by zinit.

Configure prompt appearance.

Currently using powerlevel10k. powerlevel10k is the fastest prompt I've found that provides the contextual information I want (git status, insert/normal mode indicator, last command status code, etc.). It accomplishes this through two primary mechanisms: asynchronous loading and a faster, custom-built git status. The asynchronous nature allows input nearly instanteously as contextual information loads in the background. The faster git status dramatically speeds up output of git contextual information.

Appearance:

prompt

Store secrets such as API tokens.

This file is not checked in to version control (ignored in $DOTFILES/.gitignore) and sourced only if it exists.

Customize ZLE syntax highlighting.

The default comment highlighting is unreadable on my terminal theme. This overlay fixes that following the advice here.

Define environment variables, loaded before any other file in this folder.

Defines $DOTFILES which specifies path to the root of this repo. Used throughout zsh configuration.

This file symlinked to $HOME/.zshenv by $DOTFILES/infra/setup/bin/symlink

Source every *.zsh in $DOTFILES (NOT just .zsh files in this folder) and autoload any functions in functions folders throughout this repo. Here is the loading order:

  1. secrets.zsh - only if this file exists
  2. completion.zsh
  3. keymap.zsh
  4. manydots.zsh
  5. path.zsh
  6. dynamic_env_vars.zsh
  7. functions.zsh
  8. alias.zsh
  9. plugins.zsh
  10. prompt.zsh
  11. all .zsh files throughout this repository ($DOTFILES/**/*.zsh) excluding those in $DOTFILES/zsh (this directory).
  12. asdf.zsh
  13. local.zsh - only if this file exists

zshrc itself is loaded after zshenv based on zsh's startup file loading order.

This file symlinked to $HOME/.zshrc by $DOTFILES/infra/setup/bin/symlink