emacs-devel
[Top][All Lists]
Advanced

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

Re: Should mode commands be idempotent?


From: Stefan Monnier
Subject: Re: Should mode commands be idempotent?
Date: Sat, 23 Sep 2017 16:37:08 -0400
User-agent: Gnus/5.13 (Gnus v5.13) Emacs/26.0.50 (gnu/linux)

> the top of my todo list recently (close enough that I thought about it,
> but not close enough to get usable code out of it).

I finally found the the pseudo-code I wrote for it back then, in case
you're interested (it was in my local nadvice.el hacks).  See below
(guaranteed 100% untested).


        Stefan


;;; Changing variables in general (not just function-valued ones)

;; TODO: Handle buffer-local settings!
;; TODO: Make it work for arbitrary gv-places?
;; TODO: Maybe use it or something similar to keep track of effects of
;;       loading a file (where `id' would be the file name)?

(defun advice--var-apply-op (val op v)
  (pcase-exhaustive op
    (:override v)
    (:around (funcall v val))))

(defun advice--var-compute-val (var)
  (let ((xs (get var 'advice-var-settings)))
    (if (not xs)
        (symbol-value var)
      (let ((val (car xs)))
        (pcase-dolist (`(,_id ,op ,v) (cdr xs))
          (setq val (advice--var-apply-op val op v)))
        val))))

(defun advice--var-set (var id op v)      ;TODO: add a `depth'?
  (let ((xs (get var 'advice-var-settings)))
    (unless xs
      (setq xs (list (symbol-value var)))
      (setf (get var 'advice-var-settings) xs))
    (unless (equal (symbol-value var)
                   (advice--var-compute-val var))
      (message "Var %S changed outside of `advice-set'" var))
    ;; FIXME: We could almost use
    ;;     (setf (alist-get id (cdr xs)) (list op v))
    ;; Except that we want to add new entries at the end!
    (let ((x (assoc id (cdr xs))))
      (if x
          ;; There's already another setting for `id'.
          (setcdr x (list op v))
        (setcdr (last xs) (list (list id op v)))))
    (set var (advice--var-compute-val var))))

(defun advice--var-unset (var id)
  (let* ((xs (get var 'advice-var-settings))
         (x (assoc id (cdr xs))))
    (when x
      (delq x xs)
      (set var (advice--var-compute-val var))
      (unless (cdr xs)
        (setf (get var 'advice-var-settings) nil)))))




reply via email to

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