" " Python filetype plugin for running flake8 " Language: Python (ft=python) " Maintainer: Vincent Driessen " Version: Vim 7 (may work with lower Vim versions, but not tested) " URL: http://github.com/nvie/vim-flake8 let s:save_cpo = &cpo set cpo&vim "" ** external ** {{{ function! flake8#Flake8() call s:Flake8() call s:Warnings() endfunction function! flake8#Flake8UnplaceMarkers() call s:UnplaceMarkers() call s:Warnings() endfunction function! flake8#Flake8ShowError() call s:ShowErrorMessage() endfunction "" }}} "" ** internal ** {{{ "" warnings let s:displayed_warnings = 0 function s:Warnings() if !s:displayed_warnings let l:show_website_url = 0 let l:msg = "has been deprecated in favour of flake8 config files" for setting_name in ['g:flake8_ignore', 'g:flake8_builtins', 'g:flake8_max_line_length', 'g:flake8_max_complexity'] if exists(setting_name) echohl WarningMsg | echom setting_name l:msg | echohl None let l:show_website_url = 1 endif endfor if l:show_website_url let l:url = "http://flake8.readthedocs.org/en/latest/config.html" echohl WarningMsg | echom l:url | echohl None endif let s:displayed_warnings = 1 endif endfunction "" config function! s:DeclareOption(name, globalPrefix, default) " {{{ if !exists('g:'.a:name) if a:default != '' execute 'let s:'.a:name.'='.a:default else execute 'let s:'.a:name.'=""' endif else execute 'let l:global="g:".a:name' if l:global != '' execute 'let s:'.a:name.'="'.a:globalPrefix.'".g:'.a:name else execute 'let s:'.a:name.'=""' endif endif endfunction " }}} function! s:Setup() " {{{ "" read options " flake8 command call s:DeclareOption('flake8_cmd', '', '"flake8"') " quickfix call s:DeclareOption('flake8_quickfix_location', '', '"belowright"') call s:DeclareOption('flake8_quickfix_height', '', 5) call s:DeclareOption('flake8_show_quickfix', '', 1) " markers to show call s:DeclareOption('flake8_show_in_gutter', '', 0) call s:DeclareOption('flake8_show_in_file', '', 0) call s:DeclareOption('flake8_max_markers', '', 500) " marker signs call s:DeclareOption('flake8_error_marker', '', '"E>"') call s:DeclareOption('flake8_warning_marker', '', '"W>"') call s:DeclareOption('flake8_pyflake_marker', '', '"F>"') call s:DeclareOption('flake8_complexity_marker', '', '"C>"') call s:DeclareOption('flake8_naming_marker', '', '"N>"') "" setup markerdata if !exists('s:markerdata') let s:markerdata = {} let s:markerdata['E'] = {'name': 'Flake8_Error'} let s:markerdata['W'] = {'name': 'Flake8_Warning'} let s:markerdata['F'] = {'name': 'Flake8_PyFlake'} let s:markerdata['C'] = {'name': 'Flake8_Complexity'} let s:markerdata['N'] = {'name': 'Flake8_Nameing'} endif let s:markerdata['E'].marker = s:flake8_error_marker let s:markerdata['W'].marker = s:flake8_warning_marker let s:markerdata['F'].marker = s:flake8_pyflake_marker let s:markerdata['C'].marker = s:flake8_complexity_marker let s:markerdata['N'].marker = s:flake8_naming_marker endfunction " }}} "" do flake8 function! s:Flake8() " {{{ " read config call s:Setup() let l:executable = split(s:flake8_cmd)[0] if !executable(l:executable) echoerr "File " . l:executable . " not found. Please install it first." return endif " clear old call s:UnplaceMarkers() let s:matchids = [] let s:signids = [] " store old grep settings (to restore later) let l:old_gfm=&grepformat let l:old_gp=&grepprg let l:old_shellpipe=&shellpipe let l:old_t_ti=&t_ti let l:old_t_te=&t_te " write any changes before continuing if &readonly == 0 update endif set lazyredraw " delay redrawing " prevent terminal from blinking set shellpipe=> set t_ti= set t_te= " perform the grep itself let &grepformat="%f:%l:%c: %m\,%f:%l: %m,%-G%\\d" let &grepprg=s:flake8_cmd silent! grep! "%" " close any existing cwindows, " placed after 'grep' in case quickfix is open on autocmd QuickFixCmdPost cclose " restore grep settings let &grepformat=l:old_gfm let &grepprg=l:old_gp let &shellpipe=l:old_shellpipe let &t_ti=l:old_t_ti let &t_te=l:old_t_te " store mapping of line number to error string " process results let s:resultDict = {} let l:results=getqflist() let l:has_results=results != [] if l:has_results " save line number of each error message for result in l:results let linenum = result.lnum let s:resultDict[linenum] = result.text endfor " markers if !s:flake8_show_in_gutter == 0 || !s:flake8_show_in_file == 0 call s:PlaceMarkers(l:results) endif " quickfix if !s:flake8_show_quickfix == 0 " open cwindow execute s:flake8_quickfix_location." copen".s:flake8_quickfix_height setlocal wrap nnoremap c :cclose nnoremap q :cclose endif endif set nolazyredraw redraw! " Show status if l:has_results == 0 echon "Flake8 check OK" else echon "Flake8 found issues" endif endfunction " }}} "" markers function! s:PlaceMarkers(results) " {{{ " in gutter? if !s:flake8_show_in_gutter == 0 " define signs for val in values(s:markerdata) if val.marker != '' execute "sign define ".val.name." text=".val.marker." texthl=".val.name endif endfor endif " place let l:index0 = 100 let l:index = l:index0 for result in a:results if l:index >= (s:flake8_max_markers+l:index0) break endif let l:type = strpart(result.text, 0, 1) if has_key(s:markerdata, l:type) && s:markerdata[l:type].marker != '' " file markers if !s:flake8_show_in_file == 0 if !has_key(s:markerdata[l:type], 'matchstr') let s:markerdata[l:type].matchstr = '\%(' else let s:markerdata[l:type].matchstr .= '\|' endif let s:markerdata[l:type].matchstr .= '\%'.result.lnum.'l\%'.result.col.'c' endif " gutter markers if !s:flake8_show_in_gutter == 0 execute ":sign place ".index." name=".s:markerdata[l:type].name \ . " line=".result.lnum." file=".expand("%:p") let s:signids += [l:index] endif let l:index += 1 endif endfor " in file? if !s:flake8_show_in_file == 0 for l:val in values(s:markerdata) if l:val.marker != '' && has_key(l:val, 'matchstr') let l:val.matchid = matchadd(l:val.name, l:val.matchstr.'\)') endif endfor endif endfunction " }}} function! s:UnplaceMarkers() " {{{ " gutter markers if exists('s:signids') for i in s:signids execute ":sign unplace ".i endfor unlet s:signids endif " file markers for l:val in values(s:markerdata) if has_key(l:val, 'matchid') call matchdelete(l:val.matchid) unlet l:val.matchid unlet l:val.matchstr endif endfor endfunction " }}} function! s:ShowErrorMessage() " {{{ let l:cursorPos = getpos(".") if !exists('s:resultDict') return endif if !exists('b:showing_message') " ensure showing msg is always defined let b:showing_message = ' ' endif " if there is a message on the current line, " then echo it if has_key(s:resultDict, l:cursorPos[1]) let l:errorText = get(s:resultDict, l:cursorPos[1]) echo strpart(l:errorText, 0, &columns-1) let b:showing_message = 1 endif " if a message is already being shown, " then clear it if !b:showing_message == 0 echo let b:showing_message = 0 endif endfunction " }}} "" }}} let &cpo = s:save_cpo unlet s:save_cpo