]> Sergey Matveev's repositories - dotfiles.git/blob - vim/.vim/ftplugin/python/pylint.vim
Initial
[dotfiles.git] / vim / .vim / ftplugin / python / pylint.vim
1 " Asynchronous pylint utility call
2 " Maintainer: Sergey Matveev <stargrave@stargrave.org>
3 " License: GNU General Public License version 3 of the License or later
4 "
5 " This plugin allows you to asynchronously call pylint.
6 "
7 " * Add %{LintStatus()} to your statusline to see if pylint is running
8 " * Press <F6> to start pylint on current file
9 " * Press <S-F6> to open quickfix window with messages from pylint
10 " * All lines with corresponding pylint existing warning will be highlighted
11 " * If no warning and errors occurred, "pylint is clean" message will be shown
12 " * If existing quickfix window is found, then it won't be overwritten.
13 "   Start pylint manually (<F6>) to force its filling
14 " * After Python file is saved, pylint is automatically started
15
16 if exists('g:loaded_pylint') | finish | endif
17 let g:loaded_pylint = 1
18
19 function! LintStatus()
20     if exists("b:lint_job") && job_status(b:lint_job) == "run" | return "LN" | endif
21     return ""
22 endfunction
23
24 function! s:qffill(ch)
25     let msgs = []
26     while ch_status(a:ch) == 'buffered'
27         let msgs = add(msgs, ch_read(a:ch))
28     endwhile
29     cgetexpr msgs
30 endfunction
31
32 sign define LN text=LN texthl=Error
33
34 function! PylintFinish(ch)
35     let l:errorformat_bak = &errorformat
36     set errorformat=%f:%l:\ [%t]%m,%f:%l:%m
37     call s:qffill(a:ch)
38     let &errorformat=l:errorformat_bak
39     sign unplace *
40     let l:id = 2
41     for item in getqflist()
42         if item.lnum == 0 | continue | endif
43         execute(':sign place '.l:id.' name=LN line='.l:item.lnum.' buffer='.l:item.bufnr)
44         let l:id = l:id + 2
45     endfor
46     redraw!
47     if l:id == 2
48         echohl MoreMsg | echomsg "pylint is clean" | echohl None
49         cclose
50     endif
51 endfunction
52
53 function! PylintStart()
54     if exists("g:pylint_disable") || (exists("b:lint_job") && job_status(b:lint_job) == "run")
55         return
56     endif
57     let ignores = [
58         \"locally-disabled",
59         \"no-init",
60         \"no-self-use",
61         \"too-few-public-methods",
62         \"missing-docstring",
63         \"too-many-instance-attributes",
64         \"invalid-name",
65         \"too-many-arguments",
66         \"too-many-locals",
67         \"too-many-public-methods",
68         \"no-value-for-parameter",
69     \]
70     if !exists("g:pylint_linter") | let g:pylint_linter = "flake8" | endif
71     if g:pylint_linter == "flake8"
72         let cmdline = [
73             \"flake8",
74             \"--ignore=E501",
75             \"--format=%(path)s:%(row)d: [%(code)s] %(text)s",
76             \"--max-line-length=90",
77             \expand("%p")
78         \]
79     elseif g:pylint_linter == "pylint"
80         let cmdline = [
81             \"pylint",
82             \"--jobs=4",
83             \"--reports=n",
84             \"--msg-template={path}:{line}: [{msg_id}({symbol}), {obj}] {msg}",
85             \"--disable=" . join(ignores, ","),
86             \"--persistent=n",
87             \expand("%p")
88         \]
89     else
90         echohl WarningMsg | echomsg "Unknown linter specified" | echohl None
91         return
92     endif
93     let b:lint_job = job_start(cmdline, {"in_mode": "nl",  "err_io": "null", "close_cb": "PylintFinish"})
94 endfunction()
95
96 map <F6> :unlet! g:pylint_disable<CR>:call PylintStart()<CR>
97 map \e[17;2~ :redraw!<CR>:copen<CR>
98 autocmd BufWritePost *.py call PylintStart()