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.el88
1 files changed, 70 insertions, 18 deletions
diff --git a/lisp/yoke.el b/lisp/yoke.el index 1e1bc60..f9c4d49 100644 --- a/lisp/yoke.el +++ b/lisp/yoke.el
@@ -64,8 +64,8 @@ Execute BODY afterward.
64 (url (cond ((consp package) (cdr package)) 64 (url (cond ((consp package) (cdr package))
65 (:else nil))) 65 (:else nil)))
66 (pname (intern (format "yoke:%s" pkg))) 66 (pname (intern (format "yoke:%s" pkg)))
67 (dirvar (gensym "yoke-dir-")) 67 (dirvar '$yoke-dir)
68 ;; Keyword args 68 ;; Keyword args --- TODO: Naming could probably be better.
69 (after (plist-get body :after)) 69 (after (plist-get body :after))
70 (depends (plist-get body :depends)) 70 (depends (plist-get body :depends))
71 (whenp (plist-member body :when)) 71 (whenp (plist-member body :when))
@@ -77,6 +77,7 @@ Execute BODY afterward.
77 (autoload (cond ((plist-member body :autoload) 77 (autoload (cond ((plist-member body :autoload)
78 (plist-get body :autoload)) 78 (plist-get body :autoload))
79 (:else t))) 79 (:else t)))
80 (pre (plist-get body :pre))
80 ;; Body 81 ;; Body
81 (body (cl-loop for (this next) on body by #'cddr 82 (body (cl-loop for (this next) on body by #'cddr
82 unless (keywordp this) 83 unless (keywordp this)
@@ -102,12 +103,17 @@ Execute BODY afterward.
102 `((when ,unless (cl-return-from ,pname 103 `((when ,unless (cl-return-from ,pname
103 (format "%s (abort) :unless %S" 104 (format "%s (abort) :unless %S"
104 ',pname ',unless)))))) 105 ',pname ',unless))))))
106 ;; Evaluate `:pre' forms
107 ,@pre
105 ;; Get prerequisite packages 108 ;; Get prerequisite packages
106 ,@(cl-loop 109 ,@(cl-loop
107 for (pkg* . yoke-get-args) in depends 110 for (pkg* . yoke-get-args) in depends
108 collect `(or 111 collect `(or
109 (let ((dir (yoke-get ,@yoke-get-args 112 (let* ((pkg-spec (yoke-get ,@yoke-get-args
110 :dir ,(format "%s" pkg*)))) 113 :dir ,(format "%s" pkg*)))
114 (dir (expand-file-name (or (plist-get (cdr pkg-spec) :load)
115 "")
116 (car pkg-spec))))
111 (and dir 117 (and dir
112 ,@(if autoload 118 ,@(if autoload
113 `((yoke-generate-autoloads ',pkg* dir)) 119 `((yoke-generate-autoloads ',pkg* dir))
@@ -118,13 +124,16 @@ Execute BODY afterward.
118 ',pkg*)))) 124 ',pkg*))))
119 ;; Download the package, generate autoloads 125 ;; Download the package, generate autoloads
120 ,@(when url 126 ,@(when url
121 `((let ((,dirvar (yoke-get ,@url :dir ,(format "%s" pkg)))) 127 `((let* ((pkg-spec (yoke-get ,@url :dir ,(format "%s" pkg)))
128 (,dirvar (expand-file-name (or (plist-get (cdr pkg-spec) :load)
129 "")
130 (car pkg-spec))))
122 ,@(when autoload 131 ,@(when autoload
123 `((yoke-generate-autoloads ',pkg ,dirvar))) 132 `((yoke-generate-autoloads ',pkg ,dirvar)))
124 (add-to-list 'yoke-dirs ,dirvar nil #'string=)))) 133 (add-to-list 'yoke-dirs ,dirvar nil #'string=))))
125 ;; Evaluate the body, optionally after the features in `:after' 134 ;; Evaluate the body, optionally after the features in `:after'
126 ,@(cond (after 135 ,@(cond (after
127 `((eval-after ,after ,@body))) 136 `((yoke-eval-after ,after ,@body)))
128 (:else body))) 137 (:else body)))
129 (:success ',package) 138 (:success ',package)
130 (t (message "%s: %s (%s)" ',pname (car err) (cdr err)) 139 (t (message "%s: %s (%s)" ',pname (car err) (cdr err))
@@ -144,7 +153,7 @@ ARGS is a plist with the following possible keys:
144 download URL." 153 download URL."
145 (let* ((dir (plist-get args :dir)) 154 (let* ((dir (plist-get args :dir))
146 (load (plist-get args :load)) 155 (load (plist-get args :load))
147 (type (plist-get args :type)) 156 (type (or (plist-get args :type)))
148 (path (cond 157 (path (cond
149 ((eq type 'http) (yoke-get-http url dir)) 158 ((eq type 'http) (yoke-get-http url dir))
150 ((or (eq type 'git) 159 ((or (eq type 'git)
@@ -159,7 +168,7 @@ ARGS is a plist with the following possible keys:
159 (cond 168 (cond
160 ((file-exists-p path) 169 ((file-exists-p path)
161 (add-to-list 'load-path (expand-file-name (or load "") path)) 170 (add-to-list 'load-path (expand-file-name (or load "") path))
162 path) 171 (cons path args))
163 (:else (error "Directory \"%s\" doesn't exist." path) 172 (:else (error "Directory \"%s\" doesn't exist." path)
164 nil)))) 173 nil))))
165 174
@@ -178,7 +187,18 @@ If DIR isn't given, it's guessed from the final component of the
178URL's path and placed under `yoke-dir'." 187URL's path and placed under `yoke-dir'."
179 (let* ((dir (yoke-get--guess-directory url dir)) 188 (let* ((dir (yoke-get--guess-directory url dir))
180 (basename (file-name-nondirectory url)) 189 (basename (file-name-nondirectory url))
181 (filename (expand-file-name basename dir))) 190 ;; XXX: Is this the best idea?? PROBABLY NOT!!! Ideally I'd have
191 ;; a parameter (either dynamic var or passed in) that would give the
192 ;; name of the downloaded file. But that would take a bit of
193 ;; re-engineering, I think. So for now, it stays thus.
194 (filename (expand-file-name
195 (replace-regexp-in-string
196 (rx "-" (+ digit) ; major version
197 (+ (group "." (+ digit))) ; following version numbers
198 (group "." (+ (not space)))) ; extension
199 "\\2"
200 basename)
201 dir)))
182 (cond ((file-exists-p filename) 202 (cond ((file-exists-p filename)
183 dir) 203 dir)
184 (:else 204 (:else
@@ -187,6 +207,8 @@ URL's path and placed under `yoke-dir'."
187 (url-retrieve-synchronously url)) 207 (url-retrieve-synchronously url))
188 (condition-case e 208 (condition-case e
189 (progn 209 (progn
210 (goto-char (point-min))
211 (delete-region (point) (+ 1 (re-search-forward "^$")))
190 (make-directory dir :parents) 212 (make-directory dir :parents)
191 (write-file filename 1) 213 (write-file filename 1)
192 (message "Downloading %s... Done" url)) 214 (message "Downloading %s... Done" url))
@@ -264,7 +286,7 @@ BODY after Emacs is finished initializing."
264 (rest (cdr features))) 286 (rest (cdr features)))
265 (cond ((eq this 'init) 287 (cond ((eq this 'init)
266 `(yoke--eval-after-init 288 `(yoke--eval-after-init
267 (lambda () (eval-after ,rest ,@body)))) 289 (lambda () (yoke-eval-after ,rest ,@body))))
268 (:else 290 (:else
269 `(with-eval-after-load ',this 291 `(with-eval-after-load ',this
270 (yoke-eval-after ,rest ,@body))))))) 292 (yoke-eval-after ,rest ,@body)))))))
@@ -277,21 +299,51 @@ BODY after Emacs is finished initializing."
277 (setf (alist-get "Yoke" imenu-generic-expression nil nil #'equal) 299 (setf (alist-get "Yoke" imenu-generic-expression nil nil #'equal)
278 (list (rx (: "(yoke" (+ space) (? "(") 300 (list (rx (: "(yoke" (+ space) (? "(")
279 (group (+ (not (or "(" " " "\t" "\n")))) 301 (group (+ (not (or "(" " " "\t" "\n"))))
280 (+ space) 302 (* any)))
281 (group (+ (not space)))))
282 1))) 303 1)))
283 304
284(defun yoke-compile () 305;;; Package maintenance
306
307(defvar yoke--all "*all*"
308 "Value that `yoke--prompt-for-package' uses for all packages.")
309
310(defun yoke--choose-packages (prompt &optional onep)
311 "Choose from all of yoke's installed packages."
312 (funcall (if onep #'completing-read #'completing-read-multiple)
313 prompt
314 (cons yoke--all yoke-dirs)
315 nil :require-match nil nil
316 (unless onep yoke--all)))
317
318(defun yoke--choices (&optional selections)
319 "Either the SELECTIONS given, or all of `yoke-dirs'.
320If `yoke--all' is part of SELECTIONS, or if it's not given,
321return the full list of `yoke-dirs'."
322 (cond ((or (null selections)
323 (member yoke--all selections))
324 yoke-dirs)
325 (:else selections)))
326
327(defun yoke-compile (&rest packages)
285 "Compile all elisp files in `yoke-dirs'." 328 "Compile all elisp files in `yoke-dirs'."
286 (interactive) 329 (interactive (yoke--choose-packages "Compile packages: "))
287 (dolist (dir yoke-dirs) 330 (dolist (dir (yoke--choices packages))
288 (byte-recompile-directory dir 0))) 331 (byte-recompile-directory dir 0)))
289 332
333(defun yoke-update-autoloads (&rest packages)
334 "Update the autoloads in PACKAGES' directories."
335 (interactive (yoke--choose-packages "Generate autoloads for packages: "))
336 (dolist (dir (yoke--choices packages))
337 (message "Generating autoloads for %s..." dir)
338 (yoke-generate-autoloads (file-name-nondirectory dir) dir)
339 (message "Generating autoloads for %s... Done" dir)))
340
290(defun yoke-remove (dir) 341(defun yoke-remove (dir)
342 "Remove DIR from `yoke-dir'."
291 (interactive 343 (interactive
292 (completing-read "Remove: " yoke-dirs 344 (list (completing-read "Remove: " yoke-dirs
293 nil :require-match)) 345 nil :require-match)))
294 (delete-file dir :trash)) 346 (delete-directory dir :recursive :trash))
295 347
296(provide 'yoke) 348(provide 'yoke)
297;;; yoke.el ends here 349;;; yoke.el ends here