GNU bug report logs - #5911
flymake.el - enhancement request - flymake-goto-next-error should go to the column, if possible

Previous Next

Package: emacs;

Reported by: "D Chiesa" <dpchiesa <at> hotmail.com>

Date: Fri, 9 Apr 2010 05:56:01 UTC

Severity: wishlist

Merged with 8723

Found in version 23.2

Done: Stefan Kangas <stefankangas <at> gmail.com>

Bug is archived. No further changes may be made.

Full log


View this message in rfc822 format

From: "D Chiesa" <dpchiesa <at> hotmail.com>
To: 5911 <at> debbugs.gnu.org
Subject: bug#5911: flymake.el - enhancement request - flymake-goto-next-error should go to the column, if possible
Date: Fri, 9 Apr 2010 01:44:59 -0400
I use emacs v22.2.1 on Windows.

Flymake relies on compilation error patterns, similar to 
compilation-error-regexp-alist , to detect errors and warnings.
But flymake discards column information for any errors, and as a result, 
the functions flymake-goto-next-error and flymake-goto-prev-error do not 
position the cursor on the error column.

This discards useful information, and also makes it more difficult to add 
enhancements to flymake - such as the ability to offer a menu of "quick 
fixes" that can be applied on the spot, through 
flymake-display-err-menu-for-current-line .

The fix is to:

1- modify the flymake-ler struct, like so:

(defstruct (flymake-ler
           (:constructor nil)
           ;; cheeso = 2010 apr 8 - add col-no field
           (:constructor flymake-ler-make-ler (file line type text 
&optional full-file col-no)))
 file line type text full-file col-no)

2- modify the flymake-ler functions, accordingly

(defun flymake-ler-set-file (line-err-info file)
 (flymake-ler-make-ler file
                       (flymake-ler-line line-err-info)
                       (flymake-ler-type line-err-info)
                       (flymake-ler-text line-err-info)
                       (flymake-ler-full-file line-err-info)
                       ;; cheeso - 2010 apr 8
                       (flymake-ler-col-no line-err-info)
                       ))

(defun flymake-ler-set-full-file (line-err-info full-file)
 (flymake-ler-make-ler (flymake-ler-file line-err-info)
                       (flymake-ler-line line-err-info)
                       (flymake-ler-type line-err-info)
                       (flymake-ler-text line-err-info)
                       full-file
                       ;; cheeso - 2010 apr 8
                       (flymake-ler-col-no line-err-info)
                       ))

(defun flymake-ler-set-line (line-err-info line)
 (flymake-ler-make-ler (flymake-ler-file line-err-info)
                       line
                       (flymake-ler-type line-err-info)
                       (flymake-ler-text line-err-info)
                       (flymake-ler-full-file line-err-info)
                       ;; cheeso - 2010 apr 8
                       (flymake-ler-col-no line-err-info)
                       ))

3- modify   flymake-parse-line  to capture the column number, and store it 
in the flymake-ler struct that is created. (same as line-no, but use index 
3, instead of 2)

(defun flymake-parse-line (line)
 "Parse LINE to see if it is an error or warning.
Return its components if so, nil otherwise."
 (let ((raw-file-name nil)
       (line-no 0)
       (col-no 0)
       (err-type "e")
       (err-text nil)
       (patterns flymake-err-line-patterns)
       (matched nil))
   (while (and patterns (not matched))
     (when (string-match (car (car patterns)) line)
       (let* ((file-idx (nth 1 (car patterns)))
              (line-idx (nth 2 (car patterns)))
              (col-idx (nth 3 (car patterns)))
              )
         (setq raw-file-name (if file-idx (match-string file-idx line) 
nil))
         (setq line-no       (if line-idx (string-to-number (match-string 
line-idx line)) 0))
         (setq col-no        (if col-idx  (string-to-number (match-string 
col-idx line)) 0))
         (setq err-text      (if (> (length (car patterns)) 4)
                                 (match-string (nth 4 (car patterns)) line)
                               (flymake-patch-err-text (substring line 
(match-end 0)))))
         (or err-text (setq err-text "<no error text>"))
         (if (and err-text (string-match "^[wW]arning" err-text))
             (setq err-type "w")
           )
         (flymake-log 3 "parse line: file-idx=%s line-idx=%s file=%s 
line=%s text=%s" file-idx line-idx
                      raw-file-name line-no err-text)
         (setq matched t)))
     (setq patterns (cdr patterns)))
   (if matched
       ;; cheeso
       ;;(flymake-ler-make-ler raw-file-name line-no err-type err-text)
       (flymake-ler-make-ler raw-file-name line-no err-type err-text nil 
col-no)
     ())))


