Paging
Note: there is a public repository containing the source code and formal documentation for the programs that this post is about.
I used the venerable less
as my pager for a long time, but I wanted
something more Emacs-like. And what could be more Emacs-like than Emacs?
Fortunately I found Kaushal Modi's excellent eless
shell script, which runs
an instance of Emacs that's been adapted to make it work like a pager.
But that was almost 5 years ago, and while much of the core functionality
from eless
remains in my version — which I've not very imaginatively named
empager
— I've made a lot of changes to it, both to add functionality and
so that it works as much as possible like Emacs does when I use it as an
editor. It doesn't work exactly the same because I want it to function in as
many environments and situations as possible (such as on newly-installed
systems), so empager
- doesn't use any external packages: it only uses ones that are bundled with Emacs,
- doesn't assume that internet access is available, and
- has a minimum of external dependencies: as much as possible is contained in the script itself.
The added functionality includes:
- saving search strings and register contents across invocations (which can be useful when reopening the same file after closing it prematurely, or when looking for the same pattern in different files)
- allowing the line number at which it is to be opened to be specified for each file (using a syntax similar to the one Emacs itself uses)
- allowing the version of each file to open to be specified, provided it's under git or CVS version control
- supporting as many of the
less
program's command line options as could be reasonably easily implemented (or, in a few cases, ignored), at least when they don't conflict with the Emacs-like options thatempager
accepts- for example, if the
-F
option is specified and only one file (or source) is being paged then its contents will be written directly to the screen without starting Emacs if (and only if) those contents will all fit on a single screen
- for example, if the
- easy saving of positions: each shifted positive digit (e.g. '!' for '1') saves point (that is, the current cursor position) in the register whose name is that digit, and the digit itself jumps to the position saved in that register
- opening the current file in your main Emacs instance (using the
e
command), with point on the same line- since files in a pager can't usually be edited, many single characters
(like
e
) are repurposed to run commands
- since files in a pager can't usually be edited, many single characters
(like
If you end up trying out empager
you may notice that there are some
"idiosyncratic" keybindings. They almost always correspond to custom
keybindings that I use in my main Emacs editor, and may not be to everyone's
tastes. In which case you can edit your copy of the script to create a custom
Emacs-based pager of your very own.
But Wait: There's More!
I use empager
all the time, so I've given it the much shorter one-letter
name p
. I could have defined p
as an alias, but sometimes I find that I
want to pass it as an argument to a command like xargs
. For example, this
find . -name '*.txt' | xargs p
(or just sde txt -- p
using searchdown
) will fail if p
is an alias. I
could have also created a symbolic link to empager
named p
, but the tiny
p
script included in the repository is a little more flexible, in that it
runs whichever pager program is specified by the PAGER
environment
variable.
And speaking of environment variables, empager
also takes options from the
EMPAGER
environment variable just like less
takes them from the LESS
environment variable. (I set it to -FR
.) You can also have the man
command use empager
as its man page viewer/pager by setting and exporting
the MANPAGER
environment variable to empager
like so:
MANPAGER=empager export MANPAGER
However, in a few circumstances empager
will display some unsightly raw
escape codes. The only place that this happens consistently for me is in the
help displayed when using the help()
function in an interactive Python
shell, so I start interactive Python 2 and 3 sessions using the following
aliases:
alias py2='PAGER=bempager python2' alias py3='MANPAGER=bempager python3'
where bempager
is included in the repository and is a simple wrapper script
that removes any and all backspaces before passing data along to empager
.
(Apparently Python 2 uses the PAGER
environment variable while Python 3
uses the MANPAGER
environment variable.) I also define the alias
alias lman='MANPAGER=less man'
so that if I do encounter a man page that doesn't play well with empager
(or bempager
) then I can quickly switch to using less
for that page.
One final pager-related tweak that I'll share here is a readline
macro that
I've added to my ~/.inputrc
file:
"\C-p": " 2>&1 | p"
This allows me to very quickly redirect a command's regular and error
output to an instance of my default pager program by just typing C-p
(a.k.a. Ctrl+p
) at the end of the command. (Emacs users that use C-p
"properly" will of course want to choose a different keybinding.) For
example, if I've typed the command
curl wttr.in/:help
and then I type C-p
the command becomes
curl wttr.in/:help 2>&1 | p
and the site's help information is displayed in my default pager instead of
potentially scrolling off the screen. (Remember that you need to type C-x
C-r
in the terminal to have any changes you've made to your ~/.inputrc
file take effect there.)
If you'd like to support this site then check out my web app InEveryNook.com and see if it's of interest to you, pass it along to anyone you think might be interested in it, or both. Thanks!