All Projects โ†’ mattmc3 โ†’ zsh_unplugged

mattmc3 / zsh_unplugged

Licence: Unlicense License
๐Ÿค” perhaps you don't need a Zsh plugin manager after all...

Programming Languages

shell
77523 projects

Projects that are alternatives of or similar to zsh unplugged

Warp
Warp is a blazingly-fast modern Rust based GPU-accelerated terminal built to make you and your team more productive.
Stars: โœญ 1,319 (+1839.71%)
Mutual labels:  zsh
zsh-docker
Docker containers for all versions of Zsh.
Stars: โœญ 66 (-2.94%)
Mutual labels:  zsh
hm
Command line history manager for bash and zsh
Stars: โœญ 25 (-63.24%)
Mutual labels:  zsh
I WANT TO HELP
https://www.reddit.com/r/zsh/comments/qinb6j/httpsgithubcomzdharma_has_suddenly_disappeared_i/hil4oww/
Stars: โœญ 29 (-57.35%)
Mutual labels:  zsh
dot
No description or website provided.
Stars: โœญ 40 (-41.18%)
Mutual labels:  zsh
zsh-bench
Benchmark for interactive Zsh
Stars: โœญ 158 (+132.35%)
Mutual labels:  zsh
hstdb
Better history management for zsh. Based on ideas from https://github.com/larkery/zsh-histdb.
Stars: โœญ 25 (-63.24%)
Mutual labels:  zsh
goto
Goto - The Good Way to Program
Stars: โœญ 14 (-79.41%)
Mutual labels:  zsh
dotfiles
My Linux settings and configs
Stars: โœญ 33 (-51.47%)
Mutual labels:  zsh
DEC
Development Environment Config. Work faster than ever with my dotfiles
Stars: โœญ 39 (-42.65%)
Mutual labels:  zsh
hoard
cli command organizer written in rust
Stars: โœญ 71 (+4.41%)
Mutual labels:  zsh
dotfiles-legacy
. .โœง ยท ๐ŸŒŽ โœท โœซ ๐ŸŒ™ ยท โœต ๐Ÿš€โœต * โœต ยท ๐ŸŒŒโœซ โœท ยท โœง .
Stars: โœญ 15 (-77.94%)
Mutual labels:  zsh
crypto-websocket-extensions
๐Ÿงฐ Unified and optimized data structures across cryptocurrency exchanges
Stars: โœญ 31 (-54.41%)
Mutual labels:  extensions
zarch
The Ultimate Script For Arch Linux
Stars: โœญ 49 (-27.94%)
Mutual labels:  zsh
pm27-sdk-addons
SDK-based extensions for Pale Moon 27.1+
Stars: โœญ 19 (-72.06%)
Mutual labels:  extensions
ezsh
ezsh is a user-friendly, and interactive shell designed to simplify a beginner's view of the terminal and command line.
Stars: โœญ 12 (-82.35%)
Mutual labels:  zsh
CSEDevOps
Azure DevOps extensions from CSE DevOps team
Stars: โœญ 18 (-73.53%)
Mutual labels:  extensions
bashy
Extremely fast and simple git prompt for bash and zsh
Stars: โœญ 43 (-36.76%)
Mutual labels:  zsh
dotfiles
My dotfiles for oh-my-zsh, vim and tmux ๐Ÿ“Ÿ
Stars: โœญ 23 (-66.18%)
Mutual labels:  zsh
dotfiles
๐Ÿก .files, including zsh, tmux, vim, and git. Also macOS setup. Good stuff.
Stars: โœญ 30 (-55.88%)
Mutual labels:  zsh

zsh_unplugged

๐Ÿค” perhaps you don't need a Zsh plugin manager after all...

TLDR; You don't need a big bloated plugin manager for your Zsh plugins. A simple ~20 line function may be all you need.

Click here to skip to the code.

๐Ÿ”Œ Zsh Plugin Managers

๐Ÿ—ž๏ธ Current state

There are an embarrassingly large number of Zsh plugin managers out there. Many of them are abandonware, are no longer actively developed, are brand new without many users, or don't have much reason to even exist other than as a novelty.

Here's a list of many (but certainly not all) of them from awesome-zsh-plugins:

