// ZSH-VERY-COLORFUL-MANUALS — COLORIZE MAN PAGES // LESS_TERMCAP_* ANSI

zsh plugin · autoloaded man wrapper · injects LESS_TERMCAP_* ANSI escapes into less · no global env pollution · Solaris nroff shim

GitHub Issues
// Color scheme

>_ZSH-VERY-COLORFUL-MANUALS

Re-paints the terminal's man output with ANSI colors. The plugin autoloads a man wrapper that injects LESS_TERMCAP_* environment variables on the fly, telling man's pager (less by default) how to render bold / underline / standout. man <anything> gets green bold headers, bold-cyan underlined option names, and bright-magenta standout. The colors only kick in when you call man — nothing leaks into the parent shell.

Install

# Zinit
zinit ice lucid nocompile
zinit load MenkeTechnologies/zsh-very-colorful-manuals

# Oh My Zsh
git clone https://github.com/MenkeTechnologies/zsh-very-colorful-manuals \
    "$HOME/.oh-my-zsh/custom/plugins/zsh-very-colorful-manuals"
# then: plugins+=(zsh-very-colorful-manuals)

# Manual
git clone https://github.com/MenkeTechnologies/zsh-very-colorful-manuals
source zsh-very-colorful-manuals/zsh-very-colorful-manuals.plugin.zsh

After sourcing, the plugin appends ${0:h}/bin to fpath and runs autoload -Uz man. The next time you call man, zsh resolves the autoloaded function from bin/man instead of going straight to the system binary.

How it works

man pipes its rendered output through a pager (usually less). less reads LESS_TERMCAP_md for bold, LESS_TERMCAP_us for underline, LESS_TERMCAP_so for standout, and the matching _me / _ue / _se reset sequences. The wrapper in bin/man defines a __man() helper that builds each escape with printf '\e[…m' and hands them to the system man through env — so the variables live only in that one subprocess.

LESS_TERMCAP_mdbold start — 0;32m (green) — section headers
LESS_TERMCAP_mebold end — 0;34m (reset to blue)
LESS_TERMCAP_usunderline start — 1;36;4m (bold cyan, underlined) — option names
LESS_TERMCAP_ueunderline end — 0;1;31m (bright red)
LESS_TERMCAP_sostandout start — 0;1;35m (bright magenta) — the (END) marker and search matches
LESS_TERMCAP_sestandout end — 33m (yellow)
LESS_TERMCAP_mbblink — 0;33;44m (yellow on blue)

The exact SGR codes above are pinned by the test suite — see the engineering report for the full color contract.

What the wrapper sets

Besides the seven LESS_TERMCAP_* escapes, the env block carries three more variables into the man subprocess:

PAGER${commands[less]:-$PAGER} — resolves zsh's commands hash for less first, falling back to your $PAGER. Without this, a PAGER=most setting would ignore the LESS_TERMCAP_* coloring.
_NROFF_U1 — read by the Solaris nroff shim to enable underline (EUC) rendering. No effect on Linux/macOS.
PATH$HOME/bin:$PATH — prepends $HOME/bin so the Solaris nroff shim shadows /usr/bin/nroff.

The wrapper does not set or export LESS itself, so your less defaults (e.g. -R -F -X) are untouched. Arguments pass through verbatim — titles with spaces, glob characters, and unicode all reach man unsplit because the wrapper ends with a quoted man "$@".

Solaris nroff shim

When $OSTYPE matches solaris*, the plugin entry writes a small $HOME/bin/nroff wrapper (only if one isn't already executable). Solaris nroff lacks the -u underline flag that man pages expect; the shim intercepts the -u0 -Tlp -man invocation and rewrites it to /usr/bin/nroff -u$_NROFF_U, passing any other invocation straight through. On Linux and macOS this branch never runs — the only side effects there are the fpath+= and autoload -Uz man lines.

Try it

man ls          # green bold header, bold-cyan underlined flags
man git-rebase  # underlined options, standout search matches
man bash        # the brick-sized manual, finally readable

To confirm the wrapper is active: whence -v man should report man as a shell function (the autoloaded wrapper), not just /usr/bin/man.

Scope & non-goals

No global env pollutionThe LESS_TERMCAP_* vars are passed via env to the man subprocess only — they are never exported into your interactive shell, so other less invocations stay uncolored.
No man / less config touchedNo ~/.lesskey, no man.conf, no system theme. Removing the plugin removes the coloring with no residue.
Recursion-safeThe inner function is named __man, not man, so the trailing man "$@" resolves to the system binary rather than re-entering the wrapper.
Pager-dependentThe coloring relies on less reading LESS_TERMCAP_*. If less is absent and $PAGER is something that ignores those vars, output falls back to plain text.

Engineering report

For the full breakdown — the exact SGR color contract per LESS_TERMCAP_* key, the env-wrapper line-by-line, and the zunit test coverage map — see the engineering report.

Sibling plugins

Part of the MenkeTechnologies zsh plugin family — the MenkeTechnologiesMeta umbrella: