Сделайте, чтобы последняя команда придерживалась вершины окна терминала, в то время как выходные данные обычно прокручиваются - PullRequest
1 голос
/ 14 мая 2019

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

Как я могу это сделать?

Ответы [ 4 ]

1 голос
/ 22 мая 2019

Я не знаю, как этого добиться в терминальной сессии, но могу написать функцию для команды.

#! /bin/bash

function _sticky_cmd {
        local cmd=$@
        X=1
        L=$(tput lines)
        ((L=L-1))
        LINES=()
        eval $cmd | while IFS= read -r line; do
                pos=$((X-L))
                [ $pos -ge 0 ] || pos=0
                LINES+=("\n$line")
                echo -en "\033c$cmd : $(pwd)"
                echo -en "${LINES[@]:$pos:$L}" | sed -r 's/^ //g'
                ((X=X+1))
        done
}

_sticky_cmd 'while true; do echo "test $((n=n+1))"; sleep 0.5; done'

Это даст:

while true; do echo test $((n=n+1)); sleep 0.5; done: /home/user/test/scroll
test 1 
test 2 
test 3 
test 4 
test 5 
1 голос
/ 23 мая 2019

Экран GNU не может ( пока ) поместить запрошенный вами контент в верх вашего просмотра, но он может поместить его в внизу с использованием caption, который включает в себя строку жесткого статуса (заголовок окна):

% print 'caption always "%h"\nterm $TERM' > ~/.screenrc
% screen
% precmd() { print -Pn "\e]0;[%~] "; print -Rn "$1"; print -Pn "\e\\"; }
% preexec() { precmd "$1"; }

Будьте осторожны: первая строка перезапишет ваш ~/.screenrc, и вы, возможно, не захотите этого делать.

Это даст вам инвертированную цветом строку состояния в нижней части вашего терминала, которая содержит путь в квадратных скобках, а затем текущую команду выполнения (если она есть). Попробуйте это в вашем домашнем каталоге, например, с cd /tmp; sleep 1. Он покажет [~] cd /tmp; sleep 1 на секунду, а затем изменится на [/tmp].

precmd() и preexec() являются функциями zsh hook . ZSH запускает precmd() прямо перед отображением вашего приглашения. Непосредственно перед выполнением команды zsh запускает preexec() с $1, установленным для всей команды. (Используйте $2 для просмотра псевдонимов.)

Вышеупомянутый precmd() имеет три print вызова, чтобы гарантировать, что коды выхода ограничены из командной строки (-R подавляет интерполяцию escape-последовательности, -P включает расширение переменной пути, а -n подавляет завершающий перевод строки) , \e]0; - это один из нескольких способов запуска строки состояния, а \e\\ - один из нескольких способов ее завершения. Выше preexec() передает команду в precmd().

После того, как вы сохранили ~/.screenrc, вы можете поместить в ~/.zshrc следующее, чтобы это всегда происходило:

if [ -z "$STY" ]; then screen -r 2>/dev/null || screen; fi
precmd() { print -Pn "\e]0;[%~] "; print -Rn "$1"; print -Pn "\e\\"; }
preexec() { precmd "$1"; }

Первая строка запускает screen, если вы еще не находитесь в таком сеансе (он пытается возобновить отдельный сеанс, если он есть, или запускает новый сеанс). Вторые две строки описаны выше.

Будьте осторожны, если вы закроете терминалы, не выходя из оболочки (и, следовательно, экрана), сеансы экрана будут работать без заголовка. Это особенность, когда речь идет об удаленных сеансах SSH, которые отключаются, но не так полезны локально.

1 голос
/ 15 мая 2019

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

В ~/.zshrc добавить или отредактировать эту функцию

preexec() {
   print -Pn "\e]0;$1\a"
}
0 голосов
/ 24 мая 2019

Это работает в bash в gnome-терминал (это xterm-256color).

Сохраните приведенный ниже скрипт, например, как $ HOME / usl (сокращение от «update status line»).Затем запустите новый терминал и введите в нем следующую команду:

PROMPT_COMMAND="source $HOME/usl"

Теперь у вас есть строка состояния.Сценарий:

#!/bin/bash

# works with:
# gnome-terminal, using VTE version 0.42.5 +GNUTLS
# plus:
# GNU bash, version 4.3.48(1)-release (x86_64-pc-linux-gnu)

COLOR_BLUE="\e[1;44;37m"
COLOR_NONE="\e[m"

lines=$(tput lines)     # get the number of lines on the terminal

this_cmd=":"

update_status_line()
{
    prev_cmd="$this_cmd"
    this_cmd="`echo "$*" | head -n1`"

    # filter out ourselves
    [ "$this_cmd" == "$PROMPT_COMMAND" ] && this_cmd=":"    # or choose something different from ':'

    tput sc                 # save cursor position
    tput cup 0 0            # move cursor to row #1 columns #2 (0-based)
    tput el                 # clear from the current position to the end of the line, leaving the cursor where it is

    echo -ne "${COLOR_BLUE}[${prev_cmd}]\t\t${this_cmd}${COLOR_NONE}"

    tput csr 1 "$lines"     # set scroll region to 1-$lines (0-based)
    tput rc                 # restore cursor position

    LINES="$lines"
    stty rows "$lines"
    export LINES
}

# the DEBUG signal is delivered just before the command line is executed by bash;
# that's the moment of opportunity for us
trap 'update_status_line $BASH_COMMAND' DEBUG
...