меньше --quit-if-one-screen без --no-init

31

Я нахожусь на терминале, который поддерживает альтернативный экран, который используется less, vim и т. Д. Для восстановления предыдущего дисплея после выхода. Это хорошая функция, но она действительно отключает --quit-if-one-screenпереключатель, lessтак как в этом случае менее переключается на альтернативный экран, отображает его данные, обнаруживает, что есть только один экран, и выходит, забирая с собой содержимое альтернативного экрана.

Обычно предлагаемое решение - использовать --no-initпереключатель, чтобы вообще не использовать альтернативный экран. Однако, это несколько некрасиво , потому что я действительно хочу , чтобы использовать его в случае , если менее фактически выступает в качестве пейджера. Поэтому я ищу решение использовать альтернативный экран, только если меньше не завершается автоматически.

Я в основном буду использовать это как пейджер Git, так что сценарий оболочки-обертки, который запускается меньше только в случае достаточного количества вывода, тоже подойдет. По крайней мере, если нет способа сделать это без него.

ThiefMaster
источник
@thieMaster в этом случае, как вы определяете альтернативный экран? Я пытаюсь очистить некоторые теги, и я действительно не понимаю смысла здесь
Kiwy

Ответы:

14

Поскольку меньше 530 (выпущено в декабре 2017 года), less --quit-if-one-screenне переключается на альтернативный экран, если на нем отображается менее одного экрана. Таким образом, у вас не будет этой проблемы, если ваша версия менее свежая.

В более ранних версиях меньше приходится решать, использовать ли альтернативный экран при запуске. Вы не можете отложить этот выбор, когда он заканчивается.

Вы могли бы звонить меньше, позволить ему использовать альтернативный экран, и отслеживать контент на основном экране, если меньше завершается автоматически. Однако я не знаю, как обнаружить автоматическое завершение.

С другой стороны, не так сложно вызвать cat для коротких входов и меньше для больших входов, даже сохраняя буферизацию, так что вам не нужно ждать, пока весь ввод начнет видеть вещи в меньшем количестве (буфер может быть немного больше - вы ничего не увидите, пока у вас не будет хотя бы одного скриншота данных - но не намного).

#!/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

Вы можете предпочесть видеть линии на главном экране по мере их появления и переключаться на альтернативный экран, если линии вызывают прокрутку.

#!/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
«Меньше должно решить, использовать ли альтернативный экран, когда он запускается. Вы не можете отложить этот выбор, когда он заканчивается». - хотя, по-видимому, он этого не делает, но не может просто отложить вывод (например, команды инициализации терминала или фактические данные) до тех пор, пока он не получит X строк. Если stdin исчерпан, пока X <TERMINAL_LINES, он просто выгрузит все на stdout и выйдет, иначе он инициализирует альтернативный экран и сделает то, что должен делать
ThiefMaster
1
В итоге я использовал измененную версию вашего первого примера кода: gist.github.com/ThiefMaster/8331024 ($ LINES был пуст, когда вызывался как git-pager, и я думаю, что вы забыли $n
увеличить
@ThiefMaster Спасибо за отзыв. Обратите внимание, что вы должны вставить #!/bin/bashсвой скрипт, так как вы используете специфичную для bash конструкцию, так как ваш скрипт не будет работать в системах (таких как Ubuntu), где /bin/shнет bash.
Жиль "ТАК ... перестать быть злым"
3
Мне очень понравилась эта идея, и я разработал ее немного дальше (с большим количеством функций): github.com/stefanheule/smartless
stefan
1
@ThiefMaster: lessтакже может (но не) иметь дополнительный способ выйти, где он печатает текущее содержимое экрана после отправки строки un-init. Таким образом, вы могли бы воспользоваться преимуществом альтернативного экрана, не загромождая прокрутку, но по-прежнему оставляя соответствующую часть man-страницы или что-либо еще в терминале после выхода.
Питер Кордес
9

GNU less v. 530 включает в себя исправление Fedora, на которое ссылается @ paul-antoine-arras, и больше не будет выводить последовательность инициализации терминала, когда --quit-if-one-screenона используется и вход помещается на один экран.

eigengrau82
источник
4
Пользователи Homebrew в Mac OS могут сразу получить это поведение, запустив его brew install lessи убедившись, что у $LESSнего F и пропущено X.
Райан Паттерсон,
Это мой любимый ответ. Я немедленно скачал Less 5.3.0 из GNU и скомпилировал его сам. Отличный намек!
iBug
5

Для медленных входов, например git log -Gregex, вы хотите:

A) строки, которые должны появиться на главном экране по мере их появления, затем переключитесь на альтернативный экран, когда необходима прокрутка (поэтому первый $LINESрезультат вывода всегда будет отображаться в вашем прокрутке); если так, продолжайте со вторым из ответов Жиля .

B) строки, которые должны появиться на альтернативном экране, но выйдите из альтернативного экрана и распечатайте строки на главном экране, если прокрутка окажется ненужной (таким образом, никакой вывод не будет отображаться в вашем прокрутке, если требуется прокрутка); если это так, используйте скрипт ниже:

Он teeвводит во временный файл, а затем lessвыходит catиз временного файла, если он содержит меньше строк, чем высота экрана:

#!/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"

Используйте это с export PAGER='/path/to/script'. Этого должно быть достаточно, чтобы gitиспользовать его, если вы уже не переопределены core.pager.

Для возможных улучшений, см. Также мою чуть более конкретную версию этого скрипта по адресу: https://github.com/johnmellor/scripts/blob/master/bin/least

Джон Меллор
источник
3

Это долго решалось в дистрибутивах на основе Red Hat путем изменения поведения опции -F в lessисходном коде: посмотрите этот патч из проекта Fedora, чья первая версия датируется 2008 годом. Идея состоит в том, чтобы просто получить высоту терминал (т. е. максимальное количество строк, которые могут быть отображены одновременно) и пропустить последовательности инициализации и деинициализации, когда файл помещается на одном экране. Таким образом, нет необходимости использовать опцию -X и -F для любой длины файла.

Parras
источник