+(defun mdw-remprop-nondestructive (indic plist)
+ "Return a plist like PLIST, only without the first entry for INDIC.
+The PLIST is not itself modified."
+ (if (getf plist indic)
+ (let* ((head (cons nil nil))
+ (tail head))
+ (while (and plist (not (eq (car plist) indic)))
+ (let* ((i (pop plist)) (v (pop plist))
+ (vv (cons v nil)) (ii (cons i vv)))
+ (rplacd tail ii)
+ (setq tail vv)))
+ (rplacd tail (cddr plist))
+ (cdr head))
+ plist))
+
+(defun* mdw-cons-replace
+ (item list &rest keys &key (key '#'identity) &allow-other-keys)
+ "Return LIST, with ITEM at the start, replacing any existing matching item.
+Specifically, any item in the list satisfying the test are removed
+\(nondestructively), and then the new ITEM is added to the front."
+ (cons item (apply #'remove* (funcall key item) list :key key
+ (mdw-remprop-nondestructive :key keys))))
+
+(defmacro* mdw-pushnew-replace (item place &rest keys)
+ "Add ITEM to the list PLACE, replacing any existing matching item.
+Specifically, any item in the list satisfying the test are removed
+\(nondestructively), and then the new ITEM is added to the front.
+
+Evaluation order for the keywords is a bit screwy: don't rely on it."
+ (cond ((fboundp 'cl-callf2)
+ `(cl-callf2 mdw-cons-replace ,item ,place ,@keys))
+ ((fboundp 'cl-setf-do-modify)
+ ;; `cl-setf-do-modify' returns a list (LETS STORE FETCH).
+ (let ((setf-things (cl-setf-do-modify place (cons 'list keys))))
+ `(let (,@(car setf-things))
+ ,(cl-setf-do-store (cadr setf-things)
+ `(mdw-cons-replace ,item ,place
+ ,@keys)))))
+ (t (error "Don't know how to hack places on this Emacs."))))
+