summary refs log tree commit diff stats
path: root/lisp/yoke.el
diff options
context:
space:
mode:
Diffstat (limited to 'lisp/yoke.el')
-rw-r--r--lisp/yoke.el66
1 files changed, 50 insertions, 16 deletions
diff --git a/lisp/yoke.el b/lisp/yoke.el index 2673e5e..4f40869 100644 --- a/lisp/yoke.el +++ b/lisp/yoke.el
@@ -32,7 +32,7 @@ directory created."
32 (message "Downloading %S... done" repo)) 32 (message "Downloading %S... done" repo))
33 dir)) 33 dir))
34 34
35(defun yoke-lasso (pkg repo) 35(defun yoke-lasso (pkg repo &optional load-path)
36 "Add PKG to `load-path' so it can be used. 36 "Add PKG to `load-path' so it can be used.
37If PKG is not installed, install it from REPO. Packages will be 37If PKG is not installed, install it from REPO. Packages will be
38installed to `yoke-dir'." 38installed to `yoke-dir'."
@@ -40,7 +40,8 @@ installed to `yoke-dir'."
40 (yoke-git repo dir) 40 (yoke-git repo dir)
41 (cond 41 (cond
42 ((file-exists-p dir) 42 ((file-exists-p dir)
43 (add-to-list 'load-path dir) 43 (when (or load-path dir)
44 (add-to-list 'load-path (expand-file-name (or load-path dir))))
44 ;; This bit is stolen from `straight'. 45 ;; This bit is stolen from `straight'.
45 (eval-and-compile (require 'autoload)) 46 (eval-and-compile (require 'autoload))
46 (let ((generated-autoload-file 47 (let ((generated-autoload-file
@@ -91,6 +92,31 @@ Similar-ish to `plist-get', but works on non-proper plists."
91 (setq list (cdr list))) 92 (setq list (cdr list)))
92 (reverse r))) 93 (reverse r)))
93 94
95(defun eval-after-init (fn)
96 "Evaluate FN after inititation, or now if Emacs is initialized.
97FN is called with no arguments."
98 (if after-init-time
99 (funcall fn)
100 (add-hook 'after-init-hook fn)))
101
102(defmacro eval-after (features &rest body)
103 "Evaluate BODY, but only after loading FEATURES.
104FEATURES can be an atom or a list; as an atom it works like
105`with-eval-after-load'. The special feature `init' will evaluate
106BODY after Emacs is finished initializing."
107 (declare (indent 1)
108 (debug (form def-body)))
109 (if (eq features 'init)
110 `(eval-after-init (lambda () ,@body))
111 (unless (listp features)
112 (setq features (list features)))
113 (if (null features)
114 (macroexp-progn body)
115 (let* ((this (car features))
116 (rest (cdr features)))
117 `(with-eval-after-load ',this
118 (eval-after ,rest ,@body))))))
119
94(defun yoke-pkg-name (pkg) 120(defun yoke-pkg-name (pkg)
95 (intern (format "yoke:%s" pkg))) 121 (intern (format "yoke:%s" pkg)))
96 122
@@ -98,28 +124,36 @@ Similar-ish to `plist-get', but works on non-proper plists."
98 &optional repo 124 &optional repo
99 &body body 125 &body body
100 &key 126 &key
101 requires ; :requires ((PKG REPO)...) 127 after ; :after (FEATURE...)
102 dest ; :dest DESTINATION 128 depends ; :depends ((PKG REPO)...)
129 load ; :load DIRECTORY
103 (when t whenp) ; :when PREDICATE 130 (when t whenp) ; :when PREDICATE
104 (unless nil unlessp) ; :unless PREDICATE 131 (unless nil unlessp) ; :unless PREDICATE
105 &allow-other-keys) 132 &allow-other-keys)
106 "Yoke a PKG into your Emacs session." 133 "Yoke a PKG into your Emacs session."
107 (declare (indent defun)) 134 (declare (indent defun))
108 (let ((name (yoke-pkg-name pkg))) 135 (let ((name (yoke-pkg-name pkg))
136 (body (delete2 body
137 :depends :when :unless :after :load)))
109 `(cl-block ,name 138 `(cl-block ,name
110 (condition-case e 139 (condition-case e
111 (let ((*yoke-name* ',name) 140 (let ((*yoke-name* ',name)
112 (*yoke-repo* ,repo) 141 (*yoke-repo* ,repo)
113 (*yoke-dest* ,(when repo `(yoke-repo-dir ',pkg ,repo)))) 142 (*yoke-dest* ,(when repo `(yoke-repo-dir ',pkg ,repo))))
114 ,@(list (cond 143 ,@(cond
115 ((and whenp unlessp) 144 ((and whenp unlessp)
116 `(when (or (not ,when) ,unless) 145 `((when (or (not ,when) ,unless)
117 (cl-return-from ,name nil))) 146 (cl-return-from ,name nil))))
118 (whenp `(unless ,when (cl-return-from ,name nil))) 147 (whenp `((unless ,when (cl-return-from ,name nil))))
119 (unlessp `(when ,unless (cl-return-from ,name nil))))) 148 (unlessp `((when ,unless (cl-return-from ,name nil)))))
120 ,@(cl-loop for (pkg repo) in requires 149 ,@(cl-loop for (pkg* repo* load-path*) in depends
121 collect `(or (yoke-lasso ',pkg ,repo) 150 collect `(or (yoke-lasso ',pkg* ,repo* ,load-path*)
122 (cl-return-from ,name nil))) 151 (cl-return-from ,name nil)))
123 ,@(when repo `((yoke-lasso ',pkg ,repo))) 152 ,@(cond
124 ,@(delete2 body :requires :when :unless)) 153 (repo `((yoke-lasso ',pkg ,repo ,load)))
125 (t (message "%s: %S" ',name e)))))) 154 (load `((add-to-list 'load-path ,load))))
155 ,@(if after
156 `((eval-after ,after ,@body))
157 body))
158 (:success ',pkg)
159 (t (message "%s: %s" ',name e))))))