First a bit of context for those who don't know gradle. It's basically like make except that you don't have to have gradle installed on your computer. It ships with projects as a file called gradlew. So for instance a gradle project could look like:

├── gradlew
└── src
    └── main
        └── java
            └── com
                └── foo
                    └── bar
                        ├── Bar.java
                        ├── Baz.java
                        ├── Foo.java
                        └── Qux.java

And from the root directory I can run commands like ./gradlew build or ./gradlew test to build/test my code.

Now vim. First I :set autochdir in my .vimrc. Second, my current buffer is Foo.java.

I want to run :make which would trigger ../../../../../../gradlew. How can I set makeprg such that no matter what's my :pwd it'll call gradlew (I guess that could be achieved using dirname in a loop but I'm not sure if that's the most efficient/cleanest way to do that).


  • Create a script/program that is invoked by vim and recursively searches up the hierarchy for gradlew (be sure to terminate at / if not found). The alternative is to put some information in every dir under src, or keep an external database for each directory in a project/the whole disc, both of which would be more efficient on usage, but clumsy to create and maintain.
    – Anthon
    Mar 14 '14 at 3:52

For those looking to do the same thing (or similar things), it's doable by creating a new compiler that use findfile, and reuse errorformat from some other compiler + slight modifications. The end result looks like:

let s:gradlew = escape(findfile('gradlew', '.;') . " -b " . findfile('build.gradle', '.;'), ' \')

if exists("current_compiler")

if exists(":CompilerSet") != 2      " older Vim always used :setlocal
  command -nargs=* CompilerSet setlocal <args>

let current_compiler = s:gradlew
execute "CompilerSet makeprg=" . s:gradlew
" copied from javac.vim + added the :compileJava bits
CompilerSet errorformat=%E:compileJava%f:%l:\ %m,%E%f:%l:\ %m,%-Z%p^,%-C%.%#,%-G%.%#
  • Awesome. This is so useful. Thank you! Apr 1 at 2:22

To add to foo's comment above, note that it is helpful to add './' to the s:gradlew variable, i.e.:

let s:gradlew = escape('./' . findfile('gradlew', '.;') . " -b " . findfile('build.gradle', '.;'), ' \')

This will allow gradlew to execute even when the file is in the current working directory. Without this, you may see the error "command not found: gradlew".

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.