Zsh Plugin Manager Performance Current state
antibody ๐Ÿ‡ fast ๐Ÿ‘ฟ Maintenance mode, no new features
antigen ๐Ÿข slow ๐Ÿ‘ฟ Maintenance mode, no new features
antidote ๐Ÿ‡ fast โœ… Active
sheldon โ“ unknown โœ… Active
zcomet ๐Ÿ‡ fast โœ… Active
zgem โ“ unknown โ˜ ๏ธ Abandonware
zgen ๐Ÿ‡ fast โ˜ ๏ธ Abandonware
zgenom ๐Ÿ‡ fast โœ… Active
zinit-continuum ๐Ÿ‡ fast โœ… Active *
zinit ๐Ÿ‡ fast ๐Ÿคฌ Author deleted project
zit โ“ unknown ๐Ÿ‘ฟ Few/no recent commits
znap ๐Ÿ‡ fast โœ… Active
zplug ๐Ÿข slow โ˜ ๏ธ Abandonware
zplugin ๐Ÿ‡ fast ๐Ÿคฌ Renamed to zinit, author deleted
zpm ๐Ÿ‡ fast โœ… Active
zr โ“ unknown ๐Ÿ‘ฟ Few/no recent commits

Full disclosure, I'm the author of one of these - antidote (formerly called pz).

There's new ones popping up all the time too:

Zsh Plugin Manager Performance Current state
mzpm โ“ unknown ๐Ÿฃ New
tzpm โ“ unknown ๐Ÿฃ New
uz โ“ unknown ๐Ÿฃ New
zed โ“ unknown ๐Ÿฃ New

๐Ÿงจ The catalyst

In January 2021, the plugin manager I was using, antibody, was deprecated. The author even went so far as to say:

Most of the other plugin managers catch up on performance, thus keeping this [antibody] does not make sense anymore.

Prior to that, I used zgen, which also stopped being actively developed and the developer seems to have disappeared. (Shoutout to @jandamm for carrying on Zgen with Zgenom!)

In November 2021, a relatively well known and popular Zsh plugin manager, zinit, was removed from GitHub entirely and without warning. In fact, the author deleted almost his entire body of work. Zinit was really popular because it was super fast, and the author promoted his projects in multiple venues for many years. (Shoutout to the folks running zdharma-continuum though - great work keeping Zinit alive!)

With all the instability in the Zsh plugin manager space, it got me wondering why I even bother with a plugin manager at all.

๐Ÿ’ก The simple idea

After antibody was deprecated, I tried znap, but it was in early development at the time and kept breaking, so like many others before me, I decided to write my own - antidote.

When developing antidote, my goal was simple - make a plugin manager that was fast, functional, and easy to understand - which was everything I loved about zgen. While antidote is a great project, I kept wondering if I could cut further down to a single function and do away with plugin management utilities altogether.

Thus was born... zsh_unplugged.

This isn't a plugin manager - it's a way to show you how to manage your own plugins using small, easy to understand snippets of Zsh. All this with the hope that perhaps, once-and-for-all, we can do away with the idea that we even need to use bloated Zsh plugin manager projects and just simply do it ourselves.

You can grab a ~20 line function and you have everything you need to manage your own plugins from here on out. By way of contrast, I ran a rough line count of zinit's codebase which comes out to nearly a whopping ~10,000 lines.

zinit_tmpdir=$(mktemp -d)
git clone --depth 1 https://github.com/zdharma-continuum/zinit $zinit_tmpdir
wc -l $zinit_tmpdir/**/*.zsh
[[ -d $zinit_tmpdir ]] && rm -rf $zinit_tmpdir

Results:

      18 /var/folders/z0/w4blz6g14td2lf3b41gmhgd80000gn/T/tmp.w2WtwTZJ/docker/init.zsh
      61 /var/folders/z0/w4blz6g14td2lf3b41gmhgd80000gn/T/tmp.w2WtwTZJ/docker/utils.zsh
     186 /var/folders/z0/w4blz6g14td2lf3b41gmhgd80000gn/T/tmp.w2WtwTZJ/share/git-process-output.zsh
      51 /var/folders/z0/w4blz6g14td2lf3b41gmhgd80000gn/T/tmp.w2WtwTZJ/share/rpm2cpio.zsh
      19 /var/folders/z0/w4blz6g14td2lf3b41gmhgd80000gn/T/tmp.w2WtwTZJ/share/single-line.zsh
      23 /var/folders/z0/w4blz6g14td2lf3b41gmhgd80000gn/T/tmp.w2WtwTZJ/tests/setup.zsh
      12 /var/folders/z0/w4blz6g14td2lf3b41gmhgd80000gn/T/tmp.w2WtwTZJ/tests/teardown.zsh
     147 /var/folders/z0/w4blz6g14td2lf3b41gmhgd80000gn/T/tmp.w2WtwTZJ/zinit-additional.zsh
    3486 /var/folders/z0/w4blz6g14td2lf3b41gmhgd80000gn/T/tmp.w2WtwTZJ/zinit-autoload.zsh
    2389 /var/folders/z0/w4blz6g14td2lf3b41gmhgd80000gn/T/tmp.w2WtwTZJ/zinit-install.zsh
     404 /var/folders/z0/w4blz6g14td2lf3b41gmhgd80000gn/T/tmp.w2WtwTZJ/zinit-side.zsh
    3139 /var/folders/z0/w4blz6g14td2lf3b41gmhgd80000gn/T/tmp.w2WtwTZJ/zinit.zsh
    9935 total

