-
Notifications
You must be signed in to change notification settings - Fork 2
/
Copy pathquicksys.lisp
147 lines (115 loc) · 4.88 KB
/
quicksys.lisp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
#|
Manoel Vilela & Lucas Vieira © 2019 MIT
|#
(in-package #:quicksys)
;; DIST: alist :: key -> plist
;; key: symbol
(defparameter *dists*
'((bodge (:url "http://bodge.borodust.org/dist/org.borodust.bodge.txt"
:realname org.borodust.bodge))
(bodge-testing (:url "http://bodge.borodust.org/dist/org.borodust.bodge.testing.txt"
:realname org.borodust.bodge.testing))
(cl21 (:url "http://dists.cl21.org/cl21.txt"))
(goheecus (:url "http://hyperprostor.g6.cz/ql/goheecus.txt"))
(monkeylib (:url "http://www.gigamonkeys.com/quicklisp/monkeylib/current.txt"))
(ultralisp (:url "http://dist.ultralisp.org"))
(shirakumo (:url "http://dist.tymoon.eu/shirakumo.txt")))
"*DISTS* is an ALIST of PLISTS, each being one of the distributions available
in QL-META.")
(defun %dist-id (dist-name)
"%DIST-ID converts DIST-NAME to an inner key representation."
(if (typep dist-name 'string)
(intern (string-upcase dist-name) :quicksys)
(intern (symbol-name dist-name) :quicksys)))
(defun %dist-realname (dist)
"%DIST-REALNAME generates the name of a DIST as a downcase string."
(string-downcase
(symbol-name (or (getf (cadr dist) :realname)
(car dist)))))
(defun dist-string (dist)
"DIST-STRING produces a DIST representation in a human-readable format."
(format nil "#<DIST ~A / ~A>"
(car dist)
(dist-url dist)))
(defun dist-properties (dist)
"DIST-PROPERTIES returns the list of properties of a DIST."
(cadr dist))
(defun dist-url (dist)
"DIST-URL returns the url property of a DIST"
(getf (dist-properties dist) :url))
(defun get-dist (dist-name)
"GET-DIST retrieves a DIST based on DIST-NAME, if existing. Otherwise, returns NIL."
(assoc (%dist-id dist-name)
*dists*))
(defun get-dists-urls (&optional (dists *dists*))
"GET-DISTS-URLS returns a list of all dist urls defined in *DISTS*."
(loop for dist in dists
collect (dist-url dist)))
(defun get-dists-names (&optional (dists *dists*))
"GET-DISTS-NAMES returns a list of all dist names defined in *DISTS*"
(loop for (key plist) in dists
collect key))
(defun installedp (dist)
"INSTALLEDP checks whether a DIST was installed through QL-DIST."
(let ((dist-obj (ql-dist:find-dist (%dist-realname dist))))
(and dist-obj (ql-dist:installedp dist-obj))))
(defun install-dist (dist-name &key (force nil))
"INSTALL-DIST installs a dist DIST-NAME using QL-DIST.
As default, use the parameters (:prompt nil :replace t) on
ql-dist:install-dist to avoid human interaction.
If DIST-NAME doesn't exist as a key in *DISTS*, this function
raises an error."
(let ((dist (get-dist dist-name)))
(cond ((null dist)
(error (format nil "error: ~a not found" dist-name)))
((and (not force)
(installedp dist)) t)
(t (apply #'ql-dist:install-dist
(cons (dist-url dist)
'(:prompt nil :replace t)))))))
(defun uninstall-dist (dist-name)
"UNINSTALL-DIST a dist DIST-NAME using QL-DIST.
Returns NIL on uninstallation error and when the dist DIST-NAME were not
installed in the first place. Otherwise, returns T."
(let ((dist (get-dist dist-name)))
(when (and dist (installedp dist))
(let* ((dist-obj (ql-dist:find-dist (%dist-realname dist))))
(ql-dist:uninstall dist-obj)))))
(defun quickload (system &key (dist nil) (silent nil))
"QUICKLOAD wraps QL:QUICKLOAD.
If DIST is specified, QUICKLOAD will attempt to fetch the system from it. If the
specified DIST were not installed prior to system installation, it is removed
again.
Specifying SILENT suppresses output."
(let* ((%dist (get-dist dist))
(installed-before (and %dist (installedp %dist))))
(when dist
(install-dist dist))
(ql:quickload system :silent silent)
(unless installed-before
(uninstall-dist dist))))
(defgeneric dist-apropos-list (term)
(:documentation
"DIST-APROPOS-LIST returns a list of DISTs based in a matching TERM.
This function considers %dist-realname and dist-url when searching.")
(:method ((term symbol))
(dist-apropos-list (symbol-name term)))
(:method ((term string))
(let ((result '())
(nterm (remove-if (lambda (c)
(eq c #\*))
(string-downcase term))))
(dolist (dist *dists* (nreverse result))
(when (or (search nterm (%dist-realname dist))
(search nterm (dist-url dist)))
(push dist result))))))
(defgeneric dist-apropos (term)
(:documentation
"DIST-APROPOS searches for a dist containing TERM and prints it to *STANDARD-OUTPUT*.
This function effectively wraps DIST-APROPOS-LIST so it is printed nicely on
console.")
(:method (term)
(mapcan (lambda (dist)
(format t "~A~%" (dist-string dist)))
(dist-apropos-list term))
(values)))