(defvar figleaf-annotation-file ".figleaf.el")
(defvar figleaf-annotations nil)
+(defun find-figleaf-annotation-file ()
+ (let ((dir (file-name-directory buffer-file-name))
+ (olddir "/"))
+ (while (and (not (equal dir olddir))
+ (not (file-regular-p (concat dir figleaf-annotation-file))))
+ (setq olddir dir
+ dir (file-name-directory (directory-file-name dir))))
+ (and (not (equal dir olddir)) (concat dir figleaf-annotation-file))
+))
+
(defun load-figleaf-annotations ()
- (let ((coverage
- (with-temp-buffer
- (insert-file-contents figleaf-annotation-file)
- (let ((form (read (current-buffer))))
- (eval form)))))
+ (let* ((annotation-file (find-figleaf-annotation-file))
+ (coverage
+ (with-temp-buffer
+ (insert-file-contents annotation-file)
+ (let ((form (read (current-buffer))))
+ (eval form)))))
(setq figleaf-annotations coverage)
coverage
))
(save-excursion
(dolist (ov (overlays-in (point-min) (point-max)))
(delete-overlay ov))
+ (setq figleaf-this-buffer-is-annotated nil)
))
-(defun figleaf-annotate (filename)
- (interactive)
- (let* ((allcoverage (load-figleaf-annotations))
- (thiscoverage (gethash filename allcoverage))
- (covered-lines (car thiscoverage))
- (code-lines (car (cdr thiscoverage)))
- )
- (save-excursion
- (dolist (ov (overlays-in (point-min) (point-max)))
- (delete-overlay ov))
- (dolist (covered-line covered-lines)
- (goto-line covered-line)
- ;;(add-text-properties (point) (line-end-position) '(face bold) )
- (overlay-put (make-overlay (point) (line-end-position))
+(defun figleaf-annotate (&optional show-code)
+ (interactive "P")
+ (let ((allcoverage (load-figleaf-annotations))
+ (filename-key buffer-file-name)
+ thiscoverage code-lines covered-lines uncovered-code-lines
+ )
+ (while (and (not (gethash filename-key allcoverage nil))
+ (string-match "/" filename-key))
+ ;; eat everything up to and including the first slash, then look again
+ (setq filename-key (substring filename-key
+ (+ 1 (string-match "/" filename-key)))))
+ (setq thiscoverage (gethash filename-key allcoverage nil))
+ (if thiscoverage
+ (progn
+ (setq figleaf-this-buffer-is-annotated t)
+ (setq code-lines (nth 0 thiscoverage)
+ covered-lines (nth 1 thiscoverage)
+ uncovered-code-lines (nth 2 thiscoverage)
+ )
+
+ (save-excursion
+ (dolist (ov (overlays-in (point-min) (point-max)))
+ (delete-overlay ov))
+ (if show-code
+ (dolist (line code-lines)
+ (goto-line line)
+ ;;(add-text-properties (point) (line-end-position) '(face bold) )
+ (overlay-put (make-overlay (point) (line-end-position))
;'before-string "C"
;'face '(background-color . "green")
- 'face '(:background "dark green")
- )
- )
- (dolist (code-line code-lines)
- (goto-line code-line)
- (overlay-put (make-overlay (point) (line-end-position))
+ 'face '(:background "dark green")
+ )
+ ))
+ (dolist (line uncovered-code-lines)
+ (goto-line line)
+ (overlay-put (make-overlay (point) (line-end-position))
;'before-string "D"
- ;'face '(:background "blue")
- ;'face '(:underline "blue")
- 'face '(:box "blue")
- )
- )
-)))
+ ;'face '(:background "blue")
+ ;'face '(:underline "blue")
+ 'face '(:box "red")
+ )
+ )
+ )
+ )
+ (message "unable to find coverage for this file"))
+))
+
+(defun figleaf-toggle-annotations (show-code)
+ (interactive "P")
+ (if figleaf-this-buffer-is-annotated
+ (figleaf-unannotate)
+ (figleaf-annotate show-code))
+)
+
+
+(setq figleaf-this-buffer-is-annotated nil)
+(make-variable-buffer-local 'figleaf-this-buffer-is-annotated)
+
+(define-minor-mode figleaf-annotation-minor-mode
+ "Minor mode to annotate code-coverage information"
+ nil
+ " FA"
+ '(
+ ("\C-ca" . figleaf-toggle-annotations)
+ )
+
+ () ; forms run on mode entry/exit
+)
+
return a[:i]
return ""
-def write_el(r2):
- filenames = sorted(r2.keys())
- out = open(".figleaf.el", "w")
- out.write("(setq figleaf-results '(\n")
- for f in filenames:
- linenumbers = r2[f]
- out.write(' ("%s" (%s))\n' % (f, " ".join([str(ln)
- for ln in linenumbers])))
- out.write(" ))\n")
- out.close()
+## def write_el(r2):
+## filenames = sorted(r2.keys())
+## out = open(".figleaf.el", "w")
+## out.write("(setq figleaf-results '(\n")
+## for f in filenames:
+## linenumbers = r2[f]
+## out.write(' ("%s" (%s))\n' % (f, " ".join([str(ln)
+## for ln in linenumbers])))
+## out.write(" ))\n")
+## out.close()
def write_el(r2, source):
filenames = sorted(r2.keys())
out = open(".figleaf.el", "w")
+ out.write("""
+;; This is an elisp-readable form of the figleaf coverage data. It defines a
+;; single top-level hash table in which the load-path-relative filename (like
+;; allmydata/download.py) is the key, and the value is a three-element list.
+;; The first element of this list is a list of line numbers that represent
+;; actual code. The second is a list of line numbers for lines which got used
+;; during the unit test. The third is a list of line numbers for code lines
+;; that were not covered (since 'code' and 'covered' start as sets, this last
+;; list is equal to 'code - covered').
+
+""")
out.write("(let ((results (make-hash-table :test 'equal)))\n")
for f in filenames:
covered_linenumbers = r2[f]
code_linenumbers = source[f]
- out.write(" (puthash \"%s\" '((%s) (%s)) results)\n"
+ uncovered_code = code_linenumbers - covered_linenumbers
+ out.write(" (puthash \"%s\" '((%s) (%s) (%s)) results)\n"
% (f,
- " ".join([str(ln) for ln in sorted(covered_linenumbers)]),
" ".join([str(ln) for ln in sorted(code_linenumbers)]),
+ " ".join([str(ln) for ln in sorted(covered_linenumbers)]),
+ " ".join([str(ln) for ln in sorted(uncovered_code)]),
))
out.write(" results)\n")
out.close()