Skip to content

Repository files navigation

Starship-FTL

MIT License version

A faster-than-light (FTL) drive for Starship Zsh prompts

Warning

This is experimental. Prompt drawing is full of edge cases we haven't seen yet, and some we may not be able to solve for. If it works for your prompt, awesome! If it doesn't, file a bug report and include the starship.toml that isn't working. We may not be able to address every edge case, but we'll give it a shot.

Starship renders a prompt in milliseconds, but you still stare at an empty screen while the rest of your .zshrc loads. Starship-FTL draws your prompt before the rest of your config runs, then swaps in the real one when loading finishes. Startup does the same work as before, it just stops making you wait to see something. It also adds a clean up for your old prompts after you run a command (aka: a transient prompt).

The technique comes from romkatv's instant-zsh gist, the same idea behind powerlevel10k's instant prompt.

Features

  • FTL Prompt:
    • Enable by calling ftl-prompt starship
    • Prompt appears immediately, before plugins and completions load
    • Anything printed during startup, stdout and stderr, is captured and replayed above the real prompt instead of being erased
    • Hopefully no flickering: the swap happens in a single write bracketed by synchronized update marks, and the stray partial-line mark is suppressed while loading
    • Allows you to also set your cursor style up front instead of waiting for your config to load
    • Works with starship out of the box, or with any promptinit theme you build
    • The prompt drawn up front can come from your starship.toml, so there is no second prompt definition to keep in sync
  • FTL Transient:
    • Enable by calling ftl-transient on
    • Finished commands collapse to a short prompt
    • Zsh ships with a transient right prompt, enabled with setopt TRANSIENT_RPROMPT

All features are optional, and require you to enable the ones you want.

Installation

Install with a plugin manager

With antidote, add to the top of your .zsh_plugins.txt:

mattmc3/starship-ftl post:"ftl-prompt starship"

If you want to enable the transient prompt as well, use this:

mattmc3/starship-ftl post:"ftl-prompt starship; ftl-transient on"

Manual installation

If you don't use a plugin manager, you can clone and source this manually:

git clone https://github.com/mattmc3/starship-ftl ${ZDOTDIR:-$HOME}/.starship-ftl
source ${ZDOTDIR:-$HOME}/.starship-ftl/starship-ftl.plugin.zsh

Then, at the very top of your .zshrc, after making sure starship is in your path:

# .zshrc
path=(/path/to/starship/bin $path)
source /path/to/starship-ftl/starship-ftl.plugin.zsh
ftl-prompt starship  # show your starship prompt instantly
ftl-transient on     # optional: enable transient prompt

Starship configs

The starship theme takes an optional config argument:

ftl-prompt starship mytheme

The config resolves to the first of these that exists:

  1. The argument itself, as a path to a .toml file
  2. $ZDOTDIR/themes/mytheme.toml
  3. ${XDG_CONFIG_HOME:-$HOME/.config}/starship/mytheme.toml

Alternative for really slow themes

By default the theme loads first and its own prompt is drawn, so what you see is your real prompt. That's normally what you want and costs a few milliseconds, which is the right thing for most themes. For a very slow theme however, -p allows you to draw an approximation immediately and loads the theme behind it:

ftl-prompt -p '%~ %# ' starship

For best results, make the approximation resemble your real prompt.

Drawing the approximation from your config

With starship, the approximation can come out of starship.toml instead of a string, so there is only one prompt definition to keep in sync. -P draws the ftl-prompt profile:

ftl-prompt -P starship
[profiles]
# Drawn by starship-ftl before the real prompt is ready. Same shape as `format`,
# minus anything that has to shell out, git especially, so the cost stays flat
# no matter how big the repo is.
ftl-prompt = """\
$directory\
$python$character\
"""

-P is for the starship theme only, and it's an alternative to -p, not an addition. A config with no ftl-prompt profile gets a message and the real prompt, the same as leaving the flag off.

Only the left prompt is drawn. A right prompt appears when the real one does.

This costs one starship call before anything is on screen, which -p does not, and both are far cheaper than loading the theme first.

Cursor style

A cursor style set by a plugin or editor config only takes effect once it loads. To apply it up front, set the style before calling ftl-prompt:

zstyle ':ftl-prompt:' cursor bar

Styles are block, underline, or bar, with an optional blinking- prefix, or a raw DECSCUSR number 0-6.

This covers the gap until your own config loads. It doesn't replace a plugin that manages cursor shape, like one that changes the cursor per vi mode.

The zsh prompt system

Themes are ordinary promptinit themes, loaded from a prompt_<name>_setup file on fpath. ftl-prompt runs that setup function, applies the prompt_opts it asks for and records prompt_theme, which is the part of the prompt system that matters for setting one theme once.

It does not run promptinit, which globs every fpath entry for every theme on the system to build a list only prompt -l and prompt -p read. Nor does it tear down a theme that was already set: this runs at the top of your .zshrc, where there is never one to tear down.

If you want prompt -l, prompt -p or prompt -r, or you're switching themes in a running shell, run promptinit yourself. After your prompt is set it costs nothing, because the prompt is already on screen:

ftl-prompt starship
autoload -Uz promptinit && promptinit

Cache

Every question this asks starship is a process spawn, and those spawns are most of what it costs at startup. The answers are cached under ${XDG_CACHE_HOME:-~/.cache}/starship-ftl, keyed on the size and modification time of the starship binary and your config, so editing starship.toml invalidates the cache on your next shell.

Two edits slip past that key: a config restored from a backup or copied with cp -p, which keeps its old timestamp, and one landing in the same timestamp tick as the previous edit. If your prompt ever disagrees with your config, rule that out first:

rm -rf ${XDG_CACHE_HOME:-~/.cache}/starship-ftl

To ask starship every time instead, before calling ftl-prompt:

zstyle ':starship-ftl:' cache no

Transient prompt

Replace the prompt on a finished command with a short one, so scrollback reads as a list of commands instead of a wall of prompts. Opt in, off by default.

Add a profile to your starship.toml:

[profiles]
transient = "[❯](bold purple) "

Then, once your prompt is set up:

ftl-transient on

ftl-transient off turns it back off. The profile name defaults to transient; pass another to use it instead:

ftl-transient on my-short-prompt

Only the left prompt is touched, so a finished command keeps whatever its right prompt showed. To drop that too, use zsh's own option:

setopt transient_rprompt

Related projects

License

MIT

About

Faster-than-light drive for the Zsh starship prompt (and other non-starship prompts too)

Topics

Resources

Stars

21 stars

Watchers

1 watching

Forks

Releases

Packages

Contributors

Languages