水平分割 shell 以显示 ls -al 和 pwd

水平分割 shell 以显示 ls -al 和 pwd

我使用 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以便它可以在自己的行上。

相关内容