diff options
Diffstat (limited to 'evil-common.el')
-rw-r--r-- | evil-common.el | 112 |
1 files changed, 112 insertions, 0 deletions
diff --git a/evil-common.el b/evil-common.el new file mode 100644 index 0000000..d92afce --- /dev/null +++ b/evil-common.el @@ -0,0 +1,112 @@ +;;;; Common functions and utilities + +(defun evil-add-to-alist (list-var key val &rest elements) + "Add the assocation of KEY and VAL to the value of LIST-VAR. +If the list already contains an entry for KEY, update that entry; +otherwise add at the end of the list." + (let ((tail (symbol-value list-var))) + (while (and tail (not (equal (car-safe (car-safe tail)) key))) + (setq tail (cdr tail))) + (if tail + (setcar tail (cons key val)) + (add-to-list list-var (cons key val) t)) + (if elements + (apply 'evil-add-to-alist list-var elements) + (symbol-value list-var)))) + +(defun evil-concat-lists (&rest sequences) + "Concatenate lists, removing duplicates. +The firstmost occurrence of an element is retained. +Cons cells are treated as alist entries." + (let ((result (pop sequences)) + (tail (copy-sequence (pop sequences)))) + (catch 'empty + (dolist (elt result) + (cond + ((null tail) + (throw 'empty t)) + ((consp elt) + (setq tail (assq-delete-all (car elt) tail))) + (t + (setq tail (delq elt tail)))))) + (if sequences + (apply 'evil-concatenate-lists result sequences) + (append result tail)))) + +(defun evil-get-property (alist key prop) + "Return property PROP for KEY in ALIST. +ALIST is an association list with entries in the form +\(KEY . PLIST), where PLIST is a property list. +If KEY is nil, return an association list of states and +their PROP values." + (let (result val) + (unless (keywordp prop) + (setq prop (intern (format ":%s" prop)))) + (if key + (plist-get (cdr (assq key alist)) prop) + (dolist (entry alist result) + (setq key (car entry) + val (plist-get (cdr entry) prop)) + (when val + (add-to-list 'result (cons key val) t)))))) + +(defun evil-put-property (alist-var key prop val &rest properties) + "Set PROP to VAL for KEY in ALIST-VAR. +ALIST-VAR points to an association list with entries in the form +\(KEY . PLIST), where PLIST is a property list storing PROP and VAL." + (let* ((alist (symbol-value alist-var)) + (plist (cdr (assq key alist)))) + (while + (progn + (unless (keywordp prop) + (setq prop (intern (format ":%s" prop)))) + (setq plist (plist-put plist prop val)) + (when properties + (setq prop (pop properties) + val (pop properties))))) + (set alist-var (assq-delete-all key alist)) + (add-to-list alist-var (cons key plist) t))) + +(defmacro evil-swap (this that &rest vars) + "Swap the values of variables THIS and THAT. +If three or more arguments are given, the values are rotated. +E.g., (evil-swap A B C) sets A to B, B to C, and C to A." + `(progn + (setq ,this (prog1 ,that + (setq ,that ,this))) + ,@(when vars + `((evil-swap ,that ,@vars))))) + +(defmacro evil-sort (min max &rest vars) + "Place the smallest value in MIN and the largest in MAX. +If three or more arguments are given, place the smallest +value in the first argument and the largest in the last, +sorting in between." + `(let ((sorted (sort (list ,min ,max ,@vars) '<))) + (setq ,min (pop sorted) + ,max (pop sorted) + ,@(let (forms) + (while vars + (add-to-list 'forms (pop vars) t) + (add-to-list 'forms '(pop sorted) t)) + forms)))) + +(defmacro evil-save-echo-area (&rest body) + "Save the echo area; execute BODY; restore the echo area. +Intermittent messages are not logged in the *Messages* buffer." + (declare (indent defun)) + `(let ((oldmsg (current-message)) + message-log-max) + (unwind-protect + (progn ,@body) + (if oldmsg (message "%s" oldmsg) + (message nil))))) + +(defun evil-unlogged-message (string &rest args) + "Display an unlogged message in the echo area. +That is, the message is not logged in the *Messages* buffer. +\(To log the message, just use `message'.)" + (let (message-log-max) + (apply 'message string args))) + +(provide 'evil-common) |