mirror of
https://github.com/kennethreitz-archive/krvim.git
synced 2026-06-05 23:40:18 +00:00
Update.
This commit is contained in:
Binary file not shown.
@@ -0,0 +1 @@
|
||||
default
|
||||
@@ -0,0 +1,2 @@
|
||||
ebdcc0d237c74189d8c479110eb38c2c5b408a99 70
|
||||
ebdcc0d237c74189d8c479110eb38c2c5b408a99 default
|
||||
Binary file not shown.
@@ -0,0 +1,2 @@
|
||||
[paths]
|
||||
default = http://bitbucket.org/garybernhardt/pycomplexity
|
||||
@@ -0,0 +1,4 @@
|
||||
revlogv1
|
||||
store
|
||||
fncache
|
||||
dotencode
|
||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
BIN
Binary file not shown.
Binary file not shown.
BIN
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
@@ -0,0 +1,28 @@
|
||||
data/.hgignore.i
|
||||
data/CONTRIBUTORS.i
|
||||
data/TODO.txt.i
|
||||
data/base.vim.i
|
||||
data/build.py.i
|
||||
data/complexity.py.i
|
||||
data/complexity.vim.i
|
||||
data/grammar/count_nodes.py.i
|
||||
data/grammar/everything.py.i
|
||||
data/grammar/python_ast_node_types.txt.i
|
||||
data/linum.el.i
|
||||
data/pycomplexity.el.i
|
||||
data/runtests.py.i
|
||||
data/test.py.i
|
||||
data/tests/__init__.py.i
|
||||
data/tests/manual/test_function_on_first_line.py.i
|
||||
data/tests/manual/test_functions.py.i
|
||||
data/tests/manual/test_high_complexity_module.py.i
|
||||
data/tests/manual/test_update_function.py.i
|
||||
data/tests/test_comprehensions.py.i
|
||||
data/tests/test_conditionals.py.i
|
||||
data/tests/test_exceptions.py.i
|
||||
data/tests/test_functions_and_classes.py.i
|
||||
data/tests/test_integration.py.i
|
||||
data/tests/test_loops.py.i
|
||||
data/tests/test_scoped_objects.py.i
|
||||
data/tests/test_simple_statements.py.i
|
||||
data/tests/utils.py.i
|
||||
Binary file not shown.
@@ -0,0 +1,2 @@
|
||||
70 ebdcc0d237c74189d8c479110eb38c2c5b408a99
|
||||
|
||||
@@ -0,0 +1 @@
|
||||
default
|
||||
@@ -0,0 +1,3 @@
|
||||
0
|
||||
pull
|
||||
http://bitbucket.org/garybernhardt/pycomplexity
|
||||
@@ -0,0 +1,9 @@
|
||||
Original vim script by Gary Bernhardt
|
||||
Emacs support added by Ignas Mikalajūnas
|
||||
|
||||
Patches contributed by:
|
||||
- Godefroid Chapelle
|
||||
- Steve Bedford
|
||||
- Chris Clark
|
||||
- Peter Prohaska
|
||||
|
||||
@@ -0,0 +1,3 @@
|
||||
Should catching multiple exception types in an "except" increase complexity?
|
||||
|
||||
Handle nested functions.
|
||||
@@ -0,0 +1,38 @@
|
||||
" complexity.vim
|
||||
" Gary Bernhardt (http://blog.extracheese.org)
|
||||
"
|
||||
" This will add cyclomatic complexity annotations to your source code. It is
|
||||
" no longer wrong (as previous versions were!)
|
||||
|
||||
if !has('signs')
|
||||
finish
|
||||
endif
|
||||
if !has('python')
|
||||
finish
|
||||
endif
|
||||
python << endpython
|
||||
import vim
|
||||
%(python_source)s
|
||||
endpython
|
||||
|
||||
function! ShowComplexity()
|
||||
python << END
|
||||
show_complexity()
|
||||
END
|
||||
" no idea why it is needed to update colors each time
|
||||
" to actually see the colors
|
||||
hi low_complexity guifg=#004400 guibg=#004400
|
||||
hi medium_complexity guifg=#bbbb00 guibg=#bbbb00
|
||||
hi high_complexity guifg=#ff2222 guibg=#ff2222
|
||||
endfunction
|
||||
|
||||
hi SignColumn guifg=fg guibg=bg
|
||||
hi low_complexity guifg=#004400 guibg=#004400
|
||||
hi medium_complexity guifg=#bbbb00 guibg=#bbbb00
|
||||
hi high_complexity guifg=#ff2222 guibg=#ff2222
|
||||
sign define low_complexity text=XX texthl=low_complexity
|
||||
sign define medium_complexity text=XX texthl=medium_complexity
|
||||
sign define high_complexity text=XX texthl=high_complexity
|
||||
|
||||
autocmd! BufReadPost,BufWritePost,FileReadPost,FileWritePost *.py call ShowComplexity()
|
||||
|
||||
@@ -0,0 +1,192 @@
|
||||
;;; linum.el --- Display line numbers to the left of buffers
|
||||
|
||||
;; Copyright (C) 2007, 2008 Markus Triska
|
||||
|
||||
;; Author: Markus Triska <markus.triska@gmx.at>
|
||||
;; Keywords: convenience
|
||||
|
||||
;; This file is free software; you can redistribute it and/or modify
|
||||
;; it under the terms of the GNU General Public License as published by
|
||||
;; the Free Software Foundation; either version 3, or (at your option)
|
||||
;; any later version.
|
||||
|
||||
;; This file is distributed in the hope that it will be useful,
|
||||
;; but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
;; GNU General Public License for more details.
|
||||
|
||||
;; You should have received a copy of the GNU General Public License
|
||||
;; along with GNU Emacs; see the file GPL.txt . If not, write to
|
||||
;; the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
|
||||
;; Boston, MA 02110-1301, USA.
|
||||
|
||||
;;; Commentary:
|
||||
|
||||
;; Display line numbers for the current buffer. Copy linum.el to your
|
||||
;; load-path and add to your .emacs:
|
||||
|
||||
;; (require 'linum)
|
||||
|
||||
;; Then toggle display of line numbers with M-x linum-mode. To enable
|
||||
;; line numbering in all buffers, use M-x global-linum-mode.
|
||||
|
||||
;;; Code:
|
||||
|
||||
(defconst linum-version "0.9wza")
|
||||
|
||||
(defvar linum-overlays nil "Overlays used in this buffer.")
|
||||
(defvar linum-available nil "Overlays available for reuse.")
|
||||
(defvar linum-before-numbering-hook nil
|
||||
"Functions run in each buffer before line numbering starts.")
|
||||
|
||||
(mapc #'make-variable-buffer-local '(linum-overlays linum-available))
|
||||
|
||||
(defgroup linum nil
|
||||
"Show line numbers to the left of buffers"
|
||||
:group 'convenience)
|
||||
|
||||
;;;###autoload
|
||||
(defcustom linum-format 'dynamic
|
||||
"Format used to display line numbers. Either a format string
|
||||
like \"%7d\", 'dynamic to adapt the width as needed, or a
|
||||
function that is called with a line number as its argument and
|
||||
should evaluate to a string to be shown on that line. See also
|
||||
`linum-before-numbering-hook'."
|
||||
:group 'linum
|
||||
:type 'sexp)
|
||||
|
||||
(defface linum
|
||||
'((t :inherit (shadow default)))
|
||||
"Face for displaying line numbers in the display margin."
|
||||
:group 'linum)
|
||||
|
||||
(defcustom linum-eager t
|
||||
"Whether line numbers should be updated after each command.
|
||||
The conservative setting `nil' might miss some buffer changes,
|
||||
and you have to scroll or press C-l to update the numbers."
|
||||
:group 'linum
|
||||
:type 'boolean)
|
||||
|
||||
(defcustom linum-delay nil
|
||||
"Delay updates to give Emacs a chance for other changes."
|
||||
:group 'linum
|
||||
:type 'boolean)
|
||||
|
||||
;;;###autoload
|
||||
(define-minor-mode linum-mode
|
||||
"Toggle display of line numbers in the left marginal area."
|
||||
:lighter "" ; for desktop.el
|
||||
(if linum-mode
|
||||
(progn
|
||||
(if linum-eager
|
||||
(add-hook 'post-command-hook (if linum-delay
|
||||
'linum-schedule
|
||||
'linum-update-current) nil t)
|
||||
(add-hook 'after-change-functions 'linum-after-change nil t))
|
||||
(add-hook 'window-scroll-functions 'linum-after-scroll nil t)
|
||||
;; mistake in Emacs: window-size-change-functions cannot be local
|
||||
(add-hook 'window-size-change-functions 'linum-after-size)
|
||||
(add-hook 'change-major-mode-hook 'linum-delete-overlays nil t)
|
||||
(add-hook 'window-configuration-change-hook
|
||||
'linum-after-config nil t)
|
||||
(linum-update-current))
|
||||
(remove-hook 'post-command-hook 'linum-update-current t)
|
||||
(remove-hook 'post-command-hook 'linum-schedule t)
|
||||
(remove-hook 'window-size-change-functions 'linum-after-size)
|
||||
(remove-hook 'window-scroll-functions 'linum-after-scroll t)
|
||||
(remove-hook 'after-change-functions 'linum-after-change t)
|
||||
(remove-hook 'window-configuration-change-hook 'linum-after-config t)
|
||||
(remove-hook 'change-major-mode-hook 'linum-delete-overlays t)
|
||||
(linum-delete-overlays)))
|
||||
|
||||
;;;###autoload
|
||||
(define-globalized-minor-mode global-linum-mode linum-mode linum-on)
|
||||
|
||||
(defun linum-on ()
|
||||
(unless (minibufferp)
|
||||
(linum-mode 1)))
|
||||
|
||||
(defun linum-delete-overlays ()
|
||||
"Delete all overlays displaying line numbers for this buffer."
|
||||
(mapc #'delete-overlay linum-overlays)
|
||||
(setq linum-overlays nil)
|
||||
(dolist (w (get-buffer-window-list (current-buffer) nil t))
|
||||
(set-window-margins w 0)))
|
||||
|
||||
(defun linum-update-current ()
|
||||
"Update line numbers for the current buffer."
|
||||
(linum-update (current-buffer)))
|
||||
|
||||
(defun linum-update (buffer)
|
||||
"Update line numbers for all windows displaying BUFFER."
|
||||
(with-current-buffer buffer
|
||||
(when linum-mode
|
||||
(setq linum-available linum-overlays)
|
||||
(setq linum-overlays nil)
|
||||
(save-excursion
|
||||
(mapc #'linum-update-window
|
||||
(get-buffer-window-list buffer nil 'visible)))
|
||||
(mapc #'delete-overlay linum-available)
|
||||
(setq linum-available nil))))
|
||||
|
||||
(defun linum-update-window (win)
|
||||
"Update line numbers for the portion visible in window WIN."
|
||||
(goto-char (window-start win))
|
||||
(let ((line (line-number-at-pos))
|
||||
(limit (window-end win t))
|
||||
(fmt (cond ((stringp linum-format) linum-format)
|
||||
((eq linum-format 'dynamic)
|
||||
(let ((w (length (number-to-string
|
||||
(count-lines (point-min) (point-max))))))
|
||||
(concat "%" (number-to-string w) "d")))))
|
||||
(width 0))
|
||||
(run-hooks 'linum-before-numbering-hook)
|
||||
;; Create an overlay (or reuse an existing one) for each
|
||||
;; line visible in this window, if necessary.
|
||||
(while (and (not (eobp)) (<= (point) limit))
|
||||
(let* ((str (if fmt
|
||||
(propertize (format fmt line) 'face 'linum)
|
||||
(funcall linum-format line)))
|
||||
(visited (catch 'visited
|
||||
(dolist (o (overlays-in (point) (point)))
|
||||
(when (string= (overlay-get o 'linum-str) str)
|
||||
(unless (memq o linum-overlays)
|
||||
(push o linum-overlays))
|
||||
(setq linum-available (delete o linum-available))
|
||||
(throw 'visited t))))))
|
||||
(setq width (max width (length str)))
|
||||
(unless visited
|
||||
(let ((ov (if (null linum-available)
|
||||
(make-overlay (point) (point))
|
||||
(move-overlay (pop linum-available) (point) (point)))))
|
||||
(push ov linum-overlays)
|
||||
(overlay-put ov 'before-string
|
||||
(propertize " " 'display `((margin left-margin) ,str)))
|
||||
(overlay-put ov 'linum-str str))))
|
||||
(forward-line)
|
||||
(setq line (1+ line)))
|
||||
(set-window-margins win width)))
|
||||
|
||||
(defun linum-after-change (beg end len)
|
||||
;; update overlays on deletions, and after newlines are inserted
|
||||
(when (or (= beg end)
|
||||
(= end (point-max))
|
||||
;; TODO: use string-match-p with CVS or new release
|
||||
(string-match "\n" (buffer-substring-no-properties beg end)))
|
||||
(linum-update-current)))
|
||||
|
||||
(defun linum-after-scroll (win start)
|
||||
(linum-update (window-buffer win)))
|
||||
|
||||
(defun linum-after-size (frame)
|
||||
(linum-after-config))
|
||||
|
||||
(defun linum-schedule ()
|
||||
;; schedule an update; the delay gives Emacs a chance for display changes
|
||||
(run-with-idle-timer 0 nil #'linum-update-current))
|
||||
|
||||
(defun linum-after-config ()
|
||||
(walk-windows (lambda (w) (linum-update (window-buffer w))) nil 'visible))
|
||||
|
||||
(provide 'linum)
|
||||
;;; linum.el ends here
|
||||
@@ -0,0 +1,155 @@
|
||||
;;; pycomplexity.el --- Display python code complexity to the left of buffers
|
||||
|
||||
;; Copyright (C) 2009 Ignas Mikalajunas
|
||||
|
||||
;; Author: Ignas Mikalajunas
|
||||
;; Keywords: convenience
|
||||
|
||||
;; This file is free software; you can redistribute it and/or modify
|
||||
;; it under the terms of the GNU General Public License as published by
|
||||
;; the Free Software Foundation; either version 3, or (at your option)
|
||||
;; any later version.
|
||||
|
||||
;; This file is distributed in the hope that it will be useful,
|
||||
;; but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
;; GNU General Public License for more details.
|
||||
|
||||
;; You should have received a copy of the GNU General Public License
|
||||
;; along with GNU Emacs; see the file GPL.txt . If not, write to
|
||||
;; the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
|
||||
;; Boston, MA 02110-1301, USA.
|
||||
|
||||
;;; Commentary:
|
||||
|
||||
;; Display complexity information for the current buffer.
|
||||
|
||||
;; Add to your .emacs:
|
||||
|
||||
;; (add-to-list 'load-path "~/.site-lisp/pycomplexity/")
|
||||
|
||||
;; (require 'linum)
|
||||
;; (require 'pycomplexity)
|
||||
;; (add-hook 'python-mode-hook
|
||||
;; (function (lambda ()
|
||||
;; (pycomplexity-mode)
|
||||
;; (linum-mode))))
|
||||
|
||||
;;; Code:
|
||||
|
||||
(defconst pycomplexity-version "0.1")
|
||||
|
||||
|
||||
(defvar complexity-last-change 0 "Time last change to some python buffer happened.")
|
||||
(defvar complexity-data nil "Calcuated code complexity information for this buffer.")
|
||||
(make-variable-buffer-local 'complexity-data)
|
||||
|
||||
(defgroup pycomplexity nil
|
||||
"Show complexity information to the left of buffers"
|
||||
:group 'convenience)
|
||||
|
||||
(defface pycomplexity-complexity-low
|
||||
'((t (:background "green"
|
||||
:foreground "green")))
|
||||
"Face that marks simple code "
|
||||
:group 'pycomplexity)
|
||||
|
||||
(defface pycomplexity-complexity-normal
|
||||
'((t (:background "yellow"
|
||||
:foreground "yellow")))
|
||||
"Face that marks normal code "
|
||||
:group 'pycomplexity)
|
||||
|
||||
(defface pycomplexity-complexity-high
|
||||
'((t (:background "red"
|
||||
:foreground "red")))
|
||||
"Face that marks complex code "
|
||||
:group 'pycomplexity)
|
||||
|
||||
(defcustom pycomplexity-delay 5
|
||||
"Update coverage information once in this many seconds."
|
||||
:group 'pycomplexity
|
||||
:type 'int)
|
||||
|
||||
(defcustom pycomplexity-python "python"
|
||||
"Python interpreter used to run the complexity calculation script."
|
||||
:group 'pycomplexity
|
||||
:type 'string)
|
||||
|
||||
(defcustom pycomplexity-script
|
||||
(expand-file-name "complexity.py"
|
||||
(file-name-directory (or load-file-name buffer-file-name)))
|
||||
"Pycomplexity python script."
|
||||
:group 'pycomplexity
|
||||
:type 'string)
|
||||
|
||||
;;;###autoload
|
||||
(define-minor-mode pycomplexity-mode
|
||||
"Toggle display complexity of the python code you are editing."
|
||||
:lighter "" ; for desktop.el
|
||||
(if pycomplexity-mode
|
||||
(progn
|
||||
(add-hook 'after-change-functions 'pycomplexity-on-change nil t)
|
||||
(add-hook 'after-save-hook 'pycomplexity-on-change-force nil t)
|
||||
(setf linum-format 'pycomplexity-line-format)
|
||||
(pycomplexity-on-change-force))
|
||||
(setf linum-format 'dynamic)
|
||||
(remove-hook 'after-change-functions 'pycomplexity-on-change t)))
|
||||
|
||||
(defun pycomplexity-get-complexity (line data)
|
||||
(multiple-value-bind (face str complexity)
|
||||
(loop for info in data
|
||||
for from = (first info)
|
||||
for to = (second info)
|
||||
for complexity = (third info)
|
||||
when (and (>= line from)
|
||||
(<= line to))
|
||||
return (cond ((> complexity 14) (values 'pycomplexity-complexity-high "h" complexity))
|
||||
((> complexity 7) (values 'pycomplexity-complexity-normal "n" complexity))
|
||||
(t (values 'pycomplexity-complexity-low "l" complexity)))
|
||||
when (< line from)
|
||||
return (values 'default " " 0))
|
||||
(if face (values face str complexity)
|
||||
(values 'default " " 0))))
|
||||
|
||||
(defun pycomplexity-line-format (line)
|
||||
(multiple-value-bind (face str complexity)
|
||||
(pycomplexity-get-complexity line complexity-data)
|
||||
(propertize str 'face face
|
||||
'help-echo (format "Complexity of this function is %d" complexity))))
|
||||
|
||||
|
||||
(defun pycomplexity-make-buffer-copy ()
|
||||
(let* ((source-file-name buffer-file-name)
|
||||
(file-name (flymake-create-temp-inplace source-file-name "complexity")))
|
||||
(make-directory (file-name-directory file-name) 1)
|
||||
(write-region nil nil file-name nil 566)
|
||||
file-name))
|
||||
|
||||
(defun pycomplexity-get-raw-complexity-data (file-name)
|
||||
(shell-command-to-string (format "%s %s %s"
|
||||
pycomplexity-python
|
||||
pycomplexity-script
|
||||
file-name)))
|
||||
|
||||
(defun pycomplexity-on-change-force (&optional beg end len)
|
||||
(pycomplexity-on-change beg end len t))
|
||||
|
||||
(defun pycomplexity-on-change (&optional beg end len force)
|
||||
(let ((since-last-change (- (float-time) complexity-last-change)))
|
||||
(when (or (> since-last-change pycomplexity-delay) force)
|
||||
(setf complexity-last-change (float-time))
|
||||
(let* ((temp-source-file-name (pycomplexity-make-buffer-copy))
|
||||
(result (pycomplexity-get-raw-complexity-data temp-source-file-name))
|
||||
(data (loop
|
||||
for line in (save-match-data (split-string result "[\n\r]+"))
|
||||
for parsed-line = (loop for item in (split-string line)
|
||||
when item collect (read item))
|
||||
when (and parsed-line
|
||||
(equal (car (last parsed-line)) 'function))
|
||||
collect (subseq parsed-line 0 3))))
|
||||
(when data (setf complexity-data data))
|
||||
(delete-file temp-source-file-name)))))
|
||||
|
||||
(provide 'pycomplexity)
|
||||
;;; pycomplexity.el ends here
|
||||
@@ -0,0 +1 @@
|
||||
|
||||
@@ -0,0 +1,29 @@
|
||||
def RED():
|
||||
a if a else a
|
||||
a if a else a
|
||||
a if a else a
|
||||
a if a else a
|
||||
a if a else a
|
||||
a if a else a
|
||||
a if a else a
|
||||
a if a else a
|
||||
a if a else a
|
||||
a if a else a
|
||||
a if a else a
|
||||
a if a else a
|
||||
a if a else a
|
||||
a if a else a
|
||||
a if a else a
|
||||
a if a else a
|
||||
a if a else a
|
||||
a if a else a
|
||||
a if a else a
|
||||
a if a else a
|
||||
a if a else a
|
||||
a if a else a
|
||||
a if a else a
|
||||
a if a else a
|
||||
a if a else a
|
||||
a if a else a
|
||||
a if a else a
|
||||
|
||||
@@ -0,0 +1,45 @@
|
||||
def one():
|
||||
pass
|
||||
|
||||
def two():
|
||||
a if a else a
|
||||
|
||||
def three():
|
||||
a if a else a if a else a
|
||||
|
||||
def four():
|
||||
a if a else a if a else a if a else a
|
||||
|
||||
def five():
|
||||
a if a else a if a else a if a else a if a else a
|
||||
|
||||
def six():
|
||||
a if a else a if a else a if a else a if a else a if a else a
|
||||
|
||||
def seven():
|
||||
a if a else a if a else a if a else a if a else a if a else a if a else a
|
||||
|
||||
def eight():
|
||||
a if a else a if a else a if a else a if a else a if a else a if a else a if a else a
|
||||
|
||||
def nine():
|
||||
a if a else a if a else a if a else a if a else a if a else a if a else a if a else a if a else a
|
||||
|
||||
def ten():
|
||||
a if a else a if a else a if a else a if a else a if a else a if a else a if a else a if a else a if a else a
|
||||
|
||||
def eleven():
|
||||
a if a else a if a else a if a else a if a else a if a else a if a else a if a else a if a else a if a else a if a else a
|
||||
|
||||
def twelve():
|
||||
a if a else a if a else a if a else a if a else a if a else a if a else a if a else a if a else a if a else a if a else a if a else a
|
||||
|
||||
def thirteen():
|
||||
a if a else a if a else a if a else a if a else a if a else a if a else a if a else a if a else a if a else a if a else a if a else a if a else a
|
||||
|
||||
def fourteen():
|
||||
a if a else a if a else a if a else a if a else a if a else a if a else a if a else a if a else a if a else a if a else a if a else a if a else a if a else a
|
||||
|
||||
def fifteen():
|
||||
a if a else a if a else a if a else a if a else a if a else a if a else a if a else a if a else a if a else a if a else a if a else a if a else a if a else a if a else a
|
||||
|
||||
@@ -0,0 +1,2 @@
|
||||
a if a else a if a else a if a else a if a else a if a else a if a else a if a else a if a else a if a else a if a else a if a else a if a else a if a else a if a else a
|
||||
|
||||
@@ -0,0 +1,9 @@
|
||||
def foo():
|
||||
x if x else x if x else x if x else x if x else x if x else x if x else x
|
||||
# Delete this line, then save. The function should go from yellow to
|
||||
# green. Then undo and save. The *whole thing* should go back to yellow.
|
||||
x if x else x
|
||||
pass
|
||||
pass
|
||||
pass
|
||||
|
||||
@@ -0,0 +1,58 @@
|
||||
from tests.utils import complexity
|
||||
|
||||
|
||||
class describe_list_comprehensions:
|
||||
def test_list_comprehension(self):
|
||||
assert complexity("[x for x in y]").score == 2
|
||||
|
||||
def test_list_comprehension_with_inline_conditional(self):
|
||||
assert complexity("[x if y else z for x in x]").score == 3
|
||||
|
||||
def test_nested_list_comprehensions(self):
|
||||
assert complexity("[x for x in [y for y in z]]").score == 3
|
||||
|
||||
def test_list_comprehensions_with_multiple_fors(self):
|
||||
assert complexity("[x for x in y for y in z]").score == 3
|
||||
|
||||
def test_list_comprehension_with_conditional(self):
|
||||
assert complexity("[x for x in y if x]").score == 3
|
||||
|
||||
def test_list_comprehension_with_multiple_conditionals(self):
|
||||
assert complexity("[x for x in y if x and y]").score == 4
|
||||
|
||||
def test_list_comprehension_with_multiple_conditionals_and_fors(self):
|
||||
assert complexity(
|
||||
"""
|
||||
[x for x in x
|
||||
for y in y
|
||||
if x and y]
|
||||
""").score == 5
|
||||
|
||||
|
||||
class describe_generator_expression:
|
||||
def test_generator_expression(self):
|
||||
assert complexity("(x for x in y)").score == 2
|
||||
|
||||
def test_with_inline_conditional(self):
|
||||
assert complexity("(x if y else z for x in x)").score == 3
|
||||
|
||||
def test_nested(self):
|
||||
assert complexity("(x for x in (y for y in z))").score == 3
|
||||
|
||||
def test_with_multiple_fors(self):
|
||||
assert complexity("(x for x in y for y in z)").score == 3
|
||||
|
||||
def test_with_conditional(self):
|
||||
assert complexity("(x for x in y if x)").score == 3
|
||||
|
||||
def test_with_multiple_conditionals(self):
|
||||
assert complexity("(x for x in y if x and y)").score == 4
|
||||
|
||||
def test_with_multiple_conditionals_and_fors(self):
|
||||
assert complexity(
|
||||
"""
|
||||
(x for x in x
|
||||
for y in y
|
||||
if x and y)
|
||||
""").score == 5
|
||||
|
||||
@@ -0,0 +1,95 @@
|
||||
from tests.utils import complexity
|
||||
|
||||
|
||||
class describe_conditionals:
|
||||
def test_simple_branch(self):
|
||||
assert complexity(
|
||||
"""
|
||||
if x: 1
|
||||
# implicit else
|
||||
""").score == 2
|
||||
|
||||
def test_branch_with_else(self):
|
||||
assert complexity(
|
||||
"""
|
||||
if x: 1
|
||||
else: 2
|
||||
""").score == 2
|
||||
|
||||
def test_branch_with_else_if(self):
|
||||
assert complexity(
|
||||
"""
|
||||
if x: 1
|
||||
elif y: 2
|
||||
# implicit else
|
||||
""").score == 3
|
||||
|
||||
def test_branch_with_else_if_and_else(self):
|
||||
assert complexity(
|
||||
"""
|
||||
if x: 1
|
||||
elif y: 2
|
||||
else: 3
|
||||
""").score == 3
|
||||
|
||||
def test_child_nodes_of_ifs(self):
|
||||
assert complexity(
|
||||
"""
|
||||
if x:
|
||||
if y: 1
|
||||
else: 2
|
||||
else: 3
|
||||
""").score == 3
|
||||
|
||||
def test_child_nodes_of_elses(self):
|
||||
assert complexity(
|
||||
"""
|
||||
if x: 1
|
||||
else:
|
||||
if y: 1
|
||||
# implicit else
|
||||
""").score == 3
|
||||
|
||||
def test_compound_conditionals(self):
|
||||
assert complexity(
|
||||
"""
|
||||
if x or y: 1
|
||||
""").score == 3
|
||||
|
||||
def test_chained_compound_conditionals(self):
|
||||
assert complexity(
|
||||
"""
|
||||
if a or b or c and d and e: 1
|
||||
""").score == 6
|
||||
|
||||
def test_nested_compound_conditionals(self):
|
||||
assert complexity(
|
||||
"""
|
||||
if x or (y or z): 1
|
||||
""").score == 4
|
||||
|
||||
def test_logical_operator_inside_conditional_but_outside_test(self):
|
||||
assert complexity(
|
||||
"""
|
||||
if x:
|
||||
x and y
|
||||
""").score == 2
|
||||
|
||||
|
||||
class describe_inline_conditionals:
|
||||
def test_inline_conditionals(self):
|
||||
assert complexity("b if c else d").score == 2
|
||||
|
||||
def test_nested_inline_conditionals(self):
|
||||
assert complexity(
|
||||
"""
|
||||
(b
|
||||
if c
|
||||
else (d
|
||||
if e
|
||||
else f))
|
||||
""").score == 3
|
||||
|
||||
def test_logical_operator_in_inline_conditional(self):
|
||||
assert complexity("a if b and c else d").score == 3
|
||||
|
||||
@@ -0,0 +1,74 @@
|
||||
from tests.utils import complexity
|
||||
|
||||
|
||||
class describe_exception_handling:
|
||||
def test_try(self):
|
||||
assert complexity(
|
||||
"""
|
||||
try: 1
|
||||
except: 2
|
||||
""").score == 2
|
||||
|
||||
def test_try_with_multiple_excepts(self):
|
||||
assert complexity(
|
||||
"""
|
||||
try: 1
|
||||
except A: 2
|
||||
except B: 3
|
||||
except C: 4
|
||||
""").score == 4
|
||||
|
||||
def test_try_with_multiple_exception_types_in_one_except(self):
|
||||
assert complexity(
|
||||
"""
|
||||
try: 1
|
||||
except (A, B): 2
|
||||
""").score == 2
|
||||
|
||||
def test_try_with_child_nodes(self):
|
||||
assert complexity(
|
||||
"""
|
||||
try:
|
||||
if x: 1
|
||||
else: 2
|
||||
except: 2
|
||||
""").score == 3
|
||||
|
||||
def test_try_with_finally(self):
|
||||
assert complexity(
|
||||
"""
|
||||
try: 1
|
||||
except: 2
|
||||
finally: 3
|
||||
""").score == 2
|
||||
|
||||
def test_try_with_else(self):
|
||||
assert complexity(
|
||||
"""
|
||||
try: 1
|
||||
except: 2
|
||||
else: 3
|
||||
""").score == 2
|
||||
|
||||
def test_try_with_finally_and_child_nodes(self):
|
||||
# Try/finally/else/except are all deceiving. The try and finally don't
|
||||
# add any paths because they both always happen. An except adds one
|
||||
# (it can either happen or not), but an else doesn't (it's equivalent
|
||||
# to adding the code after the line in the try: that threw the
|
||||
# exception, so it doesn't add a path).
|
||||
assert complexity(
|
||||
"""
|
||||
try:
|
||||
if a: 1
|
||||
else: 2
|
||||
except:
|
||||
if a: 1
|
||||
else: 2
|
||||
else:
|
||||
if a: 1
|
||||
else: 2
|
||||
finally:
|
||||
if a: 1
|
||||
else: 2
|
||||
""").score == 6
|
||||
|
||||
@@ -0,0 +1,56 @@
|
||||
from tests.utils import complexity
|
||||
|
||||
|
||||
class describe_integration:
|
||||
def test_multiple_ifs_in_a_for_loop(self):
|
||||
assert complexity(
|
||||
"""
|
||||
for x in y:
|
||||
if x: pass
|
||||
# implicit else
|
||||
if y: pass
|
||||
# implicit else
|
||||
""").score == 4
|
||||
|
||||
def test_lambdas_in_a_function(self):
|
||||
assert complexity(
|
||||
"""
|
||||
def foo():
|
||||
x = lambda: x if x else x
|
||||
y if y else y
|
||||
""").results.named('foo').score == 3
|
||||
|
||||
def test_a_big_hairy_mess(self):
|
||||
assert complexity(
|
||||
"""
|
||||
while True: #1
|
||||
if x and y or (z and w): #4
|
||||
try:
|
||||
x or y
|
||||
raise x
|
||||
except: #1
|
||||
5
|
||||
finally:
|
||||
break
|
||||
else:
|
||||
[x for x in [x and y for x in y if z or w]] #5
|
||||
try:
|
||||
return
|
||||
except A: #1
|
||||
return
|
||||
except B: #1
|
||||
(y for y in z) #1
|
||||
finally:
|
||||
raise (x for x in z) #1
|
||||
""").score == 15
|
||||
|
||||
def test_module_stat_comes_before_function_stat(self):
|
||||
stats = complexity("def foo(): pass\npass").results
|
||||
stat_names = [stat.name for stat in stats.ordered_by_line()]
|
||||
assert stat_names == ['<module>', 'foo']
|
||||
|
||||
def test_class_stat_comes_before_module_stat(self):
|
||||
stats = complexity("class Foo: pass\npass").results
|
||||
stat_names = [stat.name for stat in stats.ordered_by_line()]
|
||||
assert stat_names == ['<module>', 'Foo']
|
||||
|
||||
@@ -0,0 +1,135 @@
|
||||
from tests.utils import complexity
|
||||
|
||||
|
||||
class describe_for_loops:
|
||||
def test_for_loops(self):
|
||||
assert complexity(
|
||||
"""
|
||||
for x in y: 1
|
||||
# implicit else
|
||||
""").score == 2
|
||||
|
||||
def test_else_clauses_on_for_loops(self):
|
||||
assert complexity(
|
||||
"""
|
||||
for x in y: 1
|
||||
else: 2
|
||||
""").score == 2
|
||||
|
||||
def test_child_nodes_of_for_loops(self):
|
||||
assert complexity(
|
||||
"""
|
||||
for x in y:
|
||||
if x: 1
|
||||
else: 2
|
||||
# implicit else
|
||||
""").score == 3
|
||||
|
||||
def test_child_nodes_in_for_loop_else_clauses(self):
|
||||
assert complexity(
|
||||
"""
|
||||
for x in y: 1
|
||||
else:
|
||||
if x: 2
|
||||
else: 3
|
||||
""").score == 3
|
||||
|
||||
def test_break_statements_in_for_loops(self):
|
||||
# This seems like it should be more complex than an if with "pass"es,
|
||||
# but it's not. The break just reroutes the "if" path: instead of
|
||||
# going to the end of the loop and back up top, it goes straight back
|
||||
# up.
|
||||
assert complexity(
|
||||
"""
|
||||
for x in y:
|
||||
if x:
|
||||
break
|
||||
""").score == 3
|
||||
|
||||
def test_break_statements_in_for_loops_with_else_clauses(self):
|
||||
# A "break" in a for loop skips the "else". My intuitive
|
||||
# interpretation is that this should increase CC by one. However, it's
|
||||
# basically a GOTO, and GOTOs don't increase the CC. Drawing the graph
|
||||
# out seems to confirm that a "break" with an "else" does not add a
|
||||
# path.
|
||||
assert complexity(
|
||||
"""
|
||||
for x in y:
|
||||
if x:
|
||||
break
|
||||
else:
|
||||
pass
|
||||
""").score == 3
|
||||
|
||||
def test_continue_statement_in_for_loop(self):
|
||||
assert complexity(
|
||||
"""
|
||||
for x in y:
|
||||
if x:
|
||||
continue
|
||||
""").score == 3
|
||||
|
||||
|
||||
# These are basically identical to the "for" loop tests, but abstracting them
|
||||
# to remove the duplication would be just as long and more confusing.
|
||||
class describe_while_loops:
|
||||
def test_while_loops(self):
|
||||
assert complexity(
|
||||
"""
|
||||
while x: 1
|
||||
# implicit else
|
||||
""").score == 2
|
||||
|
||||
def test_else_clauses_on_while_loops(self):
|
||||
assert complexity(
|
||||
"""
|
||||
while x: 1
|
||||
else: 2
|
||||
""").score == 2
|
||||
|
||||
def test_child_nodes_of_while_loops(self):
|
||||
assert complexity(
|
||||
"""
|
||||
while x:
|
||||
if x: 1
|
||||
else: 2
|
||||
# implicit else
|
||||
""").score == 3
|
||||
|
||||
def test_child_nodes_in_while_loop_else_clauses(self):
|
||||
assert complexity(
|
||||
"""
|
||||
while x: 1
|
||||
else:
|
||||
if x: 2
|
||||
else: 3
|
||||
""").score == 3
|
||||
|
||||
def test_break_statements_in_while_loops(self):
|
||||
# See discussion for "for" loops above.
|
||||
assert complexity(
|
||||
"""
|
||||
while x:
|
||||
if x:
|
||||
break
|
||||
""").score == 3
|
||||
|
||||
def test_break_statements_in_while_loops_with_else_clauses(self):
|
||||
# See discussion for for loops above.
|
||||
assert complexity(
|
||||
"""
|
||||
while x:
|
||||
if x:
|
||||
break
|
||||
else:
|
||||
pass
|
||||
""").score == 3
|
||||
|
||||
def test_continue_statement_in_while_loop(self):
|
||||
assert complexity(
|
||||
"""
|
||||
while x:
|
||||
if x:
|
||||
continue
|
||||
""").score == 3
|
||||
|
||||
@@ -0,0 +1,163 @@
|
||||
from tests.utils import complexity
|
||||
|
||||
|
||||
class describe_modules:
|
||||
def test_that_they_are_scored(self):
|
||||
assert complexity(
|
||||
"""
|
||||
a if a else a
|
||||
""").results.named('<module>').score == 2
|
||||
assert complexity(
|
||||
"""
|
||||
0 if x else 1 if y else 2
|
||||
""").results.named('<module>').score == 3
|
||||
|
||||
def test_that_they_know_their_names(self):
|
||||
assert complexity("").results.named('<module>').name == '<module>'
|
||||
|
||||
def test_that_they_know_their_line_range(self):
|
||||
stats = complexity("").results.named('<module>')
|
||||
assert stats.start_line == 1
|
||||
assert stats.end_line == 1
|
||||
|
||||
stats = complexity(
|
||||
"""
|
||||
a
|
||||
""").results.named('<module>')
|
||||
print '-%s-' % (
|
||||
"""
|
||||
a
|
||||
""")
|
||||
assert stats.start_line == 1
|
||||
assert stats.end_line == 3
|
||||
|
||||
def test_module_with_function_in_it(self):
|
||||
assert complexity(
|
||||
"""
|
||||
a if a else a
|
||||
def foo():
|
||||
a if a else a
|
||||
a if a else a
|
||||
""").results.named('<module>').score == 3
|
||||
|
||||
|
||||
class describe_functions:
|
||||
def test_that_they_are_scored(self):
|
||||
assert complexity(
|
||||
"""
|
||||
def foo():
|
||||
0 if x else 1
|
||||
""").results.named('foo').score == 2
|
||||
assert complexity(
|
||||
"""
|
||||
def foo():
|
||||
0 if x else 1 if y else 2
|
||||
""").results.named('foo').score == 3
|
||||
|
||||
def test_that_they_know_their_names(self):
|
||||
assert complexity(
|
||||
"""
|
||||
def foo(): pass
|
||||
""").results.named('foo').name == 'foo'
|
||||
|
||||
def test_that_they_know_their_line_range(self):
|
||||
stats = complexity("def foo(): pass").results.named('foo')
|
||||
assert stats.start_line == 1
|
||||
assert stats.end_line == 1
|
||||
|
||||
stats = complexity(
|
||||
"""
|
||||
def foo(): pass
|
||||
""").results.named('foo')
|
||||
assert stats.start_line == 2
|
||||
assert stats.end_line == 2
|
||||
|
||||
|
||||
class describe_classes:
|
||||
def test_that_they_are_scored(self):
|
||||
assert complexity(
|
||||
"""
|
||||
class Foo:
|
||||
0 if x else 1
|
||||
""").results.named('Foo').score == 2
|
||||
assert complexity(
|
||||
"""
|
||||
class Foo:
|
||||
0 if x else 1 if y else 2
|
||||
""").results.named('Foo').score == 3
|
||||
|
||||
def test_that_they_know_their_names(self):
|
||||
assert complexity(
|
||||
"""
|
||||
class Foo: pass
|
||||
""").results.named('Foo').name == 'Foo'
|
||||
|
||||
def test_that_they_know_their_line_range(self):
|
||||
stats = complexity("class Foo: pass").results.named('Foo')
|
||||
assert stats.start_line == 1
|
||||
assert stats.end_line == 1
|
||||
|
||||
stats = complexity(
|
||||
"""
|
||||
class Foo:
|
||||
pass
|
||||
""").results.named('Foo')
|
||||
assert stats.start_line == 2
|
||||
assert stats.end_line == 3
|
||||
|
||||
def test_that_they_include_code_interspersed_with_methods(self):
|
||||
stats = complexity(
|
||||
"""
|
||||
class Foo:
|
||||
0 if x else 1
|
||||
def foo(self): pass
|
||||
0 if x else 1
|
||||
""").results.named('Foo')
|
||||
assert stats.score == 3
|
||||
assert stats.end_line == 5
|
||||
|
||||
|
||||
|
||||
class describe_methods:
|
||||
def test_that_they_are_scored(self):
|
||||
assert complexity(
|
||||
"""
|
||||
class Foo:
|
||||
def foo():
|
||||
0 if x else 1
|
||||
""").results.named('Foo.foo').score == 2
|
||||
assert complexity(
|
||||
"""
|
||||
class Foo:
|
||||
def foo():
|
||||
0 if x else 1 if y else 2
|
||||
""").results.named('Foo.foo').score == 3
|
||||
|
||||
def test_that_they_know_their_names(self):
|
||||
assert complexity(
|
||||
"""
|
||||
class Foo:
|
||||
def foo(): pass
|
||||
""").results.named('Foo.foo').name == 'Foo.foo'
|
||||
|
||||
def test_that_they_know_their_line_range(self):
|
||||
stats = complexity(
|
||||
"""
|
||||
class Foo():
|
||||
def foo():
|
||||
pass
|
||||
""").results.named('Foo.foo')
|
||||
assert stats.start_line == 3
|
||||
assert stats.end_line == 4
|
||||
|
||||
stats = complexity(
|
||||
"""
|
||||
pass
|
||||
class Foo:
|
||||
def foo():
|
||||
pass
|
||||
pass
|
||||
""").results.named('Foo.foo')
|
||||
assert stats.start_line == 4
|
||||
assert stats.end_line == 6
|
||||
|
||||
@@ -0,0 +1,34 @@
|
||||
from tests.utils import complexity
|
||||
|
||||
|
||||
class describe_simple_statements:
|
||||
def test_pass(self):
|
||||
assert complexity('pass').score == 1
|
||||
|
||||
def test_statement_sequence(self):
|
||||
assert complexity(
|
||||
"""
|
||||
pass
|
||||
pass
|
||||
""").score == 1
|
||||
|
||||
def test_constant(self):
|
||||
assert complexity("1").score == 1
|
||||
|
||||
def test_assignment(self):
|
||||
assert complexity("x = 1").score == 1
|
||||
|
||||
def test_name(self):
|
||||
assert complexity("a").score == 1
|
||||
|
||||
def test_sequence_of_names(self):
|
||||
assert complexity(
|
||||
"""
|
||||
a
|
||||
b
|
||||
c
|
||||
""").score == 1
|
||||
|
||||
def test_logical_operators(self):
|
||||
assert complexity('a and b or (c or d and not e)').score == 1
|
||||
|
||||
@@ -0,0 +1,8 @@
|
||||
from textwrap import dedent
|
||||
|
||||
from complexity import compute_code_complexity
|
||||
|
||||
|
||||
def complexity(code):
|
||||
return compute_code_complexity(dedent(code))
|
||||
|
||||
@@ -0,0 +1,38 @@
|
||||
Installation
|
||||
------------
|
||||
1. Install [pyflakes](http://pypi.python.org/pypi/pyflakes/)
|
||||
2. Copy the file `ftplugin/python_pyflakes.vim` to your `~/.vim/ftplugin` directory
|
||||
|
||||
|
||||
Usage
|
||||
-----
|
||||
1. Open a Python file
|
||||
2. Press `<F7>` to run `pyflakes` on it
|
||||
|
||||
It shows the errors inside a quickfix window, which will allow your to quickly
|
||||
jump to the error locations by simply pressing [Enter].
|
||||
|
||||
|
||||
Customization
|
||||
-------------
|
||||
If you don't want to use the `<F7>` key for pyflakes-checking, simply remap it to
|
||||
another key. It autodetects whether it has been remapped and won't register
|
||||
the `<F7>` key if so. For example, to remap it to `<F3>` instead, use:
|
||||
|
||||
autocmd FileType python map <buffer> <F3> :call Pyflakes()<CR>
|
||||
|
||||
|
||||
Tips
|
||||
----
|
||||
A tip might be to run the Pyflakes check every time you write a Python file, to
|
||||
enable this, add the following line to your `.vimrc` file (thanks
|
||||
[Godefroid](http://github.com/gotcha)!):
|
||||
|
||||
autocmd BufWritePost *.py call Pyflakes()
|
||||
|
||||
|
||||
This plugin goes well together with the following plugins:
|
||||
|
||||
- [PEP8](http://github.com/nvie/vim-pep8) (Python coding style checker under `<F6>`)
|
||||
- [PyUnit](http://github.com/nvie/vim-pyunit) (unit test helper under `<F8>`
|
||||
and `<F9>`)
|
||||
@@ -0,0 +1,74 @@
|
||||
"
|
||||
" Python filetype plugin for running pyflakes
|
||||
" Language: Python (ft=python)
|
||||
" Maintainer: Vincent Driessen <vincent@datafox.nl>
|
||||
" Version: Vim 7 (may work with lower Vim versions, but not tested)
|
||||
" URL: http://github.com/nvie/vim-pyflakes
|
||||
"
|
||||
" Only do this when not done yet for this buffer
|
||||
if exists("b:loaded_pyflakes_ftplugin")
|
||||
finish
|
||||
endif
|
||||
let b:loaded_pyflakes_ftplugin=1
|
||||
|
||||
let s:pyflakes_cmd="/usr/local/Cellar/python/2.7/Frameworks/Python.framework/Versions/2.7/bin//pyflakes"
|
||||
|
||||
if !exists("*Pyflakes()")
|
||||
function Pyflakes()
|
||||
if !executable(s:pyflakes_cmd)
|
||||
echoerr "File " . s:pyflakes_cmd . " not found. Please install it first."
|
||||
return
|
||||
endif
|
||||
|
||||
set lazyredraw " delay redrawing
|
||||
cclose " close any existing cwindows
|
||||
|
||||
" store old grep settings (to restore later)
|
||||
let l:old_gfm=&grepformat
|
||||
let l:old_gp=&grepprg
|
||||
|
||||
" write any changes before continuing
|
||||
if &readonly == 0
|
||||
update
|
||||
endif
|
||||
|
||||
" perform the grep itself
|
||||
let &grepformat="%f:%l: %m"
|
||||
let &grepprg=s:pyflakes_cmd
|
||||
silent! grep! %
|
||||
|
||||
" restore grep settings
|
||||
let &grepformat=l:old_gfm
|
||||
let &grepprg=l:old_gp
|
||||
|
||||
" open cwindow
|
||||
let has_results=getqflist() != []
|
||||
if has_results
|
||||
execute 'belowright copen'
|
||||
setlocal wrap
|
||||
nnoremap <buffer> <silent> c :cclose<CR>
|
||||
nnoremap <buffer> <silent> q :cclose<CR>
|
||||
endif
|
||||
|
||||
set nolazyredraw
|
||||
redraw!
|
||||
|
||||
if has_results == 0
|
||||
" Show OK status
|
||||
hi Green ctermfg=green
|
||||
echohl Green
|
||||
echon "Static analysis OK"
|
||||
echohl
|
||||
endif
|
||||
endfunction
|
||||
endif
|
||||
|
||||
" Add mappings, unless the user didn't want this.
|
||||
" The default mapping is registered under to <F7> by default, unless the user
|
||||
" remapped it already (or a mapping exists already for <F7>)
|
||||
if !exists("no_plugin_maps") && !exists("no_pyflakes_maps")
|
||||
if !hasmapto('Pyflakes(')
|
||||
noremap <buffer> <F7> :call Pyflakes()<CR>
|
||||
noremap! <buffer> <F7> :call Pyflakes()<CR>
|
||||
endif
|
||||
endif
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,127 @@
|
||||
" Vim compiler file for Python
|
||||
" Compiler: Style checking tool for Python
|
||||
" Maintainer: Oleksandr Tymoshenko <gonzo@univ.kiev.ua>
|
||||
" 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
|
||||
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 <args>
|
||||
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
|
||||
+330
@@ -0,0 +1,330 @@
|
||||
" Vim syntax file
|
||||
" Language: Pandoc (superset of Markdown)
|
||||
" Maintainer: Jeremy Schultz <taozhyn@gmail.com>
|
||||
" URL:
|
||||
" Version: 2
|
||||
" Changes: 2008-11-04
|
||||
" - Fixed an issue with Block elements (header) not being highlighted when
|
||||
" placed on the first or second line of the file
|
||||
" - Fixed multi line HTML comment block
|
||||
" - Fixed lowercase list items
|
||||
" - Fixed list items gobbling to many empty lines
|
||||
" - Added highlight support to identify newline (2 spaces)
|
||||
" - Fixed HTML highlight, ignore if the first character in the
|
||||
" angle brackets is not a letter
|
||||
" - Fixed Emphasis highlighting when it contained multiple
|
||||
" spaces
|
||||
" Remark: Uses HTML and TeX syntax file
|
||||
|
||||
if version < 600
|
||||
syntax clear
|
||||
elseif exists("b:current_syntax")
|
||||
finish
|
||||
endif
|
||||
|
||||
syn spell toplevel
|
||||
syn case ignore
|
||||
syn sync linebreaks=1
|
||||
|
||||
""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
|
||||
" Set embedded HTML highlighting
|
||||
syn include @HTML syntax/html.vim
|
||||
syn match pdcHTML /<\a[^>]\+>/ contains=@HTML
|
||||
|
||||
" Support HTML multi line comments
|
||||
syn region pdcHTMLComment start=/<!--/ end=/-->/
|
||||
|
||||
|
||||
""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
|
||||
" Set embedded LaTex (pandox extension) highlighting
|
||||
" Unset current_syntax so the 2nd include will work
|
||||
unlet b:current_syntax
|
||||
syn include @LATEX syntax/tex.vim
|
||||
|
||||
" Single Tex command
|
||||
syn match pdcLatex /\\\w\+{[^}]\+}/ contains=@LATEX
|
||||
|
||||
" Tex Block (begin-end)
|
||||
syn region pdcLatex start=/\\begin{[^}]\+}\ze/ end=/\ze\\end{[^}]\+}/ contains=@LATEX
|
||||
|
||||
" Math Tex
|
||||
syn match pdcLatex /$[^$]\+\$/ contains=@LATEX
|
||||
|
||||
|
||||
""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
|
||||
" Block Elements
|
||||
""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
|
||||
|
||||
" Needed by other elements
|
||||
syn match pdcBlankLine /\(^\s*\n\|\%^\)/ nextgroup=pdcHeader,pdcCodeBlock,pdcListItem,pdcListItem1,pdcHRule,pdcTableHeader,pdcTableMultiStart,pdcBlockquote transparent
|
||||
|
||||
|
||||
"""""""""""""""""""""""""""""""""""""""
|
||||
" Title Block:
|
||||
syn match pandocTitleBlock /\%^\(%.*\n\)\{1,3}$/
|
||||
|
||||
|
||||
"""""""""""""""""""""""""""""""""""""""
|
||||
" Headers:
|
||||
|
||||
" Underlined, using == or --
|
||||
syn match pdcHeader /^.\+\n[=-]\+$/ contains=@Spell nextgroup=pdcHeader contained skipnl
|
||||
|
||||
" Atx-style, Hash marks
|
||||
syn region pdcHeader start="^\s*#\{1,6}[^#]*" end="\($\|#\+\)" contains=@Spell contained nextgroup=pdcHeader skipnl
|
||||
|
||||
|
||||
"""""""""""""""""""""""""""""""""""""""
|
||||
" Blockquotes:
|
||||
|
||||
syn match pdcBlockquote /\s*>.*$/ nextgroup=pdcBlockquote,pdcBlockquote2 contained skipnl
|
||||
syn match pdcBlockquote2 /[^>].*/ nextgroup=pdcBlockquote2 skipnl contained
|
||||
|
||||
|
||||
"""""""""""""""""""""""""""""""""""""""
|
||||
" Code Blocks:
|
||||
|
||||
" Indent with at least 4 space or 1 tab
|
||||
" This rule must appear for pdcListItem, or highlighting gets messed up
|
||||
syn match pdcCodeBlock /\(\s\{4,}\|\t\{1,}\).*\n/ contained nextgroup=pdcCodeBlock
|
||||
|
||||
" HTML code blocks, pre and code
|
||||
syn match pdcCodeStartPre /<pre>/ nextgroup=pdcCodeHTMLPre skipnl transparent
|
||||
syn match pdcCodeHTMLPre /.*/ contained nextgroup=pdcCodeHTMLPre,pdcCodeEndPre skipnl
|
||||
syn match pdcCodeEndPre /\s*<\/pre>/ contained transparent
|
||||
|
||||
" HTML code blocks, code
|
||||
syn match pdcCodeStartCode /<code>/ nextgroup=pdcCodeHTMLCode skipnl transparent
|
||||
syn match pdcCodeHTMLCode /.*/ contained nextgroup=pdcCodeHTMLCode,pdcCodeEndCode skipnl
|
||||
syn match pdcCodeEndCode /\s*<\/code>/ contained transparent
|
||||
|
||||
|
||||
"""""""""""""""""""""""""""""""""""""""
|
||||
" Lists:
|
||||
|
||||
" These first two rules need to be first or the highlighting will be
|
||||
" incorrect
|
||||
|
||||
" Continue a list on the next line
|
||||
syn match pdcListCont /\s*[^-+*].*\n/ contained nextgroup=pdcListCont,pdcListItem,pdcListSkipNL transparent
|
||||
|
||||
" Skip empty lines
|
||||
syn match pdcListSkipNL /\s*\n/ contained nextgroup=pdcListItem,pdcListSkipNL
|
||||
|
||||
" Unorder list
|
||||
syn match pdcListItem /\s*[-*+]\s\+/ contained nextgroup=pdcListSkipNL,pdcListCont skipnl
|
||||
|
||||
" Order list, numeric
|
||||
syn match pdcListItem /\s*(\?\(\d\+\|#\)[\.)]\s\+/ contained nextgroup=pdcListSkipNL,pdcListCont skipnl
|
||||
|
||||
" Order list, roman numerals (does not guarantee correct roman numerals)
|
||||
syn match pdcListItem /\s*(\?[ivxlcdm]\+[\.)]\s\+/ contained nextgroup=pdcListSkipNL,pdcListCont skipnl
|
||||
|
||||
" Order list, lowercase letters
|
||||
syn match pdcListItem /\s*(\?\l[\.)]\s\+/ contained nextgroup=pdcListSkipNL,pdcListCont skipnl
|
||||
|
||||
" Order list, uppercase letters, does not include '.'
|
||||
syn match pdcListItem /\s*(\?\u[\)]\s\+/ contained nextgroup=pdcListSkipNL,pdcListCont skipnl
|
||||
|
||||
" Order list, uppercase letters, special case using '.' and two or more spaces
|
||||
syn match pdcListItem /\s*\u\.\([ ]\{2,}\|\t\+\)/ contained nextgroup=pdcListSkipNL,pdcListCont skipnl
|
||||
|
||||
|
||||
"""""""""""""""""""""""""""""""""""""""
|
||||
" Horizontal Rules:
|
||||
|
||||
" 3 or more * on a line
|
||||
syn match pdcHRule /\s\{0,3}\(-\s*\)\{3,}\n/ contained nextgroup=pdcHRule
|
||||
|
||||
" 3 or more - on a line
|
||||
syn match pdcHRule /\s\{0,3}\(\*\s*\)\{3,}\n/ contained nextgroup=pdcHRule
|
||||
|
||||
|
||||
""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
|
||||
" Span Elements
|
||||
""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
|
||||
|
||||
"""""""""""""""""""""""""""""""""""""""
|
||||
" Links:
|
||||
|
||||
" Link Text
|
||||
syn match pdcLinkText /\[\zs[^\]]*\ze\]/ contains=@Spell
|
||||
|
||||
" Link ID
|
||||
syn match pdcLinkID /\][ ]\{0,1}\[\zs[^\]]*\ze\]/
|
||||
|
||||
" Skip [ so we do not highlight it
|
||||
syn match pdcSkip /^[ ]\{0,3}\[/ nextgroup=pdcLinkID
|
||||
|
||||
" Link ID - definition
|
||||
syn match pdcLinkID /[^\]]*\ze\]:/ nextgroup=pdcSkip skipwhite contained
|
||||
|
||||
" Skip ]: so we do not highlight it
|
||||
syn match pdcSkip /\]:/ contained nextgroup=pdcLinkURL skipwhite
|
||||
|
||||
" Link URL
|
||||
syn region pdcLinkURL start=/\](\zs/ end=/)/me=e-1
|
||||
|
||||
" Link URL on ID definition line
|
||||
syn match pdcLinkURL /\s\+.*\s\+\ze[("']/ nextgroup=pdcLinkTitle skipwhite contained
|
||||
syn match pdcLinkURL /\s*.*\s*[^)"']\s*$/ contained
|
||||
syn match pdcLinkURL /\s*.*\s*[^)"']\s*\n\s*\ze[("']/ contained nextgroup=pdcLinkTitle skipwhite
|
||||
|
||||
" Link URL for inline <> links
|
||||
syn match pdcLinkURL /<http[^>]*>/
|
||||
syn match pdcLinkURL /<[^>]*@[^>]*.[^>]*>/
|
||||
|
||||
" Link Title
|
||||
syn match pdcLinkTitle /\s*[("'].*[)"']/ contained contains=@Spell
|
||||
|
||||
|
||||
"""""""""""""""""""""""""""""""""""""""
|
||||
" Emphasis:
|
||||
|
||||
" Using underscores
|
||||
syn match pdcEmphasis / \(_\|__\)\([^_ ]\|[^_]\( [^_]\)\+\)\+\1/ contains=@Spell
|
||||
|
||||
" Using Asterisks
|
||||
syn match pdcEmphasis / \(\*\|\*\*\)\([^\* ]\|[^\*]\( [^\*]\)\+\)\+\1/ contains=@Spell
|
||||
|
||||
|
||||
"""""""""""""""""""""""""""""""""""""""
|
||||
" Inline Code:
|
||||
|
||||
" Using single back ticks
|
||||
syn region pdcCode start=/`/ end=/`\|^\s*$/
|
||||
|
||||
" Using double back ticks
|
||||
syn region pdcCode start=/``[^`]*/ end=/``\|^\s*$/
|
||||
|
||||
|
||||
"""""""""""""""""""""""""""""""""""""""
|
||||
" Images:
|
||||
" Handled by link syntax
|
||||
|
||||
|
||||
"""""""""""""""""""""""""""""""""""""""
|
||||
" Misc:
|
||||
|
||||
" Pandoc escapes all characters after a backslash
|
||||
syn match NONE /\\\W/
|
||||
|
||||
|
||||
""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
|
||||
" Span Elements
|
||||
""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
|
||||
|
||||
"""""""""""""""""""""""""""""""""""""""
|
||||
" Subscripts:
|
||||
syn match pdcSubscript /\~\([^\~\\ ]\|\(\\ \)\)\+\~/ contains=@Spell
|
||||
|
||||
"""""""""""""""""""""""""""""""""""""""
|
||||
" Superscript:
|
||||
syn match pdcSuperscript /\^\([^\^\\ ]\|\(\\ \)\)\+\^/ contains=@Spell
|
||||
|
||||
"""""""""""""""""""""""""""""""""""""""
|
||||
" Strikeout:
|
||||
syn match pdcStrikeout /\~\~[^\~ ]\([^\~]\|\~ \)*\~\~/ contains=@Spell
|
||||
|
||||
|
||||
"""""""""""""""""""""""""""""""""""""""
|
||||
" Definitions:
|
||||
syn match pdcDefinitions /:\(\t\|[ ]\{3,}\)/ nextgroup=pdcListItem,pdcCodeBlock,pdcBlockquote,pdcHRule
|
||||
|
||||
"""""""""""""""""""""""""""""""""""""""
|
||||
" Footnote:
|
||||
syn match pdcFootnoteID /\[\^[^\]]\+\]/ nextgroup=pdcFootnoteDef
|
||||
|
||||
" This does not work correctly
|
||||
syn region pdcFootnoteDef start=/:/ end=/^\n\+\(\(\t\+\|[ ]\{4,}\)\S\)\@!/ contained contains=pdcFootnoteDef
|
||||
|
||||
" Inline footnotes
|
||||
syn region pdcFootnoteDef matchgroup=pdcFootnoteID start=/\^\[/ matchgroup=pdcFootnoteID end=/\]/
|
||||
|
||||
|
||||
"""""""""""""""""""""""""""""""""""""""
|
||||
" Tables:
|
||||
"
|
||||
" Regular Table
|
||||
syn match pdcTableHeader /\s*\w\+\(\s\+\w\+\)\+\s*\n\s*-\+\(\s\+-\+\)\+\s*\n/ contained nextgroup=pdcTableBody
|
||||
syn match pdcTableBody /\s*\w\+\(\s\+\w\+\)\+\s*\n/ contained nextgroup=pdcTableBody,pdcTableCaption skipnl
|
||||
syn match pdcTableCaption /\n\+\s*Table.*\n/ contained nextgroup=pdcTableCaptionCont
|
||||
syn match pdcTableCaptionCont /\s*\S.\+\n/ contained nextgroup=pdcTableCaptionCont
|
||||
|
||||
" Multi-line Table
|
||||
syn match pdcTableMultiStart /^\s\{0,3}-\+\s*\n\ze\(\s*\w\+\(\s\+\w\+\)\+\s*\n\)\+\s*-\+\(\s\+-\+\)\+\s*\n/ contained nextgroup=pdcTableMultiHeader
|
||||
syn match pdcTableMultiEnd /^\s\{0,3}-\+/ contained nextgroup=pdcTableMultiCaption skipnl
|
||||
syn match pdcTableMultiHeader /\(\s*\w\+\(\s\+\w\+\)\+\s*\n\)\+\s*-\+\(\s\+-\+\)\+\s*\n/ contained nextgroup=pdcTableMultiBody
|
||||
syn match pdcTableMultiBody /^\(\s\{3,}[^-]\|[^-\s]\).*$/ contained nextgroup=pdcTableMultiBody,pdcTableMultiSkipNL,pdcTableMultiEnd skipnl
|
||||
syn match pdcTableMultiSkipNL /^\s*\n/ contained nextgroup=pdcTableMultiBody,pdcTableMultiEnd skipnl
|
||||
syn match pdcTableMultiCaption /\n*\s*Table.*\n/ contained nextgroup=pdcTableCaptionCont
|
||||
|
||||
|
||||
|
||||
"""""""""""""""""""""""""""""""""""""""
|
||||
" Delimited Code Block: (added in 1.0)
|
||||
syn region pdcCodeBlock matchgroup=pdcCodeStart start=/^\z(\~\{3,}\) \( {[^}]\+}\)\?/ matchgroup=pdcCodeEnd end=/^\z1\~*/
|
||||
|
||||
|
||||
"""""""""""""""""""""""""""""""""""""""
|
||||
" Newline, 2 spaces at the end of line means newline
|
||||
syn match pdcNewLine / $/
|
||||
|
||||
|
||||
""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
|
||||
" Highlight groups
|
||||
""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
|
||||
hi link pdcHeader Title
|
||||
hi link pdcBlockquote Comment
|
||||
hi link pdcBlockquote2 Comment
|
||||
|
||||
hi link pdcHTMLComment Comment
|
||||
|
||||
hi link pdcHRule Underlined
|
||||
"hi link pdcHRule Special
|
||||
|
||||
hi link pdcListItem Operator
|
||||
hi link pdcDefinitions Operator
|
||||
|
||||
hi link pdcEmphasis Special
|
||||
hi link pdcSubscript Special
|
||||
hi link pdcSuperscript Special
|
||||
hi link pdcStrikeout Special
|
||||
|
||||
hi link pdcLinkText Underlined
|
||||
hi link pdcLinkID Identifier
|
||||
hi link pdcLinkURL Type
|
||||
hi link pdcLinkTitle Comment
|
||||
|
||||
hi link pdcFootnoteID Identifier
|
||||
hi link pdcFootnoteDef Comment
|
||||
hi link pandocFootnoteCont Error
|
||||
|
||||
hi link pdcCodeBlock String
|
||||
hi link pdcCodeHTMLPre String
|
||||
hi link pdcCodeHTMLCode String
|
||||
hi link pdcCode String
|
||||
hi link pdcCodeStart Comment
|
||||
hi link pdcCodeEnd Comment
|
||||
|
||||
hi link pandocTitleBlock Comment
|
||||
|
||||
hi link pdcTableMultiStart Comment
|
||||
hi link pdcTableMultiEnd Comment
|
||||
hi link pdcTableHeader Define
|
||||
hi link pdcTableMultiHeader Define
|
||||
hi link pdcTableBody Identifier
|
||||
hi link pdcTableMultiBody Identifier
|
||||
hi link pdcTableCaption Label
|
||||
hi link pdcTableMultiCaption Label
|
||||
hi link pdcTableCaptionCont Label
|
||||
|
||||
hi link pdcNewLine Error
|
||||
|
||||
|
||||
" For testing
|
||||
hi link pdctest Error
|
||||
|
||||
|
||||
let b:current_syntax = "pandoc"
|
||||
|
||||
Reference in New Issue
Block a user