使最后一个命令粘在终端窗口顶部,同时输出正常滚动



我想打印哪个命令正在运行以及哪个目录中始终作为窗口的第一行,即使命令的输出通常会导致它滚动。我希望正常输出显示在下方并正常滚动。

我该怎么做?

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 钩子函数。ZSH 在呈现提示之前precmd()运行。在执行命令之前,zsh 运行preexec(),并将$1设置为整个命令。(使用$2遍历别名。

上面的precmd()有三个print调用,以确保从命令行限制转义码(-R禁止转义序列插值,-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会话时,这是一项功能,但在本地没有那么有用。

我能想到的第一个技巧是将命令放在终端模拟器的标题中。
它将出现在窗口标题或选项卡名称中。
您可能需要调整设置才能显示它。

~/.zshrc添加或编辑此功能

preexec() {
print -Pn "e]0;$1a"
}

我不知道如何在您的终端会话中实现这一点,但可以为命令编写一个函数。

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

以下内容在 gnome-terminal (即 xterm-256color) 中的 bash 中工作。

例如,将下面的脚本保存为 $HOME/usl("更新状态行"的缩写)。 然后启动一个新终端,并在该终端中发出以下命令:

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}]tt${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

最新更新