Re: [GNU ELPA] New package: flymake-harper

João Távora <[email protected]>
Newsgroups gmane.emacs.devel
Message-ID <CALDnm52G29nWqvARikdU3SxsE2NnsoG2CyDhSD7JMZbO=irr9A@mail.gmail.com>
You are correct! Sorry!

João

On Tue, Aug 18, 2026 at 1:46 PM Philip Kaludercic <[email protected]> wrote:
>
> It seems you forgot to attach the file?
>
> On 18 August 2026 14:33:58 CEST, "João Távora" <[email protected]> wrote:
> >Eshel Yaron <[email protected]> writes:
> >
> >>> - make Flymake error category symbols for harper diagnostics
> >>> - when making diagnostics, add the correction meta-info (I presume it is
> >>>   available) in the flymake-make-diagnostic call
> >>> - use flymake-overlay-control on those category symbols.  Add a keymap,
> >>> - make a new flymake-harper command and put it on the map.  The command
> >>>   uses meta-info and does the correction
> >>> - the map is activated when you click the flymake overlay
> >>>
> >>> If you want to autocorrect a number of diagnostics, make a command that
> >>> uses flymake-diagnostics to get all diags in a region and iterate.
> >>
> >> That's a viable solution for this particular backend, but in general
> >> that's IMO way too much work for a backend, and it's still not enough:
> >> you also need to choose keybindings, tell users about them, etc.  And
> >> every backend needs to do all that separately.  That's not quite
> >> "reasonably straightforward", sorry.
> >
> >Well, I asked reasonably dumb llm to implement this, and it did pretty
> >easily follow Flymake's manual and my little guide above to make a full
> >100loc backend with the aforemention correction capability.  See
> >attached flymake-straightforward.el, it uses ripgrep to flag for the
> >word "straight" and correct it to "str8".
> >
> >> The only thing backends should worry about is providing the fix data;
> >> the frontend should take care of all UI business.
> >
> >Nothing against that, but making a "one size fits all" is usually hard.
> >There are other ways to skin a cat.  LSP the most obvious way and the
> >reason investing in a that flymake.el correction UI overhaul is probably
> >a waste of time: Eglot already gives you a UI does it for you.  Yet
> >another is describing convention in the manual and following it.  You
> >may have library facilities that reduce the churn for backends to follow
> >those conventions (though it's not really that much).  But sure,
> >eglot--mouse-call should be library function, not in flymake.el.  Then
> >you need a lib function could to add things to the margin/fringe in
> >non-conflicting ways, that's another largely unresolved can of worms,
> >also doesn't belong to flymake.  I'd focus on that.
> >
> >João



-- 
João Távora
flymake-straightforward.el (text/x-emacs-lisp, 5.7 KB)
;;; flymake-straightforward.el --- Toy Flymake backend flagging "straight" -*- lexical-binding: t; -*-

;; This is a toy backend, modeled after the annotated example in the
;; Flymake Info manual, that shells out to ripgrep(1) to flag every
;; occurrence of the word "straight" in the current buffer.  It also
;; demonstrates how a backend can offer corrections for its own
;; diagnostics, following the pattern used by eglot.el: a diagnostic
;; category symbol with a `flymake-overlay-control' keymap, plus a
;; command that reads correction meta-info out of the diagnostic's
;; DATA slot (see `flymake-make-diagnostic').

(require 'cl-lib)
(require 'flymake)

(defvar-local flymake-straightforward--proc nil
  "Grep process for the current buffer, if any.")


;;; Diagnostic category and correction UI

(put 'flymake-straightforward-warning 'flymake-category 'flymake-warning)

(defvar flymake-straightforward-diagnostics-map
  (let ((map (make-sparse-keymap)))
    (define-key map [mouse-2] #'flymake-straightforward-correct-at-mouse)
    (define-key map [left-margin mouse-1] #'flymake-straightforward-correct-at-mouse)
    map)
  "Keymap active on flymake-straightforward's diagnostic overlays.")

(put 'flymake-straightforward-warning 'flymake-overlay-control
     `((mouse-face . highlight)
       (keymap . ,flymake-straightforward-diagnostics-map)))

(defun flymake-straightforward--diag-at (pos)
  "Return a flymake-straightforward diagnostic at POS, if any."
  (cl-find 'flymake-straightforward-warning (flymake-diagnostics pos)
           :key #'flymake-diagnostic-type))

(defun flymake-straightforward--apply (diag)
  "Apply DIAG's correction, replacing its text with its replacement."
  (let ((replacement (plist-get (flymake-diagnostic-data diag) :replacement)))
    (with-current-buffer (flymake-diagnostic-buffer diag)
      (goto-char (flymake-diagnostic-beg diag))
      (delete-region (flymake-diagnostic-beg diag) (flymake-diagnostic-end diag))
      (insert replacement))))

(defun flymake-straightforward-correct ()
  "Correct the flymake-straightforward diagnostic at point."
  (interactive)
  (if-let* ((diag (flymake-straightforward--diag-at (point))))
      (flymake-straightforward--apply diag)
    (user-error "No flymake-straightforward diagnostic here")))

(defun flymake-straightforward--mouse-call (what)
  "Make an interactive lambda for calling WHAT with the mouse."
  (lambda (event)
    (interactive "e")
    (let ((start (event-start event)))
      (with-selected-window (posn-window start)
        (save-excursion
          (goto-char (posn-point start))
          (call-interactively what))))))

(defalias 'flymake-straightforward-correct-at-mouse
  (flymake-straightforward--mouse-call #'flymake-straightforward-correct)
  "Like `flymake-straightforward-correct', but for mouse events.")

(defun flymake-straightforward-correct-all (beg end)
  "Correct every flymake-straightforward straight diagnostic between BEG and END."
  (interactive (if (region-active-p) (list (region-beginning) (region-end))
                 (list (point-min) (point-max))))
  (cl-loop for diag in (flymake-diagnostics beg end)
           when (eq (flymake-diagnostic-type diag) 'flymake-straightforward-warning)
           collect diag into diags
           finally (mapc #'flymake-straightforward--apply
                          (cl-sort diags #'> :key #'flymake-diagnostic-beg))))


;;; Backend proper

(defun flymake-straightforward-backend (report-fn &rest _ignored)
  "A Flymake backend flagging the word `straight' using ripgrep.
Calls REPORT-FN once the ripgrep process has finished."
  (when (process-live-p flymake-straightforward--proc)
    (kill-process flymake-straightforward--proc))
  (let ((source (current-buffer)))
    (save-restriction
      (widen)
      (setq flymake-straightforward--proc
            (make-process
             :name "flymake-straightforward" :noquery t :connection-type 'pipe
             :buffer (generate-new-buffer " *flymake-straightforward*")
             :command '("rg" "--no-heading" "-i" "--line-number" "--column" "-w" "straight")
             :sentinel
             (lambda (proc _event)
               (when (eq 'exit (process-status proc))
                 (unwind-protect
                     (if (with-current-buffer source (eq proc flymake-straightforward--proc))
                         (with-current-buffer (process-buffer proc)
                           (goto-char (point-min))
                           (cl-loop
                            while (search-forward-regexp
                                   "^\\([0-9]+\\):\\([0-9]+\\):" nil t)
                            for line = (string-to-number (match-string 1))
                            for col = (string-to-number (match-string 2))
                            for (beg . end) = (flymake-diag-region source line col)
                            collect (flymake-make-diagnostic
                                     source beg end 'flymake-straightforward-warning
                                     "Straight!" '(:replacement "str8"))
                            into diags
                            finally (funcall report-fn diags)))
                       (flymake-log :warning "Canceling obsolete check %s" proc))
                   (kill-buffer (process-buffer proc)))))))
      (process-send-region flymake-straightforward--proc (point-min) (point-max))
      (process-send-eof flymake-straightforward--proc))))

(defun flymake-straightforward-setup ()
  "Enable the flymake-straightforward backend in the current buffer."
  (interactive)
  (add-hook 'flymake-diagnostic-functions #'flymake-straightforward-backend nil t)
  (flymake-mode 1)
  (flymake-start nil t))

(provide 'flymake-straightforward)
;;; flymake-straightforward.el ends here
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.