如何使用Vim高效地“制作”?

20

我尝试做的似乎是非常基础的东西,但我找不到任何相关的资料。我正在处理一个通常的项目:

project
|-- bin
|-- inc
`-- src

我想使用Vim中包含的make命令来制作我的项目。但是每次都要指定:make -C ../。如果当前目录中没有Makefile文件,我希望前往父目录。我已经用...

set tags+=./tags;/

在我的.vimrc中。

此外,默认情况下,make 命令输出的信息比较丑陋。是否存在选项可以为 make 命令添加颜色,并允许像在 Emacs 中一样直接访问错误信息。

谢谢。

6个回答

17

稍作修改,参考Adam的说法

 :set makeprg=[[\ -f\ Makefile\ ]]\ &&\ make\ \\\|\\\|\ make\ -C\ ..  

未转义时,这是

 [[ -f Makefile ]] && make || make -C ..

意思是伪代码风格

 if file-exists(Makefile) 
 then make
 else make -C ..

这只能向上访问一个目录。如果您想要一个更一般的解决方案,它将向上访问必要的所有目录,那么您需要能够搜索祖先目录,直到找到Makefile,并且我不确定如何在命令行上简单地执行此操作。但是编写一个脚本(使用您喜欢的任何语言),然后从makeprg中调用它应该不难。


16
可以使用 let 子句来避免这种繁琐的转义::let &makeprg = '[[ -f Makefile ]] && make || make -C ..' - ib.
3
[[ a ]] && b || c并不完全等同于if a then b else c。如果a为真且b返回一个非零的退出代码,则c也将被执行。 - Reinier Torenbeek
reiner-torenbeek: 很好的观点。[[ a ]] && (b ; true) || c 怎么样? - rampion

9

解决rampion的方案是第一步,但是它只在vim加载时计算。当我加载多个标签页时,路径可能会与另一个标签页不一致。

这里是我的解决方案(+使用tabnew)。

fun! SetMkfile()
  let filemk = "Makefile"
  let pathmk = "./"
  let depth = 1
  while depth < 4
    if filereadable(pathmk . filemk)
      return pathmk
    endif
    let depth += 1
    let pathmk = "../" . pathmk
  endwhile
  return "."
endf

command! -nargs=* Make tabnew | let $mkpath = SetMkfile() | make <args> -C $mkpath | cwindow 10

4
为了回答你的第二个问题,你可以使用VIM中的quickfix功能浏览错误。Quickfix会将错误存储在缓冲区中,并允许你前后导航。你可能需要定义错误正则表达式以使VIM能够从Make的输出中识别它们,但我似乎记得它可以很好地开箱即用(我不得不修改它在Java Ant构建中的工作方式 - 显然这里不适用)。

3

到目前为止,最简单的解决方案是在您的src目录中拥有一个Makefile,这是许多项目的设置方式,无论使用什么编辑器/IDE。您仍然可以拥有一个顶层Makefile,调用make -C src,其中src中构建规则位于src中。


我不知道为什么项目在可能的情况下不选择顶层Makefile。 - Matthew Mitchell

2
如果您在项目根目录下只有一个Makefile,可以使用另一种方法:
project
|-- bin
|-- inc
|-- src
| Makefile

如果您的项目路径存储在变量中,例如b:projectDir,则可以使用“autocommand”在执行:make:lmake之前切换到该目录:

augroup changeMakeDir
    au!
    autocmd QuickfixCmdPre *make
                \ if exists("b:projectDir") &&
                                    \ b:projectDir != expand("%:p:h") |
                    \ exe 'cd ' . b:projectDir |
                \ endif
augroup END

Projectroot插件可以用来设置b:projectDir;它还提供了将当前目录更改为项目根目录的命令:

augroup changeMakeDir
    au!
    autocmd QuickfixCmdPre make ProjectRootCD
augroup END

1
在你的 .vimrc 文件中设置 makecmd="make -C .."。

如果当前目录中没有Makefile文件,我更喜欢进入父目录。如果存在Makefile,则使用它。 - Jérôme
那并不容易。将您的makecmd设置为测试该条件的脚本... 这并不难做 :) - Adam Hawes
这正是我所问的。我不知道如何在vimrc中测试文件是否存在。 - Jérôme

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接