![水平分割 shell 以显示 ls -al 和 pwd](https://linux22.com/image/65597/%E6%B0%B4%E5%B9%B3%E5%88%86%E5%89%B2%20shell%20%E4%BB%A5%E6%98%BE%E7%A4%BA%20ls%20-al%20%E5%92%8C%20pwd.png)
我使用 zsh 作为 OSX 上的默认 shell。我希望我的 shell 始终有一个水平分割,显示我所在的当前目录的 pwd 和 ls。我该怎么做?
答案1
您的用例不是很有说服力。大多数人将当前目录作为提示的一部分; zsh 具有极其丰富的提示配置可能性(包括多行提示、左右提示等)。通过完成(在 zsh 中也是非常可配置的),您可以在需要的上下文中显示文件列表。话虽这么说,有很多方法可以实现您所描述的目标,但没有一种方法既简单又好。
仅带外壳
shell 只控制自己的输入和输出。当您执行命令时,shell 无法控制任何事情。如果你想保留终端的一部分用于ls
输出之类的东西,就需要终端的配合。“终端”、“shell”、“tty”和“控制台”之间的确切区别是什么?可能是有用的背景。
在某些终端上,您可以定义可滚动区域;可滚动区域之外的内容保持不变。我知道 xterm 支持此功能,我不知道其他流行的终端模拟器是否支持。这是一个 bash 概念验证,用于在终端的底部三分之一处显示date
,pwd
和的输出。ls
reset () {
tput reset
scrollable_lines=$((LINES*2/3))
tput csr 0 $((scrollable_lines-1))
}
update_status () {
tput sc
tput cup $((scrollable_lines+2)) 0
tput ed
date
pwd
ls -x --color=always | head -n $((LINES-scrollable_lines-3))
tput rc
}
PROMPT_COMMAND='update_status'
reset
几句话解释一下:
- 这
tput
命令发送控制序列通过获得术语信息到航站楼。 - 调用将
tput csr
滚动区域定义为顶部 2/3 行。 - 该
reset
函数需要在终端重置时执行,因为终端重置会将滚动区域重置为整个终端。 tput sc
保存光标位置,稍后用 恢复tput rc
。tput cup
将光标移动到非滚动区域的顶部。tput ed
删除已经存在的内容。update_status
每次 bash 将要显示新提示符时都会执行该函数。
我在 zsh 中尝试过这一点,但它与终端的交互比 bash 更多,因此即使是概念验证也需要更多调整。
带终端多路复用器
两个都屏幕和多路复用器可以将终端拆分为多个子窗口(Screen 将其称为区域,tmux 将其称为窗格)。您可以运行多路复用器,在顶部窗口中运行 shell,并使其在底部窗口中运行其他内容。
触发 shell 中的某些内容以使内容显示在底部窗口中很容易:只需将输出重定向到正确的终端设备即可。这里麻烦的部分是获取设备名称并根据需要保持底部窗口打开,但不再打开。
这是使用 zsh 和 screen 的概念验证。在包含的screen -c ~/etc/split.screenrc
地方运行~/etc/split.screenrc
escape ^\\\
hardstatus off
split
focus
resize 10
screen ~/bin/bottom_tty
focus
screen zsh
这将创建一个 10 行的底部区域,该区域运行程序~/bin/bottom_tty
并在上部区域运行 zsh。在 中~/bin/bottom_tty
,获取一些参数然后永远休眠:
#!/bin/sh
cat <<EOF >~/.split-screen.$PPID.tmp
bottom_tty=$(tty)
bottom_lines=$(tput lines)
bottom_pid=$$
EOF
mv ~/.split-screen.$PPID.tmp ~/.split-screen.$PPID
while true; do sleep 999999999; done
在 中.zshrc
,阅读信息并设置一些内容:
- 每次出现提示时,运行
refresh_bottom_tty
刷新底部区域的内容。 - 当zsh退出时,杀掉底部区域的程序,这样脚本就会终止。
refresh_bottom_tty () {
printf %s $terminfo[clear]
date
pwd
ls -x --color | head -n $((bottom_lines-2))
}
precmd () {
refresh_bottom_tty <>$bottom_tty 1>&0 2>&0
}
zshexit () {
kill -HUP -$bottom_pid
}
while [[ ! -e ~/.split-screen.$PPID ]]; do
sleep 1
done
. ~/.split-screen.$PPID
rm ~/.split-screen.$PPID
专用端子包装
使用一个了解您想要用它做什么的专用包装器可以做得更好、更稳健。包装器将定义一个在其中执行 shell 的虚拟终端,并且将有一个接口允许 shell 更新虚拟终端外部显示的内容。
Screen 和 tmux 实际上非常接近通过状态行提供所需的功能。然而,两者都仅限于单个状态行。如果它们被扩展为支持多行状态行,您可以在那里显示您想要的内容。
或者,您可以使用泽普蒂模块编写专用包装器。这样就会有两个 zsh 实例:一个用于包装器,一个用于运行命令。即使要进行概念验证,代码也比我在这个答案中写的要多。
答案2
我不知道 showinsls
输出,但 zsh 有一个漂亮的功能RPROMPT
。把这个放进.zshrc
去看看是否满足你的需求:
PROMPT=$'%n@%m\n%! %% '
RPROMPT='# %d'
这会将当前工作目录放在提示符的右侧。我在其中包含一个带有换行符的示例PROMPT
,以便如果RPROMPT
不能按您的意愿工作,您可以了解如何将“%d”放入 的值中,PROMPT
以便它可以在自己的行上。