【问题标题】:Bash: call script with customized keyboard shortcuts?Bash:使用自定义键盘快捷键调用脚本?
【发布时间】:2011-05-06 10:06:02
【问题描述】:

假设我有一个脚本“myscript.sh”,其内容只是echo $PWD。我想以某种方式将此脚本绑定到 bash (gnome-terminal) 中的组合键 - 这样当我按下此组合键时,“myscript.sh”的输出将插入(“粘贴”)光标处在终端的位置。

显然,bash 历史记录和行操作由 readline 处理 - 我得到的 bash 键盘快捷键的引用,请参考 readline

我还在Bash Reference Manual: Readline Init File Syntax 中看到,可以使用bind -p 列出bash 的键绑定(请参阅help bind [not 'man bind'] 了解更多信息) .因此,也许这个问题最好命名为“readline 中的自定义键盘快捷键的_binding 宏”:) 但无论如何,我想要做什么?

我想另一种方法是让脚本类似于“pwd | xsel -b”,然后我在终端上调用它——然后我可以粘贴;但我仍然想要一个单一的键盘快捷键,比如 Ctrl-Alt-H (它似乎没有用于任何事情),它会在按下时立即插入/粘贴脚本输出。

提前致谢,
干杯!

 
编辑:只是为了澄清 - 这是我想要这个设施的用例。我通常在项目文件夹中命名为cd,通常命名为myproject-folder-0012a,它受svn 的修订控制。还有一堆这样的文件夹。所以很多时候,我会在消息的第一个单词是目录名称的地方提交,如下所示:

svn ci -m "myproject-folder-0012a: here a commit message"

但这正是我不喜欢的——首先我输入了 11 个字符,速度相当快:

svn ci -m "

然后,我不能使用自动完成来获取名称(我在文件夹中)——这意味着我要么必须完全输入它(没办法:)),要么我复制粘贴它从提示符(需要选择 - 按下鼠标,拖动,释放鼠标;然后是 Ctrl+Shift+C,然后是 Ctrl+Shift+V,加上任何左/右键,如果我错过对齐 - 加上删除等,如果我做副本错误)。

含义 - 这么多工作,只是为了获得血腥提交消息的血腥文件夹名称:(我宁愿按(比如说)Ctrl-Alt-H之类的东西,并在光标位置自动插入文件夹名称,并完成它:)

我对@9​​87654343@ 的建议只是因为我可以将它放入“全局”脚本中——比如将其符号链接为/usr/bin/myscript显然,脚本的内容是echo $(basename $PWD) 而不仅仅是@ 987654346@ 满足我的需要),然后我可以这样做:

$ myscript       # this puts directory name in clipboard
$ svn ci -m "[CTRL+SHIFT+V TO PASTE HERE]myproject-folder-0012a[NOW TYPE]: here a commit message"

...哪种方式可以减少工作量,但仍然 - 然后我必须记住脚本名称,然后调用它,之前我输入svn 命令(然后我不总是记得)......而且 - 我必须调用一个命令,然后按下一个组合键;为什么我不应该只按一次组合键,然后完成它??! :)

嗯,希望这能更好地澄清我的问题......

 
EDIT2:但是,bash 键盘快捷键有用的另一个原因是,我不仅可以在 shell 命令中“粘贴/插入当前目录名称”,还可以在终端程序中,比如nano(可以说,直接使用bash 脚本或函数扩展会更困难)。

【问题讨论】:

  • 听起来像是超级用户的东西。
  • 您无需执行pwd | xsel -b 并粘贴组合。如果你用反引号括起来,反引号命令的输出将被用作执行命令的输入。
  • 嗨塞巴斯蒂安,谢谢你 - 我可以轻松地移动帖子 - 还是我必须在那里打开一个新帖子,然后粘贴过去?谢谢,干杯!
  • 嗨 Reese,我不确定反引号如何适用于我的问题,所以我试图在上面的编辑中澄清我的问题......这都是关于少输入 :)
  • 作为替代方案如何使用 shell 函数:svnci() { svn ci -m "$PWD: $1" "${@:2}" ; }。用作$ svnci "here a commit message" <extra svn args>

标签: linux bash keyboard-shortcuts readline customization


【解决方案1】:

好吧,这不是一个真正的答案,但我只想总结一下我到目前为止得到的 cmets,它们对我的问题很有用。但是,目前的问题 - 关于运行任意脚本的 bash 键盘快捷键 - 仍然没有得到回答(我仍然更喜欢用一个组合键来完成所有这些工作:)

 
首先,我可以使用“全局”脚本,例如:

$ sudo bash -c 'cat > /usr/bin/bpwd <<EOF
#!/bin/bash
basepwd=\$(basename \$(pwd))
echo -n \$basepwd                 # suppress line ending
# exec 1>/dev/null               # debug: redir stdout to null
echo -n \$basepwd | xsel -i -b    # suppress LF, and make xsel read from stdin 
# exec 1>/dev/tty                # debug: restore stdout
EOF
chmod +x /usr/bin/bpwd'

或者,我可以将 bash 函数添加到我的 .bashrc注意:确保在将这些行添加到 .bashrc 后重新加载 bash - 例如,只需在您当前的终端):

