first commit

This commit is contained in:
Qubot 2023-10-20 21:14:23 +08:00
commit ce6d203365
3 changed files with 153 additions and 0 deletions

21
LICENSE Normal file
View File

@ -0,0 +1,21 @@
MIT License
Copyright (c) 2023 Matthew Rothenberg
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.

82
README.md Normal file
View File

@ -0,0 +1,82 @@
# evalcache
> zsh plugin to cache the output of a binary initialization command, intended
> to help lower shell startup time.
## What it does
There are lots of shell wrapper tools that follow the pattern of asking you to
eval a specific init command in your shell startup, for example, rbenv asks:
eval "$(hub alias -s)"
While this is very convenient, the reality is there is a small amount of
overhead associated with shelling out to this, and the output is almost always
actually static in all of the tools I know. So why bear this cost every time
you open a new tab in your shell?
Instead, after you load this plugin, you can replace that same command with:
_evalcache hub alias -s
The first time this runs, it will cache the output of the command to a file,
which will be sourced in the future instead when it exists.
If you update a tool and expect for some reason that it's initialization might
have changed, you can simply clear the cache and it will be regenerated.
It also gracefully degrades to a no-op if the tool is no longer installed.
## Benchmarks
Some informal benchmarks from my MacBook on my .zshrc:
| command | without | first run | subsequent runs | savings |
| ------------ | ------: | --------: | --------------: | ------: |
| rbenv init | ~65ms | ~65ms | ~8ms | 88% |
| hub alias | ~30ms | ~30ms | ~6ms | 80% |
| scmpuff init | ~24ms | ~25ms | ~10ms | 58% |
The difference isn't huge, but can be handy in shaving down shell startup time,
especially if you use a bunch of these tools. Every millisecond counts!
## Options
- `$ZSH_EVALCACHE_DIR`: cache files storage, default `$HOME/.zsh-evalcache`.
- `$ZSH_EVALCACHE_DISABLE`: set to `true` if you wish to bypass evalcache.
There is a convenience function to clear the cache called `_evalcache_clear`.
## Installation
### [Antigen](https://github.com/zsh-users/antigen)
Add `antigen bundle mroth/evalcache` to your `.zshrc` with your other bundle commands.
Antigen will handle cloning the plugin for you automatically the next time you start zsh. You can also add the plugin to a running zsh with `antigen bundle mroth/evalcache` for testing before adding it to your `.zshrc`.
### [Fig](https://fig.io)
Fig adds apps, shortcuts, and autocomplete to your existing terminal.
Install `evalcache` in just one click.
<a href="https://fig.io/plugins/other/evalcache_mroth" target="_blank"><img src="https://fig.io/badges/install-with-fig.svg" /></a>
### [Oh-My-Zsh](http://ohmyz.sh/)
1. Clone this repository into `$ZSH_CUSTOM/plugins` (by default `~/.oh-my-zsh/custom/plugins`)
```sh
git clone https://github.com/mroth/evalcache ${ZSH_CUSTOM:-~/.oh-my-zsh/custom}/plugins/evalcache
```
2. Edit `~/.zshrc` to add _evalcache_ to your plugin list,
```diff
- plugins=(...)
+ plugins=(... evalcache)
```
### [Zgen](https://github.com/tarjoilija/zgen)
Add `zgen load mroth/evalcache` to your `.zshrc` file in the same function you're doing your other `zgen load` calls in. Zgen will handle automatically cloning the plugin for you the next time you do a `zgen save`.

50
evalcache.plugin.zsh Normal file
View File

@ -0,0 +1,50 @@
# Caches the output of a binary initialization command, to avoid the time to
# execute it in the future.
#
# Usage: _evalcache [NAME=VALUE]... COMMAND [ARG]...
# default cache directory
export ZSH_EVALCACHE_DIR=${ZSH_EVALCACHE_DIR:-"$HOME/.zsh-evalcache"}
function _evalcache () {
local cmdHash="nohash" data="$*" name
# use the first non-variable argument as the name
for name in $@; do
if [ "${name}" = "${name#[A-Za-z_][A-Za-z0-9_]*=}" ]; then
break
fi
done
# if command is a function, include its definition in data
if typeset -f "${name}" > /dev/null; then
data=${data}$(typeset -f "${name}")
fi
if builtin command -v md5 > /dev/null; then
cmdHash=$(echo -n "${data}" | md5)
elif builtin command -v md5sum > /dev/null; then
cmdHash=$(echo -n "${data}" | md5sum | cut -d' ' -f1)
fi
local cacheFile="$ZSH_EVALCACHE_DIR/init-${name##*/}-${cmdHash}.sh"
if [ "$ZSH_EVALCACHE_DISABLE" = "true" ]; then
eval ${(q)@}
elif [ -s "$cacheFile" ]; then
source "$cacheFile"
else
if type "${name}" > /dev/null; then
echo "evalcache: ${name} initialization not cached, caching output of: $*" >&2
mkdir -p "$ZSH_EVALCACHE_DIR"
eval ${(q)@} > "$cacheFile"
source "$cacheFile"
else
echo "evalcache: ERROR: ${name} is not installed or in PATH" >&2
fi
fi
}
function _evalcache_clear () {
rm -i "$ZSH_EVALCACHE_DIR"/init-*.sh
}