menos --quit-if-one-screen sem --no-init


31

Estou em um terminal que suporta a tela alternativa usada por less, vim etc. para restaurar a exibição anterior depois de sair. Esse é um recurso interessante, mas realmente interrompe a --quit-if-one-screentroca, lesspois, nesse caso, menos alterna para a tela alternativa, exibe seus dados, descobre que existe apenas uma tela e sai, levando o conteúdo da tela alternativa.

A solução comum sugerida é usar a --no-initopção para evitar usar a tela alternativa completamente. No entanto, este é um pouco feio, porque eu não quero usá-lo em caso menos na verdade funciona como um pager. Portanto, estou procurando uma solução para usar a tela alternativa apenas se menos não terminar automaticamente.

Eu o usarei principalmente como pager do Git, portanto, um script de shell wrapper que roda apenas menos caso haja saída suficiente também seria bom. Pelo menos se não houver como fazê-lo sem um.


@thieMaster, neste caso, como você define a tela alternativa? I tentar limpar algumas tags e eu realmente não entendo o significado aqui
kiwy

Respostas:


14

Desde menos 530 (lançado em dezembro de 2017), less --quit-if-one-screennão muda para a tela alternativa se ler menos de uma tela. Portanto, você não terá esse problema se sua versão do less for recente o suficiente.

Nas versões anteriores, menos precisa decidir se deve usar a tela alternativa quando é iniciada. Você não pode adiar essa opção para quando ela terminar.

Você poderia ligar menos, deixá-lo usar a tela alternativa e colocar o conteúdo na tela principal se menos terminar automaticamente. No entanto, não conheço uma maneira de detectar o encerramento automático.

Por outro lado, não é tão difícil chamar cat para entradas curtas e menos para entradas maiores, mesmo preservando o buffer, para que você não precise esperar que toda a entrada comece a ver as coisas em menos (o buffer pode ser um pouco maior - você não verá nada até ter pelo menos uma tela cheia de dados - mas não muito mais.

#!/bin/sh
n=3  # number of screen lines that should remain visible in addition to the content
lines=
newline='
'
case $LINES in
  ''|*[!0-9]*) exec less;;
esac
while [ $n -lt $LINES ] && IFS= read -r line; do
  lines="$lines$newline$line"
done
if [ $n -eq $LINES ]; then
  { printf %s "$lines"; exec cat; } | exec less
else
  printf %s "$lines"
fi

Você pode preferir ver as linhas na tela principal quando elas entram e alternar para a tela alternativa se as linhas causarem rolagem.

#!/bin/sh
n=3  # number of screen lines that should remain visible in addition to the content
beginning=
newline='
'
# If we can't determine the terminal height, execute less directly
[ -n "$LINES" ] || LINES=$(tput lines) 2>/dev/null
case $LINES in
  ''|*[!0-9]*) exec less "$@";;
esac
# Read and display enough lines to fill most of the terminal
while [ $n -lt $LINES ] && IFS= read -r line; do
  beginning="$beginning$newline$line"
  printf '%s\n' -- "$line"
  n=$((n + 1))
done
# If the input is longer, run the pager
if [ $n -eq $LINES ]; then
  { printf %s "$beginning"; exec cat; } | exec less "$@"
fi

5
"Menos precisa decidir se deve usar a tela alternativa quando for iniciada. Você não pode adiar essa opção para quando terminar." - embora aparentemente não faça isso, mas não poderia adiar nenhuma saída (como comandos de inicialização de terminal ou dados reais) até receber linhas X. Se stdin está esgotado, enquanto X <TERMINAL_LINES seria simplesmente despejar tudo no stdout e saída, caso contrário, seria inicializar a tela alternativa e fazer o que é suposto fazer
ThiefMaster

1
Acabei usando uma versão modificada de seu primeiro exemplo de código: gist.github.com/ThiefMaster/8331024 ($ LINHAS estava vazio quando chamado como git-pager e eu acho que você esqueceu incrementando $n)
ThiefMaster

