This commit is contained in:
Kenneth Reitz
2010-11-07 06:55:07 -05:00
parent 2357f0ba6d
commit a6e8ac9d6e
73 changed files with 3556 additions and 0 deletions
Binary file not shown.
+1
View File
@@ -0,0 +1 @@
default
@@ -0,0 +1,2 @@
ebdcc0d237c74189d8c479110eb38c2c5b408a99 70
ebdcc0d237c74189d8c479110eb38c2c5b408a99 default
Binary file not shown.
+2
View File
@@ -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.
@@ -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
+3
View File
@@ -0,0 +1,3 @@
Should catching multiple exception types in an "except" increase complexity?
Handle nested functions.
+38
View File
@@ -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()
+192
View File
@@ -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))
+38
View File
@@ -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
+127
View File
@@ -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
View File
@@ -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"