do not edit — generated by btf.
git.druid.rocksindexdruid520radiumradium-checkonsave.el

radium-checkonsave.el


;;; radium-checkonsave.el, on-save syntax check without lsp -*- lexical-binding: t; -*-
;;
;; silently syntax-checks whatever i just saved into a background
;; compilation buffer, reporting only pass/fail in the echo area - no
;; lsp. if it fails i pop the buffer so the errors are clickable /
;; jumpable the normal compilation-mode way (M-g n / M-g p). each file
;; gets its own *checkonsave:<file>* buffer, and a re-save before the
;; last check finished kills the old process so they never race.
;;
;; the compile column is set so gcc's "file:line:col: error:" clicks
;; land on the right spot; %s in each command is the shell-quoted path.
 
(defvar radium-checkonsave-alist
  '((c-mode                . "gcc -fsyntax-only -x c -Wall -Wextra %s")
    (nsc-mode              . "nscc %s -o /dev/null")
    (ada-mode              . "gnatmake -q -gnatc %s")
    (asm-mode              . "as -o /dev/null %s")
    (cperl-mode            . "perl -c %s")
    (sh-mode               . "sh -n %s")
    (emacs-lisp-mode       . "emacs --batch -Q --eval '(kill-emacs (if (byte-compile-file %S) 0 1))'")
    (python-mode           . "python3 -c 'import ast,sys; ast.parse(open(sys.argv[1]).read(), sys.argv[1])' %s"))
  "major mode -> shell command template (%s = shell-quoted file name)
run in the background after every save. gcc gets -x c so .h headers
are checked as plain c, not guessed; nscc needs no such flag - a .nsh
compiles standalone exactly like a .nsc, confirmed directly against
real kaboom source (a header of bare declarations, like syscalls.nsh,
and a real .nsc both exit 0). languages with no one-shot syntax
checker on netbsd (scheme, forth, kona, cron) just aren't listed.")
 
(defun radium-checkonsave ()
  (let ((cmd (cdr (assq major-mode radium-checkonsave-alist))))
    (when (and cmd buffer-file-name
               (executable-find (car (split-string cmd))))
      (let* ((file buffer-file-name)
             (base (file-name-nondirectory file))
             ;; %S in a template (only emacs-lisp-mode's) means "format
             ;; this as a real elisp string literal" - format's own %S
             ;; already does that (prin1-to-string) itself, so passing
             ;; file raw here is correct; pre-stringifying it first (as
             ;; this used to) double-quotes it, e.g. (byte-compile-file
             ;; "\"/x.el\""), which is not a valid path and always
             ;; failed - confirmed by running the built command.
             (arg (if (string-match "%S" cmd)
                      file
                    (shell-quote-argument file)))
             (full (format cmd arg))
             (buf (get-buffer-create (format "*checkonsave:%s*" base))))
        (with-current-buffer buf
          (let ((inhibit-read-only t))
            (erase-buffer)
            (unless (derived-mode-p 'compilation-mode)
              (compilation-mode)))
          (setq default-directory (file-name-directory file)))
        ;; one buffer per file, and only one live check per file - a
        ;; save right after another save kills the stale run first.
        (when-let ((old (get-buffer-process buf)))
          (delete-process old))
        (make-process
         :name (format "checkonsave:%s" base)
         :buffer buf
         :command (list "/bin/sh" "-c" full)
         :sentinel
         (lambda (_proc event)
           (when (and (string-match-p "finished\\|exited" event)
                      (buffer-live-p buf))
             (let ((ok (string-prefix-p "finished" event)))
               (with-current-buffer buf
                 (goto-char (point-min)))
               (if ok
                   (message "ok: %s syntax check." base)
                 (message "err: %s syntax check - %s to jump."
                          base
                          (substitute-command-keys "\\`M-g n'"))
                 (display-buffer buf))))))))))
 
(add-hook 'after-save-hook #'radium-checkonsave)
 
(provide 'radium-checkonsave)
powered by btf.