*Note: SLOC is not intended as an indicator of much here beyond a rough comparison of effort, maintainability, and complexity

๐ŸŽ‰ The code

โš™๏ธ The bare metal way

If you don't want to use anything resembling a plugin manager at all, you could simply clone and source plugins yourself manually:

ZPLUGINDIR=$HOME/.zsh/plugins

if [[ ! -d $ZPLUGINDIR/zsh-autosuggestions ]]; then
  git clone https://github.com/zsh-users/zsh-autosuggestions $ZPLUGINDIR/zsh-autosuggestions
fi
if [[ ! -d $ZPLUGINDIR/zsh-history-substring-search ]]; then
  git clone https://github.com/zsh-users/zsh-history-substring-search $ZPLUGINDIR/zsh-history-substring-search
fi
if [[ ! -d $ZPLUGINDIR/z ]]; then
  git clone https://github.com/rupa/z $ZPLUGINDIR/z
fi

source $ZPLUGINDIR/zsh-autosuggestions/zsh-autosuggestions.plugin.zsh
source $ZPLUGINDIR/zsh-history-substring-search/zsh-history-substring-search.plugin.zsh
source $ZPLUGINDIR/z/z.sh

This can get pretty cumbersome and tricky to maintain. You need to figure out each plugin's init file, and sometimes adding a plugin to your fpath is required. While this method works, there's another way...

๐Ÿงฉ The humble plugin-load function

If we go one level of abstraction higher than manual git clone calls, we can use a simple function wrapper as the basis for everything you need to manage your own Zsh plugins:

# clone a plugin, identify its init file, source it, and add it to your fpath
function plugin-load {
  local repo plugin_name plugin_dir initfile initfiles
  ZPLUGINDIR=${ZPLUGINDIR:-${ZDOTDIR:-$HOME/.config/zsh}/plugins}
  for repo in $@; do
    plugin_name=${repo:t}
    plugin_dir=$ZPLUGINDIR/$plugin_name
    initfile=$plugin_dir/$plugin_name.plugin.zsh
    if [[ ! -d $plugin_dir ]]; then
      echo "Cloning $repo"
      git clone -q --depth 1 --recursive --shallow-submodules https://github.com/$repo $plugin_dir
    fi
    if [[ ! -e $initfile ]]; then
      initfiles=($plugin_dir/*.plugin.{z,}sh(N) $plugin_dir/*.{z,}sh{-theme,}(N))
      [[ ${#initfiles[@]} -gt 0 ]] || { echo >&2 "Plugin has no init file '$repo'." && continue }
      ln -sf "${initfiles[1]}" "$initfile"
    fi
    fpath+=$plugin_dir
    (( $+functions[zsh-defer] )) && zsh-defer . $initfile || . $initfile
  done
}

That's it. ~20 lines of code and you have a simple, robust Zsh plugin management alternative that is likely as fast as most everything else out there.

What this does is simply clones a Zsh plugin's git repository, and then examines that repo for an appropriate .zsh file to use as an init script. We then find and symlink the plugin's init file if necessary, which allows us to get the performance advantage of static sourcing rather than searching for which plugin files to load every time we open a new terminal.

Then, the plugin is sourced and added to fpath.

You can even get turbocharged-hypersonic-load-speed-magic ๐Ÿš€ if you really need every last bit of performance. See how here.

โ“ How do you use this in your own Zsh config?

You are free to grab the plugin-load function above and put it directly in your .zshrc, maintain it yourself, and never rely on anyone else's plugin manager again. Or, this repo makes the plugin-load function available as a plugin itself if you prefer. Here's an example .zshrc:

# where do you want to store your plugins?
ZPLUGINDIR=${ZPLUGINDIR:-${ZDOTDIR:-$HOME/.config/zsh}/plugins}

# get zsh_unplugged and store it with your other plugins
if [[ ! -d $ZPLUGINDIR/zsh_unplugged ]]; then
  git clone --quiet https://github.com/mattmc3/zsh_unplugged $ZPLUGINDIR/zsh_unplugged
fi
source $ZPLUGINDIR/zsh_unplugged/zsh_unplugged.plugin.zsh

# make list of the Zsh plugins you use
repos=(
  # plugins that you want loaded first
  sindresorhus/pure

  # other plugins
  zsh-users/zsh-completions
  rupa/z
  # ...

  # plugins you want loaded last
  zsh-users/zsh-syntax-highlighting
  zsh-users/zsh-history-substring-search
  zsh-users/zsh-autosuggestions
)

# now load your plugins
plugin-load $repos

โ“ How do I update my plugins?

Updating your plugins is as simple as deleting the $ZPLUGINDIR and reloading Zsh.

ZPLUGINDIR=~/.config/zsh/plugins
rm -rfi $ZPLUGINDIR
zsh

If you are comfortable with git commands and prefer to not rebuild everything, you can run git pull yourself, or even use a simple plugin-update function:

function plugin-update {
  ZPLUGINDIR=${ZPLUGINDIR:-$HOME/.config/zsh/plugins}
  for d in $ZPLUGINDIR/*/.git(/); do
    echo "Updating ${d:h:t}..."
    command git -C "${d:h}" pull --ff --recurse-submodules --depth 1 --rebase --autostash
  done
}

โ“ How do I list my plugins?

You can see what plugins you have installed with a simple ls command:

ls $ZPLUGINDIR

If you need something fancier and would like to see the git origin of your plugins, you could run this command:

for d in $ZPLUGINDIR/*/.git; do
  git -C "${d:h}" remote get-url origin
done

โ“ How do I remove a plugin?

You can just remove it from your plugins list in your .zshrc. To delete it altogether, feel free to run rm:

# remove the fast-syntax-highlighting plugin
rm -rfi $ZPLUGINDIR/fast-syntax-highlighting

โ“ How do I load my plugins with hypersonic speed ๐Ÿš€?

You can get turbocharged-hypersonic-load-speed-magic if you choose to use the romkatv/zsh-defer plugin. Essentially, if you add romkatv/zsh-defer to your plugins list, everything you load afterwards will use zsh-defer, meaning you'll get speeds similar to zinit's turbo mode.

Notably, if you like the zsh-abbr plugin for fish-like abbreviations in Zsh, using zsh-defer will boost performance greatly.

โš ๏ธ Warning - the author of zsh-defer does not recommend using the plugin this way, so be careful and selective about which plugins you load with zsh-defer. If you get weird behavior from a plugin, then load it before zsh-defer. In my extensive testing, the biggest benefit came only from especially sluggish plugins like zsh-abbr.

โ“ What if I want my plugins to be even faster?

If you are an experienced Zsh user, you may know about zcompile, which takes your Zsh scripts and potentially speeds them up by compiling them to byte code. If you feel confident you know what you're doing and want to eek every last bit of performance out of your Zsh, you can use this function

function plugin-compile {
  ZPLUGINDIR=${ZPLUGINDIR:-$HOME/.config/zsh/plugins}
  autoload -U zrecompile
  local f
  for f in $ZPLUGINDIR/**/*.zsh{,-theme}(N); do
    zrecompile -pq "$f"
  done
}