4 - introduce new fn flymake-er-get-line-col , which returns (LINE COL) for 
the error.

(defun flymake-er-get-line-col (err-info)
 (list (nth 0 err-info)
       (flymake-ler-col-no (car (nth 1 err-info))) ;; xxxx
       ))

5- transform all fns that get line number info, to get line+col info:

(defun flymake-get-first-err-line-col (err-info-list)
 "Return first line with error."
 (when err-info-list
   (flymake-er-get-line-col (car err-info-list))))

(defun flymake-get-last-err-line-col (err-info-list)
 "Return last line with error."
 (when err-info-list
   (flymake-er-get-line-col (nth (1- (length err-info-list)) 
err-info-list))))

(defun flymake-get-next-err-line-col (err-info-list line-no)
 "Return next line with error."
 (when err-info-list
   (let* ((count  (length err-info-list))
          (idx    0))
     (while (and (< idx count) (>= line-no (flymake-er-get-line (nth idx 
err-info-list))))
       (setq idx (1+ idx)))
     (if (< idx count)
         (flymake-er-get-line-col (nth idx err-info-list))))))

(defun flymake-get-prev-err-line-col (err-info-list line-no)
 "Return previous line with error."
 (when err-info-list
   (let* ((count (length err-info-list)))
     (while (and (> count 0) (<= line-no (flymake-er-get-line (nth (1- 
count) err-info-list))))
       (setq count (1- count)))
     (if (> count 0)
         (flymake-er-get-line-col (nth (1- count) err-info-list))))))


6- modify flymake-goto-next-error to use the column information

(defun flymake-goto-next-error ()
 "Go to next error in error ring. Return (LINE COL), or nil if there are no 
errors."
 (interactive)
 (let* ((line-col (flymake-get-next-err-line-col flymake-err-info 
(flymake-current-line-no)))
        (line-no (car line-col))
        (col-no  (cadr line-col))
       )
   (when (not line-no)
     (setq line-col (flymake-get-first-err-line-col flymake-err-info))
     (setq line-no (car line-col)
           col-no  (cadr line-col))
     (flymake-log 1 "passed end of file"))
   (if line-no
       (flymake-goto-line line-col)
     (flymake-log 1 "no errors in current buffer"))))

7- same for flymake-goto-prev-error

(defun flymake-goto-prev-error ()
 "Go to previous error in err ring."
 (interactive)
 (let* ((line-col (flymake-get-prev-err-line-col flymake-err-info 
(flymake-current-line-no)))
        (line-no (car line-col))
        (col-no  (cadr line-col))
       )
   (when (not line-no)
       (setq line-col (flymake-get-last-err-line-col flymake-err-info))
       (setq line-no (car line-col)
             col-no  (cadr line-col))
       (flymake-log 1 "passed beginning of file"))
   (if line-no
       (flymake-goto-line line-col)
     (flymake-log 1 "no errors in current buffer"))))

8- modify flymake-goto-line to accept a (LINE COL) list, and act accordingly

(defun flymake-goto-line (line-col)
 "LINE-COL contains (LINE-NO COL-NO). Go to line LINE-NO, then skip to the 
COL-NO column."
 (let ((line-no (car line-col))
       (col-no (cadr line-col))
       )
   (goto-line line-no)
   (when col-no
     (while (> col-no 1)
       (setq col-no (1- col-no))
       (forward-char))))
 line-col)


-Dino Chiesa







This bug report was last modified 2 years and 219 days ago.

Previous Next


GNU bug tracking system
Copyright (C) 1999 Darren O. Benham, 1997,2003 nCipher Corporation Ltd, 1994-97 Ian Jackson.