asyncrun 发布六年后的更新 - V2EX
skywind3000
V2EX    Vim

asyncrun 发布六年后的更新

  •  2
     
  •   skywind3000 Jan 5, 2022 4166 views
    This topic created in 1588 days ago, the information mentioned may be changed or developed.

    asyncrun.vim 是个发布于今六年前的老插件了,常常被大家用来在 quickfix 中异步运行 shell 命令,当时 vim 还是 7.4.1829 ,+job 特性刚刚能用,因为做这个插件给 bram 提了十几个关于 +job 和 quickfix 的 issue ,都被他快速修正了,并在 8.1 时变得稳定可用。

    应该说这个插件是伴随 vim 8.0 一路成长稳定起来的,在修改了多年 bug 的同时,也通过收集到的有价值的反馈来不断的打磨自己。乘着新年之际,给大家分享一些该插件最近两年的主要更新,或许能够对大家提高工作效率有所帮助。

    外部终端

    不论 Vim 还是 NeoVim 引入内置终端都好多年了,但仍然有一些人习惯在系统终端或者 tmux 之类的地方执行任务。asyncrun 提供了一个 User-Defined Runners 的机制,可以让你按想要的方式运行命令,并同时发布了一些预置的 runner 让你可以方便的用外置终端运行特定命令:

    Runner 描述 依赖
    gnome 在新的 gnome-terminal 窗口里运行 GNOME
    gnome_tab 在 gnome-terminal 的新 tab 里运行 GNOME
    tmux 在 tmux pane 里运行 Vimux
    xfce 在新的 xfce 的 terminal 窗口里运行 xfce4-terminal
    konsole 在新的 konsole 终端里运行 KDE
    macos 在新的 macOS 系统 terminal 里运行 macOS
    iterm 在一个新的 iterm2 tab 里运行 macOS + iTerm2
    external 在一个新的 cmd 窗口里运行 Windows

    当使用 -mode=term 参数调用 asyncrun 命令时,可以用 -pos={runner} 参数来指定 runner 名字:

    :AsyncRun -mode=term -pos=gnome ls -la :AsyncRun -mode=term -pos=floaterm ls -la :AsyncRun -mode=term -pos=tmux ls -la 

    当你在 GVim 里使用 gnome, konsole, external 或者 xfce 这些 runner 运行命令时,你将会得到同 IDE 里运行命令行程序一模一样的体验:

    如果你在终端下使用 Vim ,那么一个新的 gnome-terminal 或者 iterm2 的 tab 是个很恰当的方式:

    或者,在一个 tmux 的分屏里运行命令:

    除去外部终端外,还有不少 runner 可以和各种著名的 Vim/NeoVim 内置终端增强插件们打交道:

    Runner 描述 依赖
    floaterm 在一个新的 floaterm 窗口里 floaterm
    floaterm_reuse 在一个可复用的 floaterm 窗口里 floaterm
    quickui 在一个 quickui 的 popup 终端里 vim-quickui
    toggleterm 再一个 toggleterm 的窗口里 toggleterm.nvim
    termhelp 在 terminal-help 的窗口里(可复用) vim-terminal-help

    使用 floaterm 这个 runner 的效果:

    Terminal-help:

    所有 Runner 皆可定制,可以修改或者定义新的 runner ,见项目 wiki customize runner.

    Internal terminal

    另外一个比有意思的更新就是对 (neo)vim 内置终端的封装,可以用内置终端运行命令:

    " run command in the internal-terminal in a new tab :AsyncRun -mode=term -pos=tab ls -la :AsyncRun -mode=term -pos=TAB ls -la " open on the left/right/top/bottom side :AsyncRun -mode=term -pos=left ls -la :AsyncRun -mode=term -pos=right ls -la :AsyncRun -mode=term -pos=top ls -la :AsyncRun -mode=term -pos=bottom ls -la 

    你也许会奇怪,这和直接用内置的 :term xxx 运行 shell 命令有什么区别呢?为什么要用 asyncrun 来调度内置终端呢?理由很简单,便利性:

    • 命令里支持类似 $(VIM_FILENAME) 或者 $(VIM_ROOT) 的宏变量替换:

      :AsyncRun -mode=term -pos=TAB ls -la $(VIM_FILEDIR) 
    • 可以用 -cwd= 参数指定运行路径:

      :AsyncRun -mode=term -pos=TAB -cwd=~/github ls -la 
    • 更容易的指定终端窗口的位置和尺寸(非 tab 模式):

      :AsyncRun -mode=term -pos=bottom -rows=8 ls -la :AsyncRun -mode=term -pos=right -cols=40 ls -la 
    • 可以用 -focus=0 参数进行无干扰模式(避免切换焦点到新的终端窗口上带来的分心):

      :AsyncRun -mode=term -pos=tab -focus=0 ls -la 
    • 可以用 -close 来指定程序结束后自动关闭终端窗口:

      :AsyncRun -mode=term -pos=tab -focus=0 -close ls -la 
    • 可以在任务结束时触发 vim 命令提醒你任务结束:

      :AsyncRun -mode=term -post=echo\ 'notify' ls -la 

    还有其他一些额外好处:

    • 配套系统变量类似 $VIM_FILENAME 之类的会同时初始化。
    • 可以用 -listed=0 来避免在 buffer-list 里列入 terminal buffer 。
    • 可以用 -hidden=1 来将 terminal buffer 的 bufhidden 设置为 hide
    • 可以用 -reuse 来指定复用已经结束的内置终端窗口。
    • 可以为 Vim / NeoVim 提供完全一致的体验(二者内置终端还是有不少体验上的差别)。

    最重要的是 vim/neovim 中用 :term xxx 传递包含多个单双引号,竖线,重定向符号等的复杂命令时,经常不能正确解析,特别是一些小众 shell 或者 windows 下面,而 AsyncRun 命令可以准确的传递参数。

    在终端下使用 Vim 时,我个人最喜欢的内置终端位置是 -pos=TAB,和小写的 -pos=tab 不同,这个方式会在当前 tabpage 的 左边 创建新 tab 运行内置终端命令。如此,在命令结束的时候,就能刚好回到我先前工作的 tabpage ,也回到我之前编辑的文档上:

    除去宏变量替换外,上面大部分行为是可以用 :term 命令搭配 2-3 条其他命令来完成,但是用 asyncrun 只需要一条唯一的命令就能搞定这些琐碎的事情,并且消除了 vim 和 neovim 的体验差别。

    Summary

    asyncrun.vim 提供了可以用任何方式运行命令的方式,并且为他们提供了统一的封装和诸如宏变量,工作目录指定,窗口位置和焦点控制之类的增强。你可以从项目的 wiki: 命令用法说明 查看更多用法。

    PS:如果你觉得为不同的项目或者文件类型建立 asyncrun 的 keymap 很麻烦,你可以试试兄弟插件 asynctasks.vim,它使用 asyncrun 作为运行命令的后端,并且给 vim 引入了类似 vscode 任务系统的机制,不管是运行外部命令还是执行内部 vim 命令,一切行为皆可以看作 “任务”,而对于同一个任务,在不同的项目内又有不同的执行方式,asynctasks.vim 可以帮你轻松的打理这些问题。

    16 replies    2022-06-29 13:47:50 +08:00
    icySoda
        1
    icySoda  
       Jan 5, 2022 via iPhone
    这标题起得好像 6 年才更新一次似的
    kindjeff
        2
    kindjeff  
       Jan 5, 2022 via Android
    如果用 floatterm 等 terminal 插件的话,直接启动一个 terminal 再去敲命令不是更顺手么(另外 floatterm 和很多 shell 命令有直接的集成)
    kindjeff
        3
    kindjeff  
       Jan 5, 2022 via Android
    floatterm->floaterm
    xuboying
        4
    xuboying  
       Jan 5, 2022
    Asyncrun 应该可以理解成 vsc 的 task 吧,或者说后者是借鉴 asyncrun ?
    执行 ls 这种只是演示例子,实际上应该执行一些更复杂的命令
    skywind3000
        5
    skywind3000  
    OP
       Jan 5, 2022 via iPhone
    @kindjeff 对于偶然用的命令,终端里直接敲即可,对于重复命令,显然自动化更好,比如可以 map 到 f9 或者 f10 上,一按可。
    skywind3000
        6
    skywind3000  
    OP
       Jan 5, 2022 via iPhone
    @xuboying asynctasks.vim 才是对标 vscode 的 task ,而且更强。
    haoliang
        7
    haoliang  
       Jan 5, 2022
    对 neovim 的深度支持我比较惊讶,因为结合之前在知乎看到的楼主关于 neovim 的回答,楼主给我的感觉是对 neovim 并不看好。
    完整看下来,我其实没有找到适合的使用场景。tmux (popup)、rofi 、neovim (lua 、floatwin) 已经解决我可以想见的异步任务使用场景了。
    可能我这回复像是单纯在刷存在感...不过我早上就看到这帖子,脑子里搁了一天,就当提供一个没有引入该工具的路人视角吧
    skywind3000
        8
    skywind3000  
    OP
       Jan 6, 2022
    @haoliang 这和你开发用的语言有关,比如你如果是开机启动个浏览器,然后就一直改代码,刷新浏览器,那么确实没有用武之地,你如果开发需要频繁编译,或者执行的程序,那你一看就知道用在哪里了。
    xuboying
        9
    xuboying  
       Jan 6, 2022
    趁着大佬在问个问题
    我现在用 vim 比较少,主要我觉得还是我不太会用。比如我想实现 git grep 以后加入到 leadf 的 quickfixwindow , 每次调用都很慢。我是这么做的:

    先在 quickui 里加一个内容,然后执行这个菜单,调用命令行,补完 git 的 grep 的关键字
    我觉得不满意的地方是,调用麻烦,mapping 用完了。quickui 也不能实现调用顺序重排序。操错比较慢
    命令重复执行不能重新补全,比如写错一个字需要修改一下,就得全部重写
    另外 quicikui 和 leadf 都很现代化了,输入筐还是老实的命令行,体验不是特别好。
    不知道大佬能不能给点建议。谢谢

    call quickui#menu#install("&File", [
    \ ['Asyncrun (git grep)', 'call _My_UI_asyncrun("git grep -nw --column " . expand("<cword>"))', ''],

    function! _My_UI_asyncrun(reply) abort
    let l:my_input=input("command=> ", a:reply)
    echo l:my_input
    execute 'AsyncRun -strip -raw -post=call\ _My_Update_quicklist() ' .l:my_input
    endfunction


    function! _My_Update_quicklist() abort
    let l:foo=getqflist()
    let l:bar=[]
    let l:skip=0
    for l:aaa in l:foo
    if l:aaa.valid==1
    let l:skip=1
    break
    endif
    call add(l:bar, l:aaa.text)
    endfor
    if l:skip == 0
    cgetexpr l:bar
    endif
    execute 'LeaderfQuickFix'
    endfunction
    skywind3000
        10
    skywind3000  
    OP
       Jan 6, 2022
    xuboying
        11
    xuboying  
       Jan 6, 2022
    @skywind3000 #10 感谢! quickui 让上了年纪人不用记太多复杂命令了,非常棒! Rebase 到最新的 tag 后能用这个 input 模块了。
    zbinlin
        12
    zbinlin  
       Jan 9, 2022
    可以实现 Bexec 插件那样的功能吗?

    PS:好像之前问过类似的问题?
    skywind3000
        13
    skywind3000  
    OP
       Jan 12, 2022   1
    @zbinlin 更新一下,我给你加了一下,通过 asyncrun 的 “命令修改器” 机制来完成:

    :AsyncRun -program=shebang -raw $(VIM_FILEPATH)
    :AsyncRun -program=shebang -mode=term -pos=top $(VIM_FILEPATH)
    skywind3000
        14
    skywind3000  
    OP
       Jan 12, 2022   1
    @zbinlin 你可以定义成一个命令:

    command! -nargs=0 AsyncBexec AsyncRun -program=shebang -mode=term -pos=top $(VIM_FILEPATH)

    然后用 :AsyncBexec 代替你的老命了
    Kaiv2
        15
    Kaiv2  
       Jan 27, 2022
    很好用,配合 LeaderF, floaterm 直接起飞
    linuxyz
        16
    linuxyz  
       Jun 29, 2022
    忙去 GitHub 一!
    About     Help     Advertise     Blog     API     FAQ     Solana     1080 Online   Highest 6679       Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 72ms UTC 22:53 PVG 06:53 LAX 15:53 JFK 18:53
    Do have faith in what you're doing.
    ubao msn snddm index pchome yahoo rakuten mypaper meadowduck bidyahoo youbao zxmzxm asda bnvcg cvbfg dfscv mmhjk xxddc yybgb zznbn ccubao uaitu acv GXCV ET GDG YH FG BCVB FJFH CBRE CBC GDG ET54 WRWR RWER WREW WRWER RWER SDG EW SF DSFSF fbbs ubao fhd dfg ewr dg df ewwr ewwr et ruyut utut dfg fgd gdfgt etg dfgt dfgd ert4 gd fgg wr 235 wer3 we vsdf sdf gdf ert xcv sdf rwer hfd dfg cvb rwf afb dfh jgh bmn lgh rty gfds cxv xcv xcs vdas fdf fgd cv sdf tert sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf shasha9178 shasha9178 shasha9178 shasha9178 shasha9178 liflif2 liflif2 liflif2 liflif2 liflif2 liblib3 liblib3 liblib3 liblib3 liblib3 zhazha444 zhazha444 zhazha444 zhazha444 zhazha444 dende5 dende denden denden2 denden21 fenfen9 fenf619 fen619 fenfe9 fe619 sdf sdf sdf sdf sdf zhazh90 zhazh0 zhaa50 zha90 zh590 zho zhoz zhozh zhozho zhozho2 lislis lls95 lili95 lils5 liss9 sdf0ty987 sdft876 sdft9876 sdf09876 sd0t9876 sdf0ty98 sdf0976 sdf0ty986 sdf0ty96 sdf0t76 sdf0876 df0ty98 sf0t876 sd0ty76 sdy76 sdf76 sdf0t76 sdf0ty9 sdf0ty98 sdf0ty987 sdf0ty98 sdf6676 sdf876 sd876 sd876 sdf6 sdf6 sdf9876 sdf0t sdf06 sdf0ty9776 sdf0ty9776 sdf0ty76 sdf8876 sdf0t sd6 sdf06 s688876 sd688 sdf86