โ“ How can I use this with Zsh frameworks like Oh-My-Zsh or Prezto?

Oh-My-Zsh and Prezto have their own built-in methods for managing the loading of plugins. You don't need this script if you are using those frameworks. However, you also don't need a separate plugin manager utility. Here's how you go plugin manager free with Zsh frameworks:

Oh-My-Zsh

If you are using Oh-My-Zsh, the way to go without a plugin manager would be to utilize the $ZSH_CUSTOM path.

Note that this assumes your init file is called {plugin_name}.plugin.zsh which may not be true.

repos=(
  marlonrichert/zsh-hist
  zsh-users/zsh-syntax-highlighting
  zsh-users/zsh-autosuggestions
)
for repo in $repos; do
  if [[ ! -d $ZSH_CUSTOM/${repo:t} ]]; then
    git clone https://github.com/${repo} $ZSH_CUSTOM/plugins/${repo:t}
  fi
done

# add your external plugins to your OMZ plugins list
plugins=(
  ...
  zsh-hist
  zsh-autosuggestions
  ...
  zsh-syntax-highlighting
)

Prezto

If you are using Prezto, the way to go without a plugin manager would be to utilize the $ZPREZTODIR/contrib path.

Note that this assumes your init file is called {plugin_name}.plugin.zsh which may not be true.

repos=(
  rupa/z
  marlonrichert/zsh-hist
  mattmc3/zman
)
for repo in $repos; do
  if [[ ! -d $ZPREZTODIR/contrib/${repo:t} ]]; then
    git clone https://github.com/${repo} $ZPREZTODIR/contrib/${repo:t}/external
    echo "source \${0:A:h}/external/${repo:t}.plugin.zsh" > $ZPREZTODIR/contrib/${repo:t}/init.zsh
  fi
done

# add plugins to your Prezto plugins list in .zpreztorc
zstyle ':prezto:load' pmodule \
  ... \
  z \
  zsh-hist \
  ... \
  zman
Note that the project description data, including the texts, logos, images, and/or trademarks, for each open source project belongs to its rightful owner. If you wish to add or remove any projects, please contact us at [email protected].