" Vimball Archiver by Charles E. Campbell, Jr., Ph.D. UseVimball finish doc/checksyntax.txt [[[1 344 *checksyntax.txt* checksyntax -- Check syntax when saving a file (php, ruby, tex ...) Author: Tom Link, micathom at gmail com The checksyntax plugin runs an external syntax checker for the current buffer whenever the buffer is saved (by calling the |:CheckSyntax| command). Syntax errors are managed as location or quickfix lists. If any syntax error occurs, the |location-list| is opened (users can redefine |CheckSyntaxFail()| to change this behaviour). You can use any |location-list| related command to navigate the list of syntax errors. If quickfixsigns (vimscript #2584) is installed, lines containing syntax errors will be marked with signs. Experimental: If AsyncCommand (vimscript #3431) is installed, syntax checks can be peformed asynchronously -- see also |g:checksyntax#run_alternatives|, |g:checksyntax#run_all_alternatives| and |g:checksyntax#async_runner|. By default, |:CheckSyntax| is mapped to (if not mapped already), and automatically executed when saving the buffer. :CheckSyntax! or will run all syntax checkers for a given filetype if multiple alternatives are defined and installed on your computer. The |:CheckSyntax| command takes one optional argument: the mode (default: &filetype). As the plugin doesn't provide syntax checks by its own. This is done by an external syntax checker that has to be installed on your computer. Pre-defined syntax checkers (the respective syntax checker has to be installed): c, cpp ... Requires splint html ... Requires tidy java ... Requires jlint (http://jlint.sourceforge.net), checkstyle (http://checkstyle.sourceforge.net), pmd (http://pmd.sourceforge.net) javascript ... Syntax check; requires jshint, esprima, gjslint, jslint, jsl, pmd lua ... Requires luac (run luac -p) php ... Syntax check; requires php (run php -l) python ... Requires pyflakes or pylint r ... Requires codetools::checkUsage, lint::lint, or svTools::lint ruby ... Requires ruby (run ruby -c) tex, latex ... Requires chktex (run chktex -q -v0) viki ... Requires deplate xhtml ... Requires tidy xml, docbk ... Requires xmllint, pmd Syntax checker definitions are kept in: autoload/checksyntax/defs/{&filetype}.vim Run this command to find out, which filetypes are supported: > :echo globpath(&rtp, 'autoload/checksyntax/defs/*.vim') This plugin was originally based on Klaus Horsten's php_console (vimscript #779) and it is the successor of php_check_syntax.vim (vimscript #1272). ----------------------------------------------------------------------- Install~ Edit the vba file and type: > :so % See :help vimball for details. If you have difficulties or use vim 7.0, please make sure, you have the current version of vimball (vimscript #1502) installed or update your runtime. Optional enhancements: quickfixsigns (vimscript #2584) ... Use signs AsyncCommand (vimscript #3431) ... Run commands asynchronously ======================================================================== Contents~ :CheckSyntax ......................... |:CheckSyntax| g:checksyntax_key_single ............. |g:checksyntax_key_single| g:checksyntax_key_all ................ |g:checksyntax_key_all| g:checksyntax_auto ................... |g:checksyntax_auto| g:checksyntax#auto_enable_rx ......... |g:checksyntax#auto_enable_rx| g:checksyntax#auto_disable_rx ........ |g:checksyntax#auto_disable_rx| g:checksyntax#show_cmd ............... |g:checksyntax#show_cmd| g:checksyntax#lines_expr ............. |g:checksyntax#lines_expr| g:checksyntax#preferred .............. |g:checksyntax#preferred| g:checksyntax#async_runner ........... |g:checksyntax#async_runner| :CheckSyntaxStatus ................... |:CheckSyntaxStatus| g:checksyntax#run_alternatives ....... |g:checksyntax#run_alternatives| g:checksyntax#run_all_alternatives ... |g:checksyntax#run_all_alternatives| g:checksyntax#windows ................ |g:checksyntax#windows| g:checksyntax#null ................... |g:checksyntax#null| g:checksyntax#cygwin_path_rx ......... |g:checksyntax#cygwin_path_rx| g:checksyntax#cygwin_expr ............ |g:checksyntax#cygwin_expr| g:checksyntax#check_cygpath .......... |g:checksyntax#check_cygpath| CheckSyntaxSucceed ................... |CheckSyntaxSucceed()| CheckSyntaxFail ...................... |CheckSyntaxFail()| g:checksyntax#prototypes ............. |g:checksyntax#prototypes| checksyntax#AddChecker ............... |checksyntax#AddChecker()| checksyntax#GetChecker ............... |checksyntax#GetChecker()| checksyntax#Check .................... |checksyntax#Check()| checksyntax#AddJob ................... |checksyntax#AddJob()| checksyntax#RemoveJob ................ |checksyntax#RemoveJob()| checksyntax#Status ................... |checksyntax#Status()| checksyntax#GetList .................. |checksyntax#GetList()| checksyntax#NullOutput ............... |checksyntax#NullOutput()| checksyntax#MaybeUseCygpath .......... |checksyntax#MaybeUseCygpath()| g:checksyntax#pmd#cmd ................ |g:checksyntax#pmd#cmd| g:checksyntax#pmd#args ............... |g:checksyntax#pmd#args| checksyntax#pmd#Cmd .................. |checksyntax#pmd#Cmd()| ======================================================================== plugin/checksyntax.vim~ *:CheckSyntax* CheckSyntax[!] [NAME] Check the current buffer's syntax (type defaults to &filetype). Or use NAME instead of &filetype. With the bang !, run all alternatives (see |g:checksyntax#run_alternatives|). *g:checksyntax_key_single* g:checksyntax_key_single (default: '') Map for running the preferred syntax checkers on the current buffer. *g:checksyntax_key_all* g:checksyntax_key_all (default: '') Map for running all suitable syntax checkers on the current buffer. *g:checksyntax_auto* g:checksyntax_auto (default: 1) If 1, enable automatic syntax checks after saving a file. If 2, enable automatic syntax checks when saving and loading a file. NOTE: This variable must be customized in vimrc before loading this plugin. See also |g:checksyntax|, |g:checksyntax#auto_enable_rx| and |g:checksyntax#auto_disable_rx|. ======================================================================== autoload/checksyntax.vim~ *g:checksyntax#auto_enable_rx* g:checksyntax#auto_enable_rx (default: '') Enable automatic checking for filetypes matching this rx. Set to "." to enable for all filetypes. This requires |g:checksyntax_auto| to be > 0. This variable overrules any filetype-specific settings in |g:checksyntax|. *g:checksyntax#auto_disable_rx* g:checksyntax#auto_disable_rx (default: '') Disable automatic checking for filetypes matching this rx. Set to "." to disable for all filetypes. This requires |g:checksyntax_auto| to be > 0. This variable overrules any filetype-specific settings in |g:checksyntax|. *g:checksyntax#show_cmd* g:checksyntax#show_cmd (default: {'qfl': 'copen', 'loc': 'lopen'}) A dictionary of VIM commands that are used to display the qf/loc lists. If empty, do nothing. *g:checksyntax#lines_expr* g:checksyntax#lines_expr (default: '') A vim expression that determines the number of lines of the qfl/loc window. If empty, don't set the size. A useful value is: > let g:checksyntax#lines_expr = 'min([&previewheight, &lines / 2, len(getloclist(0))])' < *g:checksyntax#preferred* g:checksyntax#preferred (default: {'xml': '.'}) A dictionary of 'filetype' => |regexp|. If only one alternative should be run (see |g:checksyntax#run_alternatives|), check only those syntax checkers whose names matches |regexp|. *g:checksyntax#async_runner* g:checksyntax#async_runner (default: has('clientserver') && !empty(v:servername) && exists(':AsyncMake') ? 'asynccommand' : '') Supported values: asynccommand ... Use the AsyncCommand plugin *:CheckSyntaxStatus* :CheckSyntaxStatus Show status information (pending async tasks). *g:checksyntax#run_alternatives* g:checksyntax#run_alternatives (default: 'first' . (!empty(g:checksyntax#async_runner) ? ' async' : '')) How to handle alternatives. Possible values: first ... Use the first valid entry all ... Run all valid alternatives one after another Alternatively, the following flag can be added in order to change how the alternatives are run: async ... Run alternatives asynchronously (see also |g:checksyntax#async_runner|) *g:checksyntax#run_all_alternatives* g:checksyntax#run_all_alternatives (default: 'all' . (!empty(g:checksyntax#async_runner) ? ' async' : '')) How to run "all" alternatives -- e.g., when calling the |:CheckSyntax| command with a bang. *g:checksyntax#windows* g:checksyntax#windows (default: &shell !~ 'sh' && (has('win16') || has('win32') || has('win64'))) *g:checksyntax#null* g:checksyntax#null (default: g:checksyntax#windows ? 'nul' : (filereadable('/dev/null') ? '/dev/null' : '')) *g:checksyntax#cygwin_path_rx* g:checksyntax#cygwin_path_rx (default: '/cygwin/') If a full windows filename (with slashes instead of backslashes) matches this |regexp|, it is assumed to be a cygwin executable. *g:checksyntax#cygwin_expr* g:checksyntax#cygwin_expr (default: '"bash -c ''". escape(%s, "''\\") ."''"') For cygwin binaries, convert command calls using this vim expression. *g:checksyntax#check_cygpath* g:checksyntax#check_cygpath (default: g:checksyntax#windows && s:Executable('cygpath')) If true, check whether we have to convert a path via cyppath -- see |checksyntax#MaybeUseCygpath| *CheckSyntaxSucceed()* CheckSyntaxSucceed(type, manually) This function is called when no syntax errors were found. *CheckSyntaxFail()* CheckSyntaxFail(type, manually, bg) This function is called when a syntax error was found. *g:checksyntax#prototypes* g:checksyntax#prototypes (default: {'loc': {}, 'qfl': {}}) Contains prototype definitions for syntax checkers that use the |location-list| ("loc") or the |quixfix|-list. *checksyntax#AddChecker()* checksyntax#AddChecker(filetype, ...) Define a syntax checker definition for a given filetype. If filetype ends with "?", add only if no checker with the given name is defined. A checker definition is a dictionary with the following fields: Mandatory (either one of the following): cmd ........ A shell command used as 'makeprg' to check the file. cmdexpr .... A vim expression that returns the cmd compiler ... A vim compiler that is used to check the file. exec ....... A vim command used to check the file (deprecated; use cmdexpr & process_list instead) Optional: efm ....... An 'errorformat' string. prepare .... An ex command that is run before doing anything. ignore_nr .. A list of error numbers that should be ignored. listtype ... Either loc (default) or qfl include .... Include another definition process_list .. Process a list of issues if ......... An expression to test *once* whether a syntax checker should be used. if_executable .. Test whether an application is executable. buffers .... Keep results only for either "current", "listed", or "all" buffers compiler_args .. Internal use cmd_args ... Internal use Optional top-level fields: auto ....... Run automatically when saving a file (see also |g:checksyntax#auto_enable_rx| and |g:checksyntax#auto_disable_rx|) modified ... The name of a pseudo-filetype that should be used if the buffer was modified run_alternatives ... A string that defines how to run alternatives (overrides |g:checksyntax#run_alternatives|). Top-level fields affect how syntax checkers for a filetype are run. *checksyntax#GetChecker()* checksyntax#GetChecker(filetype, ...) *checksyntax#Check()* checksyntax#Check(manually, ?bang='', ?filetype=&ft, ?background=1) Perform a syntax check. If bang is not empty, run all alternatives (see |g:checksyntax#run_alternatives|). If filetype is empty, the current buffer's 'filetype' will be used. If background is true, display the list of issues in the background, i.e. the active window will keep the focus. *checksyntax#AddJob()* checksyntax#AddJob(make_def) *checksyntax#RemoveJob()* checksyntax#RemoveJob(job_id) *checksyntax#Status()* checksyntax#Status() *checksyntax#GetList()* checksyntax#GetList(name, make_def, type) *checksyntax#NullOutput()* checksyntax#NullOutput(flag) *checksyntax#MaybeUseCygpath()* checksyntax#MaybeUseCygpath(cmd) If cmd seems to be a cygwin executable, use cygpath to convert filenames. This assumes that cygwin's which command returns full filenames for non-cygwin executables. ======================================================================== autoload/checksyntax/pmd.vim~ *g:checksyntax#pmd#cmd* g:checksyntax#pmd#cmd (default: '') The command to run pmd. *g:checksyntax#pmd#args* g:checksyntax#pmd#args (default: '-f text') *checksyntax#pmd#Cmd()* checksyntax#pmd#Cmd(language, args, rulesets) vim:tw=78:fo=tcq2:isk=!-~,^*,^|,^":ts=8:ft=help:norl: plugin/checksyntax.vim [[[1 87 " checksyntax.vim -- Check syntax when saving a file (php, ruby, tex ...) " @Author: Tom Link (micathom AT gmail com) " @License: GPL (see http://www.gnu.org/licenses/gpl.txt) " @Created: 04-Mai-2005. " @Last Change: 2012-08-28. " GetLatestVimScripts: 1431 0 :AutoInstall: checksyntax.vim " @Revision: 430 if exists('g:loaded_checksyntax') finish endif let g:loaded_checksyntax = 400 if !exists('g:checksyntax') let g:checksyntax = {} endif " :display: CheckSyntax[!] [NAME] " Check the current buffer's syntax (type defaults to &filetype). " Or use NAME instead of &filetype. " " With the bang !, run all alternatives (see " |g:checksyntax#run_alternatives|). command! -bang -nargs=? CheckSyntax call checksyntax#Check(1, "", ) " @TPluginInclude if !exists('g:checksyntax_key_single') " Map for running the preferred syntax checkers on the current " buffer. let g:checksyntax_key_single = '' "{{{2 endif " @TPluginInclude if !exists('g:checksyntax_key_all') " Map for running all suitable syntax checkers on the current " buffer. let g:checksyntax_key_all = '' "{{{2 endif if !exists('g:checksyntax_auto') " If 1, enable automatic syntax checks after saving a file. " If 2, enable automatic syntax checks when saving and loading a " file. " NOTE: This variable must be customized in vimrc before loading " this plugin. " " See also |g:checksyntax|, |g:checksyntax#auto_enable_rx| and " |g:checksyntax#auto_disable_rx|. let g:checksyntax_auto = 1 "{{{2 endif " @TPluginInclude augroup CheckSyntax autocmd! if !exists('g:checksyntax_auto') || g:checksyntax_auto >= 1 autocmd BufWritePost * call checksyntax#Check(0) endif if exists('g:checksyntax_auto') && g:checksyntax_auto >= 2 autocmd BufEnter * if !exists('b:checksyntax_runs') \ | call checksyntax#Check(0, 0, &ft, 1) \ | endif endif augroup END " @TPluginInclude if !hasmapto(':CheckSyntax') if empty(maparg(g:checksyntax_key_single, 'n')) exec 'noremap' g:checksyntax_key_single ':CheckSyntax' endif if empty(maparg(g:checksyntax_key_single, 'i')) exec 'inoremap' g:checksyntax_key_single ':CheckSyntax' endif if empty(maparg(g:checksyntax_key_all, 'n')) exec 'noremap' g:checksyntax_key_all ':CheckSyntax!' endif if empty(maparg(g:checksyntax_key_all, 'i')) exec 'inoremap' g:checksyntax_key_all ':CheckSyntax!' endif endif autoload/checksyntax.vim [[[1 1086 " @Author: Tom Link (mailto:micathom AT gmail com?subject=[vim]) " @Website: http://www.vim.org/account/profile.php?user_id=4037 " @License: GPL (see http://www.gnu.org/licenses/gpl.txt) " @Revision: 1395 if !exists('g:checksyntax#auto_enable_rx') " Enable automatic checking for filetypes matching this rx. " Set to "." to enable for all filetypes. " This requires |g:checksyntax_auto| to be > 0. " This variable overrules any filetype-specific settings in " |g:checksyntax|. let g:checksyntax#auto_enable_rx = '' "{{{2 endif if !exists('g:checksyntax#auto_disable_rx') " Disable automatic checking for filetypes matching this rx. " Set to "." to disable for all filetypes. " This requires |g:checksyntax_auto| to be > 0. " This variable overrules any filetype-specific settings in " |g:checksyntax|. let g:checksyntax#auto_disable_rx = '' "{{{2 endif if !exists('g:checksyntax#show_cmd') " A dictionary of VIM commands that are used to display the qf/loc " lists. " If empty, do nothing. let g:checksyntax#show_cmd = {'qfl': 'copen', 'loc': 'lopen'} "{{{2 endif if !exists('g:checksyntax#lines_expr') " A vim expression that determines the number of lines of the " qfl/loc window. If empty, don't set the size. " A useful value is: > " let g:checksyntax#lines_expr = 'min([&previewheight, &lines / 2, len(getloclist(0))])' let g:checksyntax#lines_expr = '' "{{{2 endif if !exists('g:checksyntax#debug') let g:checksyntax#debug = 0 endif if !exists('g:checksyntax#preferred') " A dictionary of 'filetype' => |regexp|. " If only one alternative should be run (see " |g:checksyntax#run_alternatives|), check only those syntax " checkers whose names matches |regexp|. let g:checksyntax#preferred = {'xml': '.'} "{{{2 endif if !exists('g:checksyntax#async_runner') " Supported values: " asynccommand ... Use the AsyncCommand plugin let g:checksyntax#async_runner = has('clientserver') && !empty(v:servername) && exists(':AsyncMake') ? 'asynccommand' : '' "{{{2 if has('clientserver') && empty(v:servername) echohl WarningMsg echom "CheckSyntax: Run vim with the --servername NAME command line option to enable use of AsyncCommand" echohl NONE endif endif if !empty(g:checksyntax#async_runner) " Show status information (pending async tasks). command! CheckSyntaxStatus call s:Status() endif if !exists('g:checksyntax#run_alternatives') " How to handle alternatives. Possible values: " " first ... Use the first valid entry " all ... Run all valid alternatives one after another " " Alternatively, the following flag can be added in order to change " how the alternatives are run: " " async ... Run alternatives asynchronously (see also " |g:checksyntax#async_runner|) let g:checksyntax#run_alternatives = 'first' . (!empty(g:checksyntax#async_runner) ? ' async' : '') "{{{2 endif if !exists('g:checksyntax#run_all_alternatives') " How to run "all" alternatives -- e.g., when calling the " |:CheckSyntax| command with a bang. let g:checksyntax#run_all_alternatives = 'all' . (!empty(g:checksyntax#async_runner) ? ' async' : '') "{{{2 endif if !exists('g:checksyntax#windows') let g:checksyntax#windows = &shell !~ 'sh' && (has('win16') || has('win32') || has('win64')) "{{{2 endif if !exists('g:checksyntax#null') let g:checksyntax#null = g:checksyntax#windows ? 'nul' : (filereadable('/dev/null') ? '/dev/null' : '') "{{{2 endif if !exists('g:checksyntax#cygwin_path_rx') " If a full windows filename (with slashes instead of backslashes) " matches this |regexp|, it is assumed to be a cygwin executable. let g:checksyntax#cygwin_path_rx = '/cygwin/' "{{{2 endif if !exists('g:checksyntax#cygwin_expr') " For cygwin binaries, convert command calls using this vim " expression. let g:checksyntax#cygwin_expr = '"bash -c ''". escape(%s, "''\\") ."''"' "{{{2 endif let s:cygwin = {} function! s:CygwinBin(cmd) "{{{3 " TLogVAR a:cmd if !g:checksyntax#windows return 0 elseif has_key(s:cygwin, a:cmd) let rv = s:cygwin[a:cmd] else if !s:Executable('cygpath', 1) || !s:Executable('which', 1) let rv = 0 else let which = substitute(system('which '. shellescape(a:cmd)), '\n$', '', '') " echom "DBG which:" which if which =~ '^/' let filename = system('cygpath -ma '. shellescape(which)) " echom "DBG filename:" filename let rv = filename =~ g:checksyntax#cygwin_path_rx else let rv = 0 endif endif let s:cygwin[a:cmd] = rv endif " TLogVAR rv return rv endf let s:executables = {} function! s:Executable(cmd, ...) "{{{3 " TLogVAR a:cmd " echom "DBG has_key(s:executables, a:cmd)" has_key(s:executables, a:cmd) if !has_key(s:executables, a:cmd) let ignore_cyg = a:0 >= 1 ? a:1 : !g:checksyntax#windows let s:executables[a:cmd] = executable(a:cmd) != 0 && (ignore_cyg || s:CygwinBin(a:cmd)) endif " echom "DBG s:executables[a:cmd]" s:executables[a:cmd] return s:executables[a:cmd] endf if !exists('g:checksyntax#check_cygpath') " If true, check whether we have to convert a path via cyppath -- " see |checksyntax#MaybeUseCygpath| let g:checksyntax#check_cygpath = g:checksyntax#windows && s:Executable('cygpath') "{{{2 endif if !exists('*CheckSyntaxSucceed') " This function is called when no syntax errors were found. function! CheckSyntaxSucceed(type, manually) call g:checksyntax#prototypes[a:type].Close() if a:manually echo echo 'Syntax ok.' endif endf endif if !exists('*CheckSyntaxFail') " This function is called when a syntax error was found. function! CheckSyntaxFail(type, manually, bg) " TLogVAR a:type, a:manually, a:bg call g:checksyntax#prototypes[a:type].Open(a:bg) endf endif if !exists('g:checksyntax#prototypes') " Contains prototype definitions for syntax checkers that use the " |location-list| ("loc") or the |quixfix|-list. let g:checksyntax#prototypes = {'loc': {}, 'qfl': {}} "{{{2 endif function! s:Open(bg, type) "{{{3 " TLogVAR a:bg let cmd = get(g:checksyntax#show_cmd, a:type, '') if !empty(cmd) if empty(g:checksyntax#lines_expr) || !empty(lines) let bufnr = bufnr('%') let winnr = winnr() exec cmd if a:bg && bufnr != bufnr('%') if !empty(g:checksyntax#lines_expr) let lines = eval(g:checksyntax#lines_expr) " TLogVAR lines exec 'resize' lines endif wincmd p endif endif endif endf if empty(g:checksyntax#prototypes.loc) function! g:checksyntax#prototypes.loc.Close() dict "{{{3 lclose endf function! g:checksyntax#prototypes.loc.Open(bg) dict "{{{3 call s:Open(a:bg, 'loc') endf function! g:checksyntax#prototypes.loc.GetExpr(args) dict "{{{3 " TLogDBG system(a:args) return s:RunCmd('lgetexpr', 'system('. string(a:args). ')') endf function! g:checksyntax#prototypes.loc.Make(args) dict "{{{3 return s:RunCmd('lmake!', a:args) endf function! g:checksyntax#prototypes.loc.Get() dict "{{{3 return copy(getloclist(0)) endf function! g:checksyntax#prototypes.loc.Set(list) dict "{{{3 call setloclist(0, a:list) endf endif if empty(g:checksyntax#prototypes.qfl) function! g:checksyntax#prototypes.qfl.Close() dict "{{{3 cclose endf function! g:checksyntax#prototypes.qfl.Open(bg) dict "{{{3 call s:Open(a:bg, 'qfl') endf function! g:checksyntax#prototypes.qfl.GetExpr(args) dict "{{{3 " TLogDBG system(a:args) return s:RunCmd('cgetexpr', 'system('. string(a:args). ')') endf function! g:checksyntax#prototypes.qfl.Make(args) dict "{{{3 return s:RunCmd('make!', a:args) endf function! g:checksyntax#prototypes.qfl.Get() dict "{{{3 return copy(getqflist()) endf function! g:checksyntax#prototypes.qfl.Set(list) dict "{{{3 call setqflist(a:list) endf endif function! s:RunCmd(cmd, args) "{{{3 try " TLogVAR a:cmd, a:args, &efm exec 'silent' a:cmd a:args return 1 catch echohl Error echom v:exception echohl NONE return 0 endtry endf let s:checkers = {} let s:top_level_fields = ['modified', 'auto', 'run_alternatives', 'alternatives'] let s:mandatory = ['cmd', 'cmdexpr', 'compiler', 'exec'] " Define a syntax checker definition for a given filetype. " If filetype ends with "?", add only if no checker with the given name " is defined. " " A checker definition is a dictionary with the following fields: " " Mandatory (either one of the following): " " cmd ........ A shell command used as 'makeprg' to check the file. " cmdexpr .... A vim expression that returns the cmd " compiler ... A vim compiler that is used to check the file. " exec ....... A vim command used to check the file (deprecated; use " cmdexpr & process_list instead) " " Optional: " " efm ....... An 'errorformat' string. " prepare .... An ex command that is run before doing anything. " ignore_nr .. A list of error numbers that should be ignored. " listtype ... Either loc (default) or qfl " include .... Include another definition " process_list .. Process a list of issues " if ......... An expression to test *once* whether a syntax checker " should be used. " if_executable .. Test whether an application is executable. " buffers .... Keep results only for either "current", "listed", or " "all" buffers " compiler_args .. Internal use " cmd_args ... Internal use " " Optional top-level fields: " " auto ....... Run automatically when saving a file (see also " |g:checksyntax#auto_enable_rx| and " |g:checksyntax#auto_disable_rx|) " modified ... The name of a pseudo-filetype that should be used if " the buffer was modified " run_alternatives ... A string that defines how to run " alternatives (overrides " |g:checksyntax#run_alternatives|). " " Top-level fields affect how syntax checkers for a filetype are run. function! checksyntax#AddChecker(filetype, ...) "{{{3 if a:0 == 1 && type(a:1) == 3 let alternatives = a:1 else let alternatives = a:000 endif " TLogVAR alternatives if !empty(alternatives) let [update, filetype] = s:UpName(a:filetype) " TLogVAR filetype, update, a:000, a:0, type(a:1) if !has_key(s:checkers, filetype) let s:checkers[filetype] = {'alternatives': {}, 'order': []} endif for make_def in alternatives " Copy top_level_fields for upkey in s:top_level_fields let [kupdate, key] = s:UpName(upkey) if has_key(make_def, key) && (kupdate || !has_key(s:checkers[filetype], key)) let s:checkers[filetype][key] = remove(make_def, key) endif endfor " If there are other fields, add make_def if !empty(make_def) if has_key(make_def, 'cmdexpr') let make_def.cmd = eval(make_def.cmdexpr) endif " TLogVAR make_def if !has_key(make_def, 'cmd') || !empty(make_def.cmd) let [update_name, name] = s:UpNameFromDef(make_def) if empty(name) throw "CheckSyntax: Name must not be empty: ". filetype .': '. string(make_def) elseif empty(filter(copy(s:mandatory), 'has_key(make_def, v:val)')) throw "CheckSyntax: One of ". join(s:mandatory, ', ') ." must be defined: ". filetype .': '. string(make_def) else let new_item = !has_key(s:checkers[filetype].alternatives, name) if update || update_name || new_item let s:checkers[filetype].alternatives[name] = make_def if new_item call add(s:checkers[filetype].order, name) endif endif endif endif endif endfor endif endf function! checksyntax#GetChecker(filetype, ...) "{{{3 call checksyntax#Require(a:filetype) let alts = get(get(s:checkers, a:filetype, {}), 'alternatives', {}) if a:0 == 0 return values(alts) else return values(filter(copy(alts), 'index(a:000, v:key) != -1')) endif endf " :nodoc: " Run |:make| based on a syntax checker definition. function! s:RunSyncWithEFM(make_def) "{{{3 " TLogVAR a:make_def let type = get(a:make_def, 'listtype', 'loc') let shellpipe = &shellpipe let errorformat = &errorformat if has_key(a:make_def, 'shellpipe') let &shellpipe = get(a:make_def, 'shellpipe') " TLogVAR &shellpipe endif if has_key(a:make_def, 'efm') let &errorformat = get(a:make_def, 'efm') " TLogVAR &errorformat endif try if has_key(a:make_def, 'cmd') let cmddef = s:ExtractCompilerParams(a:make_def, '%', a:make_def.cmd) let cmd = s:NativeCmd(cmddef.cmd) " TLogVAR cmd let rv = g:checksyntax#prototypes[type].GetExpr(cmd) " TLogVAR rv, getqflist() return rv elseif has_key(a:make_def, 'exec') exec a:make_def.exec return 1 endif finally if &shellpipe != shellpipe let &shellpipe = shellpipe endif if &errorformat != errorformat let &errorformat = errorformat endif endtry endf let s:convert_filenames = {} function! s:ConvertFilenames(make_def, props) "{{{3 for key in ['filename', 'altname'] let filename = a:props[key] let convert_filename = get(a:make_def, 'convert_filename', '') if !empty(convert_filename) if !has_key(s:convert_filenames, convert_filename) let s:convert_filenames[convert_filename] = {} endif if has_key(s:convert_filenames[convert_filename], filename) let filename = s:convert_filenames[convert_filename][filename] else " TLogVAR filename, convert_filename let cmd = printf(convert_filename, shellescape(filename)) " TLogVAR cmd let filename = system(cmd) let filename = substitute(filename, '\n$', '', '') let s:convert_filenames[convert_filename][filename] = filename endif " TLogVAR filename endif let a:make_def[key] = filename endfor return a:make_def endf let s:loaded_checkers = {} " :nodoc: function! checksyntax#Require(filetype) "{{{3 if empty(a:filetype) return 0 else if !has_key(s:loaded_checkers, a:filetype) exec 'runtime! autoload/checksyntax/defs/'. a:filetype .'.vim' let s:loaded_checkers[a:filetype] = 1 endif return has_key(s:checkers, a:filetype) endif endf function! s:NativeCmd(cmd) "{{{3 if !empty(g:checksyntax#cygwin_expr) && s:CygwinBin(matchstr(a:cmd, '^\S\+')) let cmd = eval(printf(g:checksyntax#cygwin_expr, string(a:cmd))) " TLogVAR cmd return cmd else return a:cmd endif endf " :nodoc: function! s:Cmd(make_def) "{{{3 if has_key(a:make_def, 'cmd') let cmd = matchstr(a:make_def.cmd, '^\(\\\s\|\S\+\|"\([^"]\|\\"\)\+"\)\+') else let cmd = '' endif return cmd endf " :nodoc: function! s:UpName(upname) "{{{3 if a:upname =~ '?$' let update = 0 let name = substitute(a:upname, '?$', '', '') else let update = 1 let name = a:upname endif return [update, name] endf " :nodoc: function! s:UpNameFromDef(make_def) "{{{3 let name = get(a:make_def, 'name', '') if empty(name) let name = get(a:make_def, 'compiler', '') endif if empty(name) let name = s:Cmd(a:make_def) endif return s:UpName(name) endf function! s:ValidAlternative(make_def) "{{{3 " TLogVAR a:make_def if has_key(a:make_def, 'if') return eval(a:make_def.if) elseif has_key(a:make_def, 'if_executable') return s:Executable(a:make_def.if_executable) else return 1 endif endf function! s:GetValidAlternatives(filetype, run_alternatives, alternatives) "{{{3 " TLogVAR a:filetype, a:run_alternatives, a:alternatives let valid = {} for name in get(get(s:checkers, a:filetype, {}), 'order', []) let alternative = a:alternatives[name] " TLogVAR alternative if s:ValidAlternative(alternative) if has_key(alternative, 'cmd') let cmd = s:Cmd(alternative) " TLogVAR cmd if !empty(cmd) && !s:Executable(cmd) continue endif endif let valid[name] = alternative if a:run_alternatives =~? '\' break endif endif endfor return valid endf let s:run_alternatives_all = 0 " :nodoc: function! checksyntax#RunAlternativesMode(make_def) "{{{3 let rv = s:run_alternatives_all ? g:checksyntax#run_all_alternatives : get(a:make_def, 'run_alternatives', g:checksyntax#run_alternatives) " TLogVAR a:make_def, rv return rv endf function! s:GetDef(filetype) "{{{3 " TLogVAR a:filetype if has_key(s:checkers, a:filetype) let dict = s:checkers let rv = s:checkers[a:filetype] else let dict = {} let rv = {} endif if !empty(dict) let alternatives = get(rv, 'alternatives', {}) " TLogVAR alternatives if !empty(alternatives) let alternatives = s:GetValidAlternatives(a:filetype, checksyntax#RunAlternativesMode(rv), alternatives) " TLogVAR alternatives if len(alternatives) == 0 let rv = {} else let rv = copy(rv) let rv.alternatives = alternatives endif endif endif return rv endf let s:async_pending = {} let g:checksyntax#issues = {} function! g:checksyntax#issues.Reset() dict "{{{3 let self.issues = [] let self.type = 'loc' endf call g:checksyntax#issues.Reset() function! g:checksyntax#issues.AddList(name, make_def, type) dict "{{{3 if a:type == 'qfl' let self.type = a:type endif let issues = checksyntax#GetList(a:name, a:make_def, a:type) if !empty(issues) let self.issues += issues endif return issues endf function! g:checksyntax#issues.Display(manually, bg) dict "{{{3 if empty(self.issues) call g:checksyntax#prototypes[self.type].Set(self.issues) call CheckSyntaxSucceed(self.type, a:manually) else " TLogVAR self.issues call sort(self.issues, 's:CompareIssues') " TLogVAR self.issues " TLogVAR self.type call g:checksyntax#prototypes[self.type].Set(self.issues) " TLogVAR self.type, a:manually, a:bg call CheckSyntaxFail(self.type, a:manually, a:bg) endif endf " :def: function! checksyntax#Check(manually, ?bang='', ?filetype=&ft, ?background=1) " Perform a syntax check. " If bang is not empty, run all alternatives (see " |g:checksyntax#run_alternatives|). " If filetype is empty, the current buffer's 'filetype' will be used. " If background is true, display the list of issues in the background, " i.e. the active window will keep the focus. function! checksyntax#Check(manually, ...) let bang = a:0 >= 1 ? !empty(a:1) : 0 let filetype = a:0 >= 2 && a:2 != '' ? a:2 : &filetype let bg = a:0 >= 3 && a:3 != '' ? a:3 : 0 " TLogVAR a:manually, bang, filetype, bg let s:run_alternatives_all = bang if !&autochdir let wd = getcwd() exec 'lcd' fnameescape(expand('%:p')) endif try let defs = s:GetDefsByFiletype(a:manually, filetype) " TLogVAR defs if !empty(defs.make_defs) if !exists('b:checksyntax_runs') let b:checksyntax_runs = 1 else let b:checksyntax_runs += 1 endif " TLogVAR &makeprg, &l:makeprg, &g:makeprg, &errorformat if defs.run_alternatives =~? '\' && has_key(g:checksyntax#preferred, filetype) let preferred_rx = g:checksyntax#preferred[filetype] let defs.make_defs = filter(defs.make_defs, 's:UpNameFromDef(v:val)[1] =~ preferred_rx') endif let async = !empty(g:checksyntax#async_runner) && defs.run_alternatives =~? '\' if !empty(s:async_pending) if !a:manually && async echohl WarningMsg echo "CheckSyntax: Still waiting for async results ..." echohl NONE return else let s:async_pending = {} endif endif let props = { \ 'bg': bg, \ 'bufnr': bufnr('%'), \ 'filename': expand('%'), \ 'altname': expand('#'), \ 'manually': a:manually, \ } call g:checksyntax#issues.Reset() for [name, make_def] in items(defs.make_defs) " TLogVAR make_def, async let make_def1 = copy(make_def) let done = 0 if async call extend(make_def1, props) let make_def1 = s:ConvertFilenames(make_def1, make_def1) let make_def1.name = name let make_def1.job_id = name .'_'. make_def1.bufnr let done = s:Run_async(make_def1) endif if !done let make_def1 = s:ConvertFilenames(make_def1, props) let done = s:Run_sync(name, filetype, make_def1) endif endfor " echom "DBG 1" string(list) if empty(s:async_pending) call g:checksyntax#issues.Display(a:manually, bg) endif endif finally if !&autochdir exec 'lcd' fnameescape(wd) endif let s:run_alternatives_all = 0 endtry redraw! endf function! s:Status() "{{{3 if empty(s:async_pending) echo "CheckSyntax: No pending jobs" else echo "CheckSyntax: Pending jobs:" for [job_id, make_def] in items(s:async_pending) echo printf(" %s: bufnr=%s, cmd=%s", \ job_id, \ make_def.bufnr, \ make_def.name \ ) endfor endif endf function! s:GetDefsByFiletype(manually, filetype) "{{{3 " TLogVAR a:manually, a:filetype let defs = {'mode': '', 'make_defs': {}} call checksyntax#Require(a:filetype) " let defs.mode = 'auto' let make_def = a:manually ? {} : s:GetDef(a:filetype .',auto') " TLogVAR 1, make_def if empty(make_def) let make_def = s:GetDef(a:filetype) " TLogVAR 2, make_def endif if &modified if has_key(make_def, 'modified') let make_def = s:GetDef(make_def.modified) " TLogVAR 3, make_def else echohl WarningMsg echom "Buffer was modified. Please save it before calling :CheckSyntax." echohl NONE return endif endif " TLogVAR make_def if empty(make_def) return defs endif if !empty(g:checksyntax#auto_enable_rx) && a:filetype =~ g:checksyntax#auto_enable_rx let auto = 1 elseif !empty(g:checksyntax#auto_disable_rx) && a:filetype =~ g:checksyntax#auto_disable_rx let auto = 0 else let auto = get(make_def, 'auto', 0) endif " TLogVAR auto if !(a:manually || auto) return defs endif let defs.run_alternatives = checksyntax#RunAlternativesMode(make_def) " TLogVAR &makeprg, &l:makeprg, &g:makeprg, &errorformat " TLogVAR make_def let defs.make_defs = get(make_def, 'alternatives', {'*': make_def}) return defs endf function! s:CompareIssues(i1, i2) "{{{3 let l1 = get(a:i1, 'lnum', 0) let l2 = get(a:i2, 'lnum', 0) " TLogVAR l1, l2, type(l1), type(l2) return l1 == l2 ? 0 : l1 > l2 ? 1 : -1 endf function! s:WithCompiler(compiler, exec, default) "{{{3 if exists('g:current_compiler') let cc = g:current_compiler else let cc = '' endif try exec 'compiler '. a:compiler exec a:exec finally if cc != '' let g:current_compiler = cc exec 'compiler '. cc endif endtry return a:default endf function! s:RunSyncChecker(filetype, make_def) let bufnr = bufnr('%') let pos = getpos('.') let type = get(a:make_def, 'listtype', 'loc') try if has_key(a:make_def, 'compiler') " <+TODO+> Use s:ExtractCompilerParams and run s:RunSyncWithEFM let args = get(a:make_def, 'compiler_args', '%') let rv = s:WithCompiler(a:make_def.compiler, \ 'call g:checksyntax#prototypes[type].Make('. string(args) .')', \ 1) else let rv = s:RunSyncWithEFM(a:make_def) endif " TLogVAR rv return rv catch echohl Error echom "Exception" v:exception "from" v:throwpoint echom v:errmsg echohl NONE finally " TLogVAR pos, bufnr if bufnr != bufnr('%') exec bufnr 'buffer' endif call setpos('.', pos) endtry return 0 endf function! s:Run_async(make_def) "{{{3 " TLogVAR a:make_def let make_def = a:make_def let cmd = '' if has_key(make_def, 'cmd') let cmd = get(make_def, 'cmd', '') " let cmd .= ' '. shellescape(make_def.filename) if has_key(a:make_def, 'cmd_args') let cmddef = s:ExtractCompilerParams(a:make_def, '', a:make_def.cmd) let cmd = cmddef.cmd else let cmd .= ' '. escape(make_def.filename, '"''\ ') endif elseif has_key(make_def, 'compiler') let compiler_def = s:WithCompiler(make_def.compiler, \ 'return s:ExtractCompilerParams('. string(a:make_def) .', "")', \ {}) " TLogVAR compiler_def if !empty(compiler_def) let cmd = compiler_def.cmd let make_def.efm = compiler_def.efm endif endif " TLogVAR cmd if !empty(cmd) try let cmd = s:NativeCmd(cmd) " TLogVAR cmd let rv = checksyntax#async#{g:checksyntax#async_runner}#Run(cmd, make_def) call checksyntax#AddJob(make_def) return rv catch /^Vim\%((\a\+)\)\=:E117/ echohl Error echom 'Checksyntax: Unsupported value for g:checksyntax#async_runner: '. string(g:checksyntax#async_runner) echohl NONE let g:checksyntax#async_runner = '' return 0 endtry else echohl WarningMsg echom "CheckSyntax: Cannot run asynchronously: ". make_def.name echohl NONE return 0 endif endf function! s:ReplaceMakeArgs(make_def, cmd, args) "{{{3 let cmd = a:cmd if !empty(a:args) && stridx(cmd, '$*') == -1 let cmd .= ' '. a:args endif let replaced = [] if stridx(cmd, '%') != -1 let cmd = substitute(cmd, '%\(\%(:[phtre]\)\+\)\?', '\=s:Filename(a:make_def, "%", submatch(1))', 'g') call add(replaced, '%') endif if stridx(cmd, '$*') != -1 if index(replaced, '%') == -1 let cmd = substitute(cmd, '\V$*', a:args .' '. escape(a:make_def['filename'], '\'), 'g') call add(replaced, '%') else let cmd = substitute(cmd, '\V$*', a:args, 'g') endif call add(replaced, '$*') endif if stridx(cmd, '#') != -1 let cmd = substitute(cmd, '#\(\%(:[phtre]\)\+\)\?', '\=s:Filename(a:make_def, "#", submatch(1))', 'g') call add(replaced, '#') endif return cmd endf function! s:Filename(make_def, type, mod) "{{{3 if a:type == '%' let filename = a:make_def.filename elseif a:type == '#' let filename = a:make_def.altname else throw "CheckSyntax/s:Filename: Internal error: type = ". a:type endif if !empty(a:mod) let filename = fnamemodify(filename, a:mod) endif return escape(filename, '\') endf function! s:ExtractCompilerParams(make_def, args, ...) "{{{3 let cmd = a:0 >= 1 ? a:1 : &makeprg let args = get(a:make_def, 'compiler_args', a:args) let cmd = s:ReplaceMakeArgs(a:make_def, cmd, args) let compiler_def = { \ 'cmd': cmd, \ 'efm': &errorformat \ } " TLogVAR compiler_def return compiler_def endf let s:status_expr = 'checksyntax#Status()' function! checksyntax#AddJob(make_def) "{{{3 let s:async_pending[a:make_def.job_id] = a:make_def if exists('g:tstatus_exprs') if index(g:tstatus_exprs, s:status_expr) == -1 call add(g:tstatus_exprs, s:status_expr) endif endif endf function! checksyntax#RemoveJob(job_id) "{{{3 let rv = has_key(s:async_pending, a:job_id) if rv call remove(s:async_pending, a:job_id) if empty(s:async_pending) && exists('g:tstatus_exprs') let idx = index(g:tstatus_exprs, s:status_expr) if idx != -1 call remove(g:tstatus_exprs, idx) endif endif endif return rv ? len(s:async_pending) : -1 endf function! checksyntax#Status() "{{{3 let n = len(s:async_pending) if n == 0 return '' else return 'PendingChecks='. n endif endf function! s:Run_sync(name, filetype, make_def) "{{{3 " TLogVAR a:name, a:filetype, a:make_def let make_def = a:make_def if has_key(make_def, 'include') let include = s:GetDef(make_def.include) if !empty(include) let make_def = extend(copy(make_def), include, 'keep') endif endif exec get(make_def, 'prepare', '') if s:RunSyncChecker(a:filetype, make_def) let type = get(make_def, 'listtype', 'loc') call g:checksyntax#issues.AddList(a:name, make_def, type) return 1 else return 0 endif endf function! checksyntax#GetList(name, make_def, type) "{{{3 " TLogVAR a:type let list = g:checksyntax#prototypes[a:type].Get() " TLogVAR list " TLogVAR 1, len(list), has_key(a:make_def, 'process_list') if !empty(list) && has_key(a:make_def, 'process_list') " TLogVAR a:make_def.process_list let list = call(a:make_def.process_list, [list]) " TLogVAR 2, len(list) endif if !empty(list) let list = filter(list, 's:FilterItem(a:make_def, v:val)') " TLogVAR 3, len(list) " TLogVAR a:type, list if !empty(list) let list = map(list, 's:CompleteItem(a:name, a:make_def, v:val)') " TLogVAR 4, len(list) " TLogVAR a:type, list endif endif " TLogVAR "return", list return list endf function! s:CompleteItem(name, make_def, val) "{{{3 " TLogVAR a:name, a:make_def, a:val if get(a:val, 'bufnr', 0) == 0 let a:val.bufnr = bufnr('%') endif let text = get(a:val, 'text', '') let a:val.text = substitute(text, '^\s\+\|\s\+$', '', 'g') let type = get(a:val, 'type', '') if !empty(type) let a:val.text = printf('[%s] %s', type, a:val.text) endif if !empty(a:name) let text = get(a:val, 'text', '') if !empty(text) let a:val.text = a:name .': '. text endif endif " TLogVAR a:val return a:val endf function! s:FilterItem(make_def, val) "{{{3 if a:val.lnum == 0 && a:val.pattern == '' return 0 elseif has_key(a:val, 'nr') && has_key(a:make_def, 'ignore_nr') && index(a:make_def.ignore_nr, a:val.nr) != -1 return 0 elseif has_key(a:make_def, 'buffers') let buffers = a:make_def.buffers if buffers == 'listed' && !buflisted(a:val.bufnr) return 0 elseif buffers == 'current' && a:val.bufnr != a:make_def.bufnr return 0 endif endif return 1 endf function! checksyntax#NullOutput(flag) "{{{3 if empty(g:checksyntax#null) return '' else return a:flag .' '. g:checksyntax#null endif endf " If cmd seems to be a cygwin executable, use cygpath to convert " filenames. This assumes that cygwin's which command returns full " filenames for non-cygwin executables. function! checksyntax#MaybeUseCygpath(cmd) "{{{3 " echom "DBG" a:cmd if g:checksyntax#check_cygpath && s:CygwinBin(a:cmd) return 'cygpath -u %s' endif return '' endf autoload/checksyntax/pmd.vim [[[1 37 " @Author: Tom Link (mailto:micathom AT gmail com?subject=[vim]) " @License: GPL (see http://www.gnu.org/licenses/gpl.txt) " @Revision: 13 if !exists('g:checksyntax#pmd#cmd') " The command to run pmd. let g:checksyntax#pmd#cmd = '' "{{{2 endif if !exists('g:checksyntax#pmd#args') let g:checksyntax#pmd#args = '-f text' "{{{2 endif function! checksyntax#pmd#Cmd(language, args, rulesets) "{{{3 if empty(g:checksyntax#pmd#cmd) return '' else let args = [g:checksyntax#pmd#args, a:args, '-l', a:language] if !exists('b:checksyntax_project_dir') if exists('b:project_dir') let b:checksyntax_project_dir = b:project_dir else let b:checksyntax_project_dir = expand('%:h') endif endif call add(args, '-d '. shellescape(b:checksyntax_project_dir)) let rulesets = join(map(copy(a:rulesets), 'a:language ."-". v:val'), ',') let args += ['-R', rulesets] return printf("%s %s", \ g:checksyntax#pmd#cmd, \ join(args)) endif endf