]> git.madduck.net Git - etc/vim.git/blob - autoload/flake8.vim

madduck's git repository

Every one of the projects in this repository is available at the canonical URL git://git.madduck.net/madduck/pub/<projectpath> — see each project's metadata for the exact URL.

All patches and comments are welcome. Please squash your changes to logical commits before using git-format-patch and git-send-email to patches@git.madduck.net. If you'd read over the Git project's submission guidelines and adhered to them, I'd be especially grateful.

SSH access, as well as push access can be individually arranged.

If you use my repositories frequently, consider adding the following snippet to ~/.gitconfig and using the third clone URL listed for each project:

[url "git://git.madduck.net/madduck/"]
  insteadOf = madduck:

13fe7687bb3054b0560f167e31a43b8ad69c9ea9
[etc/vim.git] / autoload / flake8.vim
1 "
2 " Python filetype plugin for running flake8
3 " Language:     Python (ft=python)
4 " Maintainer:   Vincent Driessen <vincent@3rdcloud.com>
5 " Version:      Vim 7 (may work with lower Vim versions, but not tested)
6 " URL:          http://github.com/nvie/vim-flake8
7
8 let s:save_cpo = &cpo
9 set cpo&vim
10
11 "" ** external ** {{{
12
13 function! flake8#Flake8()
14     call s:Flake8()
15     call s:Warnings()
16 endfunction
17
18 function! flake8#Flake8UnplaceMarkers()
19     call s:UnplaceMarkers()
20     call s:Warnings()
21 endfunction
22
23 function! flake8#Flake8ShowError()
24     call s:ShowErrorMessage()
25 endfunction
26
27 "" }}}
28
29 "" ** internal ** {{{
30
31 "" warnings 
32
33 let s:displayed_warnings = 0
34 function s:Warnings()
35   if !s:displayed_warnings
36     let l:show_website_url = 0
37
38     let l:msg = "has been deprecated in favour of flake8 config files"
39     for setting_name in ['g:flake8_ignore', 'g:flake8_builtins', 'g:flake8_max_line_length', 'g:flake8_max_complexity']
40       if exists(setting_name)
41         echohl WarningMsg | echom setting_name l:msg | echohl None
42         let l:show_website_url = 1
43       endif
44     endfor
45
46     if l:show_website_url
47       let l:url = "http://flake8.readthedocs.org/en/latest/config.html"
48       echohl WarningMsg | echom l:url | echohl None
49     endif
50     let s:displayed_warnings = 1
51   endif
52 endfunction
53
54 "" config
55
56 function! s:DeclareOption(name, globalPrefix, default)  " {{{
57     if !exists('g:'.a:name)
58         if a:default != ''
59             execute 'let s:'.a:name.'='.a:default
60         else
61             execute 'let s:'.a:name.'=""'
62         endif
63     else
64         execute 'let l:global="g:".a:name'
65         if l:global != ''
66             execute 'let s:'.a:name.'="'.a:globalPrefix.'".g:'.a:name
67         else
68             execute 'let s:'.a:name.'=""'
69         endif
70     endif
71 endfunction  " }}}
72
73 function! s:Setup()  " {{{
74     "" read options
75
76     " flake8 command
77     call s:DeclareOption('flake8_cmd', '', '"flake8"')
78     " quickfix
79     call s:DeclareOption('flake8_quickfix_location', '', '"belowright"')
80     call s:DeclareOption('flake8_quickfix_height', '', 5)
81     call s:DeclareOption('flake8_show_quickfix', '', 1)
82     " markers to show
83     call s:DeclareOption('flake8_show_in_gutter', '',   0)
84     call s:DeclareOption('flake8_show_in_file', '',   0)
85     call s:DeclareOption('flake8_max_markers', '', 500)
86     " marker signs
87     call s:DeclareOption('flake8_error_marker', '', '"E>"')
88     call s:DeclareOption('flake8_warning_marker', '', '"W>"')
89     call s:DeclareOption('flake8_pyflake_marker', '', '"F>"')
90     call s:DeclareOption('flake8_complexity_marker', '', '"C>"')
91     call s:DeclareOption('flake8_naming_marker', '', '"N>"')
92
93     "" setup markerdata
94
95     if !exists('s:markerdata')
96         let s:markerdata = {}
97         let s:markerdata['E'] = {'name': 'Flake8_Error'}
98         let s:markerdata['W'] = {'name': 'Flake8_Warning'}
99         let s:markerdata['F'] = {'name': 'Flake8_PyFlake'}
100         let s:markerdata['C'] = {'name': 'Flake8_Complexity'}
101         let s:markerdata['N'] = {'name': 'Flake8_Nameing'}
102     endif
103     let s:markerdata['E'].marker = s:flake8_error_marker
104     let s:markerdata['W'].marker = s:flake8_warning_marker
105     let s:markerdata['F'].marker = s:flake8_pyflake_marker
106     let s:markerdata['C'].marker = s:flake8_complexity_marker
107     let s:markerdata['N'].marker = s:flake8_naming_marker
108
109 endfunction  " }}}
110
111 "" do flake8
112
113 function! s:Flake8()  " {{{
114     " read config
115     call s:Setup()
116
117     let l:executable = split(s:flake8_cmd)[0]
118
119     if !executable(l:executable)
120         echoerr "File " . l:executable . " not found. Please install it first."
121         return
122     endif
123
124     " clear old
125     call s:UnplaceMarkers()
126     let s:matchids = []
127     let s:signids  = []
128
129     " store old grep settings (to restore later)
130     let l:old_gfm=&grepformat
131     let l:old_gp=&grepprg
132     let l:old_shellpipe=&shellpipe
133     let l:old_t_ti=&t_ti
134     let l:old_t_te=&t_te
135
136     " write any changes before continuing
137     if &readonly == 0
138         update
139     endif
140
141     set lazyredraw   " delay redrawing
142
143     " prevent terminal from blinking
144     set shellpipe=>
145     set t_ti=
146     set t_te=
147
148     " perform the grep itself
149     let &grepformat="%f:%l:%c: %m\,%f:%l: %m"
150     let &grepprg=s:flake8_cmd
151     silent! grep! "%"
152     " close any existing cwindows,
153     " placed after 'grep' in case quickfix is open on autocmd QuickFixCmdPost
154     cclose
155
156     " restore grep settings
157     let &grepformat=l:old_gfm
158     let &grepprg=l:old_gp
159     let &shellpipe=l:old_shellpipe
160     let &t_ti=l:old_t_ti
161     let &t_te=l:old_t_te
162     " store mapping of line number to error string
163
164     " process results
165     let s:resultDict = {} 
166
167     let l:results=getqflist()
168     let l:has_results=results != []
169     if l:has_results
170         " save line number of each error message        
171         for result in l:results
172             let linenum = result.lnum
173             let s:resultDict[linenum] = result.text
174         endfor
175
176         " markers
177         if !s:flake8_show_in_gutter == 0 || !s:flake8_show_in_file == 0
178             call s:PlaceMarkers(l:results)
179         endif
180         " quickfix
181         if !s:flake8_show_quickfix == 0
182             " open cwindow
183             execute s:flake8_quickfix_location." copen".s:flake8_quickfix_height
184             setlocal wrap
185             nnoremap <buffer> <silent> c :cclose<CR>
186             nnoremap <buffer> <silent> q :cclose<CR>
187         endif
188     endif
189
190     set nolazyredraw
191     redraw!
192
193     " Show status
194     if l:has_results == 0
195         echon "Flake8 check OK"
196     else
197         echon "Flake8 found issues"
198     endif
199 endfunction  " }}}
200
201
202 function! s:MakeMap(results)  " {{{
203     for result in a:results
204     endfor
205 endfunction  " }}}
206
207 "" markers
208 function! s:PlaceMarkers(results)  " {{{
209     " in gutter?
210     if !s:flake8_show_in_gutter == 0
211         " define signs
212         for val in values(s:markerdata)
213             if val.marker != ''
214                 execute "sign define ".val.name." text=".val.marker." texthl=".val.name
215             endif
216         endfor
217     endif
218
219     " place
220     let l:index0 = 100
221     let l:index  = l:index0
222     for result in a:results
223         if l:index >= (s:flake8_max_markers+l:index0)
224             break
225         endif
226         let l:type = strpart(result.text, 0, 1)
227         if has_key(s:markerdata, l:type) && s:markerdata[l:type].marker != ''
228             " file markers
229             if !s:flake8_show_in_file == 0
230                 if !has_key(s:markerdata[l:type], 'matchstr')
231                     let s:markerdata[l:type].matchstr = '\%('
232                 else
233                     let s:markerdata[l:type].matchstr .= '\|'
234                 endif
235                 let s:markerdata[l:type].matchstr .= '\%'.result.lnum.'l\%'.result.col.'c'
236             endif
237             " gutter markers
238             if !s:flake8_show_in_gutter == 0
239                 execute ":sign place ".index." name=".s:markerdata[l:type].name
240                             \ . " line=".result.lnum." file=".expand("%:p")
241                 let s:signids += [l:index]
242             endif
243             let l:index += 1
244         endif
245     endfor
246
247     " in file?
248     if !s:flake8_show_in_file == 0
249         for l:val in values(s:markerdata)
250             if l:val.marker != '' && has_key(l:val, 'matchstr')
251                 let l:val.matchid = matchadd(l:val.name, l:val.matchstr.'\)')
252             endif
253         endfor
254     endif
255 endfunction  " }}}
256
257 function! s:UnplaceMarkers()  " {{{
258     " gutter markers
259     if exists('s:signids')
260         for i in s:signids
261             execute ":sign unplace ".i
262         endfor
263         unlet s:signids
264     endif
265     " file markers
266     for l:val in values(s:markerdata)
267         if has_key(l:val, 'matchid')
268             call matchdelete(l:val.matchid)
269             unlet l:val.matchid
270             unlet l:val.matchstr
271         endif
272     endfor
273 endfunction  " }}}
274
275 function! s:ShowErrorMessage()  " {{{
276     let l:cursorPos = getpos(".")
277     if !exists('s:resultDict')
278         return
279     endif
280
281     " if there is a message on the current line,
282     " then echo it 
283     if has_key(s:resultDict, l:cursorPos[1])
284         let l:errorText = get(s:resultDict, l:cursorPos[1]) 
285         echo strpart(l:errorText, 0, &columns-1)
286         let b:showing_message = 1
287     endif
288
289     " if a message is already being shown,
290     " then clear it
291     if !b:showing_message == 0
292         echo
293         let b:showing_message = 0
294     endif
295
296 endfunction  " }}}
297
298 "" }}}
299
300 let &cpo = s:save_cpo
301 unlet s:save_cpo
302