programa de pager como menos, capaz de repetir as N linhas principais

15

Existe alguma maneira de fazer o lessprograma repetir a primeira linha (ou as primeiras 2 linhas) em todas as páginas exibidas?

Existe algum outro programa de pager que possa fazer isso?

Esta seria uma killer-app para o banco de dados de mesa de navegação, pense mysqlou psqlou gqlplus...

Para aqueles que não entendem a idéia, veja a captura de tela na parte inferior desta página . Eu quero repetir a linha do cabeçalho + barra ascii horizontal.

filiprem
fonte
Oh, garoto, isso pede uma extensão para menos, como um ponto do Painel Congelado. Por exemplo - - painel de congelamento 10,2 manteria 1 linha de cabeçalho de coluna e 10 cabeçalho de linha de coluna. A rolagem horizontal e vertical preservaria os cabeçalhos de linha e coluna, respectivamente. Isso seria muito legal de usar em um pager psql (merlinmoncure.blogspot.com/2007/10/better-psql-with-less.html)
Gunther Schadow

Respostas:

12

Existe uma solução usando o Vim.

Primeiro, precisamos de uma macro do Vim, que fará a maior parte do trabalho, salve-a em ~/.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()

Segundo, para emular um pager, preciso invocar o vim para que ele:

  • leia entrada padrão
  • mas se o argumento for dado na linha de comando, leia o que vier lá
  • trabalhar no modo somente leitura
  • pule todos os scripts init, mas execute menos macro definida acima

Coloquei isso como um script auxiliar em ~/bin/vimpager:

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

Terceiro, preciso substituir a variável de ambiente $ PAGER, mas apenas para o psql (adicione isso ao meu ~/.bash_aliases):

if which vimpager &>/dev/null; then
  alias psql='PAGER=vimpager psql';
fi
filiprem
fonte
Isso é adorável, eu tentei. Agora, seria bom se também fosse possível adicionar cabeçalhos de linha, em vez desses números de linha.
Gunther Schadow
4

Você já experimentou o modo SQL no Emacs / XEmacs?

Certamente não é tão simples de usar quanto moreou less, mas faz o que você pede, deixando uma linha de cabeçalho enquanto rola os resultados na vertical e na horizontal.

bsd
fonte
Obrigado, eu não conheço o Emacs, mas parece interessante. Eu acabaria precisando de um script de shell que: iniciasse o emacs, execute o psql lá (com determinados parâmetros), ative o modo sql e faça o que eu quero (sempre congele as duas linhas principais quando houver resultados de consultas maiores que o tamanho da tela) . alguma dica sobre isso?
28811 filiprem
3

Isso empresta muito da resposta aceita, mas acrescenta ...

  • Rolagem mais rápida
  • Não é possível rolar acidentalmente para o cabeçalho
  • Destaque de sintaxe (algum crédito pertence aqui )
    • Números positivos / negativos, datas, horas, NULLVerdadeiro / Falso (e T / F, S / N, Sim / Não)
    • Números de linha, se você os tiver antes de um caractere de pipe.
  • Texto de ajuda
  • Suporte para o Vim incluído no Git for Windows
  • Não ameace atualizar a exibição se o buffer stdin mudar

Algumas partes podem precisar ser ajustadas para sua saída específica, pois eu não uso psql. Também tenho funções auxiliares ligeiramente diferentes para meus propósitos, mas elas são semelhantes às da resposta aceita.

Entrada de amostra

  | ID |   First   |     Last     | Member | Balance |
--+----+-----------+--------------+--------+---------+
 1|  4 | Tom       | Hanks        | False  |    0.00 |
 2| 12 | Susan     | Patterson    | True   |   10.00 |
 3| 23 | Harriet   | Langford-Wat | False  |    0.00 |
 4|  8 | Jerry     |     NULL     | True   | -382.94 |
[… More rows …]
10| 87 | Horace    | Weaver       | False  |   47.52 |

Código

