Skip to content

Latest commit

 

History

History
223 lines (164 loc) · 5.23 KB

plugins.md

File metadata and controls

223 lines (164 loc) · 5.23 KB

Plugins

A plugin is a FreSH script in ~/.fresh/plugins named <name>.plugin. It is sourced into your shell at startup, so it can define aliases, functions and variables. There is no manifest, no metadata and no install step.

plugin                 # list what is installed, loaded ones are marked
plugin load git        # load one right now, for this session
rehash                 # reload the theme and every plugin after editing a file

rehash re-sources whatever FRESH_THEME and FRESH_PLUGINS name, so editing a plugin and running rehash applies it without opening a new shell. It adds and replaces: an alias you deleted from the file stays until the shell restarts, because sourcing a file cannot know what used to be in it.

Load them on every start with:

# ~/.freshrc
FRESH_PLUGINS="git dirs sys"

Names are separated by spaces and loaded in that order.

The bundled plugins

git

g gs ga gc gco gb gd gl gp gpl
groot     cd to the top of the repository
gclean    list branches already merged

dirs

.. ... ....   go up one, two, three levels
ll la l       ls variations
mkcd dir      create a directory and enter it
up            go up one level and list

sys

path      print PATH
reload    source ~/.freshrc
h c       history, clear
ports     listening sockets
psg name  processes matching a name

edit

e         run $EDITOR
rc        edit ~/.freshrc
edit x    open a file with its default program

Writing one

Create ~/.fresh/plugins/docker.plugin:

# docker shortcuts
alias d='docker'
alias dc='docker compose'
alias dps='docker ps'
alias di='docker images'

dsh() {
  docker exec -it "$1" sh
}

dclean() {
  docker container prune -f
  docker image prune -f
}

Add it:

FRESH_PLUGINS="git dirs sys docker"

or try it without editing anything:

plugin load docker

What a plugin can do

Anything a script can do, because it is just a script. The useful patterns:

Aliases for short commands.

alias k='kubectl'

Functions when you need arguments in the middle, or several steps.

backup() {
  cp "$1" "$1.$(date +%Y%m%d)"
}

Environment for tools you always want configured.

export EDITOR=nvim
export PAGER=cat

PATH additions, guarded so repeated loading does not stack up.

test -d "$HOME/tools" && export PATH="$HOME/tools;$PATH"

Conditional setup, so a plugin can be harmless when the tool is missing.

if which cargo > nul 2>&1; then
  alias cb='cargo build'
  alias ct='cargo test'
fi

Help pages

describe gives anything you add a page under help <name>, in the same shape as the built in ones:

describe <name> <summary> [<usage>] [<detail>]
dsh() {
  docker exec -it "$1" sh
}

describe dsh "open a shell inside a running container" "dsh <container>"
λ help dsh

  dsh  open a shell inside a running container
  dsh <container>

  <required>  [optional]  ... repeatable

Write the usage in the same notation the shell uses: <required>, [optional], ... for repeatable. The fourth argument is a block of detail printed under the usage line, which is where flags belong:

describe dclean "remove stopped containers and unused images" \
  "dclean [-a]" \
  "  -a   images with no tag as well
Asks for nothing and does not stop anything that is running."

Aliases need no describe. help ll finds ll='ls -l' on its own and prints the alias with the page for ls. Describe one anyway when the alias does something the target's page does not explain.

Naming an existing command replaces its page, so a plugin that changes what gs does can say so:

alias gs='git status --short --branch'
describe gs "the short status, with the branch line" "gs"

Everything described shows up in the help overview under Described by plugins, so a user can see what a plugin added without reading the file.

Rules of thumb

  • Keep it fast. Everything in a plugin runs before your first prompt appears. Avoid network calls, and avoid $(...) that shells out to a slow program.
  • Do not print anything on load. A plugin that writes to the screen makes every new shell noisy.
  • Do not change the current directory. Users do not expect a new shell to start somewhere unexpected.
  • Guard anything machine specific with a test, so the same plugin works on a machine where the tool is not installed.
  • Prefix helper functions that are not meant to be called directly, so they do not collide with a real command. FreSH resolves a function before a program on PATH, so naming a function git will shadow git everywhere.

Load order and overriding

Plugins are sourced after ~/.freshrc and after the theme. So:

  • a plugin alias wins over an alias set earlier in .freshrc
  • a plugin that sets FRESH_PROMPT wins over the theme

If you want the opposite, drop FRESH_PLUGINS and load them by hand at the top of .freshrc:

plugin load git dirs
alias gs='git status --short'   # yours wins now

Sharing

A plugin is one file with no dependencies, so sharing it is sending the file. To install someone else's, copy it into ~/.fresh/plugins and add its name to FRESH_PLUGINS. Read it first: it runs with your privileges every time you open a shell.