escape code

less: a love story

joepd, 27 December 2013

Less. I use it more and more. I would not be surprised if at least a fourth of my time in a console window actually is spent within less. It is just a pager, you say? True, but one that has been in active development since 1983. The original developer currently is still the maintainer. You don't need to be an experimental archeologist to put this tool to use. Getting acquainted to this pager will pay itself off pretty fast.

If you haven't done so yet, have a look at man 1 less. The synopsis looks like Sesamestreet episode with brain damage:

less [-[+]aABcCdeEfFgGiIJKLmMnNqQrRsSuUVwWX~]

It might appear that this overabundance of seemingly unneeded features could serve as a practical definition of bloatware. These are just the options without arguments. Most of the same options can be used from within the application itself. Once you notice that you like some options, you can make those default. There are some true gems hidden in the following alphabet soup from the synopsis. I will show which ones I regularly use, but only after having a close look at the searching capabilities of less.

Effective use of less implies that one can use its searching possibilities. Striking the / initiates a search, and enter concludes it. Use n to go to the next match, N for the previous. Searching backward is started off with ?.

Search handles by default regular expressions. With some terminal escape codes set up, less will highlight the matches. I often type a string like this as a make-shift highlighter:

/someID=[0-9]+|error|(STATE|button).*$

Less stores the searches in ~/.lesshist, or in any file indicated by the environment variable $LESSHISTFILE. After starting typing /, the up and down arrows are available to use previous searches.

A search can also be started from the shell. When I already know what to look for, I often use this, also to leave traces of what I am interested in in the shell history. Chances are that I already used this search term in the shell, or will in the near future. Next to helping myself to use zsh's history completion feature, this has proven to be a real time saver when I need to revisit the same problem again. A typical use is when I want to know what happened at a specific time:

% less +/^16:34 logfile

This will open the file, and jump immediately to the first line with that time stamp. Less will also store this search in its history file. Unfortunatelty, there is no mechanism to search the past searches.

The most recent search term has a special role when pressing ESC-F. New content of the file will be displayed as with tail -f or the normal F-function, but the scrolling will stop with the first match of the most recent search.

A lesser known search facility is the one initiated by &. This filters the output to just the matching lines. I use this often when looking at the output of some command: One can refrain from running the command again only to use grep to find the interesting lines. A renewed search is done on the whole output, so one cannot apply a filter on a filter. Specifying lines that do not match the expression (grep -v), can be initiated by typing &!. After having refined the search pattern, the result can be saved with s filename.

The &-filter interacts with the search history. As I regularly have to dig in a logfiles where the first encounter is really helped by such a filter, I set up an alias like this:

alias lf="less +$'&event1|action2|state3|error\n' "

With this less-filter I can quickly get a birds eye perspective on the events. The filter can be disabled by an empty filter, so by pressing &[enter]. and can easily zoom in, and have this search string ready for poor man's highlighting. A quick -N to display line numbers, and typing the number of where I want to start to look, followed by g, brings me immediately to where I want to be.

When less is running, the following keys I use most:

G
Go to end of file. Before that, check if the file has changed. Great for viewing log files.
g
Go to beginning of file, or, when a number is pressed first, go to that line number.
ESC-u
Undo search highlighting.
F
Follow file. It's like tail -f, but after the BREAK signal (CTRL+c), all the niceties of the pager are still intact. And: tail -f cannot do the line wrapping.
Number%
Type in 50%, and you'll see the middle of the file.
-S[Enter]
Toggle line wrapping.
-i[Enter]
Toggle case insensitive search.
-N and -n
Enable and disable line numbers.

Despite the numerous options, I am not using so much more in my day to day usage of less. Some options can be specified on the command line. The following I consider nice:

-R
For when the file contains raw characters, for example ANSI color codes. This causes less not to choke on colored output, or to see the garbage in a binary file, instead of an error message.
-X

This causes the screen not to be repainted after less exits. After viewing a file or man-page, I find it increadibly useful to be able to see the last screen in my terminal emulator's scroll back window. Just make the part visible that is of interest, and you have the reference visible when typing your command. In most terminal emulators, Shift+PgUp/PgDown gets the relevant info back again.

This setting makes most sense when the output is not too long, or if you know you'll be able to get to the important points in few jumps. To disable this feature, use -+X as an option.

It is unfortunate that everything that has been displayed in less is retained in the scrollback. It would be more convenient to only have a screen full of output in the console, especially when needing to browse insane amounts of text. I have not yet managed to fix this.

-M
Get a long prompt in less. Useful info about filename, length of file, and current position.

To have less always use the same options that you like, it listens to the $LESS environment variable in your ~/.bashrc or $ZDOTDIR/.zshrc. I have set mine to the following:

export LESS='MSRiX'

These letters have the following effect: long prompt, chop long lines, raw, case insensitive search, keep output in scrollback buffer.

Possibly, your distribution, or you yourself, has set up some nice colors to display different colors in man-pages. I have the following escape codes somewhere in the startup files of my shell:

export LESS_TERMCAP_mb=$'\e[01;31m'       # begin blinking
export LESS_TERMCAP_md=$'\e[01;38;5;74m'  # begin bold
export LESS_TERMCAP_me=$'\e[0m'           # end mode
export LESS_TERMCAP_so=$'\e[38;5;070m'    # begin standout (info box, search)
export LESS_TERMCAP_se=$'\e[0m'           # end standout-mode
export LESS_TERMCAP_us=$'\e[04;38;5;146m' # begin underline
export LESS_TERMCAP_ue=$'\e[0m'           # end underline
export MAN_KEEP_FORMATTING=1

The last entry might not be clear. When piping the output of man to less, the colors are not retained. Unless the MAN_KEEP_FORMATTING environment variable has a value.

The same trick I use in Something that I often use if I want to see : man less | less +/'^ *-X'. This jumps directly to the place where -X is in front of a line, possibly with some spaces. Most of the time, it just jumps to the explanation that you want to see, otherwise press n to jump to the next hit.