" :HeadPager
" Turn vim into a pager with a header row
" Adapted from /unix//a/27840/143088
fun! HeadPager()
    " If you didn't get three lines, shortcut out
    if line('$') < 3
        set nocompatible
        nmap <silent> q :qa!<c-M>
        nmap <silent> Q :qa!<c-M>
        return
    endif

    set noswapfile
    set nocompatible
    set nowrap
    set scrollopt=hor
    set scrollbind

    " Hide statusline in lower window
    set laststatus=0
    " Explain mapped chars in status line.
    set statusline=\ \ \ Q\ to\ quit\.\ Arrows\ or\ mousewheel\ to\ scroll\.\ \(Vim\ commands\ work\,\ too\.\)

    " Delete/copy header lines
    silent execute '1,2d'

    " Split screen with new buffer (opens at top)
    execute 'new'

    " Switch to upper split
    wincmd k

    " Paste the header over the blank line
    execute 'norm! Vp'

    " Header highlighting
    syn match Pipe "|"
    hi def Pipe ctermfg=blue
    syn match Any /[^|]\+/
    hi def Any ctermfg=yellow

    " Switch back to lower split for scrolling
    wincmd j

    " Set lower split height to maximum
    execute "norm! \<c-W>_"

    " Syntax highlighting
    syn cluster CellContents contains=None
    syn match Pipe "|" contained nextgroup=@CellContents skipwhite
    hi def Pipe ctermfg=blue

    " Start with newline or |. End right before next | or EOL
    syn region Cell start=/\v(^|\|)\s*/ end=/\v(\||$)\@=/ contains=LineNumber,Pipe

    syn match NumPos /\v\+?\d+(,?\d{3})*\.?\d*\ze *(\||$)\@=/ contained
    syn match NumNeg   /\v-\d+(,?\d{3})*\.?\d*\ze *(\||$)\@=/ contained
    syn match NumZero         /\v[+-]?0+\.?0*\ze *(\||$)\@=/  contained
    hi def NumPos ctermfg=cyan
    hi def NumNeg ctermfg=red
    hi def NumZero ctermfg=NONE
    syn cluster CellContents add=NumPos,NumNeg,NumZero

    syn match DateVal /\v\d{4}-\d{2}-\d{2}/ contained nextgroup=TimeVal skipwhite
    syn match TimeVal /\v\d{1,2}:\d{2}(:\d{2})?(\.\d+)?(Z| ?\c[AP]M)?\ze *(\||$)\@=/ contained
    hi def DateVal ctermfg=magenta
    hi def TimeVal ctermfg=magenta
    syn cluster CellContents add=DateVal,TimeVal

    syn match TrueVal /\v\c(t(rue)?|y(es)?)\ze *(\||$)\@=/ contained
    syn match FalseVal /\v\c(f(alse)?|no?)\ze *(\||$)\@=/ contained
    hi def TrueVal ctermfg=green
    hi def FalseVal ctermfg=red
    syn match NullVal /\v\cnull?\ze *(\||$)\@=/ contained
    hi def NullVal ctermbg=gray ctermfg=black
    syn cluster CellContents add=TrueVal,FalseVal,NullVal

    syn match LineNumber /^ *\d\+/ contained
    hi def LineNumber ctermfg=yellow

    " Arrows do scrolling instead of moving
    nmap <silent> <Up> 3<c-Y>
    nmap <silent> <Down> 3<c-E>
    nmap <silent> <Left> zH
    nmap <silent> <Right> zL
    nmap <Space> <PageDown>
    " Faster quit (I tend to forget about the upper panel)
    nmap <silent> q :qa!<c-M>
    nmap <silent> Q :qa!<c-M>

    " Ignore external updates to the buffer
    autocmd! FileChangedShell */fd/*
    autocmd! FileChangedRO */fd/*
endfun
command! -nargs=0 HeadPager call HeadPager()
Michael - onde está Clay Shirky
fonte
2

Você pode usar várias 'regiões' em 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

Então você só precisa definir a variável de ambiente $ FILE:

$ FILE=$HOME/.bash_profile screen -mc screenrc.sql
Arcege
fonte
1
isso é quase o que eu queria, mas (a) a janela de topo não vá para a direita, por isso é inútil para mesas largas
filiprem
Não sabe ao certo o que você quer dizer com 'inútil para mesas grandes'; A tela pode se expandir para o tamanho do terminal (se não executar o fitcomando de tela). Eu tinha pensado que você não queria que o topo rolasse. Quando eu testei sozinho, ambas as janelas rolam como deveriam. A parte superior rola duas linhas (1-2, 3-4, 5-6 etc.) e a parte inferior rola conforme necessário. Qual é o comportamento que você está vendo /
Arcege
0

Você pode adicionar um número antes do 'encaminhamento' e ele rolará N linhas, e não um comprimento total. Portanto, se a janela do seu terminal tiver 40 linhas, digite 38fpara começar a rolar apenas 38 linhas, deixando as 2 últimas na última 'página'. Na página de manual:

   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.
Arcege
fonte
1
Preciso manter primeiro , não as últimas N linhas. Como "congelar as N linhas principais" na planilha do Google.
filiprem
Ah desculpa. Não sei se um utilitário faria isso. O que sugiro é: use screenou tmuxpara criar dois painéis, redimensione a primeira para duas linhas ( resize 2) e execute less, no segundo painel, execute lessnormalmente. Você pode configurá-lo como um script com um arquivo .screenrc específico. Veja resposta alternativa.
Arcege