Search code examples
emacsflymakeflyspell

Using One Key for Both flymake And flyspell


I am using flymake with pyflakes to check my python code and flyspell to check my strings and comments. I want to have one function which will go to the next error, or will display information about the error if currently at an error. How would I write this function?


Solution

  • This code provides functionality which jumps you to the next error, and if it's a flymake error, displays information for it, if it's a flyspell error, it corrects it for you. If you don't want the auto-correction, un-comment the line that calls 'my-flyspell-message and remove the line before that which calls 'flyspell-auto-correct-word - and you'll just get a message about the word being misspelled.

    The first line binds this to the keybinding C-c n. For more information on binding keys, see the info page Key Bindings.

    (global-set-key (kbd "C-c n") 'my-display-error-or-next-error)
    (defun my-display-error-or-next-error ()
      "display information for current error, or go to next one"
      (interactive)
      (when (or (not (my-at-flymake-error))
                (not (my-at-flyspell-error)))
        ;; jump to error if not at one
        (my-goto-next-error))
    
      (cond ((my-at-flymake-error)
             ;; if at flymake error, display menu
             (flymake-display-err-menu-for-current-line))
            ((my-at-flyspell-error)
             ;; if at flyspell error, fix it
             (call-interactively 'flyspell-auto-correct-word)
             ;; or, uncomment the next line to just get a message
             ;; (my-flyspell-message)
             )))
    
    (defun my-at-flyspell-error ()
      "return non-nill if at flyspell error"
      (some 'flyspell-overlay-p (overlays-at (point))))
    
    (defun my-at-flymake-error ()
      "return non-nil if at flymake error"
      (let* ((line-no             (flymake-current-line-no))
             (line-err-info-list  (nth 0 (flymake-find-err-info flymake-err-info line-no))))
        line-err-info-list))
    
    (defun my-goto-next-error ()
      "jump to next flyspell or flymake error"
      (interactive)
      (let* ((p (point))
             (spell-next-error-function '(lambda ()
                                     (forward-word) (forward-char)
                                     (flyspell-goto-next-error)))
             (spell-pos (save-excursion
                          (funcall spell-next-error-function)
                          (point)))
             (make-pos (save-excursion
                         (flymake-goto-next-error)
                         (point))))
        (cond ((or (and (< p make-pos) (< p spell-pos))
                   (and (> p make-pos) (> p spell-pos)))
               (funcall (if (< make-pos spell-pos)
                            'flymake-goto-next-error
                          spell-next-error-function)))
              ((< p make-pos)
               (flymake-goto-next-error))
    
              ((< p spell-pos)
               (funcall spell-next-error-function)))))
    
    (defun my-flyspell-message ()
      (interactive)
      (let ((word (thing-at-point 'word)))
        (set-text-properties 0 (length word) nil word)
        (message "Missspelled word: %s" word)))