我有一个bash
终端窗口,我可以在其中执行只一声令下foo
。因此,我希望每一行(当然在提示之后)都以“foo”开头,这样我只需键入函数的选项和参数,而不是重复的函数名称。当然,如果能够更改自动插入的字符串就好了,但这就是不是必需的为我。
例子
当我打开终端时,无需输入任何内容,我想看到的是:
user@host:~/ $ foo
然后我键入--option argument
,当我按下时,将使用给定的和调用Enter该函数。foo
--option
argument
我尝试过的
我尝试摆弄$PS1
并$PROMPT_COMMAND
使用xdotool type "foo "
,令人惊讶的是它实际上有效,但不幸的是它也打印“foo”前提示符非常难看:
user@host:~/ $ PROMPT_COMMAND='xdotool type "foo "'
foo user@host:~/ $ foo
我还发现并尝试了该preexec
功能Ryan Caloras 的 bash-preexec 脚本,但它有完全相同的问题。
如何回显(a(executable-)string)到提示符,以便光标在行尾闪烁?是相关的,但是那里的答案无法将某些内容(--option argument
)添加到要执行的命令中。不过我没有测试过——这么简单的事情zsh
应该有一个解决方案,你不觉得吗?bash
答案1
对于zsh
,它应该只是一个问题:
precmd() print -z 'foo '
或者避免它覆盖用户排队的命令Alt+q:
zle-line-init() { [ -n "$BUFFER" ] || LBUFFER='foo '; }
zle -N zle-line-init
使用bash
, 代替xdotool
,您可以使用TIOCSTI
ioctl
:
insert() {
perl -le 'require "sys/ioctl.ph";
ioctl(STDIN, &TIOCSTI, $_) for split "", join " ", @ARGV' -- "$@"
}
PROMPT_COMMAND='insert "foo "'
这是更可取的,xdotool
因为它将这些字符直接插入到bash
正在读取的设备的输入缓冲区中。仅当有一台 X 服务器正在运行时才起作用(例如,在控制台或真实终端上或在(没有)xdotool
上不起作用),它是由 标识的服务器,并且是您正在与之交互的服务器,并且终端正在运行的模拟器在评估时具有焦点。ssh
-X
$DISPLAY
bash
$PROMPT_COMMAND
现在,就像您的xdotool
情况一样,因为这ioctl()
是在显示提示之前完成的,并且 tty 终端线路规则被 readline 退出icanon+echo
模式,您可能会看到回声其中foo
tty 线路规则弄乱了显示。
您可以通过插入一个字符串来解决这个问题回声是不可见的(如果仅使用 Unicode 语言环境,则类似于 U+200B)并将其绑定到插入的操作"foo "
:
insert() {
perl -le 'require "sys/ioctl.ph";
ioctl(STDIN, &TIOCSTI, $_) for split "", join " ", @ARGV' -- "$@"
}
bind $'"\u200b":"foo "'
PROMPT_COMMAND="insert $'\u200b'"
或者您可以延迟TIOCSTI
ioctl 足够长的时间,以便 readline 有时间初始化:
insert_with_delay() {
perl -le 'require "sys/ioctl.ph";
$delay = shift @ARGV;
unless(fork) {
select undef, undef, undef, $delay;
ioctl(STDIN, &TIOCSTI, $_) for split "", join " ", @ARGV;
}' -- "$@";
}
PROMPT_COMMAND='insert_with_delay 0.05 "foo "'
如果像方法中一样zsh
,您想要处理用户在显示提示之前输入文本的情况,您可以
- 流走通过
tcflush(0, TCIFLUSH)
在ioctlperl
之前执行 aTIOCSTI
(也需要一个-MPOSIX
选项),或者 就像在该
zsh
方法中一样,通过在(移动到末尾)之前和之后插入(假设您使用(默认)编辑模式,将光标移动到行的开头) ,确保foo
在缓冲区的开头插入:^A
emacs
foo
^E
insert_with_delay 0.05 $'\1foo \5'
或者
bind $'"\u200b":"\1foo \5"'
答案2
您所要求的听起来并不常见,因此没有一种简单的方法来做到这一点也就不足为奇了。
使用纯 bash,您可以使用read
内置函数读取该行,然后eval
执行它。模拟提示(我在下面近似您的提示)。
#!/bin/bash
PROMPT=$'\e[1m'$USER@$HOSTNAME:$PWD$' $ \e[0m'
IFS= read -r -e -i "foo " -p "$PROMPT" line
eval "$line"
exit
将其放入脚本中并告诉您的终端模拟器运行该脚本。
或者,在终端模拟器中运行 Screen。您可以使用它的stuff
命令来模拟输入。