【问题标题】:How to execute file I'm editing in Vi(m)如何执行我在 Vi(m) 中编辑的文件
【发布时间】:2010-10-31 12:05:38
【问题描述】:

如何执行我在 Vi(m) 中编辑的文件并在拆分窗口中获取输出(如在 SciTE 中)?

当然我可以这样执行:

:!scriptname

但是是否可以避免编写脚本名称以及如何在拆分窗口而不是屏幕底部获取输出?

【问题讨论】:

  • :!% 会让你避免写'scriptname'。下面的解决方案更好,但我想我会提到这一点,以防你决定 :!% 就足够了。
  • 另外注意,您可以使用 %:p(而不仅仅是 %)来引用当前文件的绝对路径。如果您的当前目录在其他地方,这可能是必要的。
  • 运行 ruby​​ 脚本 :!ruby % 就可以了
  • @andy :!%:p 也解决了目录不在 $PATH 中的问题
  • :!"%:p" 来处理空格。

标签: vim exec


【解决方案1】:

make 命令。它运行makeprg 选项中设置的命令。使用% 作为当前文件名的占位符。例如,如果您正在编辑 python 脚本:

:set makeprg=python\ %

是的,你需要逃离这个空间。在此之后,您可以简单地运行:

:make

如果你愿意,你可以设置autowrite选项,它会在运行makeprg之前自动保存:

:set autowrite

这解决了执行部分。不知道有什么方法可以将该输出放入不涉及重定向到文件的拆分窗口中。

【讨论】:

  • 实际上,您的解决方案确实将输出输出到拆分窗口。使用:copen 打开通过在自己的窗口中运行:make. 生成的“错误列表”。不幸的是,要正确格式化输出,需要对 errorformat 选项进行一些修改。否则输出将被假定为 gcc 输出的格式。
  • 你对“finagling”错误格式非常肯定。它看起来像我见过的一些 perl 代码......
  • 此工具可用于从 vim 中“制作”项目(为 vim 提供类似 IDE 的功能)。 Brian Carper 的解决方案 (:let f=expand("%")|vnew|execute '.!ruby "' . f . '"') 虽然看起来很神秘,但完全符合问题作者的要求。
【解决方案2】:

要访问当前缓冲区的文件名,请使用%。要将其放入变量中,您可以使用 expand() 函数。要使用新缓冲区打开新窗口,请使用 :new:vnew。要将命令的输出通过管道传输到当前缓冲区,请使用 :.! 。把它们放在一起:

:let f=expand("%")|vnew|execute '.!ruby "' . f . '"'

显然用你想要的任何命令替换ruby。我使用了execute,所以我可以用引号将文件名括起来,所以如果文件名中有空格,它就会起作用。

【讨论】:

  • @baboonWorksFine 使用:command! R let f=expand("%")|vnew|execute '.!ruby "' . f . '"' 可以只使用:R 来执行他的命令
  • 即使在执行时需要用户输入的脚本也可以运行它吗?
【解决方案3】:

我通过地图使用了一种更具侵入性的机制:

map ;e :w<CR>:exe ":!python " . getreg("%") . "" <CR>

就这样吧,这样我就不必保存了,然后走。走吧。

【讨论】:

  • 如果你设置了自动写入选项,你可以运行 :make 并且它...自动保存之前。
【解决方案4】:

对于我使用过的 Shell 脚本

:set makeprg=%

:make

