我想打印哪个命令正在运行以及哪个目录中始终作为窗口的第一行,即使命令的输出通常会导致它滚动。我希望正常输出显示在下方并正常滚动。
我该怎么做?
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