]> git.eshelyaron.com Git - emacs.git/commitdiff
Allow multiple forms after keywords
authorNicolas Richard <theonewiththeevillook@yahoo.fr>
Mon, 10 Feb 2014 17:02:59 +0000 (18:02 +0100)
committerNicolas Richard <theonewiththeevillook@yahoo.fr>
Mon, 10 Feb 2014 17:57:27 +0000 (18:57 +0100)
* use-package.el (use-package-mplist-get):
(use-package-plist-get):
(use-package-mplist-keys): new functions

(plist-get-value):
(use-package): use new functions

(plist-keys): remove function

The idea is to allow a modified kind of plist where keys are all
keywords that appear in the list, and values are the intermediary
elements. If a keyword is present but it's another keyword just after it
(like (use-package :defer :config (setq foo 'bar))), its associated
value will be t. If a keyword is not present, its value associated value
will be nil. Otherwise the value will be the list of elements between
the keyword and the next keyword.

lisp/use-package/use-package.el

index 1a99e1258c99eaefe22f0f07e2e9c7e643319fa2..89f8987e7151d22362394d1a7df2aa146383da69 100644 (file)
   )
   "Keywords recognized by `use-package'.")
 
-(defun plist-keys (plist)
-  "Return a list containing all the keys in PLIST."
-  (when plist
-    (cons
-      (car plist)
-      (plist-keys
-        (cddr plist)))))
+(defun use-package-mplist-get (plist prop)
+  "Get the values associated to PROP in PLIST, a modified plist.
+
+A modified plist is one where keys are keywords and values are
+all non-keywords elements that follow it.
+
+As a special case : if the first occurrence of the keyword PROP
+is followed by another keyword or is the last element in the
+list, the function returns t.
+
+Currently this function infloops when the list is circular."
+  (let ((tail plist)
+        found
+        result)
+    (while (and
+            (consp tail)
+            (not
+             (eq prop (car tail))))
+      (pop tail))
+    (when (eq prop (pop tail))
+      (setq found t))
+    (while (and (consp tail)
+                (not (keywordp (car tail))))
+      (push (pop tail) result))
+    (or (nreverse result) found)))
+
+(ert-deftest use-package-mplist-get ()
+  (let ((mplist '(:foo bar baz bal :blob plap plup :blam))
+        (tests '((:foo . (bar baz bal))
+                 (:blob . (plap plup))
+                 (:blam . t)
+                 (:blow . nil))))
+    (mapc (lambda (test)
+            (should
+             (equal
+              (use-package-mplist-get mplist
+                                      (car test))
+              (cdr test))))
+          tests)))
+
+(defun use-package-plist-get (plist prop)
+  "Compatibility layer between classical and modified plists.
+
+If `use-package-mplist-get' returns exactly one value, that is
+returned ; otherwise the list is returned wrapped in a `progn'."
+  (let ((values (use-package-mplist-get plist prop)))
+    (when values
+      (cond ((not (listp values))
+             values)
+            ((eq 1 (length values))
+             (car values))
+            (t (cons 'progn values))))))
+
+(defun use-package-mplist-keys (plist)
+  "Get the keys in PLIST, a modified plist.
+
+A modified plist is one where properties are keywords and values
+are all non-keywords elements that follow it."
+  (let ((result))
+    (mapc (lambda (elt)
+            (when (keywordp elt)
+              (push elt result)))
+          plist)
+    (nreverse result)))
+(ert-deftest use-package-mplist-keys ()
+  (should (equal (use-package-mplist-keys
+                  '(:foo bar baz bal :blob plap plup :blam))
+                 '(:foo :blob :blam))))
 
 (defun use-package-validate-keywords (args)
   "Error if any keyword given in ARGS is not recognized.
@@ -157,11 +218,11 @@ Return the list of recognized keywords."
       (lambda (keyword)
         (unless (memq keyword use-package-keywords)
           (error "Unrecognized keyword: %s" keyword))))
-    (plist-keys args)))
+    (use-package-mplist-keys args)))
 
-(defun plist-get-value (plist prop)
+(defun use-package-plist-get-value (plist prop)
   "Return the value of PROP in PLIST as if it was backquoted."
-  (eval (list '\` (plist-get plist prop))))
+  (eval (list '\` (use-package-plist-get plist prop))))
 
 (defmacro use-package (name &rest args)
   "Use a package with configuration options.
@@ -192,29 +253,29 @@ For full documentation. please see commentary.
 :idle adds a form to run on an idle timer
 :ensure loads package using package.el if necessary."
   (use-package-validate-keywords args) ; error if any bad keyword, ignore result
-  (let* ((commands (plist-get args :commands))
-         (pre-init-body (plist-get args :pre-init))
-         (pre-load-body (plist-get args :pre-load))
-         (init-body (plist-get args :init))
-         (config-body (plist-get args :config))
-         (diminish-var (plist-get-value args :diminish))
-         (defines (plist-get-value args :defines))
-         (idle-body (plist-get args :idle))
-         (keybindings-alist (plist-get-value args :bind))
-         (mode (plist-get-value args :mode))
+  (let* ((commands (use-package-plist-get args :commands))
+         (pre-init-body (use-package-plist-get args :pre-init))
+         (pre-load-body (use-package-plist-get args :pre-load))
+         (init-body (use-package-plist-get args :init))
+         (config-body (use-package-plist-get args :config))
+         (diminish-var (use-package-plist-get-value args :diminish))
+         (defines (use-package-plist-get-value args :defines))
+         (idle-body (use-package-plist-get args :idle))
+         (keybindings-alist (use-package-plist-get-value args :bind))
+         (mode (use-package-plist-get-value args :mode))
          (mode-alist
           (if (stringp mode) (cons mode name) mode))
-         (interpreter (plist-get-value args :interpreter))
+         (interpreter (use-package-plist-get-value args :interpreter))
          (interpreter-alist
           (if (stringp interpreter) (cons interpreter name) interpreter))
-         (predicate (plist-get args :if))
-         (pkg-load-path (plist-get-value args :load-path))
+         (predicate (use-package-plist-get args :if))
+         (pkg-load-path (use-package-plist-get-value args :load-path))
          (defines-eval (if (null defines)
                            nil
                          (if (listp defines)
                              (mapcar (lambda (var) `(defvar ,var)) defines)
                            `((defvar ,defines)))))
-         (requires (plist-get-value args :requires))
+         (requires (use-package-plist-get-value args :requires))
          (requires-test (if (null requires)
                             t
                           (if (listp requires)
@@ -225,9 +286,9 @@ For full documentation. please see commentary.
          (name-symbol (if (stringp name) (intern name) name)))
 
     ;; force this immediately -- one off cost
-    (unless (plist-get args :disabled)
+    (unless (use-package-plist-get args :disabled)
 
-      (let* ((ensure (plist-get args :ensure))
+      (let* ((ensure (use-package-plist-get args :ensure))
              (package-name
               (or (and (eq ensure t)
                        name)
@@ -325,8 +386,8 @@ For full documentation. please see commentary.
                   `(load ,name t)
                 `(require ',name nil t))))
 
-         ,(if (and (or commands (plist-get args :defer))
-                   (not (plist-get args :demand)))
+         ,(if (and (or commands (use-package-plist-get args :defer))
+                   (not (use-package-plist-get args :demand)))
               (let (form)
                 (mapc #'(lambda (command)
                           (push `(autoload (function ,command)