Plugin for compiling/running different projects. By default python, c/c++, zig, rust, lua, sh, haskell, matlab, markdown, rmarkdown and latex are supported, but other languages can be easily added. Upon run, plugin identifies the project root from lsp. If lsp is not present/initialized, root will be determined by traversing upwards in the directory tree, searching for specified identifiers. If no identifiers are found, the directory of the current file is assumed to be the root. You can also set custom run commands per project with a specified project file, which will be automatically included in the list of root identifiers.
The first command, prepended to all commands regardless of what language is used, will always be cd <root>
.
python <script> <args>
- With
CMakeLists.txt
in root directory:
mkdir build && cd build
cmake .. <args>
make -j
*Note: if clean
is passed as args, rm -rf build
will be executed instead.
- With
Makefile
in root directory:
make -j <args>
- If neither CMakeLists.txt nor Makefile exists, plugin will copy generic makefile that will scan all .c/.cpp files and run:
make -j <args>
- With
Makefile
in root directory:
make -j <args>
- With
zig.build
in root directory:
zig build <args> run
- With
Cargo.toml
in root directory:
cargo run -- <args>
- If
lua_modules
directory exists:
./lua <script> <args>
- Otherwise:
lua <script> <args>
chmod +x <script>
./<script> <args>
- If
*.cabal
file exists:
cabal run
- Otherwise:
ghc -o <dirname> <script> && ./<dirname>
octave <script> <args>
pandoc --verbose -o <script:%.pdf> <args>
*Note: -o script:%.pdf
will be passed only if -o
is not present in args.
echo "require(rmarkdown); render('<script>')" | R --vanila <args>
*Note: --vanila
is passed only if args are not specifed.
sh -c "pdflatex <script> && if grep -q 'bibliography' <script>; then if grep -q 'biblatex' <script>; then biber <script:%.> && pdflatex <script> && pdflatex <script>; else bibtex <script:%.> && pdflatex <script> && pdflatex <script>; fi; fi"
Add the following to your neovim configuration:
{
'vilari-mickopf/praise-the-run.nvim',
config = function()
require('praise-the-run').setup()
end
}
Default configuration:
require('praise-the-run').setup({
call = require('praise-the-run.project').call,
languages = {
python = {
project_file = '.pyproject',
root_identifier = {'.git', '.svn'},
run = default_runners.python
},
c = {
project_file = '.cproject',
root_identifier = {'[Mm]akefile', 'CMakeLists.txt', '.git', '.svn'},
run = default_runners.c
},
cpp = {
project_file = '.cproject',
root_identifier = {'[Mm]akefile', 'CMakeLists.txt', '.git', '.svn'},
run = default_runners.cpp
},
zig = {
project_file = '.zigproject',
root_identifier = {'[Mm]akefile', 'zig.build', '.git', '.svn'},
run = default_runners.zig
},
make = {
project_file = '.cproject',
root_identifier = {'[Mm]akefile', 'CMakeLists.txt', '.git', '.svn'},
run = default_runners.make
},
cmake = {
project_file = '.cproject',
root_identifier = {'CMakeLists.txt', '.git', '.svn'},
run = default_runners.cmake
},
rust = {
project_file = '.rustproject',
root_identifier = {'Cargo.toml', '.git', '.svn'},
run = default_runners.rust
},
lua = {
project_file = '.luaproject',
root_identifier = {'lua_modules', '.git', '.svn'},
run = default_runners.lua
},
sh = {
project_file = '.shproject',
root_identifier = {'.git', '.svn'},
run = default_runners.sh
},
haskell = {
project_file = '.hsproject',
root_identifier = {'*.cabal', '.git', '.svn'},
run = default_runners.haskell
},
matlab = {
project_file = '.mproject',
root_identifier = {'.git', '.svn'},
run = default_runners.matlab
},
markdown = {
project_file = '.mdproject',
root_identifier = {'.git', '.svn'},
run = default_runners.markdown
},
rmd = {
project_file = '.rmdproject',
root_identifier = {'.git', '.svn'},
run = default_runners.rmarkdown
},
tex = {
project_file = '.texproject',
root_identifier = {'.git', '.svn'},
run = default_runners.tex
}
}
})
Default call function will run specified command in integrated terminal:
exe 'split' | exe 'terminal %s'
call cursor(line('w$'), col('.'))
You can customize this by using a custom call command. Personally, I prefer using the terminal in a split window. Here are some additional keybindings that allow me to close the terminal when enter is pressed:
function! TerminalMappings()
nmap <silent><buffer> <Cr> :q! \| echo('Terminal closed')<Cr>
endfunction
augroup TerminalStuff
au!
au TermOpen * call TerminalMappings()
augroup end
You can override any runner with a custom function:
local function custom_runner(root, args)
-- First command of the runner will always be `cd <root>`
local command = '<cmd> ' .. vim.api.nvim_buf_get_name(0)
if args ~= '' then
command = command .. ' ' .. args
end
return command
-- You can do the same as above by using default runner:
-- return require('praise-the-run.default_runners').default_runner('<cmd>', root, args)
end
require('praise-the-run').setup({
languages = {
<lang> = {
run = custom_runner
}
}
})
The runner function takes two arguments: the root path and the provided arguments. It should always return the command to be run, represented as a string.
You can configure languages that are not support. <lang>
should match the output of :echo &filetype
for desired file type.
require('praise-the-run').setup({
languages = {
<lang> = {
project_file = '.langproject', --> optional, if nill, .<lang>project will be assigned
root_identifier = {'.git', '.svn'}, --> optional, if nil, this will be assigned
run = function(root, args) --> mandatory
return require('praise-the-run.default_runners').default_runner('cmd', root, args)
end
}
}
})
To compile/run language of the current file:
require('praise-the-run').run()
or with arguments:
require('praise-the-run').run('--some --args')
or with vim commands:
:ProjectRun
:ProjectRunWithArgs
Example project file:
{
"pre": ["./autoconfig"], /* List of pre-run commands */
"run": "make", /* Command that should be run */
"args": "-j", /* Arguments to run command */
"post": ["./run-bin"], /* List of post-run commands */
}
Can be particularly useful for python projects where you need to run a specific script consistently while editing other scripts:
{
"pre": [],
"run": "python path/to/main.py",
"args": "--some-arg",
"post": [],
}
If require('praise-the-run').run(<args>)
is used, the provided arguments <args>
will override the arguments specified in the project file.
To open the project file in a split window, use:
require('praise-the-run').open_project_file()
or use vim command:
:OpenProjectFile
If the file doesn't exist, a dummy project file with all fields empty will be created automatically in root directory.
nmap <silent> <leader>p :OpenProjectFile<Cr>
nmap <silent> <leader>c :wa<Cr>:ProjectRun<Cr>
nmap <silent> <leader>C :wa<Cr>:ProjectRunWithArgs<Cr>