diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 764ffff..378b53b 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -1,49 +1,105 @@ -# Bug reports / Github issues +# CONTRIBUTING +- - - +1\. [Bug reports / GitHub issues](#bugreps) +2\. [Submitting a patch](#patches) +3\. [General style notes](#generalstyle) +4\. [Syntax checker notes](#checkerstyle) +- - - -When reporting a bug make sure you search the existing github issues for the -same/similar issues. If you find one, feel free to add a `+1` comment with any -additional information that may help us solve the issue. + + +## 1. Bug reports / GitHub issues + +Please note that the preferred channel for posting bug reports is the +[issue tracker at GitHub][0]. Reports posted elsewhere are less likely +to be seen by the core team. + +When reporting a bug make sure you search the existing GitHub issues +for the same/similar issues. If you find one, feel free to add a `+1` +comment with any additional information that may help us solve the +issue. When creating a new issue be sure to state the following: -* Steps to reproduce the bug. -* The version of vim you are using. -* The version of syntastic you are using. +* steps to reproduce the bug; +* the version of Vim you are using (run `:ver` to find out); +* the version of syntastic you are using (see `:SyntasticInfo`). + +For syntax checker bugs also state the version of the checker executable +that you are using. Adding debugging information is typically useful +too: + +* open a file handled by your checker; +* set `g:syntastic_debug` to 1 or 3; +* run the checker; +* copy the output of `:mes`. + + + +## 2. Submitting a patch -For syntax checker bugs also state the version of the checker executable that you are using. +Before you consider adding features to syntastic, _please_ spend a few +minutes (re-)reading the latest version of the [manual][1]. Syntastic +is changing rapidly at times, and it's quite possible that some of the +features you want to add exist already. -# Submitting a patch +To submit a patch: -* Fork the repo on github -* Make a [topic branch](https://github.com/dchelimsky/rspec/wiki/Topic-Branches#using-topic-branches-when-contributing-patches) and start hacking -* Submit a pull request based off your topic branch +* fork the [repo][2] on GitHub; +* make a [topic branch][3] and start hacking; +* submit a pull request based off your topic branch. -Small focused patches are preferred. +Small, focused patches are preferred. -Large changes to the code should be discussed with the core team first. Create an issue and explain your plan and see what we say. +Large changes to the code should be discussed with the core team first. +Create an issue and explain your plan and see what we say. -# General style notes +Also make sure to update the manual whenever applicable. Nobody can use +features that aren't documented. -Following the coding conventions/styles used in the syntastic core: + -* Use 4 space indents. -* Don't use abbreviated keywords - e.g. use `endfunction`, not `endfun` (there's always room for more fun!). -* Don't use `l:` prefixes for variables unless actually required (i.e. almost never). -* Code for maintainability. We would rather a function be a couple of lines longer and have (for example) some [explaining variables](http://www.refactoring.com/catalog/introduceExplainingVariable.html) to aid readability. +## 3. General style notes -# Syntax checker style notes +Follow the coding conventions/styles used in the syntastic core: -The preferred style for error format strings is one "clause" per line. E.g. -(from the coffeelint checker): +* use 4 space indents; +* don't use abbreviated keywords - e.g. use `endfunction`, not `endfun` +(there's always room for more fun!); +* don't use `l:` prefixes for variables unless actually required (i.e. +almost never); +* code for maintainability; we would rather a function be a couple of +lines longer and have (for example) some [explaining variables][4] to +aid readability. -```viml -let errorformat = '%E%f:%l:%c: %trror: %m,' . - \ 'Syntax%trror: In %f\, %m on line %l,' . - \ '%EError: In %f\, Parse error on line %l: %m,' . - \ '%EError: In %f\, %m on line %l,' . - \ '%W%f(%l): lint warning: %m,' . - \ '%W%f(%l): warning: %m,' . - \ '%E%f(%l): SyntaxError: %m,' . - \ '%-Z%p^,' . - \ '%-G%.%#' + + +## 4. Syntax checker notes + +Make sure to read the [guide][5] if you plan to add new syntax checkers. + +Use the existing checkers as templates, rather than writing everything +from scratch. + +The preferred style for error format strings is one "clause" per line. +E.g. (from the `coffee` checker): + +```vim +let errorformat = + \ '%E%f:%l:%c: %trror: %m,' . + \ 'Syntax%trror: In %f\, %m on line %l,' . + \ '%EError: In %f\, Parse error on line %l: %m,' . + \ '%EError: In %f\, %m on line %l,' . + \ '%W%f(%l): lint warning: %m,' . + \ '%W%f(%l): warning: %m,' . + \ '%E%f(%l): SyntaxError: %m,' . + \ '%-Z%p^,' . + \ '%-G%.%#' ``` + +[0]: https://github.com/scrooloose/syntastic/issues +[1]: https://github.com/scrooloose/syntastic/blob/master/doc/syntastic.txt +[2]: https://github.com/scrooloose/syntastic +[3]: https://github.com/dchelimsky/rspec/wiki/Topic-Branches#using-topic-branches-when-contributing-patches +[4]: http://www.refactoring.com/catalog/extractVariable.html +[5]: https://github.com/scrooloose/syntastic/wiki/Syntax-Checker-Guide diff --git a/README.markdown b/README.markdown index 04effa5..d0eb41f 100644 --- a/README.markdown +++ b/README.markdown @@ -35,15 +35,16 @@ the user is notified and is happy because they didn't have to compile their code or execute their script to find them. At the time of this writing, syntax checking plugins exist for ActionScript, -Ada, AppleScript, AsciiDoc, ASM, BEMHTML, Bourne shell, C, C++, C#, Chef, -CoffeeScript, Coco, Coq, CSS, Cucumber, CUDA, D, Dart, DocBook, Dust, Elixir, -Erlang, eRuby, Fortran, Gentoo metadata, GLSL, Go, Haml, Haskell, Haxe, -Handlebars, HSS, HTML, Java, JavaScript, JSON, LESS, Lex, Limbo, LISP, -LLVM intermediate language, Lua, MATLAB, NASM, Objective-C, Objective-C++, -OCaml, Perl, Perl POD, PHP, gettext Portable Object, Puppet, Python, Racket, -reStructuredText, Ruby, Rust, SASS/SCSS, Scala, Slim, Tcl, TeX, Texinfo, Twig, -TypeScript, Vala, Verilog, VHDL, VimL, xHtml, XML, XSLT, YACC, YAML, z80, Zope -page templates, zsh. +Ada, AppleScript, Arduino, AsciiDoc, ASM, BEMHTML, Bro, Bourne shell, C, +C++, C#, Cabal, Chef, CoffeeScript, Coco, Coq, CSS, Cucumber, CUDA, D, Dart, +DocBook, Dust, Elixir, Erlang, eRuby, Fortran, Gentoo metadata, GLSL, Go, +Haml, Haskell, Haxe, Handlebars, HSS, HTML, Java, JavaScript, JSON, JSX, LESS, +Lex, Limbo, LISP, LLVM intermediate language, Lua, MATLAB, NASM, Objective-C, +Objective-C++, OCaml, Perl, Perl POD, PHP, gettext Portable Object, OS X +and iOS property lists, Puppet, Python, Racket, R, reStructuredText, Ruby, +SASS/SCSS, Scala, Slim, Tcl, TeX, Texinfo, Twig, TypeScript, Vala, Verilog, +VHDL, VimL, xHtml, XML, XSLT, YACC, YAML, z80, Zope page templates, and zsh. +See the [wiki][3] for details about the corresponding supported checkers. Below is a screenshot showing the methods that Syntastic uses to display syntax errors. Note that, in practise, you will only have a subset of these methods @@ -62,45 +63,47 @@ enabled. ## 2\. Installation -Installing syntastic is easy but first you need to have the pathogen plugin installed. If you already -have pathogen working then skip Step 1 and go to Step 2. +Installing syntastic is easy but first you need to have the [pathogen][1] +plugin installed. If you already have [pathogen][1] working then skip +[Step 1](#step1) and go to [Step 2](#step2). + ### 2.1\. Step 1: Install pathogen.vim -First I'll show you how to install tpope's [pathogen.vim][1] so that it's -easy to install syntastic. Do this in your Terminal so that you get the -pathogen.vim file and the directories it needs: - - mkdir -p ~/.vim/autoload ~/.vim/bundle; \ - curl -so ~/.vim/autoload/pathogen.vim \ - https://raw.github.com/tpope/vim-pathogen/master/autoload/pathogen.vim - -Next you *need to add this* to your ~/.vimrc: - - execute pathogen#infect() +First I'll show you how to install Tim Pope's [pathogen][1] so that it's easy to +install syntastic. Do this in your terminal so that you get the `pathogen.vim` +file and the directories it needs: +```sh +mkdir -p ~/.vim/autoload ~/.vim/bundle && \ +curl -LSso ~/.vim/autoload/pathogen.vim https://tpo.pe/pathogen.vim +``` +Next you *need* to add this to your `~/.vimrc`: +```vim +execute pathogen#infect() +``` ### 2.2\. Step 2: Install syntastic as a pathogen bundle -You now have pathogen installed and can put syntastic into ~/.vim/bundle like this: - - - cd ~/.vim/bundle - git clone https://github.com/scrooloose/syntastic.git - +You now have pathogen installed and can put syntastic into `~/.vim/bundle` like +this: +```sh +cd ~/.vim/bundle && \ +git clone https://github.com/scrooloose/syntastic.git +``` Quit vim and start it back up to reload it, then type: +```vim +:Helptags +``` +If you get an error when you do this, then you probably didn't install +[pathogen][1] right. Go back to [Step 1](#step1) and make sure you did the following: - :Helptags - -If you get an error when you do this, then you probably didn't install pathogen right. Go back to -step 1 and make sure you did the following: - -1. Created both the ~/.vim/autoload and ~/.vim/bundle directories. -2. Added the "call pathogen#infect()" line to your ~/.vimrc file -3. Did the git clone of syntastic inside ~/.vim/bundle +1. Created both the `~/.vim/autoload` and `~/.vim/bundle` directories. +2. Added the `call pathogen#infect()` line to your `~/.vimrc` file +3. Did the `git clone` of syntastic inside `~/.vim/bundle` 4. Have permissions to access all of these directories. @@ -108,91 +111,130 @@ step 1 and make sure you did the following: ## 3\. FAQ + + __Q. I installed syntastic but it isn't reporting any errors...__ A. The most likely reason is that none of the syntax checkers that it requires -is installed. For example: python requires either `flake8`, `pyflakes` -or `pylint` to be installed and in `$PATH`. To see which executables are -supported, just look in `syntax_checkers//*.vim`. Note that aliases -do not work; the actual executable must be available in your `$PATH`. Symbolic -links are okay. You can see syntastic's idea of available checkers by running -`:SyntasticInfo`. +is installed. For example: by default, python requires either `flake8` or +`pylint` to be installed and in your `$PATH`. To see which executables are +supported, look at the [wiki][3]. Note that aliases do not work; the actual +executables must be available in your `$PATH`. Symbolic links are okay though. +You can see syntastic's idea of available checkers by running `:SyntasticInfo`. Another reason it could fail is that either the command line options or the error output for a syntax checker may have changed. In this case, make sure you have the latest version of the syntax checker installed. If it still fails then create an issue - or better yet, create a pull request. -__Q. Recently some of my syntax checker options have stopped working...__ + + +__Q. The `perl` checker has stopped working...__ -A. The options are still there, they have just been renamed. Recently, -almost all syntax checkers were refactored to use the new `makeprgBuild()` -function. This made a lot of the old explicit options redundant - as they are -now implied. The new implied options usually have slightly different names to -the old options. +A. The `perl` checker runs `perl -c` against your file, which in turn +__executes__ any `BEGIN`, `UNITCHECK`, and `CHECK` blocks, and any `use` +statements in your file (cf. [perlrun][10]). This is probably fine if you +wrote the file yourself, but it's a security problem if you're checking third +party files. Since there is currently no way to disable this behaviour while +still producing useful results, the checker is now disabled by default. To +(re-)enable it, make sure the `g:syntastic_perl_checkers` list includes `perl`, +and set `g:syntastic_enable_perl_checker` to 1 in your vimrc: +```vim +let g:syntastic_enable_perl_checker = 1 +``` -e.g. Previously there was `g:syntastic_phpcs_conf`, now you must use -`g:syntastic_php_phpcs_args`. This completely overrides the arguments of -the checker, including any defaults, so you may need to look up the default -arguments of the checker and add these in. + -See `:help syntastic-checker-options` for more information. +__Q. What happened to the `rustc` checker?__ + +A. It has been included in the [Rust compiler package][12]. If you have +a recent version of the Rust compiler, the checker should be picked up +automatically by syntastic. + + __Q. I run a checker and the location list is not updated...__ -A. By default, the location list is changed only when you run the `:Errors` +A. By default the location list is changed only when you run the `:Errors` command, in order to minimise conflicts with other plugins. If you want the location list to always be updated when you run the checkers, add this line to your vimrc: ```vim -let g:syntastic_always_populate_loc_list=1 +let g:syntastic_always_populate_loc_list = 1 ``` + + __Q. How can I pass additional arguments to a checker?__ A. Almost all syntax checkers use the `makeprgBuild()` function. Those checkers that do can be configured using global variables. The general form of the -global args variables are: -```vim -syntastic___args -``` +global `args` variables is `syntastic___args`. So, If you wanted to pass "--my --args --here" to the ruby mri checker you would add this line to your vimrc: ```vim -let g:syntastic_ruby_mri_args="--my --args --here" +let g:syntastic_ruby_mri_args = "--my --args --here" ``` See `:help syntastic-checker-options` for more information. + + __Q. Syntastic supports several checkers for my filetype - how do I tell it which one(s) to use?__ A. Stick a line like this in your vimrc: ```vim -let g:syntastic__checkers=[''] +let g:syntastic__checkers = [''] ``` -To see the list of checkers for your filetype, look in -`syntax_checkers//`. +To see the list of supported checkers for your filetype look at the +[wiki][3]. -e.g. Python has the following checkers: `flake8`, `pyflakes`, `pylint` and a -native `python` checker. +e.g. Python has the following checkers, among others: `flake8`, `pyflakes`, +`pylint` and a native `python` checker. To tell syntastic to use `pylint`, you would use this setting: ```vim -let g:syntastic_python_checkers=['pylint'] +let g:syntastic_python_checkers = ['pylint'] ``` Some filetypes, like PHP, have style checkers as well as syntax checkers. These can be chained together like this: ```vim -let g:syntastic_php_checkers=['php', 'phpcs', 'phpmd'] +let g:syntastic_php_checkers = ['php', 'phpcs', 'phpmd'] ``` This is telling syntastic to run the `php` checker first, and if no errors are found, run `phpcs`, and then `phpmd`. +You can also run checkers explicitly by calling `:SyntasticCheck `. + +e.g. to run `phpcs` and `phpmd`: +```vim +:SyntasticCheck phpcs phpmd +``` + +This works for any checkers available for the current filetype, even if they +aren't listed in `g:syntastic__checkers`. You can't run checkers for +"foreign" filetypes though (e.g. you can't run, say, a Python checker if the +current filetype is `php`). + + + +__Q. How can I display together the errors found by all checkers enabled for +the current file?__ + +A. Set `g:syntastic_aggregate_errors` to 1 in your vimrc: +```vim +let g:syntastic_aggregate_errors = 1 +``` + +See `:help syntastic-aggregating-errors` for more details. + + + __Q. How can I jump between the different errors without using the location list at the bottom of the window?__ @@ -203,6 +245,8 @@ If you use these commands a lot then you may want to add shortcut mappings to your vimrc, or install something like [unimpaired][2], which provides such mappings (among other things). + + __Q. A syntax checker is giving me unwanted/strange style tips?__ A. Some filetypes (e.g. php) have style checkers as well as syntax @@ -210,6 +254,15 @@ checkers. You can usually configure the options that are passed to the style checkers, or just disable them. Take a look at the [wiki][3] to see what options are available. +Alternatively, you can use `g:syntastic_quiet_messages` to filter out the +messages you don't want to see. e.g. To turn off all style messages: +```vim +let g:syntastic_quiet_messages = { "type": "style" } +``` +See `:help syntastic_quiet_messages` for details. + + + __Q. The error window is closed automatically when I :quit the current buffer but not when I :bdelete it?__ @@ -227,8 +280,10 @@ cabbrev bd lclose\|bdelete ## 4\. Other resources The preferred place for posting suggestions, reporting bugs, and general -discussions related to syntastic is the [issue tracker at GitHub][4]. There -are also a [google group][5], and a [syntastic tag at StackOverflow][6]. +discussions related to syntastic is the [issue tracker at GitHub][4]. +A guide for writing syntax checkers can be found in the [wiki][11]. +There are also a dedicated [google group][5], and a +[syntastic tag at StackOverflow][6]. Syntastic aims to provide a common interface to syntax checkers for as many languages as possible. For particular languages, there are, of course, other @@ -244,4 +299,7 @@ a look at [jedi-vim][7], [python-mode][8], or [YouCompleteMe][9]. [6]: http://stackoverflow.com/questions/tagged/syntastic [7]: https://github.com/davidhalter/jedi-vim [8]: https://github.com/klen/python-mode -[9]: https://github.com/Valloric/YouCompleteMe +[9]: http://valloric.github.io/YouCompleteMe/ +[10]: http://perldoc.perl.org/perlrun.html#*-c* +[11]: https://github.com/scrooloose/syntastic/wiki/Syntax-Checker-Guide +[12]: https://github.com/rust-lang/rust/ diff --git a/autoload/syntastic/c.vim b/autoload/syntastic/c.vim index 82f4c70..5dad140 100644 --- a/autoload/syntastic/c.vim +++ b/autoload/syntastic/c.vim @@ -1,4 +1,4 @@ -if exists("g:loaded_syntastic_c_autoload") +if exists("g:loaded_syntastic_c_autoload") || !exists("g:loaded_syntastic_plugin") finish endif let g:loaded_syntastic_c_autoload = 1 @@ -10,14 +10,14 @@ set cpo&vim " convenience function to determine the 'null device' parameter " based on the current operating system -function! syntastic#c#NullOutput() +function! syntastic#c#NullOutput() " {{{2 let known_os = has('unix') || has('mac') || syntastic#util#isRunningWindows() return known_os ? '-o ' . syntastic#util#DevNull() : '' -endfunction +endfunction " }}}2 " read additional compiler flags from the given configuration file " the file format and its parsing mechanism is inspired by clang_complete -function! syntastic#c#ReadConfig(file) +function! syntastic#c#ReadConfig(file) " {{{2 " search in the current file's directory upwards let config = findfile(a:file, '.;') if config == '' || !filereadable(config) @@ -30,7 +30,7 @@ function! syntastic#c#ReadConfig(file) " try to read config file try let lines = readfile(config) - catch /^Vim\%((\a\+)\)\=:E48[45]/ + catch /\m^Vim\%((\a\+)\)\=:E48[45]/ return '' endtry @@ -57,12 +57,12 @@ function! syntastic#c#ReadConfig(file) endfor return join(map(parameters, 'syntastic#util#shescape(v:val)')) -endfunction +endfunction " }}}2 " GetLocList() for C-like compilers -function! syntastic#c#GetLocList(filetype, subchecker, options) +function! syntastic#c#GetLocList(filetype, subchecker, options) " {{{2 try - let flags = s:GetCflags(a:filetype, a:subchecker, a:options) + let flags = s:_getCflags(a:filetype, a:subchecker, a:options) catch /\m\C^Syntastic: skip checks$/ return [] endtry @@ -70,9 +70,9 @@ function! syntastic#c#GetLocList(filetype, subchecker, options) let makeprg = syntastic#util#shexpand(g:syntastic_{a:filetype}_compiler) . \ ' ' . flags . ' ' . syntastic#util#shexpand('%') - let errorformat = s:GetCheckerVar('g', a:filetype, a:subchecker, 'errorformat', a:options['errorformat']) + let errorformat = s:_getCheckerVar('g', a:filetype, a:subchecker, 'errorformat', a:options['errorformat']) - let postprocess = s:GetCheckerVar('g', a:filetype, a:subchecker, 'remove_include_errors', 0) ? + let postprocess = s:_getCheckerVar('g', a:filetype, a:subchecker, 'remove_include_errors', 0) ? \ ['filterForeignErrors'] : [] " process makeprg @@ -80,34 +80,45 @@ function! syntastic#c#GetLocList(filetype, subchecker, options) \ 'makeprg': makeprg, \ 'errorformat': errorformat, \ 'postprocess': postprocess }) -endfunction +endfunction " }}}2 + +" }}}1 " Private functions {{{1 " initialize c/cpp syntax checker handlers -function! s:Init() +function! s:_init() " {{{2 let s:handlers = [] let s:cflags = {} - call s:RegHandler('\m\', 'syntastic#c#CheckPhp', []) - call s:RegHandler('\m\', 'syntastic#c#CheckPython', []) - call s:RegHandler('\m\', 'syntastic#c#checkPHP', []) + call s:_regHandler('\m\', 'syntastic#c#checkPython', []) + call s:_regHandler('\m\" echohl ErrorMsg echomsg "syntastic: error: " . a:msg echohl None -endfunction +endfunction " }}}2 -function! syntastic#log#deprecationWarn(msg) - if index(s:deprecation_notices_issued, a:msg) >= 0 +function! syntastic#log#oneTimeWarn(msg) " {{{2 + if index(s:one_time_notices_issued, a:msg) >= 0 return endif - call add(s:deprecation_notices_issued, a:msg) + call add(s:one_time_notices_issued, a:msg) call syntastic#log#warn(a:msg) -endfunction +endfunction " }}}2 + +" @vimlint(EVL102, 1, l:OLD_VAR) +function! syntastic#log#deprecationWarn(old, new, ...) " {{{2 + if exists('g:syntastic_' . a:old) && !exists('g:syntastic_' . a:new) + let msg = 'variable g:syntastic_' . a:old . ' is deprecated, please use ' -function! syntastic#log#debug(level, msg, ...) + if a:0 + let OLD_VAR = g:syntastic_{a:old} + try + let NEW_VAR = eval(a:1) + let msg .= 'in its stead: let g:syntastic_' . a:new . ' = ' . string(NEW_VAR) + let g:syntastic_{a:new} = NEW_VAR + catch + let msg .= 'g:syntastic_' . a:new . ' instead' + endtry + else + let msg .= 'g:syntastic_' . a:new . ' instead' + let g:syntastic_{a:new} = g:syntastic_{a:old} + endif + + call syntastic#log#oneTimeWarn(msg) + endif +endfunction " }}}2 +" @vimlint(EVL102, 0, l:OLD_VAR) + +function! syntastic#log#debug(level, msg, ...) " {{{2 if !s:isDebugEnabled(a:level) return endif - let leader = s:logTimestamp() - call s:logRedirect(1) + let leader = s:_logTimestamp() + call s:_logRedirect(1) if a:0 > 0 " filter out dictionary functions @@ -83,68 +77,74 @@ function! syntastic#log#debug(level, msg, ...) echomsg leader . a:msg endif - call s:logRedirect(0) -endfunction + call s:_logRedirect(0) +endfunction " }}}2 -function! syntastic#log#debugShowOptions(level, names) +function! syntastic#log#debugShowOptions(level, names) " {{{2 if !s:isDebugEnabled(a:level) return endif - let leader = s:logTimestamp() - call s:logRedirect(1) + let leader = s:_logTimestamp() + call s:_logRedirect(1) - let vlist = type(a:names) == type("") ? [a:names] : a:names + let vlist = copy(type(a:names) == type("") ? [a:names] : a:names) if !empty(vlist) - call map(copy(vlist), "'&' . v:val . ' = ' . strtrans(string(eval('&' . v:val)))") + call map(vlist, "'&' . v:val . ' = ' . strtrans(string(eval('&' . v:val)))") echomsg leader . join(vlist, ', ') endif - call s:logRedirect(0) -endfunction + call s:_logRedirect(0) +endfunction " }}}2 -function! syntastic#log#debugShowVariables(level, names) +function! syntastic#log#debugShowVariables(level, names) " {{{2 if !s:isDebugEnabled(a:level) return endif - let leader = s:logTimestamp() - call s:logRedirect(1) + let leader = s:_logTimestamp() + call s:_logRedirect(1) let vlist = type(a:names) == type("") ? [a:names] : a:names for name in vlist - echomsg leader . s:formatVariable(name) + let msg = s:_formatVariable(name) + if msg != '' + echomsg leader . msg + endif endfor - call s:logRedirect(0) -endfunction + call s:_logRedirect(0) +endfunction " }}}2 -function! syntastic#log#debugDump(level) +function! syntastic#log#debugDump(level) " {{{2 if !s:isDebugEnabled(a:level) return endif - call syntastic#log#debugShowVariables(a:level, s:global_options) -endfunction + call syntastic#log#debugShowVariables( a:level, sort(keys(g:syntastic_defaults)) ) +endfunction " }}}2 + +" }}}1 " Private functions {{{1 -function! s:isDebugEnabled_smart(level) +function! s:_isDebugEnabled_smart(level) " {{{2 return and(g:syntastic_debug, a:level) -endfunction +endfunction " }}}2 -function! s:isDebugEnabled_dumb(level) +function! s:_isDebugEnabled_dumb(level) " {{{2 " poor man's bit test for bit N, assuming a:level == 2**N return (g:syntastic_debug / a:level) % 2 -endfunction +endfunction " }}}2 -let s:isDebugEnabled = function(exists('*and') ? 's:isDebugEnabled_smart' : 's:isDebugEnabled_dumb') +let s:isDebugEnabled = function(exists('*and') ? 's:_isDebugEnabled_smart' : 's:_isDebugEnabled_dumb') +lockvar s:isDebugEnabled -function! s:logRedirect(on) +function! s:_logRedirect(on) " {{{2 if exists("g:syntastic_debug_file") if a:on try execute 'redir >> ' . fnameescape(expand(g:syntastic_debug_file)) - catch /^Vim\%((\a\+)\)\=:/ + catch /\m^Vim\%((\a\+)\)\=:/ silent! redir END unlet g:syntastic_debug_file endtry @@ -152,30 +152,27 @@ function! s:logRedirect(on) silent! redir END endif endif -endfunction +endfunction " }}}2 -function! s:logTimestamp_smart() +function! s:_logTimestamp() " {{{2 return 'syntastic: ' . split(reltimestr(reltime(g:syntastic_start)))[0] . ': ' -endfunction +endfunction " }}}2 -function! s:logTimestamp_dumb() - return 'syntastic: debug: ' -endfunction - -let s:logTimestamp = function(has('reltime') ? 's:logTimestamp_smart' : 's:logTimestamp_dumb') - -function! s:formatVariable(name) +function! s:_formatVariable(name) " {{{2 let vals = [] - if exists('g:' . a:name) - call add(vals, 'g:' . a:name . ' = ' . strtrans(string(g:{a:name}))) + if exists('g:syntastic_' . a:name) + call add(vals, 'g:syntastic_' . a:name . ' = ' . strtrans(string(g:syntastic_{a:name}))) endif - if exists('b:' . a:name) - call add(vals, 'b:' . a:name . ' = ' . strtrans(string(b:{a:name}))) + if exists('b:syntastic_' . a:name) + call add(vals, 'b:syntastic_' . a:name . ' = ' . strtrans(string(b:syntastic_{a:name}))) endif return join(vals, ', ') -endfunction +endfunction " }}}2 + +" }}}1 let &cpo = s:save_cpo unlet s:save_cpo -" vim: set et sts=4 sw=4 fdm=marker: + +" vim: set sw=4 sts=4 et fdm=marker: diff --git a/autoload/syntastic/postprocess.vim b/autoload/syntastic/postprocess.vim index 877bb50..65570d9 100644 --- a/autoload/syntastic/postprocess.vim +++ b/autoload/syntastic/postprocess.vim @@ -1,4 +1,4 @@ -if exists("g:loaded_syntastic_postprocess_autoload") +if exists("g:loaded_syntastic_postprocess_autoload") || !exists("g:loaded_syntastic_plugin") finish endif let g:loaded_syntastic_postprocess_autoload = 1 @@ -6,38 +6,23 @@ let g:loaded_syntastic_postprocess_autoload = 1 let s:save_cpo = &cpo set cpo&vim -function! s:compareErrorItems(a, b) - if a:a['bufnr'] != a:b['bufnr'] - " group by files - return a:a['bufnr'] - a:b['bufnr'] - elseif a:a['lnum'] != a:b['lnum'] - return a:a['lnum'] - a:b['lnum'] - elseif a:a['type'] !=? a:b['type'] - " errors take precedence over warnings - return a:a['type'] ==? 'e' ? -1 : 1 - else - return get(a:a, 'col', 0) - get(a:b, 'col', 0) - endif -endfunction - -" natural sort -function! syntastic#postprocess#sort(errors) - return sort(copy(a:errors), 's:compareErrorItems') -endfunction +" Public functions {{{1 " merge consecutive blanks -function! syntastic#postprocess#compressWhitespace(errors) +function! syntastic#postprocess#compressWhitespace(errors) " {{{2 for e in a:errors let e['text'] = substitute(e['text'], "\001", '', 'g') let e['text'] = substitute(e['text'], '\n', ' ', 'g') let e['text'] = substitute(e['text'], '\m\s\{2,}', ' ', 'g') + let e['text'] = substitute(e['text'], '\m^\s\+', '', '') + let e['text'] = substitute(e['text'], '\m\s\+$', '', '') endfor return a:errors -endfunction +endfunction " }}}2 " remove spurious CR under Cygwin -function! syntastic#postprocess#cygwinRemoveCR(errors) +function! syntastic#postprocess#cygwinRemoveCR(errors) " {{{2 if has('win32unix') for e in a:errors let e['text'] = substitute(e['text'], '\r', '', 'g') @@ -45,23 +30,25 @@ function! syntastic#postprocess#cygwinRemoveCR(errors) endif return a:errors -endfunction +endfunction " }}}2 " decode XML entities -function! syntastic#postprocess#decodeXMLEntities(errors) +function! syntastic#postprocess#decodeXMLEntities(errors) " {{{2 for e in a:errors let e['text'] = syntastic#util#decodeXMLEntities(e['text']) endfor return a:errors -endfunction +endfunction " }}}2 " filter out errors referencing other files -function! syntastic#postprocess#filterForeignErrors(errors) +function! syntastic#postprocess#filterForeignErrors(errors) " {{{2 return filter(copy(a:errors), 'get(v:val, "bufnr") == ' . bufnr('')) -endfunction +endfunction " }}}2 + +" }}}1 let &cpo = s:save_cpo unlet s:save_cpo -" vim: set et sts=4 sw=4: +" vim: set sw=4 sts=4 et fdm=marker: diff --git a/autoload/syntastic/preprocess.vim b/autoload/syntastic/preprocess.vim new file mode 100644 index 0000000..56998d2 --- /dev/null +++ b/autoload/syntastic/preprocess.vim @@ -0,0 +1,142 @@ +if exists("g:loaded_syntastic_preprocess_autoload") || !exists("g:loaded_syntastic_plugin") + finish +endif +let g:loaded_syntastic_preprocess_autoload = 1 + +let s:save_cpo = &cpo +set cpo&vim + +" Public functions {{{1 + +function! syntastic#preprocess#cabal(errors) " {{{2 + let out = [] + let star = 0 + for err in a:errors + if star + if err == '' + let star = 0 + else + let out[-1] .= ' ' . err + endif + else + call add(out, err) + if err =~ '\m^*\s' + let star = 1 + endif + endif + endfor + return out +endfunction " }}}2 + +function! syntastic#preprocess#checkstyle(errors) " {{{2 + let out = [] + let fname = expand('%') + for err in a:errors + if match(err, '\m') > -1 + let line = str2nr(matchstr(err, '\m\ \[[^]]+\])+\ze:'', "", "")') +endfunction " }}}2 + +function! syntastic#preprocess#killEmpty(errors) " {{{2 + return filter(copy(a:errors), 'v:val != ""') +endfunction " }}}2 + +function! syntastic#preprocess#perl(errors) " {{{2 + let out = [] + + for e in a:errors + let parts = matchlist(e, '\v^(.*)\sat\s(.*)\sline\s(\d+)(.*)$') + if !empty(parts) + call add(out, parts[2] . ':' . parts[3] . ':' . parts[1] . parts[4]) + endif + endfor + + return syntastic#util#unique(out) +endfunction " }}}2 + +function! syntastic#preprocess#rparse(errors) " {{{2 + let errlist = copy(a:errors) + + " remove uninteresting lines and handle continuations + let i = 0 + while i < len(errlist) + if i > 0 && errlist[i][:1] == ' ' && errlist[i] !~ '\m\s\+\^$' + let errlist[i-1] .= errlist[i][1:] + call remove(errlist, i) + elseif errlist[i] !~ '\m^\(Lint:\|Lint checking:\|Error in\) ' + call remove(errlist, i) + else + let i += 1 + endif + endwhile + + let out = [] + let fname = '' + for e in errlist + if match(e, '\m^Lint: ') == 0 + let parts = matchlist(e, '\m^Lint: \(.*\): found on lines \([0-9, ]\+\)\(+\(\d\+\) more\)\=') + if len(parts) >= 3 + for line in split(parts[2], '\m,\s*') + call add(out, 'E:' . fname . ':' . line . ': ' . parts[1]) + endfor + endif + if len(parts) >= 5 && parts[4] != '' + call add(out, 'E:' . fname . ':0: ' . parts[1] . ' - ' . parts[4] . ' messages not shown') + endif + elseif match(e, '\m^Lint checking: ') == 0 + let fname = matchstr(e, '\m^Lint checking: \zs.*') + elseif match(e, '\m^Error in ') == 0 + call add(out, substitute(e, '\m^Error in .\+ : .\+\ze:\d\+:\d\+: ', 'E:' . fname, '')) + endif + endfor + + return out +endfunction " }}}2 + +function! syntastic#preprocess#tslint(errors) " {{{2 + return map(copy(a:errors), 'substitute(v:val, ''\m^\(([^)]\+)\)\s\(.\+\)$'', ''\2 \1'', "")') +endfunction " }}}2 + +function! syntastic#preprocess#validator(errors) " {{{2 + let out = [] + for e in a:errors + let parts = matchlist(e, '\v^"([^"]+)"(.+)') + if len(parts) >= 3 + " URL decode, except leave alone any "+" + let parts[1] = substitute(parts[1], '\m%\(\x\x\)', '\=nr2char("0x".submatch(1))', 'g') + let parts[1] = substitute(parts[1], '\m\\"', '"', 'g') + let parts[1] = substitute(parts[1], '\m\\\\', '\\', 'g') + call add(out, '"' . parts[1] . '"' . parts[2]) + endif + endfor + return out +endfunction " }}}2 + +" }}}1 + +let &cpo = s:save_cpo +unlet s:save_cpo + +" vim: set sw=4 sts=4 et fdm=marker: diff --git a/autoload/syntastic/util.vim b/autoload/syntastic/util.vim index 1ab837a..51831b4 100644 --- a/autoload/syntastic/util.vim +++ b/autoload/syntastic/util.vim @@ -1,4 +1,4 @@ -if exists('g:loaded_syntastic_util_autoload') +if exists('g:loaded_syntastic_util_autoload') || !exists("g:loaded_syntastic_plugin") finish endif let g:loaded_syntastic_util_autoload = 1 @@ -6,27 +6,23 @@ let g:loaded_syntastic_util_autoload = 1 let s:save_cpo = &cpo set cpo&vim -" strwidth() was added in Vim 7.3; if it doesn't exist, we use strlen() -" and hope for the best :) -let s:width = function(exists('*strwidth') ? 'strwidth' : 'strlen') - " Public functions {{{1 -function! syntastic#util#isRunningWindows() +function! syntastic#util#isRunningWindows() " {{{2 return has('win16') || has('win32') || has('win64') -endfunction +endfunction " }}}2 -function! syntastic#util#DevNull() +function! syntastic#util#DevNull() " {{{2 if syntastic#util#isRunningWindows() return 'NUL' endif return '/dev/null' -endfunction +endfunction " }}}2 " Get directory separator -function! syntastic#util#Slash() abort +function! syntastic#util#Slash() abort " {{{2 return (!exists("+shellslash") || &shellslash) ? '/' : '\' -endfunction +endfunction " }}}2 "search the first 5 lines of the file for a magic number and return a map "containing the args and the executable @@ -38,37 +34,38 @@ endfunction "returns " "{'exe': '/usr/bin/perl', 'args': ['-f', '-bar']} -function! syntastic#util#parseShebang() - for lnum in range(1,5) +function! syntastic#util#parseShebang() " {{{2 + for lnum in range(1, 5) let line = getline(lnum) - if line =~ '^#!' - let exe = matchstr(line, '\m^#!\s*\zs[^ \t]*') - let args = split(matchstr(line, '\m^#!\s*[^ \t]*\zs.*')) + let line = substitute(line, '\v^#!\s*(\S+/env(\s+-\S+)*\s+)?', '', '') + let exe = matchstr(line, '\m^\S*\ze') + let args = split(matchstr(line, '\m^\S*\zs.*')) return { 'exe': exe, 'args': args } endif endfor return { 'exe': '', 'args': [] } -endfunction +endfunction " }}}2 " Get the value of a variable. Allow local variables to override global ones. -function! syntastic#util#var(name) +function! syntastic#util#var(name, ...) " {{{2 return \ exists('b:syntastic_' . a:name) ? b:syntastic_{a:name} : - \ exists('g:syntastic_' . a:name) ? g:syntastic_{a:name} : '' -endfunction + \ exists('g:syntastic_' . a:name) ? g:syntastic_{a:name} : + \ a:0 > 0 ? a:1 : '' +endfunction " }}}2 " Parse a version string. Return an array of version components. -function! syntastic#util#parseVersion(version) - return split(matchstr( a:version, '\v^\D*\zs\d+(\.\d+)+\ze' ), '\m\.') -endfunction +function! syntastic#util#parseVersion(version) " {{{2 + return map(split(matchstr( a:version, '\v^\D*\zs\d+(\.\d+)+\ze' ), '\m\.'), 'str2nr(v:val)') +endfunction " }}}2 " Run 'command' in a shell and parse output as a version string. " Returns an array of version components. -function! syntastic#util#getVersion(command) +function! syntastic#util#getVersion(command) " {{{2 return syntastic#util#parseVersion(system(a:command)) -endfunction +endfunction " }}}2 " Verify that the 'installed' version is at least the 'required' version. " @@ -76,20 +73,41 @@ endfunction " the "missing" elements will be assumed to be 0 for the purposes of checking. " " See http://semver.org for info about version numbers. -function! syntastic#util#versionIsAtLeast(installed, required) - for idx in range(max([len(a:installed), len(a:required)])) - let installed_element = get(a:installed, idx, 0) - let required_element = get(a:required, idx, 0) - if installed_element != required_element - return installed_element > required_element +function! syntastic#util#versionIsAtLeast(installed, required) " {{{2 + return syntastic#util#compareLexi(a:installed, a:required) >= 0 +endfunction " }}}2 + +" Almost lexicographic comparison of two lists of integers. :) If lists +" have different lengths, the "missing" elements are assumed to be 0. +function! syntastic#util#compareLexi(a, b) " {{{2 + for idx in range(max([len(a:a), len(a:b)])) + let a_element = str2nr(get(a:a, idx, 0)) + let b_element = str2nr(get(a:b, idx, 0)) + if a_element != b_element + return a_element > b_element ? 1 : -1 endif endfor " Everything matched, so it is at least the required version. - return 1 -endfunction + return 0 +endfunction " }}}2 + +" strwidth() was added in Vim 7.3; if it doesn't exist, we use strlen() +" and hope for the best :) +let s:width = function(exists('*strwidth') ? 'strwidth' : 'strlen') +lockvar s:width + +function! syntastic#util#screenWidth(str, tabstop) " {{{2 + let chunks = split(a:str, "\t", 1) + let width = s:width(chunks[-1]) + for c in chunks[:-2] + let cwidth = s:width(c) + let width += cwidth + a:tabstop - cwidth % a:tabstop + endfor + return width +endfunction " }}}2 "print as much of a:msg as possible without "Press Enter" prompt appearing -function! syntastic#util#wideMsg(msg) +function! syntastic#util#wideMsg(msg) " {{{2 let old_ruler = &ruler let old_showcmd = &showcmd @@ -100,7 +118,7 @@ function! syntastic#util#wideMsg(msg) "convert tabs to spaces so that the tabs count towards the window "width as the proper amount of characters let chunks = split(msg, "\t", 1) - let msg = join(map(chunks[:-2], 'v:val . repeat(" ", &ts - s:width(v:val) % &ts)'), '') . chunks[-1] + let msg = join(map(chunks[:-2], 'v:val . repeat(" ", &tabstop - s:width(v:val) % &tabstop)'), '') . chunks[-1] let msg = strpart(msg, 0, &columns - 1) set noruler noshowcmd @@ -110,10 +128,10 @@ function! syntastic#util#wideMsg(msg) let &ruler = old_ruler let &showcmd = old_showcmd -endfunction +endfunction " }}}2 " Check whether a buffer is loaded, listed, and not hidden -function! syntastic#util#bufIsActive(buffer) +function! syntastic#util#bufIsActive(buffer) " {{{2 " convert to number, or hell breaks loose let buf = str2nr(a:buffer) @@ -129,11 +147,11 @@ function! syntastic#util#bufIsActive(buffer) endfor return 0 -endfunction +endfunction " }}}2 " start in directory a:where and walk up the parent folders until it " finds a file matching a:what; return path to that file -function! syntastic#util#findInParent(what, where) +function! syntastic#util#findInParent(what, where) " {{{2 let here = fnamemodify(a:where, ':p') let root = syntastic#util#Slash() @@ -162,10 +180,10 @@ function! syntastic#util#findInParent(what, where) endwhile return '' -endfunction +endfunction " }}}2 " Returns unique elements in a list -function! syntastic#util#unique(list) +function! syntastic#util#unique(list) " {{{2 let seen = {} let uniques = [] for e in a:list @@ -175,20 +193,20 @@ function! syntastic#util#unique(list) endif endfor return uniques -endfunction +endfunction " }}}2 " A less noisy shellescape() -function! syntastic#util#shescape(string) +function! syntastic#util#shescape(string) " {{{2 return a:string =~ '\m^[A-Za-z0-9_/.-]\+$' ? a:string : shellescape(a:string) -endfunction +endfunction " }}}2 " A less noisy shellescape(expand()) -function! syntastic#util#shexpand(string) +function! syntastic#util#shexpand(string) " {{{2 return syntastic#util#shescape(expand(a:string)) -endfunction +endfunction " }}}2 " decode XML entities -function! syntastic#util#decodeXMLEntities(string) +function! syntastic#util#decodeXMLEntities(string) " {{{2 let str = a:string let str = substitute(str, '\m<', '<', 'g') let str = substitute(str, '\m>', '>', 'g') @@ -196,18 +214,18 @@ function! syntastic#util#decodeXMLEntities(string) let str = substitute(str, '\m'', "'", 'g') let str = substitute(str, '\m&', '\&', 'g') return str -endfunction +endfunction " }}}2 -function! syntastic#util#redraw(full) +function! syntastic#util#redraw(full) " {{{2 if a:full redraw! else redraw endif -endfunction +endfunction " }}}2 -function! syntastic#util#dictFilter(errors, filter) - let rules = s:translateFilter(a:filter) +function! syntastic#util#dictFilter(errors, filter) " {{{2 + let rules = s:_translateFilter(a:filter) " call syntastic#log#debug(g:SyntasticDebugFilters, "applying filter:", rules) try call filter(a:errors, rules) @@ -215,23 +233,36 @@ function! syntastic#util#dictFilter(errors, filter) let msg = matchstr(v:exception, '\m^Vim\%((\a\+)\)\=:\zs.*') call syntastic#log#error('quiet_messages: ' . msg) endtry -endfunction +endfunction " }}}2 + +" Return a [high, low] list of integers, representing the time +" (hopefully high resolution) since program start +" TODO: This assumes reltime() returns a list of integers. +function! syntastic#util#stamp() " {{{2 + return reltime(g:syntastic_start) +endfunction " }}}2 + +" }}}1 " Private functions {{{1 -function! s:translateFilter(filters) +function! s:_translateFilter(filters) " {{{2 let conditions = [] for k in keys(a:filters) if type(a:filters[k]) == type([]) - call extend(conditions, map(copy(a:filters[k]), 's:translateElement(k, v:val)')) + call extend(conditions, map(copy(a:filters[k]), 's:_translateElement(k, v:val)')) else - call add(conditions, s:translateElement(k, a:filters[k])) + call add(conditions, s:_translateElement(k, a:filters[k])) endif endfor + + if conditions == [] + let conditions = ["1"] + endif return len(conditions) == 1 ? conditions[0] : join(map(conditions, '"(" . v:val . ")"'), ' && ') -endfunction +endfunction " }}}2 -function! s:translateElement(key, term) +function! s:_translateElement(key, term) " {{{2 if a:key ==? 'level' let ret = 'v:val["type"] !=? ' . string(a:term[0]) elseif a:key ==? 'type' @@ -241,11 +272,15 @@ function! s:translateElement(key, term) elseif a:key ==? 'file' let ret = 'bufname(str2nr(v:val["bufnr"])) !~# ' . string(a:term) else + call syntastic#log#warn('quiet_messages: ignoring invalid key ' . strtrans(string(a:key))) let ret = "1" endif return ret -endfunction +endfunction " }}}2 + +" }}}1 let &cpo = s:save_cpo unlet s:save_cpo -" vim: set et sts=4 sw=4 fdm=marker: + +" vim: set sw=4 sts=4 et fdm=marker: diff --git a/doc/syntastic.txt b/doc/syntastic.txt index 4d04bee..14d4b13 100644 --- a/doc/syntastic.txt +++ b/doc/syntastic.txt @@ -36,9 +36,14 @@ CONTENTS *syntastic-contents* 5.3.Configuring specific checkers..........|syntastic-config-makeprg| 6.Notes........................................|syntastic-notes| 6.1.Handling of composite filetypes........|syntastic-composite| - 6.2.Interaction with python-mode...........|syntastic-pymode| - 6.3.Interaction with the fish shell........|syntastic-fish| - 6.4.Using syntastic with the fizsh shell...|syntastic-fizsh| + 6.2.Editing files over network.............|syntastic-netrw| + 6.3.Interaction with python-mode...........|syntastic-pymode| + 6.4.Interaction with YouCompleteMe.........|syntastic-ycm| + 6.5.Interaction with the fish shell........|syntastic-fish| + 6.6.Interaction with PowerShell............|syntastic-powershell| + 6.7.Using syntastic with the fizsh shell...|syntastic-fizsh| + 6.8.Interaction with Eclim.................|syntastic-eclim| + 6.9.Interaction with vim-virtualenv........|syntastic-vim-virtualenv| 7.About........................................|syntastic-about| 8.License......................................|syntastic-license| @@ -81,7 +86,7 @@ see |syntastic-checker-options| for details. You can also change the arguments passed to a specific checker as well. Use |:SyntasticCheck| to manually check right now. Use |:SyntasticToggleMode| -to switch between active (checking on writting the buffer) and passive (manual) +to switch between active (checking on writing the buffer) and passive (manual) checking. ============================================================================== @@ -91,7 +96,7 @@ Syntax checking can be done automatically or on demand (see |'syntastic_mode_map'| and |:SyntasticToggleMode| for configuring this). When syntax checking is done, the features below can be used to notify the -user of errors. See |syntastic-options| for how to configure and +user of errors. See |syntastic-global-options| for how to configure and activate/deactivate these features. * A statusline flag @@ -167,6 +172,8 @@ and the SpellCap group is used for warnings. If you wish to customize the colors for highlighting you can use the following groups: SyntasticError - Links to 'SpellBad' by default SyntasticWarning - Links to 'SpellCap' by default + SyntasticStyleError - Links to SyntasticError by default + SyntasticStyleWarning - Links to SyntasticWarning by default Example: > highlight SyntasticError guibg=#2f0000 @@ -186,7 +193,12 @@ If |'syntastic_aggregate_errors'| is set, syntastic runs all checkers that apply (still cf. |syntastic-filetype-checkers|), then aggregates errors found by all checkers in a single list, and notifies you. In this mode each error message is labeled with the name of the checker that generated it, but you can -disable these labels by unsetting '|syntastic_id_checkers|'. +disable generation of these labels by turning off '|syntastic_id_checkers|'. + +If |'syntastic_sort_aggregated_errors'| is set (which is the default), messages +in the aggregated list are grouped by file, then sorted by line number, then +type, then column number. Otherwise messages produced by the same checker are +grouped together. ------------------------------------------------------------------------------ 2.6 Filtering errors *syntastic-filtering-errors* @@ -278,12 +290,35 @@ a file with a composite filetype), it might not be immediately obvious which checker has produced a given error message. This variable instructs syntastic to label error messages with the names of the checkers that created them. > let g:syntastic_id_checkers = 0 +< + *'syntastic_sort_aggregated_errors'* +Default: 1 +By default, when results from multiple checkers are aggregated in a single +error list (that is either when |syntastic_aggregate_errors| is enabled, or +when checking a file with a composite filetype), errors are grouped by file, +then sorted by line number, then grouped by type (namely errors take precedence +over warnings), then they are sorted by column number. If you want to leave +messages grouped by checker output, set this variable to 0. > + let g:syntastic_sort_aggregated_errors = 0 < *'syntastic_echo_current_error'* Default: 1 -If enabled, syntastic will echo the error associated with the current line to -the command window. If multiple errors are found, the first will be used. > +If enabled, syntastic will echo current error to the command window. If +multiple errors are found on the same line, |syntastic_cursor_columns| is used +to decide which one is shown. > let g:syntastic_echo_current_error = 1 +< + *'syntastic_cursor_columns'* +Default: 1 +This option controls which errors are echoed to the command window if +|syntastic_echo_current_error| is set and multiple errors are found on the same +line. When the option is enabled, the first error corresponding to the current +column is show. Otherwise, the first error on the current line is echoed, +regardless of the cursor position on the current line. + +When dealing with very large lists of errors, disabling this option can speed +up navigation significantly: > + let g:syntastic_cursor_column = 0 < *'syntastic_enable_signs'* Default: 1 @@ -301,8 +336,8 @@ error symbols can be customized: syntastic_style_warning_symbol - For style warnings, defaults to 'S>' Example: > - let g:syntastic_error_symbol = '✗' - let g:syntastic_warning_symbol = '⚠' + let g:syntastic_error_symbol = "✗" + let g:syntastic_warning_symbol = "⚠" < *'syntastic_enable_balloons'* Default: 1 @@ -374,12 +409,12 @@ Default: {} Use this option to map non-standard filetypes to standard ones. Corresponding checkers are mapped accordingly, which allows syntastic to check files with non-standard filetypes: > - let g:syntastic_filetype_map = { 'latex': 'tex', - \ 'gentoo-metadata': 'xml' } + let g:syntastic_filetype_map = { "latex": "tex", + \ "gentoo-metadata": "xml" } < Composite filetypes can also be mapped to simple types, which disables the default behaviour of running both checkers against the input file: > - let g:syntastic_filetype_map = { 'handlebars.html': 'handlebars' } + let g:syntastic_filetype_map = { "handlebars.html": "handlebars" } < *'syntastic_mode_map'* Default: { "mode": "active", @@ -391,43 +426,42 @@ done). The option should be set to something like: > - let g:syntastic_mode_map = { 'mode': 'active', - \ 'active_filetypes': ['ruby', 'php'], - \ 'passive_filetypes': ['puppet'] } + let g:syntastic_mode_map = { "mode": "active", + \ "active_filetypes": ["ruby", "php"], + \ "passive_filetypes": ["puppet"] } < -"mode" can be mapped to one of two values - "active" or "passive". When set to -active, syntastic does automatic checking whenever a buffer is saved or +"mode" can be mapped to one of two values - "active" or "passive". When set +to "active", syntastic does automatic checking whenever a buffer is saved or initially opened. When set to "passive" syntastic only checks when the user calls |:SyntasticCheck|. The exceptions to these rules are defined with "active_filetypes" and -"passive_filetypes". In passive mode, automatic checks are still done -for all filetypes in the "active_filetypes" array. In active mode, -automatic checks are not done for any filetypes in the -"passive_filetypes" array. +"passive_filetypes". In passive mode, automatic checks are still done for +filetypes in the "active_filetypes" array (and "passive_filetypes" is +ignored). In active mode, automatic checks are not done for any filetypes in +the "passive_filetypes" array ("active_filetypes" is ignored). -At runtime, the |:SyntasticToggleMode| command can be used to switch between -active and passive mode. +If any of "mode", "active_filetypes", or "passive_filetypes" are left +unspecified, they default to values above. -If any of "mode", "active_filetypes", or "passive_filetypes" are not specified -then they will default to their default value as above. +At runtime, the |:SyntasticToggleMode| command can be used to switch between +active and passive modes. *'syntastic_quiet_messages'* Default: {} Use this option to filter out some of the messages produced by checkers. The option should be set to something like: > - let g:syntastic_quiet_messages = { "level": "warnings", \ "type": "style", \ "regex": '\m\[C03\d\d\]', \ "file": ['\m^/usr/include/', '\m\c\.h$'] } < - Each element turns off messages matching the patterns specified by the corresponding value. Values are lists, but if a list consist of a single -element you can omit adding the brackets (e.g. you can write "style" instead of -["style"]). +element you can omit adding the brackets (e.g. you can write "style" instead +of ["style"]). Elements with values [] or '' are ignored (this is useful for +overriding filters, cf. |filter-overrides|). "level" - takes one of two values, "warnings" or "errors" "type" - can be either "syntax" or "style" @@ -436,9 +470,26 @@ element you can omit adding the brackets (e.g. you can write "style" instead of "file" - is matched against the filename the error refers to, as a case sensitive |regular-expression|. +If |'syntastic_id_checkers'| is set, filters are applied before error messages +are labeled with the names of the checkers that created them. + There are also checker-specific variants of this option, providing finer control. They are named |'syntastic___quiet_messages'|. +For a particular checker, if both a |'syntastic_quiet_messages'| filter and +a checker-specific filter are present, they are both applied (to the list of +errors produced by the said checker). In case of conflicting values for the +same keys, the values of the checker-specific filters take precedence. + + *filter-overrides* +Since filter elements with values [] or '' are ignored, you can disable global +filters for particular checkers, by setting the values of the corresponding +elements in |'syntastic___quiet_messages'| to [] or ''. For +example, the following setting will silence all warnings, except for the +ones produced by "pylint": > + let g:syntastic_quiet_messages = { "level": "warnings" } + let g:syntastic_python_pylint_quiet_messages = { "level" : [] } +< *'syntastic_stl_format'* Default: [Syntax: line:%F (%t)] Use this option to control what the syntastic statusline text contains. Several @@ -504,7 +555,7 @@ List of filetypes handled by checkers external to syntastic. If you have a Vim plugin that adds a checker for syntastic, and if the said checker deals with a filetype that is unknown to syntastic, you might consider adding that filetype to this list: > - let g:syntastic_extra_filetypes = [ 'make', 'gitcommit' ] + let g:syntastic_extra_filetypes = [ "make", "gitcommit" ] < This will allow |:SyntasticInfo| to do proper tab completion for the new filetypes. @@ -518,14 +569,14 @@ filetypes. *'g:syntastic__checkers'* You can tell syntastic which checkers to run for a given filetype by setting a variable 'g:syntastic__checkers' to a list of checkers, e.g. > - let g:syntastic_php_checkers = ['php', 'phpcs', 'phpmd'] + let g:syntastic_php_checkers = ["php", "phpcs", "phpmd"] < *'b:syntastic_checkers'* There is also a per-buffer version of this setting, 'b:syntastic_checkers'. When set, it takes precedence over |'g:syntastic__checkers'|. You can use this in an autocmd to configure specific checkers for particular paths: > - autocmd FileType python if stridx(expand('%:p'), '/some/path/') == 0 | - \ let b:syntastic_checkers = ['pylint'] | endif + autocmd FileType python if stridx(expand("%:p"), "/some/path/") == 0 | + \ let b:syntastic_checkers = ["pylint"] | endif < If neither |'g:syntastic__checkers'| nor |'b:syntastic_checkers'| is set, a default list of checker is used. Beware however that this list @@ -541,10 +592,10 @@ Use |:SyntasticInfo| to see which checkers are available for a given filetype. ------------------------------------------------------------------------------ 5.2 Choosing the executable *syntastic-config-exec* - *'syntastic___exec'* + *'syntastic___exec'* The executable used by a checker is normally defined automatically, when the checkers is registered. You can however override it by setting the variable -'g:syntastic___exec': > +'g:syntastic___exec': > let g:syntastic_ruby_mri_exec = '~/bin/ruby2' < ------------------------------------------------------------------------------ @@ -553,24 +604,30 @@ checkers is registered. You can however override it by setting the variable Most checkers use the 'makeprgBuild()' function and provide many options by default - in fact you can customise every part of the command that gets called. - *'syntastic___