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

radium-ipc.el


;;; radium-ipc.el, a named-pipe command channel at ~/.radium.ipc -*- lexical-binding: t; -*-
;;
;; item 12: "essentially an elisp/keybind/etc evaluator" - a fifo, not
;; a second emacsclient. emacsclient --eval already IS a synchronous,
;; return-value-having ipc channel into the daemon (rd eval, below,
;; is nothing but a thin wrapper around exactly that) - what it can't
;; do is sit as the far end of a script/window-manager keybind/cron
;; job that just wants to fire a command at a running daemon without
;; caring about the reply. that's what this is: write one elisp form
;; (a plain eval, or a keybind trigger like `(call-interactively
;; 'save-buffer)' or `(execute-kbd-macro (kbd "C-x C-s"))' - both are
;; just eval too, no separate mini-language needed) to the fifo,
;; radium-ipc reads and evals it, the result goes to *Messages* (where
;; it's genuinely useful if you're attached to the daemon) rather than
;; back down the pipe - fire-and-forget, by design, not a limitation
;; to fix later.
;;
;; a fifo's own real gotcha: a reader sees EOF the moment the writer
;; count drops to zero, which is EVERY single write from a plain shell
;; redirect (`echo ... > fifo` opens, writes, closes) - so the
;; process reading it exits after each command, not just once at
;; shutdown. radium-ipc--sentinel respawns the reader immediately
;; every time, so the channel stays open for the next command without
;; needing a second, always-open writer fd to work around it.
;;
;; the fifo is created mode 600 (owner-only) and lives at
;; radium-ipc-path, ~/.radium.ipc by default: the same trust boundary
;; as .emacs.d itself already has - anyone who can write to it can
;; already run as this unix user, so evaling whatever it sends isn't
;; a new privilege boundary to defend, and a per-call approval prompt
;; (gptel's own tools all have one, see radium-gptel.el) would defeat
;; the entire point of a fire-and-forget scripting channel.
 
(defvar radium-ipc-path
  (or (getenv "RADIUM_IPC") (expand-file-name ".radium.ipc" "~"))
  "the fifo radium-ipc reads elisp forms from, one per line. reads
$RADIUM_IPC if set - the same env var bin/rd.sh itself already falls
back to $HOME/.radium.ipc from, so the two halves of one feature
share a single config point instead of two independently-hardcoded
defaults that could drift. override from ~/.radium.el (loaded dead
last) instead, then call `radium-ipc-start' to make it take.")
 
(defvar radium-ipc--proc nil
  "the current `cat' reader process, or nil/dead between writes.")
 
(defvar radium-ipc--buf ""
  "bytes read since the last complete line.")
 
(defun radium-ipc--eval-line (line)
  "read LINE as one elisp form and eval it, logging the result (or
the error) to *Messages* - never signals out to the reader process."
  (setq line (string-trim line))
  (unless (string-empty-p line)
    (condition-case err
        (message "radium-ipc: %s => %S" line (eval (car (read-from-string line)) t))
      (error (message "radium-ipc: %s -- err: %s" line (error-message-string err))))))
 
(defun radium-ipc--filter (_proc chunk)
  (setq radium-ipc--buf (concat radium-ipc--buf chunk))
  (while (string-match "\n" radium-ipc--buf)
    (radium-ipc--eval-line (substring radium-ipc--buf 0 (match-beginning 0)))
    (setq radium-ipc--buf (substring radium-ipc--buf (match-end 0)))))
 
(defun radium-ipc--sentinel (_proc _event)
  "respawn the reader - unless radium-ipc-path itself is gone, in
which case that respawn would immediately fail and re-trigger this
same sentinel again, forever: confirmed by testing exactly that
\(an isolated cat-on-a-missing-fifo repro hit ~4400 respawns in 3s,
pegging a cpu core) before this guard existed. `radium-ipc-start' is
the documented, explicit way back once the fifo is actually there
again."
  (if (file-exists-p radium-ipc-path)
      (radium-ipc--spawn)
    (message "radium-ipc: %s is gone, not respawning - M-x radium-ipc-start to recreate it."
             radium-ipc-path)))
 
(defun radium-ipc--spawn ()
  (setq radium-ipc--proc
        (make-process :name "radium-ipc"
                      :command (list "cat" radium-ipc-path)
                      :filter #'radium-ipc--filter
                      :sentinel #'radium-ipc--sentinel
                      :noquery t)))
 
(defun radium-ipc-start ()
  "create radium-ipc-path (mode 600) if it doesn't exist yet and
start (or restart) the reader listening on it. called once at startup
below; also a real interactive command for after a manual `rm' of
the fifo, or after changing radium-ipc-path (from ~/.radium.el, say)
to move to a different one - always stops whatever's currently
listening first, rather than a stale `process-live-p' check silently
no-op'ing and leaving the reader on the old path."
  (interactive)
  (when (process-live-p radium-ipc--proc)
    (set-process-sentinel radium-ipc--proc #'ignore)
    (delete-process radium-ipc--proc))
  (unless (file-exists-p radium-ipc-path)
    (call-process "mkfifo" nil nil nil radium-ipc-path)
    (set-file-modes radium-ipc-path #o600))
  (radium-ipc--spawn))
 
(radium-ipc-start)
 
(provide 'radium-ipc)
powered by btf.