bug-gnu-emacs
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

bug#5911: flymake.el - enhancement request - flymake-goto-next-error sho


From: D Chiesa
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









reply via email to

[Prev in Thread] Current Thread [Next in Thread]