[分享][AutoHotkey] 将搜索框文本作为 cmd 命令运行,并将输出覆盖写入搜索框

先在 Listary 搜索框中输入文本,然后按 AutoHotkey 热键 Alt + =。输入的字符串将被当作一条命令在 cmd 中运行,其输出将被填入 Listary 搜索框,替换原来的字符串。

用例

AHK-Listary-Alt =-001

操作:在 Listary 搜索框中输入 date /t,然后按 Alt + =

效果:搜索框文本将会被先替换为 “Please wait …”,在命令完成之后,又被替换为 “17-10-29 周日”,最后光标置于末尾。

注意

  1. 命令输出的末尾的换行符都会被删去,但其他换行符目前不作处理。

  2. 运行命令的工作目录是系统临时目录。

  3. 热键 Alt + = 在 Listary Options 界面也会生效,使得 Listary 不会接收到这个组合键。如果要在 Listary 中设置 Alt + = 为热键,需要先按住 = 再按下 Alt。实际上通常不会这样设置,因为 AutoHotkey 已经截获了 Alt + =,即使设置了也用不了。

  4. 命令是在隐藏的 cmd 窗口中运行,如果输入了一个不会自动结束的命令,如不带参数的 date,将无法通过关闭窗口来结束该 cmd 进程。在结束该 cmd 进程之前,AutoHotkey 热键线程也不会结束,此时热键 Alt + = 将不起作用。解决方法是手动结束相应的 cmd 进程。重启 AutoHotkey 脚本能使 Alt + = 重新可用,但 cmd 进程不受影响。由于脚本使用了系统剪贴板,剪贴板事先被清空,重启脚本将导致原剪贴板内容不会被恢复。

代码 (AutoHotkey)

; By DiamondbacK <http://discussion.listary.com/t/3791>
; [Listary]
#IfWinExist ahk_exe Listary.exe ahk_class Listary_WidgetWin_0
!=:: ; Execute the input string and replace it with the output.
  listaryEvaluate() {
    /*
      Make Listary the “Last Found” window, but WinWait doesn't work for
      launcher mode. I don't know why.
    */
    IfWinActive ahk_exe Listary.exe ahk_class Listary_WidgetWin_0
    {}
    ControlGetText text, ListarySearchBox1
    ControlSetText ListarySearchBox1, Please wait ...
    clipBak := ClipboardAll
    Clipboard =
    RunWait %ComSpec% /c "%text%" | Clip, %A_Temp%, Hide
    ControlSetText ListarySearchBox1, % RTrim(Clipboard, "`r`n")
    SendInput {End}
    Clipboard := clipBak
  }
#IfWinActive
2 Likes

十分感谢分享 :thumbsup:

谢谢分享!
请问有是否有办法能让Alt + = 后自动将执行结果插入到 当前 鼠标的 光标位置?

可以研究一下,但需要确认一下你的具体意思。

比如

  1. 我在vscode 里写代码, 需要获得当前时间,或者某个ip地址
  2. 调出 listary , 然后输入 命令 A, 调用 脚本 B , 获得输出结果 C
  3. 将C 填入 vscode 目前的光标 插入位置

不限于vscode, 应该是能填入任何 允许输入的地方(输入框)

估计目前listary 缺少和输入相关的接口,所以做不到吧

试试下面这个。这里我换了一个热键 !p,也就是 Alt + p,需要的话可以改成 !=。两个脚本可以连起来一起用,同时生效,只要两个热键不同。

#IfWinActive ahk_exe Listary.exe ahk_class Listary_WidgetWin_0
!p:: ; Execute the input string and paste the output in the active window.
  listaryEvaluatePaste() {
    WinGet hwnd, ID, A
    ControlGetText text, ListarySearchBox1
    ControlSetText ListarySearchBox1, Please wait ...
    clipBak := ClipboardAll
    Clipboard =
    RunWait %ComSpec% /c "%text%" | Clip, %A_Temp%, Min
    Clipboard := RTrim(Clipboard, "`r`n")
    WinWaitClose ahk_id %hwnd%, , 0.5

    ; Paste Method 1
    ControlGet hwnd, Hwnd, , , A
    PostMessage % WM_PASTE := 0x0302, 0, 0, , ahk_id %hwnd%

    ; Paste Method 2
    ; SendInput +{Insert}

    Sleep 50
    Clipboard := clipBak
  }
#IfWinActive

因为不用保持 Listary 窗口,所以不必隐藏 cmd 窗口,这里选择在最小化窗口运行。这样在命令不会自动结束的情况下就可以手动关闭窗口了,但是关闭后仍然会在活动窗口内进行粘贴。

用到了剪贴板粘贴功能。由于粘贴信息发送给窗口后,系统会有一定的延迟才会完成粘贴操作,所以我用 Sleep 50 来延迟恢复剪贴板内容。如果在实际使用中发现插入的不是命令输出而是剪贴板的内容,可以适当增大 Sleep 的时间 (毫秒)。

我没有在 VSCode 中测试过。不保证所有窗口都支持这种粘贴方式,另一种方案是用按键模拟,但也不是所有窗口都有统一的粘贴快捷键。两个方法都写在脚本中了,按键模拟的一行命令注释掉了。 +{Insert} 就是 Shift + Insert,感觉比 Ctrl + v 适用面更广,后者写作 ^v

感谢细心的回复! 这就去试试~

试了一些编辑器,发现不支持 PostMessage 的有 VSCode、Sublime Text、Notepad++、Vim,而它们默认配置下都支持 Shift + Insert

已经验证可行,谢谢。发现AHK还真方便,自带spy。

补充一下碰到的问题:

  1. 我win7 x64, 需要把 Listary_WidgetWin_0 替换成 Listary_WidgetWin_1 才能执行
  2. 错误命令 如 date \t 会导致 显示 Please Wait … ,没有后续动作
  3. 错误命令 如 date \t 会导致 alt + =alt + p 不再起作用,需要reload (应该是在等待cmd 的输入,导致卡死)
  1. 不知道数字后缀有什么规律,如果知道所有可能的值,有办法把它们都包括进去。也可以去掉 ahk_class 这个条件。

  2. 这属于主贴中提到的不会自动结束的命令 (注意4)。

  3. 同上。