2017-02-09 04:08:59 -05:00
|
|
|
;;; plist.el
|
|
|
|
(provide 'doom-lib-mplist)
|
|
|
|
|
|
|
|
;; The built-in plist library won't work when the list is a malformed plist,
|
2017-03-01 22:25:13 -05:00
|
|
|
;; which is a plist that has multiple (or no) forms following its properties.
|
|
|
|
;; For example: (:x 5 :y 1 2 3 :z).
|
2017-02-09 04:08:59 -05:00
|
|
|
;;
|
2017-03-01 22:25:13 -05:00
|
|
|
;; This library was written for mplists, but use the standard plist-* functions
|
|
|
|
;; for regular plists -- they're faster.
|
2017-02-09 04:08:59 -05:00
|
|
|
;;
|
|
|
|
;; (let ((a '(abc :commands 1 :config 3 4 5)))
|
2017-02-23 00:06:12 -05:00
|
|
|
;; (mplist! a &delete :commands :config))
|
2017-02-09 04:08:59 -05:00
|
|
|
|
|
|
|
;;;###autoload
|
2017-02-23 00:06:12 -05:00
|
|
|
(defmacro mplist! (var action &rest args)
|
2017-03-01 22:25:13 -05:00
|
|
|
"A convenience macro for dealing with doom-mplist-* functions.
|
2017-02-09 04:08:59 -05:00
|
|
|
|
|
|
|
Examples:
|
2017-02-23 00:06:12 -05:00
|
|
|
(mplist! plist &delete :x :y)
|
|
|
|
(mplist! plist &get :x)"
|
2017-02-09 04:08:59 -05:00
|
|
|
(declare (indent defun))
|
|
|
|
(let ((fn-sym (intern (format "doom-mplist-%s" (substring (symbol-name action) 1)))))
|
|
|
|
(when (fboundp fn-sym)
|
|
|
|
(if (memq action '(&delete &put))
|
|
|
|
`(setq ,var (,fn-sym ,var ,@args))
|
|
|
|
`(,fn-sym ,var ,@args)))))
|
|
|
|
|
|
|
|
;;;###autoload
|
2017-03-01 22:25:13 -05:00
|
|
|
(defun doom-mplist-delete (mplist &rest keys)
|
|
|
|
"Thoroughly removes a property and its values from an mplist."
|
|
|
|
(if (apply 'doom-mplist-member mplist keys)
|
2017-02-09 04:08:59 -05:00
|
|
|
(let (forms)
|
2017-03-01 22:25:13 -05:00
|
|
|
(while mplist
|
|
|
|
(if (not (and (keywordp (car mplist)) (memq (car mplist) keys)))
|
|
|
|
(setq forms (append forms (list (pop mplist))))
|
|
|
|
(pop mplist)
|
|
|
|
(while (and mplist (not (keywordp (car mplist))))
|
|
|
|
(pop mplist))))
|
2017-02-09 04:08:59 -05:00
|
|
|
forms)
|
2017-03-01 22:25:13 -05:00
|
|
|
mplist))
|
2017-02-09 04:08:59 -05:00
|
|
|
|
|
|
|
;;;###autoload
|
2017-03-01 22:25:13 -05:00
|
|
|
(defun doom-mplist-put (mplist key value)
|
|
|
|
"Like `plist-put', but for mplists."
|
|
|
|
(when (doom-mplist-member mplist key)
|
|
|
|
(doom-mplist-delete mplist key))
|
|
|
|
(setq mplist (append mplist (list key value))))
|
2017-02-09 04:08:59 -05:00
|
|
|
|
|
|
|
;;;###autoload
|
2017-03-01 22:25:13 -05:00
|
|
|
(defun doom-mplist-get (mplist &rest keys)
|
|
|
|
"Like `plist-get', but for mplists. If KEYS is only one keyword, return the
|
|
|
|
mplist associated with it. If KEYS is multiple, return a list of associated
|
|
|
|
mplists."
|
2017-02-09 04:08:59 -05:00
|
|
|
(if (cdr keys)
|
2017-03-01 22:25:13 -05:00
|
|
|
(let ((keys (mapcar (lambda (key) (memq key mplist)) keys))
|
2017-02-09 04:08:59 -05:00
|
|
|
values)
|
|
|
|
(dolist (forms keys)
|
|
|
|
(when forms
|
|
|
|
(push (cdr forms) values)))
|
|
|
|
values)
|
2017-03-01 22:25:13 -05:00
|
|
|
(cdr (memq (car keys) mplist))))
|
2017-02-09 04:08:59 -05:00
|
|
|
|
|
|
|
;;;###autoload
|
2017-03-01 22:25:13 -05:00
|
|
|
(defun doom-mplist-member (mplist &rest keys)
|
|
|
|
"Return t if any of KEYS (keywords) are in MPLIST."
|
|
|
|
(cl-some (lambda (key) (memq key mplist)) keys))
|
2017-02-09 04:08:59 -05:00
|
|
|
|
|
|
|
|