5

Sometimes we run a command in the terminal, and the output is too large, and we forgot to put "| less" in the end. So I am wondering would it possible to page the output when it is too large in zsh?

I tried to implement this feature by using python and less:

#!/usr/bin/env python3 termHeight = 25 import sys from subprocess import Popen, PIPE p = Popen(['unbuffer'] + sys.argv[1:], stdin=PIPE, stdout=PIPE) lines = [] for count in range(termHeight): line = p.stdout.readline() if not line: break print(line.decode('utf8'), end='') lines += [line] if line: q = Popen(['less', '-Mr'], stdin=PIPE) q.stdin.writelines(lines) while True: line = p.stdout.readline() if not line: break q.stdin.write(line) q.communicate() 

let's save this python script to p.py. So when we run "python p.py some commands" like "python p.py ls --help", if the output is more than 25 lines, this script will use less to display the output.

The problem is I can not get input from user. Which means this solution does not work with interactive program at all.

4 Answers 4

9

Try adding this to your .zshrc

export LESS="-FX" 
  • -F = “Causes less to automatically exit if the entire file can be displayed on the first screen.”
  • -X = “Disables sending the termcap initialization and deinitialization strings to the terminal.” (stops less clearing the screen)

For me this means less is used as the pager when there’s more than a screen of text, and zsh’s built-in pager (zsh -c '< /dev/fd/0', like cat) is used when not.

HTH

Sign up to request clarification or add additional context in comments.

4 Comments

Yessssss! Been trying to figure out how to do this forever.
Correct me if I'm wrong, but that doesn't actually cause zsh to use less as a pager.
Does not handle ANSI color either.
Having PAGER="less" and LESS="-FXR" seems to work best for me, allows colors to work for example.
4

I'm not sure this is possible. It would require zsh to do two things:

  1. Determine if the command is writing to standard output
  2. Intercept that output and display to a pager if necessary.

The second one is fairly simple. What we would really do is pass the output of every command to less and use a pair of options to quit less automatically if only one screen is needed.

preexec () { eval "$3" | less -XF } 

However, the first criterium is trickier: we wouldn't want such commands as

  • vi foo.txt
  • less bar.rtf
  • ssh remote.host.com

to be piped through less. Unfortunately, it's not obvious to me how to automatically distinguish between the programs that we do and don't want to pipe through less.

2 Comments

highlight color will lose
@ife you can still force color with: --color=always for commands that support it... For example, ls -l --color=always | less -RFX... When commands detect their output is connected to a pipe, it usually means output is being parsed so they don't add ANSI color escape sequences to make parsing easier... --color=always overrides that and sends color escape codes even when the output is a pipe.
0

Perhaps another option is to use something like screen or tmux rather than trying to force zsh to page for you. This solution provides support for editors such as vim, ssh connections, pagers less, more etc, and also gives multi-command scroll-back abilities which piping each command through a pager doesn't allow.

This approach would give you:

  • Scroll-back (quite a lot of scroll-back) over multiple commands (instead of just the last-entered command).
  • Re-attachment to your sessions (so you don't lose the scroll-back from the morning session when you get back from lunch).

This approach costs you:

  • You need to make a session to attach to before you run commands. This isn't much work, but in my experience the times I forget to use screen are the times I really, really wanted to.

Comments

0

What you can certainly do is wrap commands that may output more than one screen of text with shell functions.

That would be something like, which would act like an automatically paged ls

function ls { command ls $@ | less -RFX } 

You can also write something that would take a list of command names as entry and would generate that wrapper functions for each command. Therefore, you would only need to add new command names to a file and regenerate the wrappers.

That would be my workaround.

1 Comment

highlight color will lose

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.