Take the 2-minute tour ×
Unix & Linux Stack Exchange is a question and answer site for users of Linux, FreeBSD and other Un*x-like operating systems.. It's 100% free, no registration required.

Is there any way to make less program repeat first line (or first 2 lines) on every displayed page?

Is there any other pager program which can do this?

This would be a killer-app for database table browsing, think mysql or psql or gqlplus...

For those of you who don't get the idea, see the screenshot in the bottom of this page. I want to repeat header line + horizontal ascii bar.

share|improve this question

4 Answers 4

up vote 5 down vote accepted

I found a solution using Vim on this page

First, we need a Vim macro, which will do most of the work, I save it in ~/.vim/plugin/less.vim:

" :Less
" turn vim into a pager for psql aligned results 
fun! Less()
  set nocompatible
  set nowrap
  set scrollopt=hor
  set scrollbind
  set number
  execute 'above split'
  " resize upper window to one line; two lines are not needed because vim adds separating line
  execute 'resize 1'
  " switch to lower window and scroll 2 lines down 
  wincmd j
  execute 'norm! 2^E'
  " hide statusline in lower window
  set laststatus=0
  " hide contents of upper statusline. editor note: do not remove trailing spaces in next line!
  set statusline=\  
  " arrows do scrolling instead of moving
  nmap ^[OC zL
  nmap ^[OB ^E
  nmap ^[OD zH
  nmap ^[OA ^Y
  nmap <Space> <PageDown>
  " faster quit (I tend to forget about the upper panel)
  nmap q :qa^M
  nmap Q :qa^M
endfun
command! -nargs=0 Less call Less()

Second, to emulate a pager, I need to invoke vim so that it will:

  • read standard input
  • but if argument is given on command line, read whatever comes there
  • work in read-only mode
  • skip all init scripts, but instead execute Less macro defined above

I put this together as helper script in ~/bin/vimpager:

#!/bin/bash
what=-
test "$@" && what="$@"
exec vim -u NONE -R -S ~/.vim/plugin/less.vim -c Less $what

Third, I need to override environment variable $PAGER, but only for psql (add this to my ~/.bash_aliases):

if which vimpager &>/dev/null; then
  alias psql='PAGER=vimpager psql';
fi
share|improve this answer
    
I've seen people say that answers on stack exchange should contain the full answer, not just a link because links go dead, as it seems this one has. :-( I found it in the wayback machine here: web.archive.org/web/20130425064032/http://… I guess copyright doesn't allow a copy and paste into the answer. –  chmac May 2 at 19:28
    
Thanks for sharing, it is a useful script. However, please add the full answer here. –  Florian Bw May 22 at 15:08
    
@FlorianBw Thanks for editing the post to include the text. I approved it but please note that adding "Edit: Solution from the URL" in the text is not part of the answer and should not be in the text. This can be seen from the edit history and not made explicit in the text. –  Anthon May 22 at 15:42

Have you tried SQL Mode in Emacs/XEmacs?

It's certainly not as simple to use as more or less, but it does what your asking for, leaving a header row while scrolling results vertically and horizontally.

share|improve this answer
    
Thanks, I don't know Emacs but it sound interesting. I would eventually need a shell script which would: start emacs, run psql there, (with given conn. params), enable sql-mode and do what I want (always freeze top 2 rows when there are query results larger than screen size). any hints on that? –  filiprem Dec 28 '11 at 14:03

You could use multiple 'regions' in screen:

$ cat screenrc.sql
escape ^aa  # adjust as needed
bind q quit # to quickly exit
screen 0 less ${FILE}
screen 1 less ${FILE}
split  # create two regions
focus top # starting with the top region
resize 4  # make it four lines (one for screen line, one for less prompt)
select 0  # display window 0
focus bottom  # in the bottom region
select 1  # display window 1 and focus here

Then you just need to set the $FILE environment variable:

$ FILE=$HOME/.bash_profile screen -mc screenrc.sql
share|improve this answer
    
this is almost what I wanted, but (a) the top window does not scroll right, so it is useless for wide tables –  filiprem Dec 28 '11 at 19:53
    
Not sure what you mean by 'useless for wide tables'; screen can expand to the size of the terminal (if it doesn't run the fit screen command). I had thought that you didn't want the top to scroll. When I tested it on my own, both windows scroll as they should. The top scrolls two lines (1-2, 3-4, 5-6, etc.) and the bottom scrolls as needed. What is the behavior you are seeing/ –  Arcege Dec 28 '11 at 20:05

You can add a number before the 'forward' and it will scroll N lines, not a full length. So if your terminal window is 40 lines, type 38f to start scrolling only 38 lines, leaving the last 2 line from the last 'page.' From the manpage:

   SPACE or ^V or f or ^F
          Scroll forward N  lines,  default  one  window  (see  option  -z
          below).   If  N  is  more  than  the screen size, only the final
          screenful is displayed.  Warning: some systems use ^V as a  spe‐
          cial literalization character.

   z      Like  SPACE,  but  if  N is specified, it becomes the new window
          size.

   b or ^B or ESC-v
          Scroll backward N lines,  default  one  window  (see  option  -z
          below).   If  N  is  more  than  the screen size, only the final
          screenful is displayed.
share|improve this answer
    
I need to keep first, not last N lines. As "freeze top N rows" in Google Spreadsheet. –  filiprem Dec 28 '11 at 13:29
    
Ah, sorry. I don't know if a utility that would do that. Then what I suggest is: use screen or tmux to create two panes, resize of the first one to two lines (resize 2) and then run less, in the second pane, run less normally. You could set this up as a script with a specific .screenrc file. See alternate answer. –  Arcege Dec 28 '11 at 14:14

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.