$ echo '
bpwd2() { basepwd=${PWD##*/} ; echo -n $basepwd | xsel -i -b ; echo -n $basepwd ; }
svnci-test() { echo -n "$(bpwd2): $*" ; }
svnci-m() { svn ci -m "$(bpwd2): $*" ; }' >> ~/.bashrc

 
基本上,我最初误解了 Reese Moore 的建议 - 你确实可以使用反引号 - 考虑这个命令会话(在运行上述命令之后):

$ bpwd
Desktop\
$ bpwd2
Desktop\
$ echo `bpwd`
Desktop
$ echo "`bpwd2` 2"
Desktop 2

这是我需要了解摩尔的“反引号命令的输出将用作执行命令的输入”(但是,还需要注意从输出);或者,就我而言,我可以打电话

svn ci -m "`bpwd`: my message here"
# svn ci -m "${PWD##*/}: my message here" # alternatively

...或者,我可以按照 camh 的建议,使用 svnci-m 作为函数(在我的情况下,我几乎从不使用 svn ci 的附加参数,所以我的版本略有不同 em>)。为了测试参数是否正确传递,我可以使用svnci-test 函数:

$ svnci-test "my message"
Desktop: my message\

 
感谢到目前为止的 cmets,
干杯!

【讨论】:

    【解决方案2】:

    通过单次按键完成您想做的事情的一种方法是利用 bash 中的可编程完成功能。您可能使用 bash_completion 工具/包设置了一些可编程完成。如果没有,请查看它以了解它是如何完成的细节。

    这个想法是让可编程完成在您点击 svn 提交消息的开头时识别,然后让它返回一个完成,这是您要插入的文本(当前目录的基本名称)。

    我只涉足可编程完成,所以我不能给你详细信息,但上面提到的 bash_completion 包或subversion completion script 可能是一个好的开始。

    【讨论】:

      【解决方案3】:

      简单版:

      shell 提示符下的这个命令:

      bind '"\ee": "${PWD##*/}\e\C-e"'
      

      或将此行添加到您的~/.inputrc

      "\ee": "${PWD##*/}\e\C-e"
      

      将导致 Alt-e 在命令行中插入当前目录的基本名称。它要求存在 readline 函数 shell-expand-line 的默认绑定,即 \e\C-e(如果不同,可以进行调整)。我还假设您使用的是 Bash 的 emacs 模式。

      不幸的是,它会导致已经输入的内容也被扩展。这样做的影响之一是在输入后:

      svn ci -m "
      

      然后按Alt-e,引号就会消失。有几种方法可以解决这个问题。

      一,假设您将失去的只是报价,然后手动将其添加回来或让 readline 宏为您添加:

      bind '"\ee": "${PWD##*/}\e\C-e\eb\"\C-e"'
      

      这不是很令人满意。

      高级版:

      或者,两个,终止行,插入,然后将行拉回:

      bind '"\ee": " \C-u \C-a\C-k${PWD##*/}\e\C-e\C-y\C-a\C-y\ey\b"'
      

      bind '"\ee": " \C-u \C-a\C-k${PWD##*/}\e\C-e\C-y\C-a\C-y\ey\b\ef\C-f"'
      

      这会使行的其余部分保持不变(没有其他内容被扩展或删除),但它使用了终止环,因此它可能会使其处于与您预期不同的状态(如果您正在使用它)。它还在插入的目录名称之后插入一个空格(宏中的空格用于确保如果宏在行首或行尾执行,则不会反刍旧的 kill-ring 内容)。无论光标在行中的位置如何,宏都应该起作用。插入将在光标的位置进行,将光标留在相同的位置[在第一个版本中]。

      编辑:第二个版本将光标留在插入的目录名和空格之后。

      编辑 2:

      在这方面,readline 函数 shell-forward-word(未绑定)比 forward-word\ef)做得更好。你可以像这样使用它:

      bind '"\ew":shell-forward-word'
      bind '"\ee": " \C-u \C-a\C-k${PWD##*/}\e\C-e\C-y\C-a\C-y\ey\b\ew\C-f"'
      

      顺便说一下,你应该知道 Bash 键盘快捷键在其他程序中是无效的,例如 nano

      【讨论】:

      • 这样做可以使命令行上的功能可用于任何用途,而无需修改和维护多个完成功能。
      • 哇,丹尼斯,感谢您的精彩回答(我永远无法通过文档阅读自己:))。几件事:首先,Alt-e 不适合gnome-terminal - 因为它必然会打开编辑菜单;不过,Alt-o 是可用的。我只是先用 Alt-e 尝试了bind“在 shell 提示符下”,但什么也没发生;和 bind -P 没有列出 Alt-e。然后,我将"\eo": "${PWD##*/}\e\C-e" 添加到一个新的~/.inputrc,启动了一个新终端,并且Alt-o 工作(注意:您的条目在开始时有一个' - 它将键' 绑定到命令,而不是Alt-e!)。但是,它有效 - 谢谢!
      • PS:bind -P 不会列出 Alt-o(据我所知是\eo),即使 Alt-o 处于活动状态!?您能否推荐一种方法来检查哪些键绑定可用于bash/readline - 包括自定义键?另外,感谢nano.. 的留言。干杯!
      • PSS:感谢 edit 2 / shell-forward-word - 效果很好 :) 干杯!编辑:找到了,bind -S 列出了绑定到宏的键...
      • @sdaau:很抱歉单引号的错别字。请注意,man readline 表示如果 ~/.inputrc 存在,则读取它。只有没有,才会读取/etc/inputrc。您可以通过使~/.inputrc 的第一行说$include /etc/inputrc 然后在之后进行覆盖和添加来将后者包含在前者中。在查找未绑定的击键时,可以使用以下便捷命令:bind -psv | LC_COLLATE=C sort | less
      猜你喜欢
      • 2012-08-28
      • 1970-01-01
      • 2017-09-17
      • 1970-01-01
      • 1970-01-01
      • 2012-07-16
      • 1970-01-01
      • 2012-11-23
      • 2012-08-16
      相关资源
      最近更新 更多