【讨论】:

    【解决方案5】:

    Vim 有! ("bang") 命令,它直接从 VIM 窗口执行 shell 命令。此外,它允许启动与管道连接并读取标准输出的命令序列。

    例如:

    ! node %
    

    相当于打开命令提示符窗口并启动命令:

    cd my_current_directory 
    node my_current_file
    

    详情请见"Vim tips: Working with external commands"

    【讨论】:

      【解决方案6】:

      我的 vimrc 中有一个快捷方式:

      nmap <F6> :w<CR>:silent !chmod 755 %<CR>:silent !./% > .tmp.xyz<CR>
           \ :tabnew<CR>:r .tmp.xyz<CR>:silent !rm .tmp.xyz<CR>:redraw!<CR>
      

      这会写入当前缓冲区,使当前文件可执行(仅限 unix),执行它(仅限 unix)并将输出重定向到 .tmp.xyz,然后创建一个新选项卡,读取文件,然后将其删除。

      分解:

      :w<CR>                             write current buffer
      :silent !chmod 755 %<CR>           make file executable
      :silent !./% > .tmp.xyz<CR>        execute file, redirect output
      :tabnew<CR>                        new tab
      :r .tmp.xyz<CR>                    read file in new tab
      :silent !rm .tmp.xyz<CR>           remove file
      :redraw!<CR>                       in terminal mode, vim get scrambled
                                         this fixes it
      

      【讨论】:

      • 我很喜欢你的方案,用了一段时间后,觉得还可以改进。所以这是我的看法::w&lt;CR&gt;:silent !chmod +x %:p&lt;CR&gt;:silent !%:p 2&gt;&amp;1 | tee ~/.vim/output&lt;CR&gt;:split ~/.vim/output&lt;CR&gt;:redraw!&lt;CR&gt; — 这会将 stdout 和 stderr 都重定向到临时文件,在此之前,它会将所有内容打印到 stdout,因此如果脚本需要很长时间才能运行,您实际上会看到它在工作。此外,它与目录无关(通过绝对路径打开文件时出现错误)。但是,它不会以交互方式运行脚本,而且我还没有找到实现它的方法。
      • 仅供参考——在@Cyril 的解决方案中,我不得不转义管道符号:| -> \|
      【解决方案7】:

      你可以使用vim的插件bexec。据我所知,最新版本是 0.5。

      然后:

      $ mkdir -p ~/.vim/plugin
      $ mv bexec-0.5.vba ~/.vim/plugin
      $ vim ~/.vim/plugin/bexec-0.5.vba
      

      编辑 .vba 文件时在 vim 内部做:

      :so %
      

      会显示一些输出,让您知道 bexec.vim 已编写以及文档等。

      现在,您可以通过在 vim 中打开您的(具有 #! 解释器正常工作的任何语言脚本)并运行来测试它

      :Bexec 
      

      注意:我希望拆分是垂直的而不是水平的,所以我做到了:

      $ grep -i -n split ~/.vim/plugin/bexec.vim | grep -i hor
      102:    let bexec_splitdir = "hor" " hor|ver
      261:        exec {"ver":"vsp", "hor":"sp"}[g:bexec_splitdir]
      

      并将值从“hor”更改为“ver”..

      我知道这是一个老问题,但我希望这可以帮助那里的人。我在参加 Coursera 的 Startup Engineering 课程时遇到了同样的问题,Palaji 教授使用 Emacs 而我不喜欢 Emacs..

      【讨论】:

      • 您应该在本地 .vimrc 中更改首选项相关设置。 bexec 提供“let bexec_splitdir='hor'”设置,无需修改插件代码即可实现。
      【解决方案8】:

      基于@SethKriticos 和@Cyril 的回答,我现在使用以下内容:

      function! Setup_ExecNDisplay()
        execute "w"
        execute "silent !chmod +x %:p"
        let n=expand('%:t')
        execute "silent !%:p 2>&1 | tee ~/.vim/output_".n
        " I prefer vsplit
        "execute "split ~/.vim/output_".n
        execute "vsplit ~/.vim/output_".n
        execute "redraw!"
        set autoread
      endfunction
      
      function! ExecNDisplay()
        execute "w"
        let n=expand('%:t')
        execute "silent !%:p 2>&1 | tee ~/.vim/output_".n
        " I use set autoread
        "execute "1 . 'wincmd e'"
      endfunction
      
      :nmap <F9> :call Setup_ExecNDisplay()<CR>
      :nmap <F2> :call ExecNDisplay()<CR>
      

      使用 F9 设置新窗口,使用 F2 执行您的脚本并打开您的输出文件。

      我还在输出文件名中添加了脚本名称,以便您可以同时将其用于多个脚本。

      【讨论】:

        【解决方案9】:

        @xorpaul

        我一直在寻找这个脚本(python/Windows)。由于 Windows 中没有“三通”,因此我将其更改为:

        function! Setup_ExecNDisplay()
          execute "w"
          let n=expand('%:t')
          execute "silent ! python % > d:\\temp\\output_".n ." 2>&1"
          execute "vsplit d:\\temp\\output_".n
          execute "redraw!"
          set autoread
        endfunction
        
        function! ExecNDisplay()
          execute "w"
          let n=expand('%:t')
          execute "silent ! python % > d:\\temp\\output_".n . " 2>&1"
        endfunction
        
        :nmap <F9> :call Setup_ExecNDisplay()<CR>
        :nmap <F2> :call ExecNDisplay()<CR>
        

        【讨论】:

          【解决方案10】:

          在你的.vimrc你可以粘贴这个函数

          function! s:ExecuteInShell(command)
            let command = join(map(split(a:command), 'expand(v:val)'))
            let winnr = bufwinnr('^' . command . '$')
            silent! execute ':w'
            silent! execute  winnr < 0 ? 'vnew ' . fnameescape(command) : winnr . 'wincmd w'
            setlocal buftype=nowrite bufhidden=wipe nobuflisted noswapfile nowrap number
            silent! execute 'silent %!'. command
            silent! redraw
            silent! execute 'au BufUnload <buffer> execute bufwinnr(' . bufnr('#') . ') . ''wincmd w'''
            silent! execute 'nnoremap <silent> <buffer> <LocalLeader>r :call <SID>ExecuteInShell(''' . command . ''')<CR>'
            silent! execute 'wincmd w'
            " echo 'Shell command ' . command . ' executed.'
          endfunction
          command! -complete=shellcmd -nargs=+ Shell call s:ExecuteInShell(<q-args>)
          cabbrev shell Shell
          

          之后,以vim 运行命令:shell python ~/p.py 为例。您将在拆分窗口中获得输出。 + 以p.py 为例,修改后再次运行相同的命令,此函数不会再次创建新窗口,它会在上一个(相同的)分割窗口中显示结果。

          【讨论】:

          • 这太棒了,谢谢!再次写入缓冲区时,如何将其更改为重新运行?
          【解决方案11】:

          Vim 8 内置了一个交互式终端。要在拆分窗格中运行当前的 bash 脚本:

          :terminal bash %
          

          或简称

          :ter bash %
          

          % 扩展为当前文件名。

          来自:help terminal

          The terminal feature is optional, use this to check if your Vim has it:
              echo has('terminal')
          If the result is "1" you have it.
          

          【讨论】:

            【解决方案12】:

            如下图使用冒号和感叹号

            :!

            【讨论】:

              【解决方案13】:

              我推荐插件quickrun。配置快速且简单。这是一个小演示:

              【讨论】:

                猜你喜欢
                • 2020-08-30
                • 2012-11-11
                • 2014-03-27
                • 2011-06-19
                • 2020-05-23
                • 2017-02-09
                • 1970-01-01
                • 2011-05-02
                • 2018-10-21
                相关资源
                最近更新 更多