绘制ZSH提示时获取当前光标位置

4
我正在尝试从绘制ZSH shell提示符的函数中读取当前光标位置(当前行号和列号)并将其存储在变量中。我的目标是仅在有足够的空行而不会导致额外滚动时,在提示符下方显示内容。
在交互式shell中,我可以使用以下命令:
echo -ne "\033[6n"
read -t 1 -s -d 'R' line
line="${line##*\[}"
line="${line%;*}"
echo "XX $line XX"
# Prints: XX 2 XX"

然而,如果我启动一个干净的 zsh -f,并将其放入一个函数中,在呈现提示时执行该函数,那么它就无法工作:
setopt prompt_subst
prompt_fn(){
  echo -ne "\033[6n"
  read -t 1 -s -d 'R' line
  line="${line##*\[}"
  line="${line%;*}"
  echo "XX $line XX"
}
PROMPT='`prompt_fn` '

终端返回的 ANSI 转义序列被附加到当前命令中(就像我在键盘上输入一样),但不会被上面的 read -t 1 -s -d 'R' line 命令所捕获。我怀疑 ZSH 在绘制提示符时禁用了对 STDIN 的访问,但我不知道如何暂时恢复对其的访问权限(在绘制提示符之前或在绘制它所需的十分之一秒内键入的普通键盘击键不应被拦截),也不知道如何使用 ZLE 访问该信息。
编辑:如果用户在显示提示符之前已经输入了命令的开头,则不应丢弃该输入。目前我找到的解决方法(请参见下面我的答案)会读取并丢弃这些字符。这很令人沮丧,因为当我打开一个新的终端窗口并立即开始输入时,输入的字符在提示符出现之前就被丢弃了。
2个回答

4
直接从/dev/tty读取似乎大部分情况下都能正常工作,但它仍会吞噬在prompt_fn开始和read命令之间输入的任何内容。如果prompt_fn在到达该点之前需要做一些工作,则可能导致某些用户输入被丢弃。希望有人能提出更好的解决方案。
setopt prompt_subst
prompt_fn(){
  echo -ne "\033[6n" > /dev/tty
  read -t 1 -s -d 'R' line < /dev/tty
  line="${line##*\[}"
  line="${line%;*}"
  echo "XX $line XX"
}
PROMPT='`prompt_fn` '

1
也许你想查看这些文档中基于 minibuffer 的内容:

http://zsh.sourceforge.net/Guide/zshguide04.html

“minibuffer”是Emacs的又一个概念;它是一个提示符,出现在命令行下方,供您输入编辑器本身所需的一些编辑内容。我在zsh插件中使用它来打印出光标下命令的帮助信息。我只显示文本,但您应该能够做其他事情。这里有一个示例链接:cheat buffer example。您也可以在这里找到关于zsh widgets的一些信息。这可能与您相关:BUFFERLINES(整数)是屏幕上当前显示的编辑缓冲区所需的屏幕行数(即在最后一次重新显示之后未对前面的参数进行任何更改);只读。

感谢您的回答。BUFFERLINES 表示提示符的高度,而不是窗口剩余部分的高度。它仅在 ZLE 中可用,但使用 prompt_subst 的提示符未在“zle 模式”下执行。我找不到任何关于 cheatbuffer 的来源或网页。 - Suzanne Soy
1
啊,我明白你的意思了。我所提到的“cheatbuffer”是我在尝试使用zsh时编写的一个小项目:https://github.com/trungng92/cheatbuffer但不幸的是,我没有答案来获取窗口剩余的高度。 - trung

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接