⚙️ ❮ ZSH Navigation Tools ❯

Salvydas Luklosius
6 min readFeb 11, 2022

| GitHub | Twitter | Join the team |

Recap

In a ZI Series, covered basics on how to use history effectively, syntax highlighting, etc. This time navigation using Zsh in the command line will be taken to another level.

Introduction

Video: Google Drive

The available tools:

  • n-aliases - browse aliases, relegates editing to vared
  • n-cd - browses dirstack and bookmarked directories, allows entering the selected directory
  • n-functions - browses functions, relegates editing to zed or vared
  • n-history - browses history, allows to edit and run commands from it
  • n-kill - browses processes list, allows sending a signal to a selected process
  • n-env - browses environment, relegates editing to vared
  • n-options - browse options, allows toggling their state
  • n-panelize - loads output of a given command into the list for browsing

All tools support horizontal scroll with <,>, {,}, h, l or left and right cursors. Other keys are:

  • H, ? (from n-history) - run n-help
  • Ctrl-R - start n-history, the incremental, multi-keyword history searcher (Zsh binding)
  • Ctrl-A - rotate entered words (1+2+3 -> 3+1+2)
  • Ctrl-F - fix mode (approximate matching)
  • Ctrl-L - redraw of whole display
  • Ctrl-T - browse themes (next theme)
  • Ctrl-G - browse themes (previous theme)
  • Ctrl-U - half page up
  • Ctrl-D - half page down
  • Ctrl-P - previous element (also done with vim's k)
  • Ctrl-N - next element (also done with vim's j)
  • [, ] - jump directory bookmarks in n-cd and typical signals in n-kill
  • g, G - beginning and end of the list
  • / - show incremental search
  • F3 - show/hide incremental search
  • Esc - exit incremental search, clearing filter
  • Ctrl-W (in incremental search) - delete whole word
  • Ctrl-K (in incremental search) - delete whole line
  • Ctrl-O, o - enter uniq mode (no duplicate lines)
  • Ctrl-E, e - edit private history (when in private history view)
  • F1 - (in n-history) - switch view
  • F2, Ctrl-X, Ctrl-/ - search predefined keywords (defined in config files)

Set of tools like n-history - multi-word history searcher, n-cd - directory bookmark manager, n-kill - htop like kill utility, and more.

Based on n-list, a tool generating a selectable curses-based list of elements that has access to the current Zsh session, i.e. has broad capabilities to work together
with it.

Feature highlights include incremental multi-word searching, approximate matching, ANSI coloring, themes, unique mode, horizontal scroll, grepping, advanced history management, and various integrations with Zsh.

Install ZNT with the script

sh -c " $(curl -fsSL https://raw.githubusercontent.com/z-shell/zsh-navigation-tools/main/doc/install.sh) "

To update run the command again.

.zshrc will be updated with only 8 lines of code, which will be added at the bottom.

Install using ZI

Install using Zgen

Add zgen load z-shell/zsh-navigation-tools to .zshrc and issue a zgen reset (this assumes that there is a proper zgen save construct in .zshrc).

The config files will be available in ~/.config/znt.

Installation With Antigen

The config files will be in ~/.config/znt.

Single File Manual Installation

Running script doc/generate_single_file will create a single-file version of ZNT.

It can be sourced from .zshrc. Don't forget about configuration files as described above.

Manual Installation

After extracting ZNT to {some-directory} add following two lines to ~/.zshrc:

As you can see, no plugin manager is needed to use the *.plugin.zsh file.

The above two lines of code are all that almost all plugin managers do.

What’s needed is only:

source "{some-directory}/zsh-navigation-tools.plugin.zsh"

because ZNT detects if it is used by any plugin manager and can handle $fpath update by itself.

Truly Manual Installation

Copy (or link) all n-* and znt-* files to /usr/share/zsh/site-functions/(or /usr/local/share/zsh/site-functions/, check with echo $fpath[1]) and then add:

autoload n-list n-cd n-env n-kill n-panelize n-options n-aliases n-functions n-history n-help

Create aliases to avoid typing of the minus sign “-”:

Don’t forget to copy configuration files.

They should go to ~/.config/znt. Moreover, n-cd works together with option AUTO_PUSHD and you should have:

History Widget

To have n-history as the incremental searcher bound to Ctrl-R copy znt-* files into the */site-functions dir (unless you do single file install) and add:

autoload znt-history-widget zle -N znt-history-widget bindkey "^R" znt-history-widget

to .zshrc. This is done automatically when using the installer, zgen, antigen, or single file install.

Two other widgets exist, znt-cd-widget and
znt-kill-widget, they too can be assigned to key combinations ( autoload is done
in.zshrc so no need of it):

zle -N znt-cd-widget bindkey "^B" znt-cd-widget zle -N znt-kill-widget bindkey "^Y" znt-kill-widget

Configuration

ZNT has configuration files located in ~/.config/znt. The files are:

n-list.conf contains main configuration variables:

Read remaining configuration files to see what’s in them. Nevertheless, the configuration can be also set from zshrc.

There are 5 standard zshrc configuration variables:

The above variables will work for n-history tool.

For other tools, change _history_ to e.g. _cd_,
for the n-cd tool. The same works for all 8 tools.

A common configuration of the tools uses variables with _list_ in them:

If you used ZNT before v2.1.12, remove old configuration files ~/.config/znt/*.conf so that ZNT
can update them to the latest versions that support integration with Zshrc.

If you used the installer then run it again (after the removal of configuration files).

Programming

The function n-list is used as follows:

This is all that is needed to be done to have the features like ANSI coloring, incremental multi-word search, unique mode, horizontal scroll, non-selectable elements (grepping is done outside n-list, see the tools for how it can be done).

To set up non-selectable entries add their indices into array NLIST_NONSELECTABLE_ELEMENTS:

typeset -a NLIST_NONSELECTABLE_ELEMENTS NLIST_NONSELECTABLE_ELEMENTS =( 1 )

The result is stored as $reply[REPLY] ($ isn't needed before REPLY because of the arithmetic context inside []).

The returned array might be different from input arguments as n-list can process them via incremental search or uniq mode.

$REPLY is the index in that possibly processed array.

To set up entries that can be jumped to with [,] keys add their indices to NLIST_HOP_INDEXES array:

n-list can automatically colorize entries according to a Zsh pattern. Following example will colorize all numbers with blue:

Blue is the default color, it doesn’t have to be set.

The alternative will work when in parenthesis, i.e. (a|b).

BTW by using this method you can colorize the output of the tools, via their config files (check out e.g. n-cd.conf,
it is using this).

Performance

ZNT is fastest with Zsh before 5.0.6 and starting from 5.2

A tip

Zsh plugins may look scary, as they seem to have some “architecture”. What a plugin is, is that:

  1. It has its directory added to fpath
  2. It has any first *.plugin.zsh file sourced

That’s it. When one contributes to Oh-My-Zsh or creates a plugin for any plugin manager, he only needs to account for this.

The same with doing any non-typical Zsh Navigation Tools installation.

Note

Be aware of this

Fixing tmux, screen, and Linux vt

If TERM=screen-256color (often a case for tmux and screen sessions) then ncv terminfo capability will have 2 nd bit set.

This in general means that the underline won’t work.

To fix this by creating your own ncv=0-equipped terminfo file, run:

Similar is for Linux virtual terminal:

It will not display underline properly, but will instead highlight by a color,
which is quite nice. The same will not work for FreeBSD’s vt, ZNT will detect
if that vt is used and will revert to highlighting elements via reverse mode.

--

--