diff --git a/lisp/doom-lib.el b/lisp/doom-lib.el index 261cdf17a..92a3bc7d4 100644 --- a/lisp/doom-lib.el +++ b/lisp/doom-lib.el @@ -325,6 +325,49 @@ TRIGGER-HOOK is a list of quoted hooks and/or sharp-quoted functions." (put 'doom-compile-function 'timer nil)))))) +;; +;;; Deep copying + +(cl-defgeneric doom-copy (val &optional _deep?) + "Return a (optionally deep) copy of VAL." + (cl-check-type val (or integer float boolean symbol null)) + val) + +(cl-defmethod doom-copy ((val record) &optional deep?) + "Return a (optionally deep) copy of record VAL." + (if deep? + (cl-loop with newval = (copy-sequence val) + for idx from 1 to (length (cdr (cl-struct-slot-info (type-of val)))) + do (aset newval idx (doom-copy (aref newval idx) t)) + finally return newval) + (copy-sequence val))) + +(cl-defmethod doom-copy ((val sequence) &optional deep?) + "Return a (optionally deep) copy of sequence VAL." + (if (stringp val) + (if deep? val (purecopy val)) + (if deep? + (when-let ((newval (mapcar (doom-rpartial #'doom-copy t) val))) + (if (vectorp val) + (apply #'vector newval) + newval)) + (copy-sequence val)))) + +(cl-defmethod doom-copy ((val cons) &optional deep?) + "Return a (optionally deep) copy of cons cell/list VAL." + (cons (doom-copy (car val) deep?) + (doom-copy (cdr val) deep?))) + +(cl-defmethod doom-copy ((val hash-table) &optional deep?) + "Return a (optionally deep) copy of hash table VAL." + (let ((table (copy-hash-table val))) + (when deep? + (maphash (lambda (key val) + (puthash key (doom-copy val t) table)) + table)) + table)) + + ;; ;;; Sugars