I have this function to compile my tex files:
function! CompileTex()
silent write!
call setqflist([])
echon "compiling with arara ..."
exec 'lcd %:h'
if expand("%:p") =~# '\(figuras\|figures\)'
let mainfile = fnameescape(expand("%:p"))
else
let mainfile = fnameescape(Tex_GetMainFileName())
endif
let &l:makeprg = 'arara -v ' . mainfile
silent make!
if !empty(getqflist())
copen
wincmd J
else
cclose
redraw
echon "successfully compiled"
endif
endfunction
The first conditional is there because when creating figures I want to compile the current buffer even if there is a main file. However when I call the function in a path that contains "figures" I get
Error detected while processing function CompileTex:
line 4:
E499: Empty file name for '%' or '#', only works with ":p:h": lcd %:h
and the mainfile variable is set to the main tex file and not to the current buffer as I want.
Try as the error message suggests, and change "lcd %:h" to "lcd %:p:h".
Also, you don't need the :exec. Just write it directly, it's an ex command:
function! CompileTex()
silent write!
call setqflist([])
echon "compiling with arara ..."
lcd %:p:h
...
etc.
Related
I already use a vim function in Linux vimrc file to execute Java files by just pressing 'F5'.
Below is the function which I use.
inoremap <F5> <Esc> :call CompileRunGcc()<CR><CR>
func! CompileRunGcc()
exec "w"
if &filetype == 'java'
exec "!javac %"
exec "!time java -cp %:p:h %:t:r"
endif
endfunc
But when there is a compiling error, it shows the error message and also the output of the previous compiled program.
What I want is to be shown only the error message without the output of the previous compiled program. How can I do that?
IMO, you'd better use the quickfix list feature to import the errors and warnings found into Vim. From there you'll be able to navigate the errors with :cnext, :cprev...
Regarding what's best with Java, you'll have to explore the various Java related compiler plugins. There is a :compiler javac for instance.
Regarding how to know whether the compilation has succeeded or not I use the method I've described in a similar Q/A: https://stackoverflow.com/a/56991040/15934
The only thing that changes is the way the exec_line variable would be built. It would look like (untested)
" From my build-tools-wrapper plugin
function! lh#btw#build#_get_metrics() abort
let qf = getqflist()
let recognized = filter(qf, 'get(v:val, "valid", 1)')
" TODO: support other locales, see lh#po#context().tranlate()
let errors = filter(copy(recognized), 'v:val.type == "E" || v:val.text =~ "\\v^ *(error|erreur)"')
let warnings = filter(copy(recognized), 'v:val.type == "W" || v:val.text =~ "\\v^ *(warning|attention)"')
let res = { 'all': len(qf), 'errors': len(errors), 'warnings': len(warnings) }
return res
endfunction
" in a java ftplugin
function s:build_and_run(file) abort
let tgt = fnamemodify(a:file, ':r')
" to make sure the buffer is saved
exe 'update ' . a:file
exe 'make ' . tgt
if lh#btw#build#_get_metrics().errors
echom "Error detected, execution aborted"
copen
return
endif
let path = fnamemodify(a:file, ':p:h')
let exec_line = '!time java -cp ' . path. ' ' . tgt
exe exec_line
endfunction
" With <buffer>, I assume this is defined in a java-ftplugin, because the
" specific '!time java'. It could be generalized to many different
" languages though.
nnoremap <buffer> ยต :<C-U>call <sid>build_and_run(expand('%'))<cr>
You can use the v:shell_error variable to check whether the javac command has failed. In that case, you can skip running the program, in which case the error messages will be left around for you to inspect.
function! CompileRunGcc()
exec "w"
if &filetype ==# 'java'
exec "!javac %"
if !v:shell_error
exec "!time java -cp %:p:h %:t:r"
endif
endif
endfunction
When I create a new python script, I usually want to make it executable. I can do it in two steps: first create the file using vim; the set the permission using chmod. The question is: is it possible to merge the two steps into one?
What I would like to see is: when I create the file from vim, it will check the suffix and set proper permissions (configurable). And I expect it also works for files like .sh, .exe... Thanks.
I use the following; it checks the file's shebang (e.g. #!/usr/bin/python) instead of the file extension.
" On the initial save, make the file executable if it has a shebang line,
" e.g. #!/usr/bin/env ...
" This uses the user's umask for determining the executable bits to be set.
function! s:GetShebang()
return matchstr(getline(1), '^#!\S\+')
endfunction
function! s:MakeExecutable()
if exists('b:executable') | return | endif
let l:shebang = s:GetShebang()
if empty(l:shebang) ||
\ executable(expand('%:p')) ||
\ ! executable('chmod')
return
endif
call system('chmod +x ' . shellescape(expand('%')))
if v:shell_error
echohl ErrorMsg
echomsg 'Cannot make file executable: ' . v:shell_error
echohl None
let b:executable = 0
else
echomsg 'Detected shebang' l:shebang . '; made file executable as' getfperm(expand('%'))
let b:executable = 1
endif
endfunction
augroup ExecutableFileDetect
autocmd!
autocmd BufWritePost * call <SID>MakeExecutable()
augroup END
Consider a the following minimal vimrc:
set nocompatible
filetype plugin indent on
let g:tex_flavor = 'latex'
function! CompileLatex()
let save_pwd = getcwd()
lcd %:p:h
let compiler = 'pdflatex '
let mainfile = expand('%:p:r')
let &l:makeprg = compiler . mainfile . '.tex'
echon "compiling latex file..."
silent make!
execute 'lcd ' . save_pwd
endfunction
function! EchoLatexMessage()
redraw
echo 'This message is not shown'
endfunction
augroup echo_message
au!
au QuickFixCmdPost make call EchoLatexMessage()
augroup END
And in a foo.tex file like:
\documentclass{article}
\begin{document}
Foo
\end{document}
run :call CompileLatex(). As seen in the GIF the message This message is not shown from function EchoLatexMessage() is not shown (on the other hand the message compiling latex file... is always on screen). Why is this happening? I expect the new message to be echoed once :make finishes.
This is because of the silent make! in your function. The :silent apparently not only applies to the :make itself, but also to the autocmds invoked by it (which sort of makes sense). If you want to silence the compilation output itself, but not the messages from the autocmd, you can prepend :unsilent to :echo in the EchoLatexMessage() function.
In my vimrc I call Uncrustify by this command:
%!uncrustify -l CPP -c D:\uncrustify\default.cfg
After that on some code I get a Windows Fatal error:
But when I call uncrustify on the same code in the console using the -f option, there is no error.
How can I change my vimrc to avoid such errors in the future? What can invoke this error?
In order to integrate Uncrustify with Vim properly, add the following to your .vimrc:
" Restore cursor position, window position, and last search after running a
" command.
function! Preserve(command)
" Save the last search.
let search = #/
" Save the current cursor position.
let cursor_position = getpos('.')
" Save the current window position.
normal! H
let window_position = getpos('.')
call setpos('.', cursor_position)
" Execute the command.
execute a:command
" Restore the last search.
let #/ = search
" Restore the previous window position.
call setpos('.', window_position)
normal! zt
" Restore the previous cursor position.
call setpos('.', cursor_position)
endfunction
" Specify path to your Uncrustify configuration file.
let g:uncrustify_cfg_file_path =
\ shellescape(fnamemodify('~/.uncrustify.cfg', ':p'))
" Don't forget to add Uncrustify executable to $PATH (on Unix) or
" %PATH% (on Windows) for this command to work.
function! Uncrustify(language)
call Preserve(':silent %!uncrustify'
\ . ' -q '
\ . ' -l ' . a:language
\ . ' -c ' . g:uncrustify_cfg_file_path)
endfunction
Now you can either map this function (Uncrustify) to a combination of keys or you could do the convenient trick that I use. Create a file ~/.vim/after/ftplugin/cpp.vim where you can override any Vim settings particularly for C++ and add the following line there:
autocmd BufWritePre <buffer> :call Uncrustify('cpp')
This basically adds a pre-save hook. Now when you save the file with C++ code it will be automatically formatted by Uncrustify utilizing the configuration file you supplied earlier.
For example, the same could be done for Java: in ~/.vim/after/ftplugin/java.vim add:
autocmd BufWritePre <buffer> :call Uncrustify('java')
You got the point.
NOTE: Everything presented here is well-tested and used every day by me.
I have found the placing the following code into your .vimrc to be sufficient:
let g:uncrustifyCfgFile = '~/.uncrustify.cfg'
function! UncrustifyFunc(options) range
exec a:firstline.','.a:lastline.'!uncrustify '.a:options
\.' -c '.g:uncrustifyCfgFile.' -q -l '.&filetype
endfunction
command! -range=% UncrustifyRange <line1>,<line2>call UncrustifyFunc('--frag')
command! Uncrustify let s:save_cursor = getcurpos()
\| %call UncrustifyFunc('')
\| call setpos('.', s:save_cursor)
Note this does assume that you have "uncrustify" binary in your $PATH.
It also assumes your configure file is ~/.uncrustify.cfg however you can change that by modifiying the g:uncrustifyCfgFile variable.
To call run
:Uncrustify
It also works on ranges (which was what promoted me to make this function). Visual selection example:
:'<,'>UncrustifyRange
I have only tired it with C, CPP and JAVA (I assume others will work as well)
In addition to #Alexander Shukaev's answer, adding the following will perform a check for uncrustify config correctness and not auto format if error is detected:
let output = system('uncrustify -q -c ' . a:cfgfile)
if v:shell_error != 0
echo output
endif
return v:shell_error
endfunction
" Don't forget to add Uncrustify executable to $PATH (on Unix) or
" %PATH% (on Windows) for this command to work.
function! Uncrustify(language)
if CheckUncrustifyCfg(g:uncrustify_cfg_file_path)
echo "Config file" g:uncrustify_cfg_file_path "has errors"
echo "No formatting will be performed"
return
endif
call Preserve(':silent %!uncrustify'
\ . ' -q '
\ . ' -l ' . a:language
\ . ' -c ' . g:uncrustify_cfg_file_path)
endfunction
Can anybody help me to get solution for my requirement?
Requirement is when a user exits from vim, cppcheck should happen and if any warning or error occurs then it should be prompted to a user.
Thanks in advance.
I assume you don't care if the command is executed asynchronously, since you're quitting the buffer anyway. You can use the :! command to run shell commands and :read to capture the output to a new window:
function! s:RunShellCommand(cmdline)
let first = 1
let words = []
" Expand and escape cmd arguments.
" shellescape() should work with '\'
for part in split(a:cmdline)
if first
" skip the cmd. ugly, i know.
let first = 0
else
if part[0] =~ '\v[%#<]'
let part = expand(part)
endif
let part = shellescape(part, 1)
endif
call add(words, part)
endfor
let expanded_cmdline = join(words)
" Create the new window
botright new
setlocal buftype=nofile bufhidden=wipe nobuflisted noswapfile nowrap
call setline(1, 'Showing output from cmd: ' . expanded_cmdline)
call append(line('$'), substitute(getline(2), '.', '=', 'g'))
" This is where actual work is getting done :-)
silent execute '$read !'. expanded_cmdline
" Uncomment the line below if you want the buffer to be
" non-modifiable
" setlocal nomodifiable
1
endfunction
Then you can define an autocommand for when a buffer is unloading:
au BufUnload *.cpp s:RunShellCommand('cppcheck %')
or a somewhat more generic command which you can call at any time:
command! -complete=shellcmd -nargs=+ Shell call s:RunShellCommand(<q-args>)
Now, to prevent closing your buffer, you have to remap :wq or :q to a function that will perform the aforementioned (plus perhaps some confirmation?), since once :quit is invoked, it cannot be aborted.