Skip to content

Instantly share code, notes, and snippets.

@romkatv
Last active February 17, 2024 10:59
Show Gist options
  • Star 11 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save romkatv/8b318a610dc302bdbe1487bb1847ad99 to your computer and use it in GitHub Desktop.
Save romkatv/8b318a610dc302bdbe1487bb1847ad99 to your computer and use it in GitHub Desktop.
Make zsh start INSTANTLY with this one weird trick
# Make zsh start INSTANTLY with this one weird trick.
#
# https://asciinema.org/a/274255
#
# HOW TO USE
#
# 1. Download this script.
#
# curl -fsSL -o ~/instant-zsh.zsh https://gist.github.com/romkatv/8b318a610dc302bdbe1487bb1847ad99/raw
#
# 2. Add this at the top of your ~/.zshrc.
#
# source ~/instant-zsh.zsh
# instant-zsh-pre '%n@%m %~%# '
#
# Adjust the argument of instant-zsh-pre to be similar to your real prompt.
# For example, if you are using Powerlevel10k with lean style, this works well:
#
# instant-zsh-pre "%B%39F${${(V)${(%):-%~}//\%/%%}//\//%b%31F/%B%39F}%b%f"$'\n'"%76F❯%f "
#
# If you override PROMPT_EOL_MARK in your zsh config files, move the definition
# above the instant-zsh-pre call.
#
# 3. Add this at the bottom of your ~/.zshrc.
#
# instant-zsh-post
#
# 4. Optional: Compile instant-zsh.zsh for faster loading.
#
# zcompile ~/instant-zsh.zsh
#
# HOW IT WORKS
#
# This doesn't actually make your zsh start instantly, hence the reference to the
# "one weird trick" advertisement. It does, however, make it feel like zsh is loading
# faster. Or, put it another way, your original zsh wasn't so slow to load, but you
# thought it was slow. Now you see that it was pretty fast all along.
#
# Here's how it work. To make your zsh "start instantly" all you need to do is print
# your prompt immediately when zsh starts, before doing anything else. At the top of
# ~/.zshrc is a good place for this. If your prompt takes a long time to initialize,
# print something that looks close enough. Then, while the rest of ~/.zshrc is evaluated
# and precmd hooks are run, all keyboard input simply gets buffered. Once initialization
# is complete, clear the screen and allow the real prompt be printed where the "loading"
# prompt was before. With the real prompt in place, all buffered keyboard input is
# processed by zle.
#
# It's a bit gimmicky but it does reduce the perceived ZSH startup latency by a lot.
# To make it more interesting, add `sleep 1` at the bottom of zsh and try opening a new
# tab in your terminal. It's still instant!
# Usage: instant-zsh-pre loading-prompt
#
# Prints the specified prompt after percent expansion (but not single word shell
# expansions). The prompt is replaced inplace once the real prompt is initialized.
#
# For best results, set loading-prompt to something that looks similar
# (or, ideally, identical) to the real prompt.
#
# Must be called at the very top of ~/.zshrc. Must be paired with instant-zsh-post.
#
# If you want to override PROMPT_EOL_MARK, do it before calling instant-zsh-pre.
function instant-zsh-pre() {
zmodload zsh/terminfo
# Do nothing if terminal is lacking required capabilities.
(( ${+terminfo[cuu]} && ${+terminfo[ed]} && ${+terminfo[sc]} && ${+terminfo[rc]} )) || return 0
unsetopt localoptions prompt_cr prompt_sp
() {
emulate -L zsh
# Emulate prompt_cr and prompt_sp.
local eol_mark=${PROMPT_EOL_MARK-"%B%S%#%s%b"}
local -i fill=COLUMNS
() {
local COLUMNS=1024
local -i x y=$#1 m
if (( y )); then
while (( ${${(%):-$1%$y(l.1.0)}[-1]} )); do
echo $y
x=y
(( y *= 2 ));
done
local xy
while (( y > x + 1 )); do
m=$(( x + (y - x) / 2 ))
typeset ${${(%):-$1%$m(l.x.y)}[-1]}=$m
done
fi
(( fill -= x ))
} $eol_mark
print -r ${(%):-$eol_mark${(pl.$fill.. .)}$'\r'%b%k%f%E}$'\n\n\n\n\n\n\n\n\n'
echoti cuu 10
print -rn -- ${terminfo[sc]}${(%)1}
_clear-loading-prompt() {
unsetopt localoptions
setopt prompt_cr prompt_sp
() {
emulate -L zsh
# Clear the loading prompt. The real prompt is about to get printed.
print -rn -- $terminfo[rc]$terminfo[sgr0]$terminfo[ed]
unfunction _clear-loading-prompt
precmd_functions=(${(@)precmd_functions:#_clear-loading-prompt})
}
}
precmd_functions=($precmd_functions _clear-loading-prompt)
} "$@"
}
# Must be called at the very bottom of ~/.zshrc. Must be paired with
# instant-zsh-pre.
function instant-zsh-post() {
emulate -L zsh
if (( ${+precmd_functions} && ${+precmd_functions[(I)_clear-loading-prompt]} )); then
# Move _clear-loading-prompt to the end so that the loading prompt doesn't get
# erased too soon. This assumes that the real prompt is set during the first
# `precmd` or even earlier.
precmd_functions=(${(@)precmd_functions:#_clear-loading-prompt} _clear-loading-prompt)
fi
}
@SkyyySi
Copy link

SkyyySi commented Nov 25, 2020

Very nice, thank you! Just wondering, does this happen to be unlicensed? :)

@romkatv
Copy link
Author

romkatv commented Nov 25, 2020

No, this code hasn't been released under any license.

Note that it's only a proof of concept. Making it work properly is a lot of work (which has been done in powerlevel10k, and even more completely in zsh4humans).

@tjmgregory
Copy link

tjmgregory commented Oct 26, 2021

"%B%39F${${(V)${(%):-%~}//%/%%}////%b%31F/%B%39F}%b%f"$'\n'"%76F❯%f "

Don't suppose you recommend a guide for interpreting this, so I could learn to customise it for myself? :) Excellent work by the way 💪

@romkatv
Copy link
Author

romkatv commented Oct 26, 2021

These are expansions. They are documented in man zshexpn.

Note that this code is a proof of concept. It works in some cases but not in others. I don't recommend actually using it.

@tjmgregory
Copy link

Ah groovy, thank you so much :) Fair enough that makes sense, know you've worked on it a lot in other places 🦸

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment