将字符串注入命令行的命令,就像在执行前编辑的预填充命令

将字符串注入命令行的命令,就像在执行前编辑的预填充命令

在下面的示例中,作为$我的 bash 提示符并象征着我按下 Enter 键,我如何构造一个命令/别名,foo以便

$ foo bar⏎

是否会在命令行中输入/输入/预填充/键入“bar”(或我传递给命令的任何其他字符串),以便我可以在按 Enter 之前修改“bar”?例如

$ bar
$ barbaz⏎ 

我尝试过但没有成功echo bar > /dev/pts/123,并且不想这样做xdotool。这可能吗?


编辑:示例用例,“greppy 自动完成”:

我经常需要包含许多难以记住的参数的长命令。我将示例保存在文件中:

命令.txt:

ffmpeg -i infile.mp4 -c:v copy -c:a copy -y transcoded.mp4
sox in.wav out.wav remix 1 0

现在,如果我有上面指定的命令,我们称它为inject,我可以有一个别名

grepcomplete () {
  inject $(grep $0 commands.txt)
}

所以当我记得我需要混音一些东西,但我不记得了袜队及其参数,我可以输入grepcomplete remix,然后坐在sox in.wav out.wav remix 1 0我的命令行上,就像我输入它一样,准备好进行编辑和调整,然后按 Enter 执行它。无需选择、复制、粘贴任何内容。

正如卡米尔在评论中建议的那样,我可以使用 bash 的历史搜索(Ctrl-R),并通过history -r commands.txt在我的 bashrc 中执行类似的操作来提供我自己的“历史”。
尽管如此,我的方法的好处是我可以轻松破解它,例如通过语法突出显示显示所有匹配项。

请注意,我自己已经回答了这个问题,并提供了该命令的实现inject

答案1

这是一个小而丑陋的解决方案,受到启发通过 perl 解决方案在每个提示后插入一个字符串,使用 TIOCSTI适配Python:

bash 函数,例如.bashrc

inject () {
(python -c "import fcntl; import termios; import sys
with open('/dev/stdout', 'w') as fd:
  for c in ' '.join(sys.argv[1:]): fcntl.ioctl(fd, termios.TIOCSTI, c)" "$@" &)
}

用法:

inject foo bar

笔记:

  • 目前无法处理 Unicode!我怀疑for char in str是罪魁祸首?
  • 子shell中的背景结构( foo &) 防止在提示之前双重回显字符串
  • 它会吃掉参数之间的空格:inject foo bar= inject foo bar。使用inject "foo bar"
  • 看起来这取决于时间,所以可能会出现竞争条件?
  • 我有其他带有 Python 线程/多重处理的版本,可以在没有 bash 子 shell 的情况下完成,并且可能更适合管道、xargs 等。对于我的用例来说,这是最干净、最简单的解决方案。

答案2

您可以使用配置它~/.inputrc。如果该文件不存在,则创建该文件,并添加以下内容:

Control-P: "foo "

现在,打开一个新终端并按Ctrl+ P,字符串foo将在光标所在的位置输入。您可以选择适合您的快捷方式,并且它应该有效。

答案3

xdotool仅适用于 X 环境,不适用于 TTY shell,也可能不适用于 Wayland。


我感觉你在问的是创建您自己的 bash 完成脚本。然后,用 key“注入”(调用完成)Tab

基本思想是这个complete命令,它表示当用户按下Tab按键时 bash 会建议什么:

$ complete -W "now tomorrow never" dothis

然后,输入

$ dothis to<Tab>

填充它:

$ dothis tomorrow

对于你的例子,

$ complete -W bar foo
$ foo<Space><Tab>

将产生

$ foo bar

您可以进一步编辑。

complete命令本身可以放入~/.bashrc交互式 shell 创建期间运行。

答案4

在 Fish 中,相当于使用该commandline函数。例如:

commandline 'echo next command'

相关内容