@ThiefMaster Obrigado pelo feedback. Observe que você deve inserir #!/bin/bashseu script, pois está usando a construção específica do bash, pois seu script não funcionará em sistemas (como o Ubuntu) onde /bin/shnão é o bash.
Gilles 'SO- stop be evil'

3
Eu realmente gostei dessa idéia, e desenvolveu-lo um pouco mais (com mais recursos): github.com/stefanheule/smartless
Stefan

1
@ThiefMaster: lesstambém pode (mas não) ter uma maneira opcional de sair, onde imprime o conteúdo atual da tela após o envio da string un-init. Portanto, você pode ter o benefício de que a tela alternativa não atrapalhe a rolagem, mas ainda deixe a parte relevante da página de manual ou qualquer outra coisa no terminal após sair.
Peter Cordes

9

O GNU less v. 530 incorpora o patch do Fedora referido por @ paul-antoine-arras e não exibirá mais a sequência de inicialização do terminal quando --quit-if-one-screenfor usada e a entrada se encaixar em uma tela.


4
Usuários homebrew no Mac OS pode obter este comportamento imediatamente, executando brew install less, e ter certeza que $LESStem F e omite X.
Ryan Patterson

Esta é a minha resposta favorita. Eu baixei imediatamente o Less 5.3.0 do GNU e o compilei. Ótima dica!
iBug 16/09/18

5

Para entradas lentas, como git log -Gregex, você deseja:

A) as linhas aparecerão na tela principal assim que entrarem e, em seguida, alternar para a tela alternativa assim que a rolagem for necessária (para que a primeira $LINESsaída sempre apareça na sua rolagem); Nesse caso, vá com a segunda das respostas de Gilles .

B) linhas para aparecer na tela alternativa, mas saia da tela alternativa e imprima as linhas na tela principal se a rolagem for desnecessária (para que nenhuma saída apareça na sua rolagem se for necessária rolagem); Nesse caso, use o script abaixo:

É teea entrada para um arquivo temporário e, uma vez que lesssai, caté o arquivo temporário se contiver menos linhas que a altura da tela:

#!/bin/bash

# Needed so less doesn't prevent trap from working.
set -m
# Keeps this script alive when Ctrl+C is pressed in less,
# so we still cat and rm $TMPFILE afterwards.
trap '' EXIT

TXTFILE=$(mktemp 2>/dev/null || mktemp -t 'tmp')

tee "$TXTFILE" | LESS=-FR command less "$@"

[[ -n $LINES ]] || LINES=$(tput lines)
[[ -n $COLUMNS ]] || COLUMNS=$(tput cols)
# Wrap lines before counting, unless you pass --chop-long-lines to less
# (the perl regex strips ANSI escapes).
if (( $(perl -pe 's/\e\[?.*?[\@-~]//g' "$TXTFILE" | fold -w "$COLUMNS" | wc -l) < $LINES )); then
    cat "$TXTFILE"
fi

rm "$TXTFILE"

Use-o com export PAGER='/path/to/script'. Isso deve ser suficiente para gitusá-lo, a menos que você já tenha substituído core.pager.

Para possíveis aprimoramentos, consulte também minha versão um pouco mais detalhada deste script em: https://github.com/johnmellor/scripts/blob/master/bin/least


3

Isso foi resolvido há muito tempo nas distribuições baseadas no Red Hat, modificando o comportamento da opção -F no lesscódigo-fonte: veja este patch do Projeto Fedora, cuja primeira versão remonta a 2008. A idéia é simplesmente obter a altura do terminal (ou seja, o número máximo de linhas que podem ser exibidas ao mesmo tempo) e para omitir as seqüências de inicialização e desinicialização quando o arquivo se encaixa em uma tela. Portanto, não é necessário usar a opção -X e -F de forma consistente, independentemente do tamanho do arquivo.

Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.