diff options
Diffstat (limited to 'lisp/yoke.el')
-rw-r--r-- | lisp/yoke.el | 88 |
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 | |||
178 | URL's path and placed under `yoke-dir'." | 187 | URL'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'. | ||
320 | If `yoke--all' is part of SELECTIONS, or if it's not given, | ||
321 | return 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 |