diff --git a/.vimrc b/.vimrc index 9746e0f..1b974cf 100644 --- a/.vimrc +++ b/.vimrc @@ -74,7 +74,7 @@ set noswapfile "}}} "COMMON: specific vim behaviour for Python files {{{ " -"remove all trailing whitespace for python before write +"remove all trailing whitespace for specified files before write autocmd BufWritePre *.py :call StripTrailingWhitespaces() autocmd BufWritePre *.rst :call StripTrailingWhitespaces() autocmd BufWritePre *.wiki :call StripTrailingWhitespaces() @@ -164,17 +164,9 @@ let g:DirDiffExcludes = "CVS,*.class,*.exe,.*.swp,*.pyc,*.pyo" "}}} "KEYS: User definied keyboard shortcuts {{{ -"set =^[[11^ -"set = ^[[23~ -"nmap :bnext -"nmap :split -"nmap :vsplit - "Cycle through buffers. map :bp map :bn -"map :bp -"map :bn "Cycle through tabs. if $TERM == 'rxvt-unicode' @@ -182,11 +174,7 @@ if $TERM == 'rxvt-unicode' map :tabp endif -map :call runPyLint() -map :call PyLintBuf() - -"map ctags plugin to show popup menu in gvim -"map :popup Tags +map :call Make() "QuickFix jumps map :cp @@ -207,8 +195,6 @@ map ]b :call OpenInFirefox() "make displaying tags easy nmap t :TlistToo -"aswell minibufexplorer -"map b :TMiniBufExplorer "eclim Buffer shortcut map b :Buffers @@ -221,42 +207,18 @@ nmap ,cs :silent call CopyFileName(0) map :TlistToo!:FufFile **/ " }}} " FUNCTIONS: usefull functions for all of th files {{{ -"Sessions -"autocmd VimEnter * call LoadSession() -"autocmd VimLeave * call SaveSession() -" -"function! SaveSession() -" execute 'mksession!' -"endfunction -" -"function! LoadSession() -" if argc() == 0 -" execute 'source Session.vim' -" endif -"endfunction - -function runPyLint() +" Simple wrapper for :make command +function Make() echohl Statement - echo "Running pylint (ctrl-c to cancel) ..." + echo "Running make (ctrl-c to cancel) ..." echohl Normal - :Pylint -endfunction -function PyLintBuf() - echohl Statement - echo "Running pylint (ctrl-c to cancel) ..." - echohl Normal - let file = expand('%:p') - let cmd = 'pylint --reports=n --output-format=text "' . file . '"' - - if has('win32') || has('win64') - let cmd = 'cmd /c "' . cmd . '"' + silent make + if getqflist() != [] + copen endif - - exec "bel silent new " . file . ".lint" - exec "silent! read! " . cmd endfunction - -function! StripTrailingWhitespaces() +" Remove trailing whitespace +function StripTrailingWhitespaces() " Preparation: save last search, and cursor position. let _s=@/ let l = line(".") @@ -284,6 +246,7 @@ function CopyFileName(full) echo l:full_fn + " copied to clipboard" endfunction +" Toggle QuickFix buffer command -bang -nargs=? QFix call QFixToggle(0) function! QFixToggle(forced) if exists("g:qfix_win") && a:forced == 0 @@ -295,6 +258,7 @@ function! QFixToggle(forced) endif endfunction +" Toggle location buffer command -bang -nargs=? LWin call LocationWindowToggle(0) function! LocationWindowToggle(forced) if exists("g:loc_win") && a:forced == 0 diff --git a/bin/pylint_parseable.py b/bin/pylint_parseable.py new file mode 100755 index 0000000..e26ff02 --- /dev/null +++ b/bin/pylint_parseable.py @@ -0,0 +1,85 @@ +#!/usr/bin/env python +""" +This script can be used as a pylint command replacement, especially useful as +a "make" command for VIm +""" +import sys +import re +from StringIO import StringIO +from optparse import OptionParser + +from pylint import lint +from pylint.reporters.text import TextReporter + + +SYS_STDERR = sys.stderr +DUMMY_STDERR = StringIO() +CONF_MSG = 'No config file found, using default configuration\n' + +def parsable_pylint(filename): + """ + Simple wrapper for pylint checker. Provides nice, parseable output. + filename - python fileneame to check + returns list of dicts of errors, i.e.: + [{'lnum': 5, 'col': 10, 'type': 'C0324', text: 'Comma not followed by a space'}, + .... + ] + + """ + # args + args = ['-rn', # display only the messages instead of full report + '-iy', # Include message's id in output + filename] + + buf = StringIO() # file-like buffer, instead of stdout + reporter = TextReporter(buf) + + sys.stderr = DUMMY_STDERR + lint.Run(args, reporter=reporter, exit=False) + sys.stderr = SYS_STDERR + + DUMMY_STDERR.seek(0) + error_list = DUMMY_STDERR.readlines() + DUMMY_STDERR.truncate(0) + if error_list and CONF_MSG in error_list: + error_list.remove(CONF_MSG) + if error_list: + raise Exception(''.join(error_list)) + + buf.seek(0) + + code_line = {} + error_list = [] + + carriage_re = re.compile(r'\s*\^+$') + error_re = re.compile(r'^([C,R,W,E,F].+):\s+?([0-9]+):?.*:\s(.*)$') + + for line in buf: + line = line.rstrip() # remove trailing newline character + + if error_re.match(line): + if code_line: + error_list.append(code_line) + code_line = {} + + code_line['type'], code_line['lnum'], code_line['text'] = \ + error_re.match(line).groups() + + if carriage_re.match(line) and code_line: + code_line['col'] = carriage_re.match(line).group().find('^') + 1 + + return error_list + +if __name__ == "__main__": + parser = OptionParser("usage: %prog python_file") + (options, args) = parser.parse_args() + if len(args) == 1: + for line in parsable_pylint(args[0]): + line['short'] = line['type'][0] + line['fname'] = args[0] + if 'col' in line: + out = "%(fname)s: %(short)s: %(lnum)s: %(col)s: %(type)s %(text)s" + else: + out = "%(fname)s: %(short)s: %(lnum)s: 0: %(type)s %(text)s" + + print out % line diff --git a/compiler/pylint.vim b/compiler/pylint.vim index fb2ece5..f7d4c5d 100644 --- a/compiler/pylint.vim +++ b/compiler/pylint.vim @@ -1,126 +1,12 @@ " Vim compiler file for Python -" Compiler: Style checking tool for Python -" Maintainer: Oleksandr Tymoshenko -" Last Change: 2009 Apr 19 -" Version: 0.5 -" Contributors: -" Artur Wroblewski -" Menno -" -" Installation: -" Drop pylint.vim in ~/.vim/compiler directory. Ensure that your PATH -" environment variable includes the path to 'pylint' executable. -" -" Add the following line to the autocmd section of .vimrc -" -" autocmd FileType python compiler pylint -" -" Usage: -" Pylint is called after a buffer with Python code is saved. QuickFix -" window is opened to show errors, warnings and hints provided by Pylint. -" Code rate calculated by Pylint is displayed at the bottom of the -" window. -" -" Above is realized with :Pylint command. To disable calling Pylint every -" time a buffer is saved put into .vimrc file -" -" let g:pylint_onwrite = 0 -" -" Displaying code rate calculated by Pylint can be avoided by setting -" -" let g:pylint_show_rate = 0 -" -" Openning of QuickFix window can be disabled with -" -" let g:pylint_cwindow = 0 -" -" Of course, standard :make command can be used as in case of every -" other compiler. -" - -if exists('current_compiler') - finish -endif -let current_compiler = 'pylint' - -if !exists('g:pylint_onwrite') - let g:pylint_onwrite = 1 +" Compiler: Static code checking tool for Python +" Maintainer: Roman 'gryf' Dobosz +" Last Change: 2010-09-12 +" Version: 1.0 +if exists("current_compiler") + finish endif -if !exists('g:pylint_show_rate') - let g:pylint_show_rate = 1 -endif - -if !exists('g:pylint_cwindow') - let g:pylint_cwindow = 1 -endif - -if exists(':Pylint') != 2 - command Pylint :call Pylint(0) -endif - -if exists(":CompilerSet") != 2 " older Vim always used :setlocal - command -nargs=* CompilerSet setlocal -endif - -" We should echo filename because pylint truncates .py -" If someone know better way - let me know :) -CompilerSet makeprg=(echo\ '[%]';\ pylint\ -r\ y\ %) - -" We could omit end of file-entry, there is only one file -" %+I... - include code rating information -" %-G... - remove all remaining report lines from quickfix buffer -CompilerSet efm=%+P[%f],%t:\ %#%l:%m,%Z,%+IYour\ code%m,%Z,%-G%.%# - -if g:pylint_onwrite - augroup python - au! - au BufWritePost * call Pylint(1) - augroup end -endif - -function! Pylint(writing) - if !a:writing && &modified - " Save before running - write - endif - - if has('win32') || has('win16') || has('win95') || has('win64') - setlocal sp=>%s - else - setlocal sp=>%s\ 2>&1 - endif - - " If check is executed by buffer write - do not jump to first error - if !a:writing - silent make - else - silent make! - endif - - if g:pylint_cwindow - cwindow - endif - - call PylintEvaluation() - - if g:pylint_show_rate - echon 'code rate: ' b:pylint_rate ', prev: ' b:pylint_prev_rate - endif -endfunction - -function! PylintEvaluation() - let l:list = getqflist() - let b:pylint_rate = '0.00' - let b:pylint_prev_rate = '0.00' - for l:item in l:list - if l:item.type == 'I' && l:item.text =~ 'Your code has been rated' - let l:re_rate = '\(-\?[0-9]\{1,2\}\.[0-9]\{2\}\)/' - let b:pylint_rate = substitute(l:item.text, '.*rated at '.l:re_rate.'.*', '\1', 'g') - " Only if there is information about previous run - if l:item.text =~ 'previous run: ' - let b:pylint_prev_rate = substitute(l:item.text, '.*previous run: '.l:re_rate.'.*', '\1', 'g') - endif - endif - endfor -endfunction +let current_compiler = "pylint" +CompilerSet makeprg=$HOME/.vim/bin/pylint_parseable.py\ % +CompilerSet efm=%f:\ %t:\ %l:\ %c:\ %m,%f:\ %t:\ %l:\ %m diff --git a/ftplugin/python/common.vim b/ftplugin/python/common.vim index 65c5c99..56cca97 100644 --- a/ftplugin/python/common.vim +++ b/ftplugin/python/common.vim @@ -1,28 +1,61 @@ -set cinkeys-=0# -set expandtab -set foldlevel=100 -set foldmethod=indent -set indentkeys-=0# -set list -set noautoindent -set shiftwidth=4 -set smartindent cinwords=if,elif,else,for,while,try,except,finally,def,class,with -set smarttab -set softtabstop=4 -set tabstop=4 -set textwidth=78 -set colorcolumn=+1 +setlocal cinkeys-=0# +setlocal indentkeys-=0# +setlocal expandtab +setlocal foldlevel=100 +setlocal foldmethod=indent +setlocal list +setlocal noautoindent +setlocal shiftwidth=4 +setlocal smartindent +setlocal cinwords=if,elif,else,for,while,try,except,finally,def,class,with +setlocal smarttab +setlocal softtabstop=4 +setlocal tabstop=4 +setlocal textwidth=78 +setlocal colorcolumn=+1 -inoremap # X# +set wildignore+=*.pyc + +"inoremap # X# "set ofu=syntaxcomplete#Complete -let g:pylint_onwrite = 0 " I don't want to run pylint on every save -compiler pylint - "autocmd FileType python setlocal omnifunc=pysmell#Complete let python_highlight_all=1 "Load views for py files autocmd BufWinLeave *.py mkview autocmd BufWinEnter *.py silent loadview + +compiler pylint + +finish "end here. all below is just for the record. + +" Pylint function, which can be optionally mapped to some keys. Currently +" not used. +if !exists('*runPyLint') + function runPyLint() + echohl Statement + echo "Running pylint (ctrl-c to cancel) ..." + echohl Normal + :Pylint + endfunction +endif + +if !exists('*PyLintBuf') + function PyLintBuf() + echohl Statement + echo "Running pylint (ctrl-c to cancel) ..." + echohl Normal + let file = expand('%:p') + let cmd = 'pylint --reports=n --output-format=text "' . file . '"' + + if has('win32') || has('win64') + let cmd = 'cmd /c "' . cmd . '"' + endif + + exec "bel silent new " . file . ".lint" + exec "silent! read! " . cmd + endfunction +endif + diff --git a/ftplugin/python/pep8_fn.vim b/ftplugin/python/pep8_fn.vim new file mode 100644 index 0000000..5c48ad0 --- /dev/null +++ b/ftplugin/python/pep8_fn.vim @@ -0,0 +1,119 @@ +" File: pep8_fn.vim +" Author: Roman 'gryf' Dobosz (gryf73 at gmail.com) +" Version: 1.0 +" Last Modified: 2010-09-12 +" +" Overview +" -------- +" This plugin provides functionality to static checks for python files +" regarding PEP8 guidance[1] as ":Pep8" command. +" +" This function does not use pep8[2] command line utility, but relies on pep8 +" module. +" +" This script uses python, therefore VIm should be compiled with python +" support. You can check it by issuing ":version" command, and search for +" "+python" inside features list. +" +" Couple of ideas was taken from pyflakes.vim[3] plugin. +" +" Installation +" ------------ +" 1. Copy the pep8_fn.vim file to the $HOME/.vim/ftplugin/python or +" $HOME/vimfiles/ftplugin/python or $VIM/vimfiles/ftplugin/python +" directory. If python directory doesn't exists, it should be created. +" Refer to the following Vim help topics for more information about Vim +" plugins: +" :help add-plugin +" :help add-global-plugin +" :help runtimepath +" 2. It should be possible to import pep8 from python interpreter (it should +" report no error): +" >>> import pep8 +" >>> +" If there are errors, install pep8 first. Simplest way to do it, is to +" use easy_install[4] shell command as a root: +" # easy_install pep8 +" 3. Restart Vim. +" 4. You can now use the ":Pep8" which will examine current python buffer +" and open quickfix buffer with errors if any. +" +" [1] http://www.python.org/dev/peps/pep-0008/ +" [2] http://pypi.python.org/pypi/pep8 +" [3] http://www.vim.org/scripts/script.php?script_id=2441 +" [4] http://pypi.python.org/pypi/setuptools + +if exists("b:did_pep8_plugin") + finish " only load once +else + let b:did_pep8_plugin = 1 +endif + +if !exists("b:did_pep8_init") + let b:did_pep8_init = 0 + + if !has('python') + echoerr "Error: the pep8_fn.vim plugin requires Vim to be compiled with +python" + finish + endif + + python << EOF +import vim +import sys +from StringIO import StringIO + +try: + import pep8 +except ImportError: + raise AssertionError('Error: pep8_fn.vim requires module pep8') + +class VImPep8(object): + + def __init__(self): + self.fname = vim.current.buffer.name + self.bufnr = vim.current.buffer.number + self.output = [] + + def reporter(self, lnum, col, text, check): + self.output.append([lnum, col, text]) + + def run(self): + pep8.process_options(['-r', vim.current.buffer.name]) + checker = pep8.Checker(vim.current.buffer.name) + checker.report_error = self.reporter + checker.check_all() + self.process_output() + + def process_output(self): + vim.command('call setqflist([])') + qf_list = [] + qf_dict = {} + + for line in self.output: + qf_dict['bufnr'] = self.bufnr + qf_dict['lnum'] = line[0] + qf_dict['col'] = line[1] + qf_dict['text'] = line[2] + qf_dict['type'] = line[2][0] + qf_list.append(qf_dict) + qf_dict = {} + + self.output = [] + vim.command('call setqflist(%s)' % str(qf_list)) + if qf_list: + vim.command('copen') +EOF + let b:did_pep8_init = 1 +endif + +if !exists('*s:Pep8') + function s:Pep8() + python << EOF +VImPep8().run() +EOF + endfunction +endif + +if !exists(":Pep8") + command Pep8 call s:Pep8() +endif diff --git a/ftplugin/python/pylint_fn.vim b/ftplugin/python/pylint_fn.vim new file mode 100644 index 0000000..28d36bf --- /dev/null +++ b/ftplugin/python/pylint_fn.vim @@ -0,0 +1,143 @@ +" File: pythonlint.vim +" Author: Roman 'gryf' Dobosz (gryf73 at gmail.com) +" Version: 1.0 +" Last Modified: 2010-09-11 +" +" Overview +" -------- +" This plugin provides ":Pylint" command, which put pylint result into quickfix +" buffer. This function does not uses pylint[1] command line utility, only +" python pylint.lint module is used instead. So it makes the pylint +" egg/package required for running this script. +" +" This script uses python, therefore VIm should be compiled with python +" support. You can check it by issuing ":version" command, and search for +" "+python" inside features list. +" +" Couple of ideas was taken from pyflakes.vim[2] plugin. +" +" Installation +" ------------ +" 1. Copy the pythonlint.vim file to the $HOME/.vim/ftplugin/python or +" $HOME/vimfiles/ftplugin/python or $VIM/vimfiles/ftplugin/python +" directory. If python directory doesn't exists, it should be created. +" Refer to the following Vim help topics for more information about Vim +" plugins: +" :help add-plugin +" :help add-global-plugin +" :help runtimepath +" 2. It should be possible to import pylint from python interpreter (it should +" report no error): +" >>> import pylint +" >>> +" If there are errors, install pylint first. Simplest way to do it, is to +" use easy_install[3] shell command as a root: +" # easy_install pylint +" 3. Restart Vim. +" 4. You can now use the ":Pylint" which will examine current python buffer +" and open quickfix buffer with errors if any. +" +" [1] http://www.logilab.org/project/pylint +" [2] http://www.vim.org/scripts/script.php?script_id=2441 +" [3] http://pypi.python.org/pypi/setuptools + +if exists("b:did_pylint_plugin") + finish " only load once +else + let b:did_pylint_plugin = 1 +endif + +if !exists("b:did_pylint_init") + let b:did_pylint_init = 0 + + if !has('python') + echoerr "Error: the pythonlint.vim plugin requires Vim to be compiled with +python" + finish + endif + + python << EOF +import vim +import sys +from StringIO import StringIO + +try: + from pylint import lint + from pylint.reporters.text import TextReporter +except ImportError: + raise AssertionError('Pylint is required for this plugin') + +class VImPylint(object): + + sys_stderr = sys.stderr + dummy_stderr = StringIO() + conf_msg = 'No config file found, using default configuration\n' + + @classmethod + def run(self): + """execute pylint and fill the quickfix""" + + # clear QF window + vim.command('call setqflist([])') + + # args + args = ['-rn', # display only the messages instead of full report + '-iy', # Include message's id in output + vim.current.buffer.name] + + buf = StringIO() # file-like buffer, instead of stdout + reporter = TextReporter(buf) + + sys.stderr = self.dummy_stderr + lint.Run(args, reporter=reporter, exit=False) + sys.stderr = self.sys_stderr + + self.dummy_stderr.seek(0) + error_list = self.dummy_stderr.readlines() + self.dummy_stderr.truncate(0) + if error_list and self.conf_msg in error_list: + error_list.remove(self.conf_msg) + if error_list: + raise Exception(''.join(error_list)) + + buf.seek(0) + + bufnr = vim.current.buffer.number + code_line = {} + error_list = [] + + carriage_re = re.compile(r'\s*\^+$') + error_re = re.compile(r'^([C,R,W,E,F].+):\s+?([0-9]+):?.*:\s(.*)$') + + for line in buf: + line = line.rstrip() # remove trailing newline character + + if error_re.match(line): + if code_line: + code_line['bufnr'] = bufnr + error_list.append(code_line) + code_line = {} + + code_line['type'], code_line['lnum'], code_line['text'] = \ + error_re.match(line).groups() + + if carriage_re.match(line) and code_line: + code_line['col'] = carriage_re.match(line).group().find('^') \ + + 1 + vim.command('call setqflist(%s)' % str(error_list)) + if error_list: + vim.command('copen') +EOF + let b:did_pylint_init = 1 +endif + +if !exists('*s:Pylint') + function s:Pylint() + python << EOF +VImPylint.run() +EOF + endfunction +endif + +if !exists(":Pylint") + command Pylint call s:Pylint() +endif