├── .readthedocs.yml
├── README.md
├── cl-rtd.asd
├── docs
├── alexandria.md
├── asdf.md
├── bordeaux-threads.md
├── cl-ppcre.md
├── cl-who.md
├── extra.css
├── fiveam.md
├── hunchentoot.md
├── index.md
├── iterate.md
├── local-time.md
├── numcl.md
├── postmodern.md
├── quicklisp.md
├── unix-opts.md
├── usocket.md
└── utilities.md
├── emacs-utils.el
├── mkdocs.yml
├── requirements.txt
├── scratch
└── postmodern.lisp
└── src
├── .gitignore
├── functions.lisp
├── md-file.lisp
├── package.lisp
├── types.lisp
├── utilities.lisp
└── variables.lisp
/.readthedocs.yml:
--------------------------------------------------------------------------------
1 | # .readthedocs.yml
2 | # Read the Docs configuration file
3 | # See https://docs.readthedocs.io/en/stable/config-file/v2.html for details
4 |
5 | # Required
6 | version: 2
7 |
8 | # Build documentation in the docs/ directory with Sphinx
9 | # sphinx:
10 | # configuration: docs/conf.py
11 |
12 | # Build documentation with MkDocs
13 | mkdocs:
14 | configuration: mkdocs.yml
15 | fail_on_warning: false
16 |
17 | # Optionally build your docs in additional formats such as PDF
18 | formats:
19 | - pdf
20 |
21 | # Optionally set the version of Python and requirements required to build your docs
22 | python:
23 | version: 3.7
24 | install:
25 | - requirements: requirements.txt
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | docs/index.md
--------------------------------------------------------------------------------
/cl-rtd.asd:
--------------------------------------------------------------------------------
1 | (asdf:defsystem "cl-rtd"
2 | :depends-on ("alexandria"
3 | "arrows"
4 | "cl-interpol"
5 | "closer-mop"
6 | "introspect-environment"
7 | "iterate"
8 | "str"
9 | "reader+swank"
10 | "trivial-types"
11 | #-swank "swank"
12 | "trivial-package-local-nicknames")
13 | :pathname #P"src/"
14 | :serial t
15 | :components ((:file "package")
16 | (:file "utilities")
17 | (:file "variables")
18 | (:file "functions") ; functions, macros, generic functions
19 | (:file "types") ; tested on SBCL
20 | (:file "md-file")))
21 |
22 | ;;; Why didn't I use docparser or declt?
23 | ;;; I tried declt. But found modifying the output format to suit my needs not
24 | ;;; worth the time investment, at least for bordeaux-threads.
25 | ;;; I found docparser leaving behind some details. I liked it for generating a
26 | ;;; output independent documentation-tree, but it seems not very complete.
27 |
28 |
--------------------------------------------------------------------------------
/docs/bordeaux-threads.md:
--------------------------------------------------------------------------------
1 | # bordeaux-threads - Threading
2 |
3 | Version: 0.8.7
4 |
5 | Licence: MIT
6 |
7 | Repository: [sionescu/bordeaux-threads - Github](https://github.com/sionescu/bordeaux-threads/)
8 |
9 | See also: [awesome-cl#parallelism-and-concurrency](https://github.com/CodyReichert/awesome-cl#parallelism-and-concurrency)
10 |
11 | *This page was possible due to the [official documentation](https://trac.common-lisp.net/bordeaux-threads/wiki/ApiDocumentation), albeit its a bit outdated.*
12 |
13 | *In case of any inaccuracies, ambiguities or suggestions, please [create an issue here](https://github.com/cl-library-docs/common-lisp-libraries/issues).*
14 |
15 | ***
16 |
17 |
18 | BORDEAUX-THREADS is a proposed standard for a minimal
19 | MP/threading interface. It is similar to the CLIM-SYS threading and
20 | lock support, but for the following broad differences:
21 |
22 | 1. Some behaviours are defined in additional detail: attention has
23 | been given to special variable interaction, whether and when
24 | cleanup forms are run. Some behaviours are defined in less
25 | detail: an implementation that does not support multiple
26 | threads is not required to use a new list (nil) for a lock, for
27 | example.
28 |
29 | 2. Many functions which would be difficult, dangerous or inefficient
30 | to provide on some implementations have been removed. Chiefly
31 | these are functions such as thread-wait which expect for
32 | efficiency that the thread scheduler is written in Lisp and
33 | 'hookable', which can't sensibly be done if the scheduler is
34 | external to the Lisp image, or the system has more than one CPU.
35 |
36 | 3. Unbalanced ACQUIRE-LOCK and RELEASE-LOCK functions have been
37 | added.
38 |
39 | 4. Posix-style condition variables have been added, as it's not
40 | otherwise possible to implement them correctly using the other
41 | operations that are specified.
42 |
43 | Threads may be implemented using whatever applicable techniques are
44 | provided by the operating system: user-space scheduling,
45 | kernel-based LWPs or anything else that does the job.
46 |
47 | Some parts of this specification can also be implemented in a Lisp
48 | that does not support multiple threads. Thread creation and some
49 | thread inspection operations will not work, but the locking
50 | functions are still present (though they may do nothing) so that
51 | thread-safe code can be compiled on both multithread and
52 | single-thread implementations without need of conditionals.
53 |
54 | To avoid conflict with existing MP/threading interfaces in
55 | implementations, these symbols live in the BORDEAUX-THREADS package.
56 | Implementations and/or users may also make them visible or exported
57 | in other more traditionally named packages.
58 |
59 | ### \*default-special-bindings\*
60 |
61 | ```lisp
62 | Variable
63 | ```
64 |
65 | This variable holds an alist associating special variable symbols
66 | to forms to evaluate. Special variables named in this list will
67 | be locally bound in the new thread before it begins executing user code.
68 |
69 | This variable may be rebound around calls to [make-thread](#make-thread) to
70 | add/alter default bindings. The effect of mutating this list is
71 | undefined, but earlier forms take precedence over later forms for
72 | the same symbol, so defaults may be overridden by consing to the
73 | head of the list.
74 |
75 | ### \*standard-io-bindings\*
76 |
77 | ```lisp
78 | Variable
79 | ```
80 |
81 | Standard bindings of printer/reader control variables as per CL:WITH-STANDARD-IO-SYNTAX.
82 |
83 | ### \*supports-threads-p\*
84 |
85 | ```lisp
86 | Variable
87 | ```
88 |
89 | This should be set to T if the running instance has thread support.
90 |
91 | ### acquire-lock
92 |
93 | ```lisp
94 | Function: (acquire-lock lock &optional (wait-p t))
95 | ```
96 | Acquire the lock `lock` for the calling thread.
97 | `wait-p` governs what happens if the lock is not available: if `wait-p`
98 | is true, the calling thread will wait until the lock is available
99 | and then acquire it; if `wait-p` is NIL, `acquire-lock` will return
100 | immediately. `acquire-lock` returns true if the lock was acquired and
101 | NIL otherwise.
102 |
103 | This specification does not define what happens if a thread
104 | attempts to acquire a lock that it already holds. For applications
105 | that require locks to be safe when acquired recursively, see instead
106 | [make-recursive-lock](#make-recursive-lock) and friends.
107 |
108 | ### acquire-recursive-lock
109 |
110 | ```lisp
111 | Function: (acquire-recursive-lock lock)
112 | ```
113 | As for [acquire-lock](#acquire-lock), but for recursive locks.
114 |
115 | ### all-threads
116 |
117 | ```lisp
118 | Function: (all-threads)
119 | ```
120 | Returns a sequence of all of the threads. This may not
121 | be freshly-allocated, so the caller should not modify it.
122 |
123 | ### condition-notify
124 |
125 | ```lisp
126 | Function: (condition-notify condition-variable)
127 | ```
128 | Notify at least one of the threads waiting for
129 | `condition-variable`. It is implementation-dependent whether one or
130 | more than one (and possibly all) threads are woken, but if the
131 | implementation is capable of waking only a single thread (not all
132 | are) this is probably preferable for efficiency reasons. The order
133 | of wakeup is unspecified and does not necessarily relate to the
134 | order that the threads went to sleep in.
135 |
136 | `condition-notify` has no useful return value. In an implementation
137 | that does not support multiple threads, it has no effect.
138 |
139 | ### condition-wait
140 |
141 | ```lisp
142 | Function: (condition-wait condition-variable lock &key timeout)
143 | ```
144 | Atomically release `lock` and enqueue the calling
145 | thread waiting for `condition-variable`. The thread will resume when
146 | another thread has notified it using [condition-notify](#condition-notify); it may also
147 | resume if interrupted by some external event or in other
148 | implementation-dependent circumstances: the caller must always test
149 | on waking that there is threading to be done, instead of assuming
150 | that it can go ahead.
151 |
152 | It is an error to call function this unless from the thread that
153 | holds `lock`.
154 |
155 | If `timeout` is nil or not provided, the system always reacquires `lock`
156 | before returning to the caller. In this case T is returned.
157 |
158 | If `timeout` is non-nil, the call will return after at most `timeout`
159 | seconds (approximately), whether or not a notification has occurred.
160 | Either NIL or T will be returned. A return of NIL indicates that the
161 | lock is no longer held and that the timeout has expired. A return of
162 | T indicates that the lock is held, in which case the timeout may or
163 | may not have expired.
164 |
165 | **NOTE**: The behavior of `condition-wait` with `timeout` diverges from
166 | the POSIX function pthread_cond_timedwait. The former may return
167 | without the lock being held while the latter always returns with the
168 | lock held.
169 |
170 | In an implementation that does not support multiple threads, this
171 | function signals an error.
172 |
173 | ### current-thread
174 |
175 | ```lisp
176 | Function: (current-thread)
177 | ```
178 | Returns the thread object for the calling
179 | thread. This is the same kind of object as would be returned by
180 | [make-thread](#make-thread).
181 |
182 | ### destroy-thread
183 |
184 | ```lisp
185 | Function: (destroy-thread thread)
186 | ```
187 | Terminates the thread `thread`, which is an object
188 | as returned by [make-thread](#make-thread). This should be used with caution: it is
189 | implementation-defined whether the thread runs cleanup forms or
190 | releases its locks first.
191 |
192 | Destroying the calling thread is an error.
193 |
194 | ### interrupt-thread
195 |
196 | ```lisp
197 | Function: (interrupt-thread thread function &rest args)
198 | ```
199 | Interrupt `thread` and cause it to evaluate `function`
200 | before continuing with the interrupted path of execution. This may
201 | not be a good idea if `thread` is holding locks or doing anything
202 | important. On systems that do not support multiple threads, this
203 | function signals an error.
204 |
205 | ### join-thread
206 |
207 | ```lisp
208 | Function: (join-thread thread)
209 | ```
210 | Wait until `thread` terminates. If `thread` has already terminated,
211 | return immediately. The return values of the thread function are
212 | returned.
213 |
214 | ### lock
215 |
216 | ### lock-p
217 |
218 | ```lisp
219 | Function: (lock-p object)
220 | ```
221 | Returns T if `object` is a lock; returns NIL otherwise.
222 |
223 | ### make-condition-variable
224 |
225 | ```lisp
226 | Function: (make-condition-variable &key name)
227 | ```
228 | Returns a new condition-variable object for use
229 | with [condition-wait](#condition-wait) and [condition-notify](#condition-notify).
230 |
231 | ### make-lock
232 |
233 | ```lisp
234 | Function: (make-lock &optional name)
235 | ```
236 | Creates a lock (a mutex) whose name is `name`. If the system does not
237 | support multiple threads this will still return some object, but it
238 | may not be used for very much.
239 |
240 | ### make-recursive-lock
241 |
242 | ```lisp
243 | Function: (make-recursive-lock &optional name)
244 | ```
245 | Create and return a recursive lock whose name is `name`. A recursive
246 | lock differs from an ordinary lock in that a thread that already
247 | holds the recursive lock can acquire it again without blocking. The
248 | thread must then release the lock twice before it becomes available
249 | for another thread.
250 |
251 | ### make-semaphore
252 |
253 | ```lisp
254 | Function: (make-semaphore &key name (count 0))
255 | ```
256 | Create a semaphore with the supplied `name` and initial counter value `count`.
257 |
258 | ### make-thread
259 |
260 | ```lisp
261 | Function: (make-thread function &key name (initial-bindings
262 | *default-special-bindings*))
263 | ```
264 | Creates and returns a thread named `name`, which will call the
265 | function `function` with no arguments: when `function` returns, the
266 | thread terminates. `name` defaults to "Anonymous thread" if unsupplied.
267 |
268 | On systems that do not support multi-threading, `make-thread` will
269 | signal an error.
270 |
271 | The interaction between threads and dynamic variables is in some
272 | cases complex, and depends on whether the variable has only a global
273 | binding (as established by e.g. DEFVAR/DEFPARAMETER/top-level SETQ)
274 | or has been bound locally (e.g. with LET or LET*) in the calling
275 | thread.
276 |
277 | - Global bindings are shared between threads: the initial value of a
278 | global variable in the new thread will be the same as in the
279 | parent, and an assignment to such a variable in any thread will be
280 | visible to all threads in which the global binding is visible.
281 |
282 | - Local bindings, such as the ones introduced by `initial-bindings`,
283 | are local to the thread they are introduced in, except that
284 |
285 | - Local bindings in the the caller of `make-thread` may or may not be
286 | shared with the new thread that it creates: this is
287 | implementation-defined. Portable code should not depend on
288 | particular behaviour in this case, nor should it assign to such
289 | variables without first rebinding them in the new thread.
290 |
291 | ### recursive-lock
292 |
293 | ### recursive-lock-p
294 |
295 | ```lisp
296 | Function: (recursive-lock-p object)
297 | ```
298 | Returns T if `object` is a recursive lock; returns NIL otherwise.
299 |
300 | ### release-lock
301 |
302 | ```lisp
303 | Function: (release-lock lock)
304 | ```
305 | Release `lock`. It is an error to call this unless
306 | the lock has previously been acquired (and not released) by the same
307 | thread. If other threads are waiting for the lock, the
308 | [acquire-lock](#acquire-lock) call in one of them will now be able to continue.
309 |
310 | This function has no interesting return value.
311 |
312 | ### release-recursive-lock
313 |
314 | ```lisp
315 | Function: (release-recursive-lock lock)
316 | ```
317 | Release the recursive `lock`. The lock will only
318 | become free after as many Release operations as there have been
319 | Acquire operations. See [release-lock](#release-lock) for other information.
320 |
321 | ### semaphore
322 |
323 | ### semaphore-p
324 |
325 | ```lisp
326 | Function: (semaphore-p object)
327 | ```
328 | Returns T if `object` is a semaphore; returns NIL otherwise.
329 |
330 | ### signal-semaphore
331 |
332 | ```lisp
333 | Function: (signal-semaphore semaphore &key (count 1))
334 | ```
335 | Increment `semaphore` by `count`. If there are threads waiting on this
336 | semaphore, then `count` of them are woken up.
337 |
338 | ### start-multiprocessing
339 |
340 | ```lisp
341 | Function: (start-multiprocessing)
342 | ```
343 | If the host implementation uses user-level threads, start the
344 | scheduler and multiprocessing, otherwise do nothing.
345 | It is safe to call repeatedly.
346 |
347 | ### thread
348 |
349 | ### thread-alive-p
350 |
351 | ```lisp
352 | Function: (thread-alive-p thread)
353 | ```
354 | Returns true if `thread` is alive, that is, if
355 | [destroy-thread](#destroy-thread) has not been called on it.
356 |
357 | ### thread-name
358 |
359 | ```lisp
360 | Function: (thread-name thread)
361 | ```
362 | Returns the name of the thread, as supplied to [make-thread](#make-thread).
363 |
364 | ### thread-yield
365 |
366 | ```lisp
367 | Function: (thread-yield)
368 | ```
369 | Allows other threads to run. It may be necessary or desirable to
370 | call this periodically in some implementations; others may schedule
371 | threads automatically. On systems that do not support
372 | multi-threading, this does nothing.
373 |
374 | ### threadp
375 |
376 | ```lisp
377 | Function: (threadp object)
378 | ```
379 | Returns true if object is a thread, otherwise NIL.
380 |
381 | ### timeout
382 |
383 | ### wait-on-semaphore
384 |
385 | ```lisp
386 | Function: (wait-on-semaphore semaphore &key timeout)
387 | ```
388 | Decrement the count of `semaphore` by 1 if the count would not be negative.
389 |
390 | Else blocks until the semaphore can be decremented. Returns generalized boolean
391 | T on success.
392 |
393 | If `timeout` is given, it is the maximum number of seconds to wait. If the count
394 | cannot be decremented in that time, returns NIL without decrementing the count.
395 |
396 | ### with-lock-held
397 |
398 | ```lisp
399 | Macro: (with-lock-held (place) &body body)
400 | ```
401 | Evaluates `body` with the lock named by `place`, the value of which
402 | is a lock created by [make-lock](#make-lock). Before the forms in `body` are
403 | evaluated, the lock is acquired as if by using [acquire-lock](#acquire-lock). After the
404 | forms in `body` have been evaluated, or if a non-local control transfer
405 | is caused (e.g. by THROW or SIGNAL), the lock is released as if by
406 | [release-lock](#release-lock).
407 |
408 | Note that if the debugger is entered, it is unspecified whether the
409 | lock is released at debugger entry or at debugger exit when execution
410 | is restarted.
411 |
412 | ### with-recursive-lock-held
413 |
414 | ```lisp
415 | Macro: (with-recursive-lock-held (place) &body body)
416 | ```
417 | Evaluates `body` with the recursive lock named by `place`, which is a
418 | reference to a recursive lock created by [make-recursive-lock](#make-recursive-lock). See
419 | [with-lock-held](#with-lock-held) etc etc
420 |
421 | ### with-timeout
422 |
423 | ```lisp
424 | Macro: (with-timeout (timeout) &body body)
425 | ```
426 |
--------------------------------------------------------------------------------
/docs/cl-ppcre.md:
--------------------------------------------------------------------------------
1 | # cl-ppcre - Regular Expressions
2 |
3 | Version: 2.1.1
4 |
5 | Licence: BSD
6 |
7 | Nickname: ppcre
8 |
9 | Repository: [edicl/cl-ppcre - Github](https://github.com/edicl/cl-ppcre)
10 |
11 | See also: [awesome-cl/#regex](https://github.com/CodyReichert/awesome-cl#regex)
12 |
13 | *This documentation is possible the [excellent official documentation](https://edicl.github.io/cl-ppcre) as of 4th May 2020.*
14 |
15 | *In case of any inaccuracies, ambiguities or suggestions, please [create an issue here](https://github.com/cl-library-docs/common-lisp-libraries/issues).*
16 |
17 | ***
18 |
19 | CL-PPCRE is a Portable Perl-Compatible Regular Expressions library for Common Lisp.
20 | This is also thread-safe, and allows specifying [regular expressions using
21 | S-expressions](#using-s-expressions).
22 |
23 |
24 | ## GETTING STARTED
25 |
26 | ### Using perl regex
27 |
28 | Per the name, `cl-ppcre` is more or less compatible with perl 5.8 including
29 | extended features like non-greedy repetitions, positive and negative
30 | look-ahead and look-behind assertions, "standalone" subexpressions,
31 | and conditional subpatterns. The following Perl features are
32 | (currently) **not** supported:
33 |
34 | - `(?{ code })` and `(??{ code })` because they obviously don't make
35 | sense in Lisp.
36 | - `\N{name}` (named characters), `\x{263a}` (wide hex characters),
37 | `\l`, `\u`, `\L`, and `\U` because they're actually not part of
38 | Perl's *regex* syntax - but see
39 | [CL-INTERPOL](https://github.com/edicl/cl-interpol/).
40 | - `\X` (extended Unicode), and `\C` (single character). But you can
41 | of course use all characters supported by your CL implementation.
42 | - Posix character classes like `[[:alpha]]`. Load `(asdf:load-system :cl-ppcre-unicode)`
43 | to install [unicode-preperty-resolver](#unicode-property-resolver) as your
44 | [property-resolver](#property-resolver). See [cl-unicode](https://edicl.github.io/cl-unicode/)
45 | for the supported unicode properties and their naming conventions.
46 | - `\G` for Perl's `pos()` because we don't have it.
47 |
48 | Note, however, that `\t`, `\n`, `\r`, `\f`, `\a`, `\e`, `\033` (octal
49 | character codes), `\x1B` (hexadecimal character codes), `\c[` (control
50 | characters), `\w`, `\W`, `\s`, `\S`, `\d`, `\D`, `\b`, `\B`, `\A`,
51 | `\Z`, and `\z` **are** supported.
52 |
53 | Users can straightaway start with:
54 |
55 | - [scan](#scan)
56 | - [scan-to-strings](#scan-to-strings)
57 | - [split](#split)
58 | - [quote-meta-chars](#quote-meta-chars)
59 | - [register-groups-bind](#register-groups-bind)
60 | - [regex-replace](#regex-replace)
61 |
62 | Register groups simply refer to the captured groups. For instance:
63 |
64 | ```lisp
65 | CL-USER> (register-groups-bind (a b) ("([^ ]+) ([^ ]+)" "hello world")
66 | (list a b))
67 | ("hello" "world")
68 | ```
69 |
70 | See the [other macros](#do-matches) for iterative versions of these.
71 |
72 | Those wanting to get into perl regular expressions, might find [their official
73 | documentation](https://perldoc.perl.org/perlre.html) useful.
74 |
75 | Users comfortable with regular expressions might also want to try
76 | [cl-interpol](https://github.com/edicl/cl-interpol/) - which provides string
77 | interpolation facilities to the lisp reader. (Yes, it's defacto!)
78 |
79 | ### Using s-expressions
80 |
81 | The basics:
82 |
83 | ```
84 | +------- Common Lisp Equivalent -------+----------- Perl Equivalent -----------+
85 | | String / Character | Literal treatment |
86 | | :void | Empty string |
87 | | :everything | Dot |
88 | | :(non-)word-boundary | \b, \B (non) |
89 | | :(non-)digit-class | \d, \D (non) |
90 | | :(non-)word-char-class | \w, \W (non) |
91 | | :(non-)whitespace-char-class | \s, \S (non) |
92 | | :start/end-anchor | ^ [start], $ [end |
93 | | :modeless-start/end-anchor | \A [start], \Z [end] |
94 | | :modeless-end-anchor-no-newline | \z |
95 | | :case-(in)sensitive-p | (?i), (?-i) [insensitive] |
96 | | :(not)-multi-line-mode-p | (?m), (?-m) [not] |
97 | | :(not)-single-line-mode-p | (?s), (?-s) [not] |
98 | | (anything else) | Syntax Error |
99 | +--------------------------------------+---------------------------------------+
100 | ```
101 |
102 | Simple combinations include `:sequence`, `:group`, `:flags`, `:register`,
103 | `:greedy-repetition`, `:non-greedy-repetition`. You could play around with
104 | [parse-string](#parse-string) to learn more about the equivalence.
105 |
106 | For instance:
107 |
108 | ```lisp
109 | * (parse-string "(ab)*")
110 | (:GREEDY-REPETITION 0 `NIL` (:REGISTER "ab"))
111 |
112 | * (parse-string "(a(b))")
113 | (:REGISTER (:SEQUENCE #\a (:REGISTER #\b)))
114 |
115 | * (parse-string "(?:abc){3,5}")
116 | (:GREEDY-REPETITION 3 5 (:GROUP "abc"))
117 | ;; (:GREEDY-REPETITION 3 5 "abc") would also be OK
118 |
119 | * (parse-string "a(?i)b(?-i)c")
120 | (:SEQUENCE #\a
121 | (:SEQUENCE (:FLAGS :CASE-INSENSITIVE-P)
122 | (:SEQUENCE #\b (:SEQUENCE (:FLAGS :CASE-SENSITIVE-P) #\c))))
123 | ;; same as (:SEQUENCE #\a :CASE-INSENSITIVE-P #\b :CASE-SENSITIVE-P #\c)
124 |
125 | * (parse-string "(?=a)b")
126 | (:SEQUENCE (:POSITIVE-LOOKAHEAD #\a) #\b)
127 |
128 | * (parse-string "aa|aaa")
129 | (:ALTERNATION "aa" "aaa")
130 | ```
131 |
132 | See the [manual](https://edicl.github.io/cl-ppcre/#create-scanner2) for the
133 | more detailed equivalence.
134 |
135 | Thus, you could equivalently use parse-trees for the functions and macros that
136 | expect regex.
137 |
138 | ```lisp
139 | * (all-matches-as-strings '(:greedy-repetition 1 nil #\a) "aaaa")
140 | ("aaaa")
141 | ```
142 |
143 | ### Performance Aspects
144 |
145 | `cl-ppcre` was intended to be fast. Indeed, [when it first appeared,
146 | it was perhaps the fastest](http://web.archive.org/web/20080624164217/http://weitz.de/cl-ppcre/#bench).
147 |
148 | However, in 2020, it can be five times as slow as Perl:
149 |
150 | ```sh
151 | time perl -e '"@{['x' x 50000000]}" =~ /([xy])*/'
152 |
153 | real 0m0.245s
154 | user 0m0.161s
155 | sys 0m0.084s
156 | ```
157 |
158 |
159 | ```lisp
160 | CL-USER> (time (progn
161 | (scan "([xy])*"
162 | (make-string 50000000 :element-type 'base-char
163 | :initial-element #\x))
164 | nil))
165 | Evaluation took:
166 | 1.116 seconds of real time
167 | 1.115901 seconds of total run time (1.111972 user, 0.003929 system)
168 | 100.00% CPU
169 | 2,463,959,814 processor cycles
170 | 50,000,032 bytes consed
171 | ```
172 |
173 | But still (more than) 5 times faster than python:
174 |
175 | ```sh
176 | time python3 -c 'import re; x = re.search("([xy])*", "x"*50000000)'
177 |
178 | real 0m7.458s
179 | user 0m4.563s
180 | sys 0m2.892s
181 | ```
182 |
183 | Or slower as well:
184 |
185 | ```sh
186 | $ ~ time python3 -c 'import re; x = re.search("x*", "x"*50000000)'
187 |
188 | real 0m0.146s
189 | user 0m0.109s
190 | sys 0m0.036s
191 | ```
192 |
193 | Honestly, though, it should be possible to use implementation specific means to speed things up
194 | - or copying the developments in the perl and/or python world.
195 |
196 | Perhaps, see the [manual](https://edicl.github.io/cl-ppcre/#blabla) for hints on speeding things
197 | up.
198 |
199 | ## FUNCTIONS AND MACROS
200 |
201 | ### all-matches
202 |
203 | ```lisp
204 | Function: (all-matches regex target-string
205 | &key (start 0) (end (length target-string)))
206 | ```
207 | Returns a list containing the start and end positions of all
208 | matches of `regex` against `target-string`, i.e. if there are N matches
209 | the list contains (* 2 N) elements. If `regex` matches an empty string
210 | the scan is continued one position behind this match.
211 |
212 | ### all-matches-as-strings
213 |
214 | ```lisp
215 | Function: (all-matches-as-strings regex target-string
216 | &key (start 0) (end (length target-string)) sharedp)
217 | ```
218 | Returns a list containing all substrings of `target-string` which
219 | match `regex`. If `regex` matches an empty string the scan is continued
220 | one position behind this match. If `sharedp` is true, the substrings may
221 | share structure with `target-string`.
222 |
223 | ### create-optimized-test-function
224 |
225 | ```lisp
226 | Function: (create-optimized-test-function test-function
227 | &key (start 0) (end *regex-char-code-limit*)
228 | (kind *optimize-char-classes*))
229 | ```
230 | Given a unary test function which is applicable to characters
231 | returns a function which yields the same boolean results for all
232 | characters with character codes from `start` to (excluding) `end`. If
233 | `kind` is `nil`, `test-function` will simply be returned. Otherwise, `kind`
234 | should be one of:
235 |
236 | * `:hash-table` - builds a hash table representing all characters which
237 | satisfy the test and returns a closure which checks if
238 | a character is in that hash table
239 |
240 | * `:charset` - instead of a hash table uses a "charset" which is a
241 | data structure using non-linear hashing and optimized to
242 | represent (sparse) sets of characters in a fast and
243 | space-efficient way (contributed by Nikodemus Siivola)
244 |
245 | * `:charmap` - instead of a hash table uses a bit vector to represent
246 | the set of characters
247 |
248 | You can also use `:hash-table*` or `:charset*` which are like `:hash-table`
249 | and `:charset` but use the complement of the set if the set contains
250 | more than half of all characters between `start` and `end`. This saves
251 | space but needs an additional pass across all characters to create the
252 | data structure. There is no corresponding `:charmap*` kind as the bit
253 | vectors are already created to cover the smallest possible interval
254 | which contains either the set or its complement.
255 |
256 | ### create-scanner
257 |
258 | ```lisp
259 | Function: (create-scanner regex
260 | &key case-insensitive-mode multi-line-mode
261 | single-line-mode extended-mode destructive)
262 | ```
263 | Accepts a regular expression - either as a
264 | parse-tree or as a string - and returns a scan closure which will scan
265 | strings for this regular expression and a list mapping registers to
266 | their names (`nil` stands for unnamed ones). The "mode" keyword
267 | arguments are equivalent to the imsx modifiers in Perl. If
268 | `destructive` is not `nil`, the function is allowed to destructively
269 | modify its first argument (but only if it's a parse tree).
270 |
271 | (More in the manual!)
272 |
273 | ### define-parse-tree-synonym
274 |
275 | ```lisp
276 | Macro: (define-parse-tree-synonym name parse-tree)
277 | ```
278 | Defines the symbol `name` to be a synonym for the parse tree
279 | `parse-tree`. Both arguments are quoted.
280 |
281 | ### do-matches
282 |
283 | ```lisp
284 | Macro: (do-matches (match-start match-end regex target-string
285 | &optional result-form &key start end)
286 | &body body)
287 | ```
288 | Iterates over `target-string` and tries to match `regex` as often as
289 | possible evaluating `body` with `match-start` and `match-end` bound to the
290 | start/end positions of each match in turn. After the last match,
291 | returns `result-form` if provided or `nil` otherwise. An implicit block
292 | named `nil` surrounds `do-matches`; `return` may be used to terminate the
293 | loop immediately. If `regex` matches an empty string the scan is
294 | continued one position behind this match. `body` may start with
295 | declarations.
296 |
297 | ### do-matches-as-strings
298 |
299 | ```lisp
300 | Macro: (do-matches-as-strings
301 | (match-var regex target-string
302 | &optional result-form &key start end sharedp)
303 | &body body)
304 | ```
305 | Iterates over `target-string` and tries to match `regex` as often as
306 | possible evaluating `body` with `match-var` bound to the substring of
307 | `target-string` corresponding to each match in turn. After the last
308 | match, returns `result-form` if provided or `nil` otherwise. An implicit
309 | block named `nil` surrounds `do-matches-as-strings`; `return` may be used to
310 | terminate the loop immediately. If `regex` matches an empty string the
311 | scan is continued one position behind this match. If `sharedp` is true,
312 | the substrings may share structure with `target-string`. `body` may start
313 | with declarations.
314 |
315 | ### do-register-groups
316 |
317 | ```lisp
318 | Macro: (do-register-groups
319 | var-list
320 | (regex target-string
321 | &optional result-form &key start end sharedp)
322 | &body body)
323 | ```
324 | Iterates over `target-string` and tries to match `regex` as often as
325 | possible evaluating `body` with the variables in `var-list` bound to the
326 | corresponding register groups for each match in turn, i.e. each
327 | variable is either bound to a string or to `nil`. For each element of
328 | `var-list` which is `nil` there's no binding to the corresponding register
329 | group. The number of variables in `var-list` must not be greater than
330 | the number of register groups. After the last match, returns
331 | `result-form` if provided or `nil` otherwise. An implicit block named `nil`
332 | surrounds `do-register-groups`; `return` may be used to terminate the loop
333 | immediately. If `regex` matches an empty string the scan is continued
334 | one position behind this match. If `sharedp` is true, the substrings
335 | may share structure with `target-string`. `body` may start with
336 | declarations.
337 |
338 | ### do-scans
339 |
340 | ```lisp
341 | Macro: (do-scans (match-start match-end reg-starts reg-ends regex target-string
342 | &optional result-form &key start end)
343 | &body body)
344 | ```
345 | Iterates over `target-string` and tries to match `regex` as often as
346 | possible evaluating BODY with `match-start`, `match-end`, `reg-starts`, and
347 | `reg-ends` bound to the four return values of each match in turn. After
348 | the last match, returns `result-form` if provided or `nil` otherwise. An
349 | implicit block named `nil` surrounds `do-scans`; `return` may be used to
350 | terminate the loop immediately. If `regex` matches an empty string the
351 | scan is continued one position behind this match. `body` may start with
352 | declarations.
353 |
354 | ### parse-string
355 |
356 | ```lisp
357 | Function: (parse-string string)
358 | ```
359 | Translate the regex string `string` into a parse tree.
360 |
361 | ### parse-tree-synonym
362 |
363 | ```lisp
364 | Function: (parse-tree-synonym symbol)
365 | ```
366 | Returns the parse tree the `symbol` symbol is a synonym for. Returns
367 | `nil` is `symbol` wasn't yet defined to be a synonym.
368 |
369 | ### ppcre-error
370 |
371 | Every error signaled by CL-PPCRE is of type `ppcre-error`. This is a direct subtype of
372 | [simple-error](http://www.lispworks.com/documentation/HyperSpec/Body/e_smp_er.htm)
373 | without any additional slots or options.
374 |
375 | ### ppcre-invocation-error
376 |
377 | Errors of type `ppcre-invocation-error` are signaled if one of the exported functions of CL-PPCRE is called with wrong or inconsistent arguments. This is a direct subtype of `ppcre-error` without any additional slots or options.
378 |
379 | ### ppcre-syntax-error
380 |
381 | An error of type `ppcre-syntax-error` is signaled if CL-PPCRE's parser encounters an error when trying to parse a regex string or to convert a parse tree into its internal representation. This is a direct subtype of `ppcre-error` with two additional slots. These denote the regex string which HTML-PPCRE was parsing and the position within the string where the error occurred. If the error happens while CL-PPCRE is converting a parse tree, both of these slots contain NIL. (See the next two entries on how to access these slots.)
382 |
383 | ### ppcre-syntax-error-pos
384 |
385 | ```lisp
386 | Function: (ppcre-syntax-error-pos condition)
387 | ```
388 | Returns the position within the string where the error occurred
389 | (or `nil` if the error happened while trying to convert a parse tree
390 |
391 | ### ppcre-syntax-error-string
392 |
393 | ```lisp
394 | Function: (ppcre-syntax-error-string condition)
395 | ```
396 | Returns the string the parser was parsing when the error was
397 | encountered (or `nil` if the error happened while trying to convert a
398 | parse tree).
399 |
400 |
401 | ### quote-meta-chars
402 |
403 | ```lisp
404 | Function: (quote-meta-chars string &key (start 0) (end (length string)))
405 | ```
406 | Quote, i.e. prefix all non-word characters in `string` with `#\\`.
407 |
408 | ### regex-apropos
409 |
410 | ```lisp
411 | Function: (regex-apropos regex &optional packages &key (case-insensitive t))
412 | ```
413 | Similar to the standard function `apropos` but returns a list of all
414 | symbols which match the regular expression REGEX. If `case-insensitive`
415 | is true and `regex` isn't already a scanner, a case-insensitive scanner
416 | is used.
417 |
418 | ### regex-apropos-list
419 |
420 | ```lisp
421 | Function: (regex-apropos-list regex &optional packages &key (case-insensitive t))
422 | ```
423 | Similar to the standard function `apropos-list` but returns a list of
424 | all symbols which match the regular expression `regex`. If
425 | `case-insensitive` is true and `regex` isn't already a scanner, a
426 | case-insensitive scanner is used.
427 |
428 | ### regex-replace
429 |
430 | ```lisp
431 | Function: (regex-replace regex target-string replacement
432 | &key (start 0) (end (length target-string))
433 | preserve-case simple-calls
434 | (element-type 'character))
435 | ```
436 | Try to match `target-string` between `start` and `end` against `regex` and
437 | replace the first match with `replacement`. Two values are returned;
438 | the modified string, and `t` if `regex` matched or `nil` otherwise.
439 |
440 | `replacement` can be a string which may contain the special substrings
441 | "\&" for the whole match, "\`" for the part of `target-string`
442 | before the match, "\'" for the part of `target-string` after the
443 | match, "\N" or "\{N}" for the Nth register where N is a positive
444 | integer.
445 |
446 | `replacement` can also be a function designator in which case the
447 | match will be replaced with the result of calling the function
448 | designated by `replacement` with the arguments `target-string`, `start`,
449 | `end`, `match-start`, `match-end`, `reg-starts`, and `reg-ends`. (`reg-starts` and
450 | `reg-ends` are arrays holding the start and end positions of matched
451 | registers or `nil` - the meaning of the other arguments should be
452 | obvious.)
453 |
454 | Finally, `replacement` can be a list where each element is a string,
455 | one of the symbols `:match`, `:before-match`, or `:after-match` -
456 | corresponding to "\&", "\`", and "\'" above -, an integer N -
457 | representing register (1+ N) -, or a function designator.
458 |
459 | If `preserve-case` is true, the replacement will try to preserve the
460 | case (all upper case, all lower case, or capitalized) of the
461 | match. The result will always be a fresh string, even if `regex` doesn't
462 | match.
463 |
464 | `element-type` is the element type of the resulting string.
465 |
466 | ### regex-replace-all
467 |
468 | ```lisp
469 | Function: (regex-replace-all regex target-string replacement
470 | &key (start 0) (end (length target-string))
471 | preserve-case simple-calls
472 | (element-type 'character))
473 | ```
474 | Try to match `target-string` between `start` and `end` against `regex` and
475 | replace all matches with `replacement`. Two values are returned; the
476 | modified string, and T if `regex` matched or `nil` otherwise.
477 |
478 | `replacement` can be a string which may contain the special substrings
479 | "\&" for the whole match, "\`" for the part of `target-string`
480 | before the match, "\'" for the part of `target-string` after the
481 | match, "\N" or "\{N}" for the Nth register where N is a positive
482 | integer.
483 |
484 | `replacement` can also be a function designator in which case the
485 | match will be replaced with the result of calling the function
486 | designated by `replacement` with the arguments `target-string`, `start`,
487 | `end`, `match-start`, `match-end`, `reg-starts`, and `reg-ends`. (`reg-starts` and
488 | `reg-ends` are arrays holding the start and end positions of matched
489 | registers or `nil` - the meaning of the other arguments should be
490 | obvious.)
491 |
492 | Finally, `replacement` can be a list where each element is a string,
493 | one of the symbols `:match`, `:before-match`, or `:after-match` -
494 | corresponding to "\&", "\`", and "\'" above -, an integer N -
495 | representing register (1+ N) -, or a function designator.
496 |
497 | If `preserve-case` is true, the replacement will try to preserve the
498 | case (all upper case, all lower case, or capitalized) of the
499 | match. The result will always be a fresh string, even if `regex` doesn't
500 | match.
501 |
502 | `element-type` is the element type of the resulting string.
503 |
504 | ### register-groups-bind
505 |
506 | ```lisp
507 | Macro: (register-groups-bind var-list
508 | (regex target-string &key start end sharedp)
509 | &body body)
510 | ```
511 | Executes `body` with the variables in `var-list` bound to the
512 | corresponding register groups after `target-string` has been matched
513 | against `regex`, i.e. each variable is either bound to a string or to
514 | `nil`. If there is no match, `body` is _not_ executed. For each element
515 | of `var-list` which is `nil` there's no binding to the corresponding
516 | register group. The number of variables in `var-list` must not be
517 | greater than the number of register groups. If `sharedp` is true, the
518 | substrings may share structure with `target-string`.
519 |
520 | ### scan
521 |
522 | ```lisp
523 | Function: (scan regex target-string &key start end real-start-pos)
524 | ```
525 | Searches `target-string` from `start` to `end` and tries
526 | to match `regex`. On success returns four values - the start of the
527 | match, the end of the match, and two arrays denoting the beginnings
528 | and ends of register matches. On failure returns `nil`. `regex` can be a
529 | string which will be parsed according to Perl syntax, a parse tree, or
530 | a pre-compiled scanner created by [create-scanner](#create-scanner). `target-string` will
531 | be coerced to a simple string if it isn't one already. The
532 | `real-start-pos` parameter should be ignored - it exists only for
533 | internal purposes.
534 |
535 |
536 | ### scan-to-strings
537 |
538 | ```lisp
539 | Function: (scan-to-strings regex target-string
540 | &key (start 0) (end (length target-string)) sharedp)
541 | ```
542 | Like `scan` but returns substrings of `target-string` instead of
543 | positions, i.e. this function returns two values on success: the whole
544 | match as a string plus an array of substrings (or `nil`s) corresponding
545 | to the matched registers. If `sharedp` is true, the substrings may
546 | share structure with `target-string`.
547 |
548 | ### split
549 |
550 | ```lisp
551 | Function: (split regex target-string
552 | &key (start 0) (end (length target-string))
553 | limit with-registers-p omit-unmatched-p sharedp)
554 | ```
555 | Matches `regex` against `target-string` as often as possible and
556 | returns a list of the substrings between the matches. If
557 | `with-registers-p` is true, substrings corresponding to matched
558 | registers are inserted into the list as well. If `omit-unmatched-p` is
559 | true, unmatched registers will simply be left out, otherwise they will
560 | show up as `nil`. `limit` limits the number of elements returned -
561 | registers aren't counted. If `limit` is `nil` (or 0 which is
562 | equivalent), trailing empty strings are removed from the result list.
563 | If `regex` matches an empty string the scan is continued one position
564 | behind this match. If `sharedp` is true, the substrings may share
565 | structure with `target-string`.
566 |
567 |
568 | ## CONFIGURATION VARIABLES
569 |
570 | ### \*allow-named-registers\*
571 |
572 | Whether the parser should support AllegroCL's named registers
573 | `(?"")` and back-reference \k syntax.
574 |
575 | ### \*allow-quoting\*
576 |
577 | Whether the parser should support Perl's \Q and \E.
578 |
579 | ### \*look-ahead-for-suffix\*
580 |
581 | Controls whether scanners will optimistically look ahead for a
582 | constant suffix of a regular expression, if there is one.
583 |
584 | ### \*optimize-char-classes\*
585 |
586 | Whether character classes should be compiled into look-ups into
587 | O(1) data structures. This is usually fast but will be costly in
588 | terms of scanner creation time and might be costly in terms of size if
589 | `*regex-char-code-limit*` is high. This value will be used as the `:kind`
590 | keyword argument to `create-optimized-test-function` - see there for the
591 | possible non-`NIL` values.
592 |
593 | ### \*property-resolver\*
594 |
595 | Should be `NIL` or a designator for a function which accepts strings
596 | and returns unary character test functions or `NIL`. This 'resolver' is
597 | intended to handle character properties' like \p{IsAlpha}. If
598 | `*property-resolver*` is `NIL`, then the parser will simply treat \p and
599 | \P as #\p and #\P as in older versions of CL-PPCRE.
600 |
601 | ### \*regex-char-code-limit\*
602 |
603 | The upper exclusive bound on the char-codes of characters which can
604 | occur in character classes. Change this value BEFORE creating
605 | scanners if you don't need the (full) Unicode support of
606 | implementations like AllegroCL, CLISP, LispWorks, or SBCL.
607 |
608 | ### \*use-bmh-matchers\*
609 |
610 | Whether the scanners created by [create-scanner](#create-scanner) should use the (fast
611 | but large) Boyer-Moore-Horspool matchers.
612 |
613 |
614 |
615 | ## SUPPORT
616 |
617 | The development version of cl-ppcre can be found [on
618 | github](https://github.com/edicl/cl-ppcre). Please use the github issue
619 | tracking system to submit bug reports. Patches are welcome, please use
620 | [GitHub pull requests](https://github.com/edicl/cl-ppcre/pulls). If you
621 | want to make a change, please [read this
622 | first](http://weitz.de/patches.html).
623 |
--------------------------------------------------------------------------------
/docs/cl-who.md:
--------------------------------------------------------------------------------
1 | # cl-who - DSL for Markup
2 |
3 | Version: 1.1.4
4 |
5 | Nickname: who
6 |
7 | Licence: BSD
8 |
9 | Repository: [edicl/cl-who - Github](https://github.com/edicl/cl-who)
10 |
11 | See also: [awesome-cl#html-generators-and-templates](https://github.com/CodyReichert/awesome-cl#html-generators-and-templates)
12 |
13 | *This documentation is possible due to the [excellent official documentation](https://edicl.github.io/cl-who) as of 5th May 2020.*
14 |
15 | *In case of any inaccuracies, ambiguities or suggestions, please [create an issue here](https://github.com/cl-library-docs/common-lisp-libraries/issues).*
16 |
17 | ***
18 |
19 | CL-WHO primarily provides a single macro [with-html-output](#with-html-output) to convert S-expressions intermingled with code into
20 | (X)HTML, XML and the likes.
21 |
22 | ## GETTING STARTED
23 |
24 | [with-html-output](#with-html-output) and [with-html-output-to-string](#with-html-output-to-string)
25 | are the basic macros to get going:
26 |
27 | ```lisp
28 | CL-USER> (defparameter *site-alist*
29 | '(("http://zappa.com/" . "Frank Zappa")
30 | ("http://marcusmiller.com/" . "Marcus Miller")
31 | ("http://www.milesdavis.com/" . "Miles Davis")))
32 | *SITE-ALIST*
33 |
34 | CL-USER> (format t
35 | (with-html-output-to-string (s nil :indent t)
36 | (loop for (link . title) in *site-alist*
37 | do (htm (:a :href link
38 | (:b (str title))) ; <- note the str!
39 | :br))))
40 |
41 |
42 | Frank Zappa
43 |
44 |
45 |
46 |
47 | Marcus Miller
48 |
49 |
50 |
51 |
52 | Miles Davis
53 |
54 |
55 |
56 | NIL
57 |
58 | CL-USER> (format t
59 | (with-output-to-string (s)
60 | (with-html-output (s s :indent t)
61 | (loop for (link . title) in *site-alist*
62 | do (htm (:a :href link
63 | (:b (str title))) ; <- note the str!
64 | :br)))))
65 |
66 |
67 | Frank Zappa
68 |
69 |
70 |
71 |
72 | Marcus Miller
73 |
74 |
75 |
76 |
77 | Miles Davis
78 |
79 |
80 |
81 | ```
82 |
83 | Inside these macros, there exist the lexically scoped macros:
84 |
85 | - **esc** as short-hand for [escape-string](#escape-string)
86 | - **fmt** as short-hand for [cl:format](http://www.lispworks.com/documentation/lw50/CLHS/Body/f_format.htm)
87 | - **htm** as short-hand for (another) `with-html-output`.
88 | - **str** as short-hand for, well, writing to the "inner html" rather than attributes;
89 | basically the difference between these two:
90 |
91 | ```lisp
92 | CL-USER> (let ((string "hello")
93 | (class "world"))
94 | (with-html-output-to-string (s nil :indent t)
95 | (htm (:div :class class string))))
96 | "
97 |
"
106 | ```
107 |
108 | In this case, `str` could equivalently be replaced by `fmt` or `esc`.
109 |
110 | Also see [html-mode](#html-mode). Detailed transformation rules are available in
111 | the [official documentation](https://edicl.github.io/cl-who/#syntax).
112 |
113 |
114 |
115 | ## CONFIGURATION VARIABLES
116 |
117 | ### \*attribute-quote-char\*
118 |
119 | ```lisp
120 | Variable
121 | ```
122 |
123 | Quote character for attributes.
124 |
125 | ### \*downcase-tokens-p\*
126 |
127 | ```lisp
128 | Variable
129 | ```
130 |
131 | If NIL, a keyword symbol representing a tag or attribute name will
132 | not be automatically converted to lowercase. If T, the tag and
133 | attribute name will be converted to lowercase only if it is in the
134 | same case. This is useful when one needs to output case sensitive
135 | XML.
136 |
137 | ### \*empty-attribute-syntax\*
138 |
139 | ```lisp
140 | Variable
141 | ```
142 |
143 | Set this to `t` to enable attribute minimization (also called
144 | "boolean attributes", or "empty attribute syntax" according to the [w3
145 | html standard](https://www.w3.org/TR/2012/WD-html-markup-20120329/syntax.html#syntax-attr-empty)). In XHTML attribute minimization is forbidden, and all
146 | attributes must have a value. Thus in XHTML boolean attributes must be
147 | defined as . In HTML5 boolean attributes
148 | can be defined as
149 |
150 | If it is NIL the attribute will be left out completely.
151 |
152 | ```
153 | (:td :nowrap nil) => "
"
154 | ```
155 |
156 | ### \*escape-char-p\*
157 |
158 | ```lisp
159 | Variable
160 | ```
161 |
162 | Used by [escape-string](#escape-string) to test whether a character should be escaped.
163 |
164 | ### \*html-empty-tag-aware-p\*
165 |
166 | ```lisp
167 | Variable
168 | ```
169 |
170 | Set this to NIL to if you want to use CL-WHO as a strict XML
171 | generator. Otherwise, CL-WHO will only write empty tags listed
172 | in [\*html-empty-tags\*](#html-empty-tags) as (XHTML mode) or (SGML
173 | mode and HTML5 mode). For all other tags, it will always generate
174 | .
175 |
176 | ### \*html-empty-tags\*
177 |
178 | ```lisp
179 | Variable
180 | ```
181 |
182 | The list of HTML tags that should be output as empty tags.
183 | See [\*html-empty-tag-aware-p\*](#html-empty-tag-aware-p).
184 |
185 | ### \*html-no-indent-tags\*
186 |
187 | ```lisp
188 | Variable
189 | ```
190 |
191 | The list of HTML tags that should disable indentation inside them. The initial
192 | value is a list containing only `:pre` and `:textarea`.
193 |
194 | ### \*prologue\*
195 |
196 | ```lisp
197 | Variable
198 | ```
199 |
200 | This is the first line that'll be printed if the `:prologue` keyword
201 | argument is T
202 |
203 | ## FUNCTIONS AND MACROS
204 |
205 | ### conc
206 |
207 | ```lisp
208 | Function: (conc &rest string-list)
209 | ```
210 | Concatenates all arguments which should be string into one string.
211 |
212 | ### convert-attributes
213 |
214 | ```lisp
215 | Function: (convert-attributes attr-list)
216 | ```
217 | Helper function for [convert-tag-to-string-list](#convert-tag-to-string-list) which converts the
218 | alist `attr-list` of attributes into a list of strings and/or Lisp
219 | forms.
220 |
221 | ### convert-tag-to-string-list
222 |
223 | ```lisp
224 | Generic Function: (convert-tag-to-string-list tag attr-list body body-fn)
225 | ```
226 | Used by `cl-who::process-tag` to convert `HTML` into a list
227 | of strings. `tag` is a keyword symbol naming the outer tag, `attr-list`
228 | is an alist of its attributes (the car is the attribute's name as a
229 | keyword, the cdr is its value), `body` is the tag's body, and `body-fn` is
230 | a function which should be applied to `body`. The function must return
231 | a list of strings or Lisp forms.
232 |
233 | ### esc
234 |
235 | ### escape-char
236 |
237 | ```lisp
238 | Function: (escape-char char &key (test *escape-char-p*))
239 | ```
240 | Returns an escaped version of the character `char` if `char` satisfies
241 | the predicate `test`. Always returns a string.
242 |
243 | ### escape-char-all
244 |
245 | ```lisp
246 | Function: (escape-char-all char)
247 | ```
248 | Escapes characters which aren't in the 7-bit ASCII character set.
249 |
250 | ### escape-char-iso-8859-1
251 |
252 | ```lisp
253 | Function: (escape-char-iso-8859-1 char)
254 | ```
255 | Escapes characters that aren't defined in ISO-8859-9.
256 |
257 | ### escape-char-minimal
258 |
259 | ```lisp
260 | Function: (escape-char-minimal char)
261 | ```
262 | Escapes only #<, #>, and #& characters.
263 |
264 | ### escape-char-minimal-plus-quotes
265 |
266 | ```lisp
267 | Function: (escape-char-minimal-plus-quotes char)
268 | ```
269 | Like [escape-char-minimal](#escape-char-minimal) but also escapes quotes.
270 |
271 | ### escape-string
272 |
273 | ```lisp
274 | Function: (escape-string string &key (test *escape-char-p*))
275 | ```
276 | Escape all characters in `string` which pass `test`. This function is
277 | not guaranteed to return a fresh string. Note that you can pass NIL
278 | for `string` which'll just be returned.
279 |
280 | ### escape-string-all
281 |
282 | ```lisp
283 | Function: (escape-string-all string)
284 | ```
285 | Escapes all characters in `string` which aren't in the 7-bit ASCII
286 | character set.
287 |
288 | ### escape-string-iso-8859-1
289 |
290 | ```lisp
291 | Function: (escape-string-iso-8859-1 string)
292 | ```
293 | Escapes all characters in `string` which aren't defined in ISO-8859-1.
294 |
295 | ### escape-string-minimal
296 |
297 | ```lisp
298 | Function: (escape-string-minimal string)
299 | ```
300 | Escapes only #<, #>, and #& in `string`.
301 |
302 | ### escape-string-minimal-plus-quotes
303 |
304 | ```lisp
305 | Function: (escape-string-minimal-plus-quotes string)
306 | ```
307 | Like [escape-string-minimal](#escape-string-minimal) but also escapes quotes.
308 |
309 | ### fmt
310 |
311 | ### htm
312 |
313 | ### html-mode
314 |
315 | ```lisp
316 | Function: (html-mode)
317 | ```
318 | Returns the current HTML mode. :SGML for (SGML-)HTML, :XML for
319 | XHTML and :HTML5 for HTML5 (HTML syntax).
320 |
321 | ```lisp
322 | Function: (setf (html-mode) mode)
323 | ```
324 |
325 | Sets the output mode to XHTML or (SGML-)HTML. MODE can be
326 | :SGML for HTML, :XML for XHTML or :HTML5 for HTML5 (HTML syntax).
327 |
328 |
329 | ### str
330 |
331 | ### with-html-output
332 |
333 | ```lisp
334 | Macro: (with-html-output (var &optional stream &rest rest &key prologue indent) &body body)
335 | ```
336 | Transform the enclosed `body` consisting of HTML as s-expressions
337 | into Lisp code to write the corresponding HTML as strings to `var` -
338 | which should either hold a stream or which'll be bound to STREAM if
339 | supplied.
340 |
341 | ### with-html-output-to-string
342 |
343 | ```lisp
344 | Macro: (with-html-output-to-string (var &optional string-form &key prologue
345 | indent) &body body)
346 | ```
347 | Transform the enclosed `body` consisting of HTML as s-expressions
348 | into Lisp code which creates the corresponding HTML as a string.
349 |
350 |
351 |
352 |
353 |
--------------------------------------------------------------------------------
/docs/extra.css:
--------------------------------------------------------------------------------
1 | .wy-side-scroll {
2 | /* background-color:#b3d9ff; */
3 | background:white;
4 | }
5 |
6 | .wy-menu-vertical a{
7 | color:black;
8 | }
9 |
10 |
11 |
12 | /* .toctree-l1 .current > a.reference.internal.current{ */
13 | /* background:#2980B9; */
14 | /* } */
15 |
16 | .rst-versions .rst-current-version{
17 | background-color:#2980B9;
18 | }
19 |
--------------------------------------------------------------------------------
/docs/fiveam.md:
--------------------------------------------------------------------------------
1 | # fiveam - Regression Testing Framework
2 |
3 | Version: 1.4.1
4 |
5 | Nickname: 5am
6 |
7 | Licence: BSD
8 |
9 | Repository: [sionescu/fiveam - Github](https://github.com/sionescu/fiveam)
10 |
11 | See also: [awesome-cl#unit-testing](https://github.com/CodyReichert/awesome-cl#unit-testing)
12 |
13 | *This documentation was possible due to [Tomek Kurez's tutorial on fiveam](http://turtleware.eu/posts/Tutorial-Working-with-FiveAM.html) and the [excellent official documentation](https://common-lisp.net/project/fiveam/docs/).*
14 |
15 | *In case of any inaccuracies, ambiguities or suggestions, please [create an issue here](https://github.com/cl-library-docs/common-lisp-libraries/issues).*
16 |
17 | ***
18 |
19 | ## GETTING STARTED
20 |
21 | ### Checks and Tests
22 |
23 | A check, defined using the macro [is](#is), is a line of code that makes sure something is indeed true. A basic check definition is of the form `(is test &rest reason-args)`.
24 |
25 | However, checks can only be defined in the context of tests:
26 |
27 | ```lisp
28 | (test test-demo
29 | "This demonstrates the basic use of test and check."
30 | (is (listp (list 1 2)))
31 | (is (= 5 (+ 2 3)) "This should pass.") ; &rest reason-args
32 | (is (= 4 4.1) "~D and ~D are not = to each other." 4 4.1))
33 | ```
34 |
35 | To run the test, simply, call [run!](#run_1):
36 |
37 | ```lisp
38 | (run! 'test-demo)
39 | ;; Running test TEST-DEMO ..f
40 | ;; Did 3 checks.
41 | ;; Pass: 2 (66%)
42 | ;; Skip: 0 ( 0%)
43 | ;; Fail: 1 (33%)
44 | ;;
45 | ;; Failure Details:
46 | ;; --------------------------------
47 | ;; TEST-DEMO [This demonstrates the basic use of test and check.]:
48 | ;; 4 and 4.1 are not = to each other.
49 | ;;
50 | ;; (= 4 4.1)
51 | ;;
52 | ;; was NIL..
53 | ;; --------------------------------
54 | ```
55 |
56 | Tests can automatically be run on (re)compilation by setting [\*run-test-when-defined\*](#run-test-when-defined) to `t`. So, simply compiling
57 |
58 | ```lisp
59 | (test another-test (is (eq t t)))
60 | ;;
61 | ;; Running test ANOTHER-TEST .
62 | ;; Did 1 check.
63 | ;; Pass: 1 (100%)
64 | ;; Skip: 0 ( 0%)
65 | ;; Fail: 0 ( 0%)
66 | ```
67 |
68 | runs the test. (Also see other [Configuration Variables](#configuration-variables).)
69 |
70 | `(run!)` can be called without arguments to run all the tests.
71 |
72 | ### Suites
73 |
74 | Tests can be grouped into suites. In fact, suites can also parent other suites.
75 |
76 | Suites can be defined using [def-suite](#def-suite), and similar to* `in-package`, the current
77 | suite can be specified using [in-suite](#in-suite).
78 |
79 | ```lisp
80 | (def-suite suite-one)
81 | (def-suite suite-two)
82 |
83 | (in-suite suite-one)
84 |
85 | (test first-test (is (= 1 1)))
86 | (test (second-test :suite suite-two) ; perhaps, not recommended
87 | (is (null nil)))
88 |
89 | (in-suite suite-two)
90 |
91 | (test third-test (is (eq 'done 'done)))
92 | ```
93 |
94 | All tests can be run with [run-all-tests](#run-all-tests). Also see the arguments to [run!](#run_1).
95 |
96 | ```lisp
97 | (run-all-tests)
98 | ;; Running test suite NIL
99 | ;; Running test FIRST-TEST .
100 | ;; Running test THIRD-TEST .
101 | ;; Running test suite SUITE-TWO
102 | ;; Running test SECOND-TEST .
103 | ;; Did 3 checks.
104 | ;; Pass: 3 (100%)
105 | ;; Skip: 0 ( 0%)
106 | ;; Fail: 0 ( 0%)
107 | ```
108 |
109 | ### More Things
110 |
111 | - Tests can be removed using [rem-test](#rem-test).
112 | - See [generators](#gen-buffer) for utilities for generating random data. These are to be used in
113 | conjunction with the [for-all](#for-all) macro. Generators are merely closures and you can
114 | define your own.
115 | - fiveam also provides the ability to [def-fixture](#def-fixture) and
116 | [with-fixture](#with-fixture); however, (as of 2016) it is [recommended to just use macros
117 | instead](https://github.com/sionescu/fiveam/issues/31).
118 | - The [signals](#signals) macro can be used to check if conditions are signalled appropriately.
119 |
120 |
121 |
122 | ## CONFIGURATION VARIABLES
123 |
124 | ### \*debug-on-error\*
125 |
126 | T if we should drop into the debugger on error, NIL otherwise.
127 | OBSOLETE: superseded by \*ON-ERROR\*
128 |
129 | ### \*debug-on-failure\*
130 |
131 | T if we should drop into the debugger on a failing check, NIL otherwise.
132 | OBSOLETE: superseded by \*ON-FAILURE\*
133 |
134 | ### \*default-test-compilation-time\*
135 |
136 | ### \*max-trials\*
137 |
138 | Number of total times we attempt to run the body of the
139 | FOR-ALL test including when the body is skipped due to failed
140 | guard conditions.
141 |
142 | Since we have guard conditions we may get into infinite loops
143 | where the test code is never run due to the guards never
144 | returning true. This second run limit prevents that.
145 |
146 | ### \*num-trials\*
147 |
148 | Number of times we attempt to run the body of the FOR-ALL test.
149 |
150 | ### \*on-error\*
151 |
152 | The action to perform on error:
153 | - :DEBUG if we should drop into the debugger
154 | - :BACKTRACE to print a backtrace
155 | - NIL to simply continue
156 |
157 | ### \*on-failure\*
158 |
159 | The action to perform on check failure:
160 | - :DEBUG if we should drop into the debugger
161 | - :BACKTRACE to print a backtrace
162 | - NIL to simply continue
163 |
164 | ### \*print-names\*
165 |
166 | T if we should print test running progress, NIL otherwise.
167 |
168 | ### \*run-test-when-defined\*
169 |
170 | When non-NIL tests are run as soon as they are defined.
171 |
172 | ### \*test-dribble\*
173 |
174 | ### \*verbose-failures\*
175 |
176 | T if we should print the expression failing, NIL otherwise.
177 |
178 |
179 | ## FUNCTIONS AND MACROS
180 |
181 |
182 |
183 | ### !
184 |
185 | ```lisp
186 | Function: (!)
187 | ```
188 | Rerun the most recently run test and explain the results.
189 |
190 | ### !!
191 |
192 | ```lisp
193 | Function: (!!)
194 | ```
195 | Rerun the second most recently run test and explain the results.
196 |
197 | ### !!!
198 |
199 | ```lisp
200 | Function: (!!!)
201 | ```
202 | Rerun the third most recently run test and explain the results.
203 |
204 | ### debug!
205 |
206 | ```lisp
207 | Function: (debug! &optional (test-spec *suite*))
208 | ```
209 | Calls (run! test-spec) but enters the debugger if any kind of error happens.
210 |
211 | ### def-fixture
212 |
213 | ```lisp
214 | Macro: (def-fixture name (&rest args) &body body)
215 | ```
216 | Defines a fixture named NAME. A fixture is very much like a
217 | macro but is used only for simple templating. A fixture created
218 | with DEF-FIXTURE is a macro which can use the special macrolet
219 | &BODY to specify where the body should go.
220 |
221 | See Also: [WITH-FIXTURE](#with-fixture).
222 |
223 |
224 | ### def-suite
225 |
226 | ```lisp
227 | Macro: (def-suite name &key description in)
228 | ```
229 | Define a new test-suite named NAME.
230 |
231 | IN (a symbol), if provided, causes this suite te be nested in the
232 | suite named by IN. NB: This macro is built on top of make-suite,
233 | as such it, like make-suite, will overrwrite any existing suite
234 | named NAME.
235 |
236 | ### def-suite\*
237 |
238 | ```lisp
239 | Macro: (def-suite* name &rest def-suite-args)
240 | ```
241 |
242 | ### def-test
243 |
244 | ```lisp
245 | Macro: (def-test name (&key depends-on (suite) fixture (compile-at) profile) &body body)
246 | ```
247 | Create a test named NAME.
248 |
249 | NAME is the symbol which names the test.
250 |
251 | DEPENDS-ON is a list of the form:
252 |
253 | (AND . test-names) - This test is run only if all of the tests
254 | in TEST-NAMES have passed, otherwise a single test-skipped
255 | result is generated.
256 |
257 | (OR . test-names) - If any of TEST-NAMES has passed this test is
258 | run, otherwise a test-skipped result is generated.
259 |
260 | (NOT test-name) - This is test is run only if TEST-NAME failed.
261 |
262 | AND, OR and NOT can be combined to produce complex dependencies.
263 |
264 | If DEPENDS-ON is a symbol it is interpreted as `(AND
265 | ,depends-on), this is accomadate the common case of one test
266 | depending on another.
267 |
268 | FIXTURE specifies a fixture to wrap the body in.
269 |
270 | If PROFILE is T profiling information will be collected as well.
271 |
272 | ### explain!
273 |
274 | ```lisp
275 | Function: (explain! result-list)
276 | ```
277 | Explain the results of RESULT-LIST using a
278 | detailed-text-explainer with output going to *test-dribble*.
279 | Return a boolean indicating whether no tests failed.
280 |
281 | ### fail
282 |
283 | ```lisp
284 | Macro: (fail &rest message-args)
285 | ```
286 | Simply generate a FAIL.
287 |
288 | ### finishes
289 |
290 | ```lisp
291 | Macro: (finishes &body body)
292 | ```
293 | Generates a pass if BODY executes to normal completion. In
294 | other words if body does signal, return-from or throw this test
295 | fails.
296 |
297 | ### for-all
298 |
299 | ```lisp
300 | Macro: (for-all bindings &body body)
301 | ```
302 | Bind `BINDINGS` to random variables and test `BODY` *num-trials* times.
303 |
304 | `BINDINGS` is a list of binding forms, each element is a list
305 | of `(BINDING VALUE &optional GUARD)`. Value, which is evaluated
306 | once when the for-all is evaluated, must return a generator which
307 | be called each time `BODY` is evaluated. `BINDING` is either a symbol
308 | or a list which will be passed to destructuring-bind. `GUARD` is a
309 | form which, if present, stops `BODY` from executing when `IT` returns
310 | NIL. The GUARDS are evaluated after all the random data has been
311 | generated and they can refer to the current value of any
312 | binding. NB: Generator forms, unlike guard forms, can not contain
313 | references to the bound variables.
314 |
315 | Examples:
316 |
317 | ```lisp
318 | (for-all ((a (gen-integer)))
319 | (is (integerp a)))
320 |
321 | (for-all ((a (gen-integer) (plusp a)))
322 | (is (integerp a))
323 | (is (plusp a)))
324 |
325 | (for-all ((less (gen-integer))
326 | (more (gen-integer) (< less more)))
327 | (is (<= less more)))
328 |
329 | (for-all (((a b) (gen-two-integers)))
330 | (is (integerp a))
331 | (is (integerp b)))
332 | ```
333 |
334 | ### gen-buffer
335 |
336 | ```lisp
337 | Function: (gen-buffer &key
338 | (length (gen-integer min 0 max 50))
339 | (element-type '(unsigned-byte 8))
340 | (elements (gen-integer :min 0 :max (1- (expt 2 8)))))
341 | ```
342 |
343 | ### gen-character
344 |
345 | ```lisp
346 | Function: (gen-character &key
347 | (code-limit char-code-limit)
348 | (code (gen-integer :min 0 :max (1- code-limit)))
349 | (alphanumericp nil))
350 | ```
351 | Returns a generator of characters.
352 |
353 | CODE must be a generator of random integers. ALPHANUMERICP, if
354 | non-NIL, limits the returned chars to those which pass
355 | alphanumericp.
356 |
357 | ### gen-float
358 |
359 | ```lisp
360 | Function: (gen-float &key bound (type 'short-float))
361 | ```
362 | Returns a generator which produces floats of type TYPE. BOUND,
363 | if specified, constrains the results to be in the range (-BOUND,
364 | BOUND).
365 |
366 | ### gen-integer
367 |
368 | ```lisp
369 | Function: (gen-integer &key
370 | (max (1+ most-positive-fixnum))
371 | (min (1- most-negative-fixnum)))
372 | ```
373 | Returns a generator which produces random integers greater
374 | than or equal to MIN and less than or equal to MAX.
375 |
376 | ### gen-list
377 |
378 | ```lisp
379 | Function: (gen-list &key
380 | (length (gen-integer :min 0 :max 10))
381 | (elements (gen-integer :min -10 :max 10)))
382 | ```
383 | Returns a generator which produces random lists. LENGTH must be
384 | an integer generator and ELEMENTS must be a generator which
385 | produces objects.
386 |
387 | ### gen-one-element
388 |
389 | ```lisp
390 | Function: (gen-one-element &rest elements)
391 | ```
392 |
393 | ### gen-string
394 |
395 | ```lisp
396 |
397 | Function: (gen-string &key
398 | (length (gen-integer :min 0 :max 80))
399 | (elements (gen-character))
400 | (element-type 'character))
401 | ```
402 | Returns a generator which produces random strings. LENGTH must
403 | be a generator which produces integers, ELEMENTS must be a
404 | generator which produces characters of type ELEMENT-TYPE.
405 |
406 | ### gen-tree
407 |
408 | ```lisp
409 | Function: (gen-tree &key (size 20) (elements (gen-integer :min -10 :max 10)))
410 | ```
411 | Returns a generator which produces random trees. SIZE controls
412 | the approximate size of the tree, but don't try anything above
413 | 30, you have been warned. ELEMENTS must be a generator which
414 | will produce the elements.
415 |
416 | ### get-fixture
417 |
418 | ```lisp
419 | Function: (get-fixture key &optional default)
420 | ```
421 |
422 | ### get-test
423 |
424 | ```lisp
425 | Function: (get-test key &optional default)
426 | ```
427 |
428 | ### in-suite
429 |
430 | ```lisp
431 | Macro: (in-suite suite-name)
432 | ```
433 | Set the *suite* special variable so that all tests defined
434 | after the execution of this form are, unless specified otherwise,
435 | in the test-suite named SUITE-NAME.
436 |
437 | See also: DEF-SUITE *SUITE*
438 |
439 | ### in-suite\*
440 |
441 | ```lisp
442 | Macro: (in-suite* suite-name &key in)
443 | ```
444 | Just like in-suite, but silently creates missing suites.
445 |
446 | ### is
447 |
448 | ```lisp
449 | Macro: (is test &rest reason-args)
450 | ```
451 | The DWIM checking operator.
452 |
453 | If TEST returns a true value a test-passed result is generated,
454 | otherwise a test-failure result is generated. The reason, unless
455 | REASON-ARGS is provided, is generated based on the form of TEST:
456 |
457 | (predicate expected actual) - Means that we want to check
458 | whether, according to PREDICATE, the ACTUAL value is
459 | in fact what we EXPECTED.
460 |
461 | (predicate value) - Means that we want to ensure that VALUE
462 | satisfies PREDICATE.
463 |
464 | Wrapping the TEST form in a NOT simply produces a negated reason
465 | string.
466 |
467 | ### is-every
468 |
469 | ```lisp
470 | Macro: (is-every predicate &body clauses)
471 | ```
472 | The input is either a list of lists, or a list of pairs. Generates (is (,predicate ,expr ,value))
473 | for each pair of elements or (is (,predicate ,expr ,value) ,@reason) for each list.
474 |
475 | ### is-false
476 |
477 | ```lisp
478 | Macro: (is-false condition &rest reason-args)
479 | ```
480 | Generates a pass if CONDITION returns false, generates a
481 | failure otherwise. Like IS-TRUE, and unlike IS, IS-FALSE does
482 | not inspect CONDITION to determine what reason to give it case
483 | of test failure
484 |
485 | ### is-true
486 |
487 | ```lisp
488 | Macro: (is-true condition &rest reason-args)
489 | ```
490 | Like IS this check generates a pass if CONDITION returns true
491 | and a failure if CONDITION returns false. Unlike IS this check
492 | does not inspect CONDITION to determine how to report the
493 | failure.
494 |
495 | ### make-fixture
496 |
497 | ### make-suite
498 |
499 | ```lisp
500 | Function: (make-suite name &key description ((in parent-suite)))
501 | ```
502 | Create a new test suite object.
503 |
504 | Overrides any existing suite named NAME.
505 |
506 | ### make-test
507 |
508 | ### pass
509 |
510 | ```lisp
511 | Macro: (pass &rest message-args)
512 | ```
513 | Simply generate a PASS.
514 |
515 | ### rem-fixture
516 |
517 | ```lisp
518 | Function: (rem-fixture key)
519 | ```
520 |
521 | ### rem-test
522 |
523 | ```lisp
524 | Function: (rem-test key)
525 | ```
526 |
527 | ### results-status
528 |
529 | ```lisp
530 | Function: (results-status result-list)
531 | ```
532 | Given a list of test results (generated while running a test)
533 | return true if no results are of type TEST-FAILURE. Returns second
534 | and third values, which are the set of failed tests and skipped
535 | tests respectively.
536 |
537 | ### run
538 |
539 | ```lisp
540 | Function: (run test-spec &key (print-names *print-names*))
541 | ```
542 | Run the test specified by TEST-SPEC.
543 |
544 | TEST-SPEC can be either a symbol naming a test or test suite, or
545 | a testable-object object. This function changes the operations
546 | performed by the !, !! and !!! functions.
547 |
548 | ### run!
549 |
550 | ```lisp
551 | Function: (run! &optional (test-spec *suite*)
552 | &key (print-names *print-names*))
553 | ```
554 |
555 | Equivalent to (explain! (run TEST-SPEC)).
556 |
557 | ### run-all-tests
558 |
559 | ```lisp
560 | Function: (run-all-tests &key (summary :end))
561 | ```
562 | Runs all defined test suites, T if all tests passed and NIL otherwise.
563 | SUMMARY can be :END to print a summary at the end, :SUITE to print it
564 | after each suite or NIL to skip explanations.
565 |
566 | ### signals
567 |
568 | ```lisp
569 | Macro: (signals condition-spec &body body)
570 | ```
571 | Generates a pass if BODY signals a condition of type
572 | CONDITION. BODY is evaluated in a block named NIL, CONDITION is
573 | not evaluated.
574 |
575 | ### skip
576 |
577 | ```lisp
578 | Macro: (skip &rest reason)
579 | ```
580 | Generates a TEST-SKIPPED result.
581 |
582 | ### test
583 |
584 | ```lisp
585 | Macro: (test name &body body)
586 | ```
587 | Create a test named NAME. If NAME is a list it must be of the
588 | form:
589 |
590 | ```lisp
591 | (name &key depends-on suite fixture compile-at profile)
592 | ```
593 |
594 | NAME is the symbol which names the test.
595 |
596 | DEPENDS-ON is a list of the form:
597 |
598 | - (AND . test-names) - This test is run only if all of the tests
599 | in TEST-NAMES have passed, otherwise a single test-skipped
600 | result is generated.
601 |
602 | - (OR . test-names) - If any of TEST-NAMES has passed this test is
603 | run, otherwise a test-skipped result is generated.
604 |
605 | - (NOT test-name) - This is test is run only if TEST-NAME failed.
606 |
607 | AND, OR and NOT can be combined to produce complex dependencies.
608 |
609 | If DEPENDS-ON is a symbol it is interpreted as `(AND
610 | ,depends-on), this is accomadate the common case of one test
611 | depending on another.
612 |
613 | FIXTURE specifies a fixture to wrap the body in.
614 |
615 | If PROFILE is T profiling information will be collected as well.
616 |
617 | ### test-names
618 |
619 | ```lisp
620 | Function: (test-names)
621 | ```
622 |
623 | ### with-fixture
624 |
625 | ```lisp
626 | Macro: (with-fixture fixture-name (&rest args) &body body)
627 | ```
628 | Insert BODY into the fixture named FIXTURE-NAME.
629 |
630 | See Also: [DEF-FIXTURE](#def-fixture).
631 |
632 |
633 |
--------------------------------------------------------------------------------
/docs/index.md:
--------------------------------------------------------------------------------
1 | # common-lisp-libraries.readthedocs.io
2 |
3 | *In case of any inaccuracies, ambiguities or suggestions, please [create an issue here](https://github.com/cl-library-docs/common-lisp-libraries/issues).*
4 |
5 | *See the [html version of this page](https://common-lisp-libraries.readthedocs.io), rather than the markdown version for the working links below.*
6 |
7 | ---
8 |
9 | ## Introduction
10 |
11 | Common Lisp documentation - libraries or the HyperSpec - isn't known to be particularly "modern" or "attractive". While those terms are subjective, ease of introduction to a technology does seem to have *some* objective component to it.
12 |
13 |
14 | ## Libraries
15 |
16 | ### Installation
17 |
18 | Each of the below libraries (except asdf and quicklisp) can be installed using quicklisp:
19 |
20 | ```lisp
21 | (ql:quickload "alexandria") ; for example
22 | ```
23 | See [quicklisp - Getting Started](./quicklisp/#getting-started) for instructions on
24 | installing quicklisp.
25 |
26 | You may want to use a local nickname when importing a package which is possible in ASDF/UIOP since version 3.3.4.3.
27 | You can either check `uiop:*uiop-version*` or `(uiop:featurep :package-local-nicknames)`.
28 | See [adding package local nicknames](https://lispcookbook.github.io/cl-cookbook/packages.html#package-local-nicknames-pln) for details.
29 |
30 | ```lisp
31 | (uiop:add-package-local-nickname #:a #:alexandria)
32 | ; OR
33 | (defpackage my-package
34 | (:use #:cl)
35 | (:local-nicknames (#:a #:alexandria)))
36 | ```
37 |
38 | ### Libraries documented so far
39 |
40 | The below list of libraries is not even the *complete list of defacto libraries*. Many more awesome Common Lisp libraries are available at [awesome-cl](https://github.com/CodyReichert/awesome-cl).
41 |
42 | #### Defacto libraries
43 |
44 | - [asdf](./asdf/) - build system for softwares (packages*)
45 | - [alexandria](./alexandria/) - a utility library
46 | - [bordeaux-threads](./bordeaux-threads/) - library for threading
47 | - [cl-ppcre](./cl-ppcre/) - regular expressions
48 | - [cl-who](./cl-who/) - DSL for Markup
49 | - [hunchentoot](./hunchentoot/) - web server
50 | - [fiveam](./fiveam/) - regression testing framework
51 | - [iterate](./iterate/) - a lispy extensible alternative to `loop`
52 | - [local-time](./local-time/) - date and time manipulation
53 | - [postmodern](./postmodern/) - PostgreSQL programming interace
54 | - [quicklisp](./quicklisp/) - library manager
55 | - [usocket](./usocket) - universal socket library
56 | - [utilities](./utilities/) - a collection of utility libraries
57 |
58 | #### Not yet defacto
59 |
60 | - [numcl](./numcl/) - lispy clone of numpy
61 | - [unix-opts](./unix-opts/) - minimalistic command line options parser
62 |
63 |
64 | \*What one might call packages in other languages are called systems in Common Lisp parlance. Instead, the word `package` in Common Lisp refers to a data structure providing namespacing
65 | for symbols. By contrast, a system is a tool to organize a bunch of files, in accordance with dependencies, and specifying how to perform certain actions on the system. A single system may contain multiple packages. See [this StackOverFlow answer](https://stackoverflow.com/questions/45642330/why-do-many-common-lisp-systems-use-a-single-packages-lisp-file/45643829#45643829) for a detailed discussion.
66 |
67 | ## Previous Efforts
68 |
69 | Documentation efforts have been made at:
70 |
71 | - [Quickdocs](http://quickdocs.org/): While it was up, I didn't particularly like the layout. I want the API at a glance! This can improve! But don't look at me. I'm also not very at ease with full automation without human intervention. As of December 2020, this is down though.
72 |
73 | - [Quickref](http://quickref.common-lisp.net/): Frankly, this is just too much. As a user, all I want to know is "What can this library do? And, how do I do it? (What functions, macros or anything is available?)" Therefore, for a user, the only good place I found was the Packages section here. It is, after all, a Reference Manual. Another excuse is, again, that I do want human intervention in documentation.
74 |
75 | - [common-lisp.net](http://common-lisp.net/): Ultimately, this is the place for most everything Common Lisp. And indeed, most of the work here is based on the official documentation. An attempt is made to "simplify" wherever need is felt.
76 |
77 | - [CLiki](http://cliki.net/): Again, layout and "at a glance"!
78 |
79 | - [UltraSpec]: I liked this. The only trouble? It isn't "quick" to build upon.
80 |
81 | - [MiniSpec](https://lamberta.github.io/minispec/): This looks like a work-in-progress-but-active perhaps-smaller version of UltraSpec. And for the parts that are done, I find this vastly better than CLHS in terms of looks and accessibility.
82 |
83 | ## UltraSpec
84 |
85 | I liked (the theme of) [UltraSpec]. I also liked [mkdocs](https://www.mkdocs.org/) - I am using mkdocs with the pre-provided [readthedocs](https://readthedocs.org/) theme. What UltraSpec seems to be good for is larger websites than what is currently here, in that it isn't as straightforward as mkdocs for library-documenters to use it.
86 |
87 | Additionally, `markdown` files and `dokuwiki` files (the format UltraSpec requires) are interconvertible (but the compatibility is untested) using [pandoc](https://pandoc.org/). (pandoc is indeed useful for a ton of other file formats!)
88 |
89 | ## mkdocs
90 |
91 | As a marketing for mkdocs: [mkdocs](https://www.mkdocs.org/#getting-started) is as simple as
92 |
93 | - `pip install mkdocs # or conda`
94 | - create a .yml configuration file (or copy and edit!)
95 | - put your markdown files inside docs/ directory (or as mentioned in the .yml file)
96 | - `mkdocs gh-deploy`# to deploy on github-pages
97 |
98 | Done!
99 |
100 | *PS: Regardless of the justifications, all I wanted was a documentation site with a "sidebar" that, both, tells the page at glance, and is easy to navigate.*
101 |
102 |
103 | [ultraspec]: https://phoe.tymoon.eu/clus/doku.php
104 |
--------------------------------------------------------------------------------
/docs/iterate.md:
--------------------------------------------------------------------------------
1 | # iterate - Psuedocodic Iteration
2 |
3 | Version: 1.5
4 |
5 | Licence: MIT
6 |
7 | Repository: [iterate/iterate - Gitlab](https://gitlab.common-lisp.net/iterate/iterate)
8 |
9 | See also: [awesome-cl#iteration](https://github.com/CodyReichert/awesome-cl#iteration)
10 |
11 | *In case of any inaccuracies, ambiguities or suggestions, please [create an issue here](https://github.com/digikar99/common-lisp.readthedocs/issues).*
12 |
13 | ***
14 |
15 | `iterate` is a powerful iteration facility for Common Lisp, and a alternative to `loop`. As opposed to `loop`, `iterate` is more lispy, extensible, besides being more powerful.
16 |
17 | See [The Iterate Manual] for a more detailed explanation of the various facilities.
18 |
19 | For a tutorial on looping in Common Lisp, check out [Loops, Iterate and Mapping - The Common Lisp Cookbook](http://lispcookbook.github.io/cl-cookbook/iteration.html).
20 |
21 | ## HIGHLIGHTS
22 |
23 | - [def*](#defclause-sequence): extensibility
24 | - [display-iterate-clauses](#display-iterate-clauses): quick help for clauses
25 | - [dsetq](#dsetq): for use outside the `iter` form
26 | - [finally-protected](#finally-protected): for protecting against unwindings
27 | - [finding-maximizing](#finding): `loop` equivalent can be quite verbose
28 | - [for](#for): lots of variants!
29 | - [generate](#generate)
30 | - [in](#in): `loop` equivalent can be quite verbose
31 | - there's no support for "true" parallel assignment - see [with](#with)
32 |
33 | ## OTHER POINTS
34 |
35 | - `iterate` does not declare variables unless asked to. See [Types and Declarations].
36 | - `into `*`var`* stores the value into *`var`* instead of returning it.
37 | - There, probably, are some idiosyncrasies involved with running the epilogue code - it is not run "always": `always`, `finding`, `finish`, `thereis`.
38 |
39 |
40 | ### Notes for myself - indications of incomplete documentation
41 |
42 | - Documentation for `finding` is incomplete here.
43 | - Documentation for `def*`, `for` has been omitted here.
44 | - When are the variable values for prologue defined?
45 | - Will there be future versions of iterate? What is the compatibility relation between `terminate` and `finish` for `for-next` [Generalized Drivers]?
46 |
47 | ### Installation
48 |
49 | If `quicklisp` is set-up, simply `(ql:quickload 'iterate)`.
50 |
51 | Otherwise [head over here](https://common-lisp.net/project/iterate/index.html).
52 |
53 | ### Accumulation vs Reduction
54 |
55 | The differences between accumulate and reducing are slight. One difference is that the functions take their arguments in a different order. Another is that in the absence of init-val, accumulate will use nil, whereas reducing will generate different code that avoids any dependence on the initial value. The reason for having both clauses is that one usually thinks of reductions (like sum) and accumulations (like collect) as different beasts.
56 |
57 |
58 | ## API (CLAUSE) REFERENCE
59 |
60 | ### accumulate
61 | `accumulate `*`expr`*` by `*`func`*` &optional initial-value `*`init-val`*` into `*`var`*
62 |
63 | This is a general-purpose accumulation clause. func should be a function of two arguments, the value of expr and the value accumulated so far in the iteration, and it should return the updated value. If no initial value is supplied, nil is used.
64 |
65 |
66 | ```lisp
67 | CL-USER> (iter (for i in '(1 2 3))
68 | (accumulate i by
69 | (lambda (i values-so-far)
70 | (cons i values-so-far))))
71 | (3 2 1)
72 | CL-USER> (iter (for i in '(1 2 3))
73 | (accumulate i by
74 | (lambda (i values-so-far)
75 | (cons i values-so-far))
76 | initial-value '(init)))
77 | (3 2 1 INIT)
78 | CL-USER> (iter (for i in '(1 2 3))
79 | (accumulate i by
80 | (lambda (i values-so-far)
81 | (cons i values-so-far))
82 | initial-value '(init) into var))
83 | NIL
84 | ```
85 |
86 |
87 | See [Accumulations], [Accumulation vs Reduction](#accumulation-vs-reduction) and [reducing](#reducing).
88 |
89 |
90 | ### accumulating
91 | An alias for [accumulate](#accumulate).
92 |
93 | ### adjoining
94 | `adjoining `*`exptr`*` &optional into `*`var`*` test `*`test`*` at `*`place`*` result-type `*`type`*
95 |
96 | Like [collect], but only adds the value of exptr if it is not already present. test, which defaults to #'eql, is the test to be used with member.
97 |
98 | ### after-each
99 | `after-each &rest `*`forms`*
100 |
101 | Executes forms at the end of the loop body, after each iteration. Forms may contain iterate clauses.
102 | ```lisp
103 | CL-USER> (iter (for i below 4)
104 | (after-each (print var))
105 | (if (oddp i)
106 | (collect i into var)
107 | (collect (* 2 i) into var)))
108 |
109 | ; (0)
110 | ; (0 1)
111 | ; (0 1 4)
112 | ; (0 1 4 3)
113 | NIL
114 | ```
115 | See [Code Placement] and [Problems with Code Movement].
116 |
117 | ### always
118 | `always `*`expr`*
119 | ```lisp
120 | CL-USER> (iter (for i below 4) (always (evenp i)))
121 | NIL
122 | ```
123 | - If expr ever evaluates to nil, then nil is immediately returned; the epilogue code is not executed.
124 | - If expr never evaluates to nil, the epilogue code is executed and the last value of expr (or t if expr was never evaluated) is returned (whereas loop would constantly return t).
125 |
126 | See [Aggregated Boolean Tests].
127 |
128 | ### appending
129 | `appending `*`exptr`*` &optional into `*`var`*` at `*`place`*
130 | Like [collect], but behaves like the Common Lisp `append`, and works only on lists.
131 | ```lisp
132 | CL-USER> (iter (for i in '((1) (2 3) (4 5 6)))
133 | (appending i))
134 | (1 2 3 4 5 6)
135 | CL-USER> (iter (for i in '((1) (2 3) (4 5 6)))
136 | (appending i into var))
137 | NIL
138 | ```
139 | See [Accumulations].
140 |
141 | ### as
142 | An alias for [for](#for).
143 |
144 | ### collect
145 | `collect `*`exptr`*` &optional into `*`var`*` test `*`test`*` at `*`place`*` result-type `*`type`*
146 | ```lisp
147 | CL-USER> (iter (for i from 1 to 5)
148 | (collect i))
149 | (1 2 3 4 5)
150 | CL-USER> (iter (for i from 1 to 5)
151 | (collect i at start)) ;; likely to be faster
152 | (5 4 3 2 1)
153 | ```
154 | - `place` can be either `beginning`/`start` or `end`: default value is `end`.
155 | - `type` should be a subtype of `sequence` - default is `list`; however, the type of sequence being constructed inside the loop is undefined when a non-list type is specified.
156 |
157 | ```lisp
158 | CL-USER> (iter (for i from 1 to 3)
159 | (collect i into vec result-type 'vector)
160 | (print vec)
161 | (finally (return vec)))
162 |
163 | ; (1)
164 | ; (1 2)
165 | ; (1 2 3)
166 | #(1 2 3)
167 | ```
168 | - `type` or `place` may be optionally quoted.
169 |
170 | See [Accumulations].
171 |
172 | ### collecting
173 | Alias for [collect].
174 |
175 | ### count
176 | Alias for [counting](#counting).
177 |
178 | This, probably, overrides the CL `count` when used in top-level inside an iterate loop.
179 | ```lisp
180 | CL-USER> (iter (for i in '(1 2 3))
181 | (finally (return (count 1 '(1 2 1)))))
182 | 2
183 | ```
184 |
185 | ### counting
186 | `counting `*`expr`*` &optional into `*`var`*
187 |
188 | See [Reductions] and [accumulate].
189 |
190 | ### declare-variables
191 | `(declare (declare-variables))`
192 |
193 | - iterate does not declare variable types unless asked to.
194 | - Declaration of types of user introduced symbols can be done by either the usual Common Lisp `declare`, but this declaration should be inside the iter form.
195 | - Declaration of internal variables or use of `the` requires one to use `declare-variables`, or set `iterate:::*always-declare-variables* to `t`.
196 |
197 | ```lisp
198 | CL-USER> (macroexpand-1 '(iter (for (the fixnum el) in '(1 2 3))
199 | (declare (DECLARE-VARIABLES))
200 | (count (oddp el))))
201 | ;; note that this produces a type declaration for el.
202 | CL-USER> (macroexpand-1 '(iter (for el in '(1 2 3))
203 | (declare (DECLARE-VARIABLES))
204 | (count (oddp el))))
205 | ;; this does not produce a type declaration for el.
206 | CL-USER> (macroexpand-1 '(iter (for (the fixnum el) in '(1 2 3))
207 | (count (oddp el))))
208 | ;; this does not produce any declarations.
209 | ```
210 | See [Types and Declarations].
211 |
212 | ### defclause-sequence
213 | [Undocumented here.]
214 |
215 | See [Extensibility Aids].
216 |
217 | ### defmacro-clause
218 | [Undocumented here]
219 |
220 | See [Rolling Your Own].
221 |
222 | ### defmacro-driver
223 | [Undocumented here.]
224 |
225 | See [Writing Drivers].
226 |
227 | ### defsynonym
228 | [Undocumented here.]
229 |
230 | See [Extensibility Aids].
231 |
232 | ### display-iterate-clauses
233 | `display-iterate-clauses &optional `*`clause-spec`*
234 |
235 | ```lisp
236 | CL-USER> (display-iterate-clauses 'repeat)
237 | ; REPEAT Repeat the loop some number of times
238 | T
239 | CL-USER> (display-iterate-clauses '(for in-vector))
240 | ; FOR IN-VECTOR &OPTIONAL FROM UPFROM DOWNFROM TO DOWNTO ABOVE BELOW BY
241 | ; WITH-INDEX Elements of a vector
242 | T
243 | ```
244 |
245 | See [On-line help].
246 |
247 | ### dsetq
248 | `dsetq`*` template expr`*
249 |
250 | Can be used outside iter.
251 | ```lisp
252 | CL-USER> (foo)
253 | FIRST
254 | SECOND
255 | CL-USER> (progn
256 | (dsetq (values a b) (foo))
257 | (list a b)) ;; undeclared variables warning
258 | (FIRST SECOND)
259 | ```
260 | See [Destructuring].
261 |
262 | ### else
263 | `else &rest `*`forms`*
264 |
265 | Forms are executed if loop is never entered, but is terminated normally.
266 | ```lisp
267 | CL-USER> (iter (for i in '(1 2 3)) (while nil)
268 | (else (write 'else)))
269 | ; ELSE
270 | NIL
271 | ```
272 | See [Code Placement] and [Problems with Code Movement].
273 |
274 | ### finally
275 | `finally &rest `*`forms`*
276 |
277 | Forms are executed after a normal termination of the loop.
278 | ```lisp
279 | CL-USER> (iter (for i in '(1 2 3)) (finally (write 'end)))
280 | ; END
281 | NIL
282 | ```
283 | See [Code Placement] and [Problems with Code Movement].
284 |
285 | ### finally-protected
286 | `finally-protected &rest `*`forms`*
287 |
288 | Forms are executed "always" - regardless of whether the termination was notmal
289 | ```lisp
290 | CL-USER> (iter (for i in-vector '(1 2 3))
291 | (finally-protected (write 'error)))
292 | ;; warnings
293 | ERROR ; Evaluation aborted on #.
294 | CL-USER> (iter (for i in '(1 2 3))
295 | (finally-protected (write 'no-error)))
296 | ; NO-ERROR
297 | NIL
298 | ```
299 | See [Code Placement] and [Problems with Code Movement].
300 |
301 | ### finding
302 | `finding `*`expr`*` such-that `*`test`*` &optionally into `*`var`*` on-failure `*`failure-value`*
303 |
304 | - The loop terminates (with epilogue code) whenever *`test`* evaluates to non-`nil`.
305 | - *`expr`* that satifies the *`test`*, or *`failure-value`*, or `nil` is returned (unless modified by epilogue).
306 | - *`failure-value`* is always evaluated.
307 |
308 | ```lisp
309 | CL-USER> (iter (for x in '(1 2 3))
310 | (finding x such-that #'evenp on-failure 'not-found))
311 | 2
312 | CL-USER> (iter (for x in '(1 2 3))
313 | (finding x such-that #'evenp on-failure (error "not found")))
314 | ; Evaluation aborted on #.
315 | CL-USER> (iter (for x in '(1 2 3))
316 | (if (evenp x) (leave x))
317 | (finally (error "not found")))
318 | 2
319 | ```
320 |
321 | `finding `*`expr`*` maximizing `*`m-expr`*` &optionally into `*`var`*
322 |
323 | `finding `*`expr`*` minimizing `*`m-expr`*` &optionally into `*`var`*
324 |
325 | - Returns *`expr`* corresponding to the maximum value of *`m-expr`*.
326 | - If *`m-expr`* is never evaluated (how?), the return value is `nil` or `0` depending on the type (or its absence) of *`expr`* (or *`var`* if supplied.)
327 | - Here, *`m-expr`* can also be a list of two symbols.
328 |
329 | ```lisp
330 | CL-USER> CL-USER> (iter (for list in '((1) (2 3) nil))
331 | (finding list maximizing (length list)))
332 | (2 3)
333 | CL-USER> (iter (for i in '(1 2 3))
334 | (finding (* 2 i) maximizing (- i) into (twice neg))
335 | (finally (return (values twice neg))))
336 | 2
337 | -1
338 | ```
339 | [Example required for the case when *`m-expr`* is not evaluated.]
340 |
341 | See [Finders].
342 |
343 |
344 | ### finish
345 | `finish`
346 |
347 | Stop the loop (and run the epilogue code).
348 | ```lisp
349 | CL-USER> (iter (for i in '(1 2 3)) (if (evenp i) (finish)))
350 | NIL
351 | ```
352 |
353 | See [Control Flow].
354 |
355 | ### first-iteration-p
356 | `first-iteration-p`
357 |
358 | `t` in the first cycle of the loop, otherwise `nil`.
359 | ```lisp
360 | CL-USER> (iter (for el in '(nil 1 2 nil 3))
361 | (when el
362 | (unless (first-iteration-p)
363 | (princ ", "))
364 | (princ el)))
365 | ; , 1, 2, 3
366 | NIL
367 | ```
368 | See [Boolean Tests].
369 |
370 | ### first-time-p
371 | `first-iteration-p`
372 |
373 | `t` only when the expression is evaluated for the first time.
374 | ```lisp
375 | CL-USER> (iter (for el in '(nil 1 2 nil 3))
376 | (when el
377 | (unless (first-time-p)
378 | (princ ", "))
379 | (princ el)))
380 | ; 1, 2, 3
381 | NIL
382 | ```
383 | See [Boolean Tests].
384 |
385 | ### for
386 | [Undocumented here.]
387 |
388 | See
389 |
390 | - [Numeric Iteration]
391 | - [Sequence Iteration]
392 | - [Variable Binding and Setting]
393 | - [Generalized Drivers]
394 | - [Previous Values of Driver Variables]
395 |
396 | ### generate
397 | See [Generators] and [for].
398 | ```lisp
399 | CL-USER> (iter (for el in '(a b nil c))
400 | (generate i upfrom 1)
401 | (if el (collect (cons el (next i)))))
402 | ((A . 1) (B . 2) (C . 3))
403 | ```
404 | `for` can be replaced by `generate` to achieve the desired result, except in the case of [Variable Binding and Setting].
405 |
406 | ### generating
407 | Alias for [generate](#generate)
408 |
409 | ### if-first-time
410 | `if-first-time `*`then`*` &optional `*`else`*
411 | ```lisp
412 | CL-USER> (iter (for i in '(1 2 3))
413 | (if-first-time
414 | (princ 'first)
415 | (print 'not-first)))
416 | ; FIRST
417 | ; NOT-FIRST
418 | ; NOT-FIRST
419 | NIL
420 | ```
421 | See [Control Flow].
422 |
423 | ### in
424 | `in`*`name`*` &rest `*`forms`*
425 | ```lisp
426 | CL-USER> (defvar ar #2A((1 2 3) (4 5 6)))
427 | AR
428 | CL-USER> (iter outer
429 | (for i below (array-dimension ar 0))
430 | (iter (for j below (array-dimension ar 1))
431 | (in outer
432 | (collect (aref ar i j)))))
433 | (1 2 3 4 5 6)
434 | ```
435 |
436 | See [Named Blocks].
437 |
438 | ### initially
439 | `in &rest `*`forms`*
440 | Place the forms in the prologue of the loop.
441 | ```lisp
442 | CL-USER> (iter (initially (princ 'hi))
443 | (for i below 3)
444 | (print i))
445 | ; HI
446 | ; 0
447 | ; 1
448 | ; 2
449 | NIL
450 | CL-USER> (iter (for i below 3)
451 | (initially (princ i)))
452 | ; -1 ;; this is probably an undefined behaviour.
453 | NIL
454 | ```
455 | See [Code Placement] and [Problems with Code Movement].
456 |
457 | ### leave
458 | `leave &optional `*`value`*
459 |
460 | Returns from the current iterate form with *`value`* or `nil`.
461 | ```lisp
462 | CL-USER> (iter (for i below 3)
463 | (leave
464 | (iter (for j below 2)
465 | (if (oddp j) (leave j)))))
466 | 1
467 | ```
468 |
469 | See [Control Flow].
470 |
471 | ### maximize
472 | `maximize `*`expr`*` &optional into `*`var`*
473 | ```lisp
474 | CL-USER> (iter (for list in '((1) (1 2) nil))
475 | (maximize (length list)))
476 | 2
477 | ```
478 | See [Reductions] and [finding](#finding).
479 |
480 | ### maximizing
481 | Alias for [maximize](#maximize).
482 |
483 | ### minimize
484 | `minimize `*`expr`*` &optional into `*`var`*
485 | ```lisp
486 | CL-USER> (iter (for list in '((1) (1 2) nil))
487 | (minimize (length list)))
488 | 0
489 | ```
490 | See [Reductions] and [finding](#finding).
491 |
492 | ### minimizing
493 | Alias for [minimize](#minimize).
494 |
495 | ### multiply
496 | `multiply `*`expr`*` &optional into `*`var`*
497 | ```lisp
498 | CL-USER> (iter (for i from 1 to 5)
499 | (multiply i))
500 | 120
501 | ```
502 | Initial value of `*`var`* is 1.
503 |
504 | See [Reductions].
505 |
506 | ### multiplying
507 | Alias for [multiply](#
508 |
509 | ### nconcing
510 | `nconcing `*`exptr`*` &optional into `*`var`*` test `*`test`*` at `*`place`*` result-type `*`type`*
511 |
512 | See [Accumulations] and [collect].
513 |
514 | ### never
515 | `never `*`expr`*
516 |
517 | Effectively `(always (not expr))`, but does not influence the last value returned by a possible other `always` clause.
518 | ```lisp
519 | CL-USER> (iter (repeat 2)
520 | (always 2)
521 | (never nil))
522 | 2
523 | ```
524 |
525 | See [Aggregated Boolean Tests]
526 |
527 | ### next
528 | See [generate](#generate).
529 |
530 | ### next-iteration
531 | `next-iteration`
532 | ```lisp
533 | CL-USER> (iter (for i below 3)
534 | (if (oddp i)
535 | (next-iteration)
536 | (collect i)))
537 | (0 2)
538 | ```
539 | ### nunioning
540 | `nunioning `*`exptr`*` &optional into `*`var`*` test `*`test`*` at `*`place`*` result-type `*`type`*
541 |
542 | See [Accumulations] and [collect].
543 |
544 | ### reducing
545 | `reducing `*`expr`*` by `*`func`*` &optional initial-value `*`init-val`*` into `*`var`*
546 | ```lisp
547 | CL-USER> (iter (for i in '(1 2 3))
548 | (reducing i by
549 | (lambda (value-so-far i)
550 | (cons i value-so-far))
551 | initial-value ()))
552 | (3 2 1)
553 | ```
554 |
555 | See [Reductions], [Accumulation vs Reduction](#accumulation-vs-reduction) and [accumulate](#accumulate).
556 |
557 | ### repeat
558 | `repeat `*`n`*
559 |
560 | Repeat the loop n times.
561 |
562 | See [Drivers].
563 | ```lisp
564 | CL-USER> (iter (repeat 3) (print 'doing))
565 |
566 | ; DOING
567 | ; DOING
568 | ; DOING
569 | NIL
570 | ```
571 |
572 | ### sum
573 | `sum `*`expr`*` &optional into `*`var`*
574 | ```lisp
575 | CL-USER> (iter (for i from 1 to 5)
576 | (sum i))
577 | 15
578 | ```
579 | ### summing
580 | Alias for [sum](#sum).
581 |
582 | ### terminate
583 | `terminate
584 |
585 | Use to terminate `for-next` clause. Effectively an alias for `finish` - but use with `for-next` to maintain compatibility with future versions of `iterate`(!).
586 |
587 | ```lisp
588 | CL-USER> (iter (for i upfrom 0)
589 | (if (> i 5) (terminate) (collect i)))
590 | (0 1 2 3 4 5)
591 | CL-USER> (iter (initially (setq i 0))
592 | (for i next
593 | (if (> i 10)
594 | (terminate)
595 | (incf i))))
596 | NIL
597 |
598 | ```
599 |
600 | See [Generalized Drivers].
601 |
602 | ### thereis
603 | `thereis `*`expr`*
604 |
605 | - If *`expr`* is ever non-`nil`, its value is returned without running the epilogue code.
606 | - Otherwise epilogue code is run, and `nil` is returned.
607 | - Cannot be used with `always` or `never`.
608 |
609 | See [Aggregated Boolean Tests].
610 |
611 | ### unioning
612 | `unioning `*`exptr`*` &optional into `*`var`*` test `*`test`*` at `*`place`*` result-type `*`type`*
613 |
614 | See [Accumulations] and [collect].
615 |
616 | ### until
617 | `until `*`expr`*
618 | ```lisp
619 | CL-USER> (iter (for i in '(1 2 3 4 5))
620 | (until (> i 5))
621 | (collect i))
622 | (1 2 3 4 5)
623 | ```
624 | Equivalent to `(if expr (finish))`.
625 |
626 | See [finish](#finish) and [Control Flow].
627 |
628 | ### while
629 | `repeat `*`n`*
630 | `until `*`expr`*
631 |
632 | Equivalent to `(if (not expr) (finish))`.
633 | ```lisp
634 | CL-USER> (iter (for i below 10)
635 | (while (= 0 (rem i 5)))
636 | (collect i))
637 | (0)
638 | ```
639 | See [finish](#finish) and [Control Flow].
640 |
641 | ### with
642 | `with `*`var`*` &optional = `*`value`*
643 |
644 | *`var`* is bound to *`value`* before the loop is entered. Binding happens sequentially, as while using a `let*`, and not in parallel as with `let`.
645 | ```lisp
646 | CL-USER> (iter (with i = 0)
647 | (while (< i 3))
648 | (collect (incf i)))
649 | (1 2 3)
650 | CL-USER> (iter (with i = 1)
651 | (for i below 3)
652 | (collect (incf i)))
653 | ; Evaluation aborted on #.
654 | ```
655 |
656 | See [Variable Binding and Setting] and [Parallel Binding and Stepping].
657 |
658 | ## OTHER RESOURCES ON ITERATE
659 |
660 | - [The Iterate Manual]
661 | - [Comparing LOOP and ITERATE](https://items.sjbach.com/211/comparing-loop-and-iterate)
662 | - [Loop v Iterate - SabraOnTheHill](https://sites.google.com/site/sabraonthehill/loop-v-iter)
663 |
664 | ---
665 |
666 | [The Iterate Manual]: https://common-lisp.net/project/iterate/index.html
667 | [tCLC]: https://github.com/LispCookbook/cl-cookbook
668 | [DLI]: appendix/Don't Loop, Iterate
669 | [Accumulations]: https://common-lisp.net/project/iterate/doc/Accumulations.html
670 | [Code Placement]: https://common-lisp.net/project/iterate/doc/Code-Placement.html#index-after_002deach-103
671 | [Problems with Code Movement]: https://common-lisp.net/project/iterate/doc/Problems-with-Code-Movement.html#Problems-with-Code-Movement
672 | [Aggregated Boolean Tests]: https://common-lisp.net/project/iterate/doc/Aggregated-Boolean-Tests.html
673 | [collect]: #collect
674 | [Reductions]: https://common-lisp.net/project/iterate/doc/Reductions.html
675 | [Types and Declarations]: https://common-lisp.net/project/iterate/doc/Types-and-Declarations.html
676 | [Extensibility Aids]: https://common-lisp.net/project/iterate/doc/Extensibility-Aids.html
677 | [Rolling Your Own]: https://common-lisp.net/project/iterate/doc/Rolling-Your-Own.html
678 | [Writing Drivers]: https://common-lisp.net/project/iterate/doc/Writing-Drivers.html
679 | [On-line help]: https://common-lisp.net/project/iterate/doc/On_002dline-Help.html
680 | [Destructuring]: https://common-lisp.net/project/iterate/doc/Destructuring.html
681 | [Finders]: https://common-lisp.net/project/iterate/doc/Finders.html
682 | [Control Flow]: https://common-lisp.net/project/iterate/doc/Control-Flow.html
683 | [Boolean Tests]: https://common-lisp.net/project/iterate/doc/Boolean-Tests.html
684 | [Numeric Iteration]: https://common-lisp.net/project/iterate/doc/Numerical-Iteration.html
685 | [Sequence Iteration]: https://common-lisp.net/project/iterate/doc/Sequence-Iteration.html
686 | [Variable Binding and Setting]: https://common-lisp.net/project/iterate/doc/Variable-Binding-and-Setting.html
687 | [Generalized Drivers]: https://common-lisp.net/project/iterate/doc/Generalized-Drivers.html
688 | [Previous Values of Driver Variables]: https://common-lisp.net/project/iterate/doc/Previous-Values-of-Driver-Variables.html
689 | [Generators]: https://common-lisp.net/project/iterate/doc/Generators.html
690 | [for]: #for
691 | [Named Blocks]: https://common-lisp.net/project/iterate/doc/Named-Blocks.html
692 | [Drivers]: https://common-lisp.net/project/iterate/doc/Drivers.html
693 | [accumulate]: #accumulate
694 | [Parallel Binding and Stepping]: https://common-lisp.net/project/iterate/doc/Parallel-Binding-and-Stepping.html#Parallel-Binding-and-Stepping
695 |
--------------------------------------------------------------------------------
/docs/local-time.md:
--------------------------------------------------------------------------------
1 | # local-time - Date and Time Manipulation
2 |
3 | Version: 1.0.6
4 |
5 | Licence: 3-clause BSD
6 |
7 | Repository: [dlowe-net/local-time](https://github.com/dlowe-net/local-time)
8 |
9 | See also: [awesome-cl#date-and-time](https://github.com/CodyReichert/awesome-cl#date-and-time)
10 |
11 | *In case of any inaccuracies, ambiguities or suggestions, please [create an issue here](https://github.com/cl-library-docs/common-lisp-libraries/issues).*
12 |
13 | *Great thanks to the excellent [official documentation](https://common-lisp.net/project/local-time/manual.html).*
14 |
15 | `local-time` library is a Common Lisp library for the manipulation
16 | of dates, times and intervals. It was originally based almost entirely
17 | upon Erik Naggum's paper [The Long Painful History of Time](http://naggum.no/lugm-time.html). Many of the core concepts originated from this paper,
18 | such as the seperation of days and seconds, the choice of 2000-03-01 as
19 | the standard epoch, and the timestring format.
20 |
21 |
22 | ## GETTING STARTED
23 |
24 | ### timestamps and timezones
25 |
26 | `local-time` deals with time in the form of [timestamp](#timestamp) and [timezone](#timezone).
27 |
28 | The following constructs deal with timezones:
29 |
30 | - [\*default-timezone\*](#default-timezone)
31 | - [+utc-zone+](#utc-zone)
32 | - [define-timezone](#define-timezone)
33 | - [find-timezone-by-location-name](#find-timezone-by-location-name)
34 | - [reread-timezone-repository](#reread-timezone-repository)
35 |
36 |
37 | **Examples**
38 |
39 | ```lisp
40 | CL-USER> (add-package-local-nickname :lt :local-time)
41 | #
42 |
43 | CL-USER> (lt:now)
44 | @2020-12-16T13:44:22.493573Z
45 |
46 | CL-USER> lt:+asctime-format+
47 | (:SHORT-WEEKDAY #\ :SHORT-MONTH #\ (:DAY 2 #\ ) #\ (:HOUR 2) #\: (:MIN 2)
48 | #\: (:SEC 2) #\ (:YEAR 4))
49 |
50 | CL-USER> (lt:format-timestring nil (lt:now)
51 | :format lt:+asctime-format+)
52 | "Wed Dec 16 13:45:24 2020"
53 |
54 | CL-USER> (lt:reread-timezone-repository)
55 | NIL
56 |
57 | CL-USER> lt::*default-timezone-repository-path*
58 | #P"/home/user/quicklisp/local-projects/local-time/zoneinfo/"
59 |
60 | CL-USER> (lt:find-timezone-by-location-name "US/Eastern")
61 | #
62 | T
63 |
64 | CL-USER> (lt:format-timestring nil (lt:now)
65 | :format lt:+asctime-format+
66 | :timezone *)
67 | "Wed Dec 16 09:00:57 2020"
68 | ```
69 |
70 | See [the cookbook](https://lispcookbook.github.io/cl-cookbook/dates_and_times.html) for more examples.
71 |
72 | ### Dealing with timestamps
73 |
74 | **Conversion: to and fro**
75 |
76 | - [now](#now)
77 | - [today](#today)
78 |
79 |
80 | - [days-in-month](#days-in-month)
81 |
82 |
83 | - [universal-to-timestamp](#universal-to-timestamp)
84 | - [unix-to-timestamp](#unix-to-timestamp)
85 | - [timestamp-to-universal](#timestamp-to-universal)
86 | - [timestamp-to-unix](#timestamp-to-unix)
87 |
88 |
89 | - [make-timestamp](#make-timestamp)
90 | - [clone-timestamp](#clone-timestamp)
91 |
92 |
93 | - [encode-timestamp](#encode-timestamp)
94 | - [decode-timestamp](#decode-timestamp)
95 | - [with-decoded-timestamp](#with-decoded-timestamp)
96 |
97 | **Querying and Manipulation**
98 |
99 | - [day-of](#day-of)
100 | - [sec-of](#sec-of)
101 | - [nsec-of](#nsec-of)
102 |
103 |
104 | - [timestamp<](#timestamp<)
105 | - [timestamp<=](#timestamp<=)
106 | - [timestamp>](#timestamp>)
107 | - [timestamp>=](#timestamp>=)
108 | - [timestamp=](#timestamp=)
109 | - [timestamp/=](#timestamp/=)
110 | - [timestamp-minimum](#timestamp-minimum)
111 | - [timestamp-maximum](#timestamp-maximum)
112 | - [timestamp-whole-year-difference](#timestamp-whole-year-difference)
113 |
114 |
115 | - [timestamp+](#timestamp+)
116 | - [timestamp-](#timestamp-)
117 | - [timestamp-maximize-part](#timestamp-maximize-part)
118 | - [timestamp-minimize-part](#timestamp-minimize-part)
119 |
120 |
121 | - [adjust-timestamp](#adjust-timestamp)
122 | - [adjust-timestamp!](#adjust-timestamp!)
123 |
124 |
125 | - [timestamp-subtimezone](#timestamp-subtimezone)
126 | - [timestamp-day-of-week](#timestamp-day-of-week)
127 | - [timestamp-millennium](#timestamp-millennium)
128 | - [timestamp-century](#timestamp-century)
129 | - [timestamp-decade](#timestamp-decade)
130 | - [timestamp-year](#timestamp-year)
131 | - [timestamp-month](#timestamp-month)
132 | - [timestamp-day](#timestamp-day)
133 | - [timestamp-hour](#timestamp-hour)
134 | - [timestamp-minute](#timestamp-minute)
135 | - [timestamp-second](#timestamp-second)
136 | - [timestamp-millisecond](#timestamp-millisecond)
137 | - [tiemstamp-microsecond](#tiemstamp-microsecond)
138 |
139 | **Parsing and Formatting**
140 |
141 | - [+iso-8601-format+](#iso-8601-format)
142 | - [+asctime-format+](#asctime-format)
143 | - [+rfc-1123-format+](#rfc-1123-format)
144 | - [+iso-week-date-format+](#iso-week-date-format)
145 | - [parse-timestring](#parse-timestring)
146 | - [format-timestring](#format-timestring)
147 | - [format-rfc3339-timestring](#format-rfc3339-timestring)
148 |
149 | **Reader Macros**
150 |
151 | - [enable-read-macros](#enable-read-macros)
152 |
153 | ### Clocks
154 |
155 | The [\*clock\*](#clock) special variable and the generic functions [clock-now](#clock-now) and [clock-today](#clock-today) are exposed so that applications may re-define the current time or date as required. This can be used for testing or to support alternate clocks.
156 |
157 | The currently supported values are:
158 |
159 | - `t` - Use the standard system clock with no adjustments
160 | - `leap-second-adjusted` - The system clock, adjusted for leap seconds using the information in [\*default-timezone\*](#default-timezone).
161 |
162 |
163 | ### Non-Gregorian Calendars
164 |
165 | Support for julian calendars is provided by the following functions:
166 |
167 | - [astronomical-julian-date](#astronomical-modified-julian-date)
168 | - [astronomical-modified-julian-date](#astronomical-modified-julian-date)
169 |
170 | ### A note on Portability
171 |
172 | This implementation assumes that time zone information is stored in the
173 | tzfile format. The default timezone is loaded from /etc/localtime. On
174 | non-POSIX systems, this will certainly give different results than the
175 | system time handling.
176 |
177 | local-time currently supports subsecond precision clocks with allegro,
178 | cmucl, sbcl, abcl, and non-Windows ccl. All others will be able to
179 | retrieve the time with second precision using `get-universal-time`. You
180 | may add support for your own implementation by implementing the clock
181 | generic protocol documented here.
182 |
183 | ## API REFERENCE
184 |
185 | ### \*clock\*
186 |
187 | ```lisp
188 | Variable
189 | Default Value: T
190 | ```
191 |
192 | Use this special variable if you need to define your own idea of the current time.
193 |
194 | The value of this variable should have the methods [clock-now](#clock-now), and
195 | [clock-today](#clock-today). The currently supported values in `local-time` are:
196 |
197 | - `t` - use the standard clock
198 | - [leap-second-adjusted](#leap-second-adjusted) - use a clock which adjusts for leap seconds using the information in [\*default-timezone\*](#default-timezone).
199 |
200 | TODO: Add / Point to a concrete example of dealing with clocks.
201 |
202 | ### \*default-timezone\*
203 |
204 | ```lisp
205 | Variable
206 | Default Value: #
207 | ```
208 |
209 | This variable contains the timezone that will be used by default if none
210 | is specified. It is loaded from `/etc/localtime` when the library is loaded.
211 | If `/etc/localtime` is not present, it will default to UTC.
212 |
213 | ### +asctime-format+
214 |
215 | ```lisp
216 | Variable
217 | Default Value: (:SHORT-WEEKDAY #\ :SHORT-MONTH #\ (:DAY 2 #\ ) #\ (:HOUR 2)
218 | #\: (:MIN 2) #\: (:SEC 2) #\ (:YEAR 4))
219 | ```
220 |
221 | This constant is bound to a format mirroring the output of the POSIX
222 | asctime() function. An output with this format will look like this:
223 | `Sat Mar 1 19:42:34 2008`.
224 |
225 | ### +day-names+
226 |
227 | ```lisp
228 | Variable
229 | Default Value: #("Sunday" "Monday" "Tuesday" "Wednesday" "Thursday" "Friday"
230 | "Saturday")
231 | ```
232 |
233 | ### +days-per-week+
234 |
235 | ```lisp
236 | Constant: 7
237 | ```
238 |
239 | ### +gmt-zone+
240 |
241 | ```lisp
242 | Variable
243 | Default Value: #
244 | ```
245 |
246 | ### +hours-per-day+
247 |
248 | ```lisp
249 | Constant: 24
250 | ```
251 |
252 | ### +iso-8601-date-format+
253 |
254 | ```lisp
255 | Variable
256 | Default Value: ((:YEAR 4) #\- (:MONTH 2) #\- (:DAY 2))
257 | ```
258 |
259 | See [+iso-8601-format+](#iso-8601-format).
260 |
261 | ### +iso-8601-format+
262 |
263 | ```lisp
264 | Variable
265 | Default Value: ((:YEAR 4) #\- (:MONTH 2) #\- (:DAY 2) #\T (:HOUR 2) #\:
266 | (:MIN 2) #\: (:SEC 2) #\. (:USEC 6) :GMT-OFFSET-OR-Z)
267 | ```
268 |
269 | This constant is bound to a description of the ISO 8601 format. An output
270 | with this format will look like this: `2008-03-01T19:42:34.608506+01:00`.
271 | This is the default format for the [format-timestring](#format-timestring) function.
272 |
273 | ### +iso-8601-time-format+
274 |
275 | ```lisp
276 | Variable
277 | Default Value: ((:HOUR 2) #\: (:MIN 2) #\: (:SEC 2) #\. (:USEC 6))
278 | ```
279 |
280 | See [+iso-8601-format+](#iso-8601-format).
281 |
282 | ### +iso-week-date-format+
283 |
284 | ```lisp
285 | Variable
286 | Default Value: ((:ISO-WEEK-YEAR 4) #\- #\W (:ISO-WEEK-NUMBER 2) #\-
287 | (:ISO-WEEK-DAY 1))
288 | ```
289 |
290 | This constant is bound to a description of the ISO 8601 Week Date format.
291 | An output with this format will look like this: `2009-W53-5`.
292 |
293 | ### +minutes-per-day+
294 |
295 | ```lisp
296 | Constant: 1440
297 | ```
298 |
299 | ### +minutes-per-hour+
300 |
301 | ```lisp
302 | Constant: 60
303 | ```
304 |
305 | ### +month-names+
306 |
307 | ```lisp
308 | Variable
309 | Default Value: #("" "January" "February" "March" "April" "May" "June" "July"
310 | "August" "September" "October" "November" "December")
311 | ```
312 |
313 | ### +months-per-year+
314 |
315 | ```lisp
316 | Constant: 12
317 | ```
318 |
319 | ### +rfc-1123-format+
320 |
321 | ```lisp
322 | Variable
323 | Default Value: (:SHORT-WEEKDAY ", " (:DAY 2) #\ :SHORT-MONTH #\ (:YEAR 4) #\
324 | (:HOUR 2) #\: (:MIN 2) #\: (:SEC 2) #\ :GMT-OFFSET-HHMM)
325 | ```
326 |
327 | This constant is bound to a description of the format defined in RFC 1123
328 | for Internet timestamps. An output with this format will look like this:
329 | `Sat, 01 Mar 2008 19:42:34 -0500`. See the [RFC 1123](https://tools.ietf.org/html/rfc1123)
330 | for the details about the possible values of the timezone field.
331 |
332 | ### +rfc3339-format+
333 |
334 | ```lisp
335 | Variable
336 | Default Value: ((:YEAR 4) #\- (:MONTH 2) #\- (:DAY 2) #\T (:HOUR 2) #\:
337 | (:MIN 2) #\: (:SEC 2) #\. (:USEC 6) :GMT-OFFSET-OR-Z)
338 | ```
339 |
340 | ### +rfc3339-format/date-only+
341 |
342 | ```lisp
343 | Variable
344 | Default Value: ((:YEAR 4) #\- (:MONTH 2) #\- (:DAY 2))
345 | ```
346 |
347 | ### +seconds-per-day+
348 |
349 | ```lisp
350 | Constant: 86400
351 | ```
352 |
353 | ### +seconds-per-hour+
354 |
355 | ```lisp
356 | Constant: 3600
357 | ```
358 |
359 | ### +seconds-per-minute+
360 |
361 | ```lisp
362 | Constant: 60
363 | ```
364 |
365 | ### +short-day-names+
366 |
367 | ```lisp
368 | Variable
369 | Default Value: #("Sun" "Mon" "Tue" "Wed" "Thu" "Fri" "Sat")
370 | ```
371 |
372 | ### +short-month-names+
373 |
374 | ```lisp
375 | Variable
376 | Default Value: #("" "Jan" "Feb" "Mar" "Apr" "May" "Jun" "Jul" "Aug" "Sep" "Oct"
377 | "Nov" "Dec")
378 | ```
379 |
380 | ### +utc-zone+
381 |
382 | ```lisp
383 | Variable
384 | Default Value: #
385 | ```
386 |
387 | A timezone corresponding to UTC.
388 |
389 | ### adjust-timestamp
390 |
391 | ```lisp
392 | Macro: (adjust-timestamp timestamp &body changes)
393 | ```
394 |
395 | Alters various parts of [timestamp](#timestamp), given a list of
396 | changes. The changes are in the format `(offset part value)` and
397 | `(set part value)`.
398 |
399 | ``` {.lisp}
400 | ;; Return a new timestamp value that points to the previous Monday
401 | (adjust-timestamp (today) (offset :day-of-week :monday))
402 |
403 | ;; Return a new timestamp value that points three days ahead from now
404 | (adjust-timestamp (today) (offset :day 3))
405 | ```
406 |
407 | Keep in mind that adjust-timestamp is not a mere setter for fields
408 | but instead it handles overflows and timezone conversions as
409 | expected. Also note that it's possible to specify multiple commands.
410 |
411 | The list of possible places to manipulate are: `:nsec` `:sec`
412 | `:sec-of-day` `:minute` `:hour` `:day` `:day-of-month` `:month`
413 | `:year`.
414 |
415 |
416 | ### adjust-timestamp!
417 |
418 | ```lisp
419 | Macro: (adjust-timestamp! timestamp &body changes)
420 | ```
421 |
422 | Just like [adjust-timestamp](#adjust-timestamp), but instead of returning a freshly constructed
423 | value, it alters the provided [timestamp](#timestamp) value (and returns it).
424 |
425 | ### all-timezones-matching-subzone
426 |
427 | ```lisp
428 | Function: (all-timezones-matching-subzone abbreviated-name)
429 | ```
430 |
431 | Returns list of lists of timezone, matched subzone and last transition time
432 | for timezones that have subzone matching specified abbreviated-name. Includes both active and historical timezones.
433 |
434 | ### astronomical-julian-date
435 |
436 | ```lisp
437 | Function: (astronomical-julian-date timestamp)
438 | ```
439 |
440 | Returns the astronomical julian date referred to by the timestamp.
441 |
442 | ### astronomical-modified-julian-date
443 |
444 | No documentation found for `astronomical-modified-julian-date`
445 |
446 | ### clock-now
447 |
448 | ```lisp
449 | Generic Function: (clock-now clock)
450 | ```
451 |
452 | Returns a timestamp for the current time given a clock.
453 | Specialize this generic function to re-define the present moment
454 |
455 | ### clock-today
456 |
457 | ```lisp
458 | Generic Function: (clock-today clock)
459 | ```
460 |
461 | Returns a timestamp for the current date given a
462 | clock. The date is encoded by convention as a timestamp with the
463 | time set to 00:00:00UTC.
464 |
465 | Specialize this generic function to re-define the present day.
466 |
467 | ### clone-timestamp
468 |
469 | ```lisp
470 | Function: (clone-timestamp timestamp)
471 | ```
472 |
473 | Returns a copy of [timestamp](#timestamp) that is `timestamp=` to it.
474 |
475 | ### date
476 |
477 | ```lisp
478 | Type
479 | ```
480 |
481 | A [timestamp](#timestamp) referring to a UTC timezone. The `sec` slot must be the first
482 | second of a day; in other words, the time elements of the `timestamp` value must
483 | have their least possible values 0.
484 |
485 |
486 | ### day-of
487 |
488 | ```lisp
489 | Generic Function: (day-of object)
490 | ```
491 |
492 | Returns the day component of [timestamp](#timestamp). Although
493 | Naggum's paper specifies that the day should be a signed fixnum, it
494 | is left unbounded for flexibility reasons.
495 |
496 |
497 | ### days-in-month
498 |
499 | ```lisp
500 | Function: (days-in-month month year)
501 | ```
502 |
503 | Returns the number of days in the given month of the specified year.
504 |
505 | ### decode-timestamp
506 |
507 | ```lisp
508 | Function: (decode-timestamp timestamp &key (timezone *default-timezone*) offset)
509 | ```
510 |
511 | Returns the decoded time as multiple values:
512 |
513 | (values ns ss mm hh day month year day-of-week daylight-saving-time-p timezone-offset timezone-abbreviation)
514 |
515 | ### define-timezone
516 |
517 | ```lisp
518 | Macro: (define-timezone zone-name zone-file &key (load NIL))
519 | ```
520 |
521 | Define [zone-name](#zone-name) (a symbol or a string) as a new timezone, lazy-loaded from zone-file (a pathname designator relative to the zoneinfo directory on this system. If load is true, load immediately.
522 |
523 | ### enable-read-macros
524 |
525 | ```lisp
526 | Function: (enable-read-macros)
527 | ```
528 |
529 | Enables the local-time reader macros for literal timestamps and universal time.
530 |
531 | ### encode-timestamp
532 |
533 | ```lisp
534 | Function: (encode-timestamp nsec sec minute hour day month year &key
535 | (timezone *default-timezone*) offset into)
536 | ```
537 |
538 | Returns a new [timestamp](#timestamp) instance corresponding to the specified
539 | time elements. offset is the number of seconds offset from UTC of the locale.
540 | If offset is not specified, the offset will be guessed from the timezone.
541 |
542 | If a [timestamp](#timestamp) is passed as the into argument, its value will be set and that
543 | [timestamp](#timestamp) will be returned. Otherwise, a new [timestamp](#timestamp) is created.
544 |
545 | ### find-timezone-by-location-name
546 |
547 | ```lisp
548 | Function: (find-timezone-by-location-name name)
549 | ```
550 |
551 | Returns the timezone found at the location name (such as `US/Eastern`).
552 | [reread-timezone-repository](#reread-timezone-repository) must be called before this function is used.
553 |
554 | ### format-rfc1123-timestring
555 |
556 | ```lisp
557 | Function: (format-rfc1123-timestring destination timestamp &key
558 | (timezone *default-timezone*))
559 | ```
560 |
561 | See [+rfc-1123-format+](#rfc-1123-format) and [format-timestring](#format-timestring).
562 |
563 |
564 | ### format-rfc3339-timestring
565 |
566 | ```lisp
567 | Function: (format-rfc3339-timestring destination timestamp &key omit-date-part
568 | omit-time-part (omit-timezone-part omit-time-part) (use-zulu t)
569 | (timezone *default-timezone*))
570 | ```
571 |
572 | Formats a timestring in the RFC 3339 format, a restricted form of the ISO-8601 timestring specification for Internet timestamps.
573 |
574 | See [+rfc3339-format+](#rfc3339-format) and [format-timestring](#format-timestring).
575 |
576 | ### format-timestring
577 |
578 | ```lisp
579 | Function: (format-timestring destination timestamp &key
580 | (format +iso-8601-format+) (timezone *default-timezone*))
581 | ```
582 |
583 | Constructs a string representation of [timestamp](#timestamp) according
584 | to format and returns it.
585 | If `destination` is T, the string is written to *STANDARD-OUTPUT*.
586 | If `destination` is a stream, the string is written to the stream.
587 |
588 | `format` is a list containing one or more of strings, characters,
589 | and keywords. Strings and characters are output literally,
590 | while keywords are replaced by the values here:
591 |
592 | :YEAR *year
593 | :MONTH *numeric month
594 | :DAY *day of month
595 | :HOUR *hour
596 | :MIN *minutes
597 | :SEC *seconds
598 | :WEEKDAY *numeric day of week starting from index 0, which means Sunday
599 | :MSEC *milliseconds
600 | :USEC *microseconds
601 | :NSEC *nanoseconds
602 | :ISO-WEEK-YEAR *year for ISO week date (can be different from regular calendar year)
603 | :ISO-WEEK-NUMBER *ISO week number (i.e. 1 through 53)
604 | :ISO-WEEK-DAY *ISO compatible weekday number (monday=1, sunday=7)
605 | :LONG-WEEKDAY long form of weekday (e.g. Sunday, Monday)
606 | :SHORT-WEEKDAY short form of weekday (e.g. Sun, Mon)
607 | :MINIMAL-WEEKDAY minimal form of weekday (e.g. Su, Mo)
608 | :SHORT-YEAR short form of year (last 2 digits, e.g. 41, 42 instead of 2041, 2042)
609 | :LONG-MONTH long form of month (e.g. January, February)
610 | :SHORT-MONTH short form of month (e.g. Jan, Feb)
611 | :HOUR12 *hour on a 12-hour clock
612 | :AMPM am/pm marker in lowercase
613 | :GMT-OFFSET the gmt-offset of the time, in +00:00 form
614 | :GMT-OFFSET-OR-Z like :GMT-OFFSET, but is Z when UTC
615 | :GMT-OFFSET-HHMM like :GMT-OFFSET, but in +0000 form
616 | :TIMEZONE timezone abbrevation for the time
617 |
618 | Elements marked by `*` can be placed in a list in the form
619 |
620 | (:keyword padding &optional (padchar #\0))
621 |
622 | The string representation of the value will be padded with the padchar.
623 |
624 | You can see examples in [+ISO-8601-FORMAT+](#iso-8601-format), [+ASCTIME-FORMAT+](#asctime-format), and [+RFC-1123-FORMAT+](#rfc-1123-format).
625 |
626 | ### invalid-timestring
627 |
628 | ```lisp
629 | Condition
630 | ```
631 |
632 |
633 | ### leap-second-adjusted
634 |
635 | No documentation found for `leap-second-adjusted`
636 |
637 | ### make-timestamp
638 |
639 | ```lisp
640 | Macro: (make-timestamp &rest args)
641 | ```
642 |
643 | Expands to an expression that creates an instance of a [timestamp](#timestamp)
644 | exactly as specified.
645 |
646 | ### modified-julian-date
647 |
648 | ```lisp
649 | Function: (modified-julian-date timestamp)
650 | ```
651 |
652 | Returns the modified julian date referred to by the timestamp.
653 |
654 | ### now
655 |
656 | ```lisp
657 | Function: (now)
658 | ```
659 |
660 | Produces a [timestamp](#timestamp) instance with the current time. Under sbcl, the new timestamp will be precise to the microsecond. Otherwise, the precision is limited to the second.
661 |
662 | ### nsec-of
663 |
664 | ```lisp
665 | Generic Function: (nsec-of object)
666 | ```
667 | Returns the `microseconds` component of the [timestamp](#timestamp). Valid values for
668 | the nanoseconds range from 0 to 999999999.
669 |
670 |
671 |
672 | ### parse-rfc3339-timestring
673 |
674 | ```lisp
675 | Function: (parse-rfc3339-timestring timestring &key (fail-on-error t)
676 | (allow-missing-time-part NIL))
677 | ```
678 |
679 | ### parse-timestring
680 |
681 | ```lisp
682 | Function: (parse-timestring timestring &key start end (fail-on-error t)
683 | (time-separator :) (date-separator -) (date-time-separator t)
684 | (fract-time-separators (quote (. ,))) (allow-missing-elements t)
685 | (allow-missing-date-part allow-missing-elements)
686 | (allow-missing-time-part allow-missing-elements)
687 | (allow-missing-timezone-part allow-missing-elements) (offset 0))
688 | ```
689 |
690 | Parses a timestring and returns the corresponding `timestamp`.
691 | Parsing begins at `start` and stops at the
692 | `end` position. If there are invalid characters within
693 | `timestring` and `fail-on-error` is `T`, then an
694 | `invalid-timestring` error is signaled, otherwise `NIL` is returned.
695 |
696 | If there is no timezone specified in `timestring` then
697 | `offset` is used as the default timezone offset (in
698 | seconds).
699 |
700 | See `local-time::split-timestring` for details. Unspecified fields in the
701 | timestring are initialized to their lowest possible value,
702 | and timezone offset is 0 (UTC) unless explicitly specified
703 | in the input string.
704 |
705 | ### reread-timezone-repository
706 |
707 | ```lisp
708 | Function: (reread-timezone-repository &key
709 | (timezone-repository *default-timezone-repository-path*))
710 | ```
711 |
712 | Walks the current repository, reading all tzinfo files updating indexes.
713 | The default timezone repository is set to the zoneinfo/ directory of the local-time system.
714 |
715 | ### sec-of
716 |
717 | ```lisp
718 | Generic Function: (sec-of object)
719 | ```
720 |
721 | Returns the `seconds` component of the [timestamp](#timestamp). Valid values for the
722 | seconds range from 0 to 86399.
723 |
724 |
725 | ### time-of-day
726 |
727 | ```lisp
728 | Type
729 | ```
730 |
731 | A [timestamp](#timestamp) with `day` slot having the value 0.
732 |
733 |
734 | ### timestamp
735 |
736 | ```lisp
737 | Class
738 | ```
739 |
740 | `timestamp` values are basically instances of
741 |
742 | ```lisp
743 | (defclass timestamp ()
744 | ((day :type integer)
745 | (sec :type integer)
746 | (nsec :type (integer 0 999999999))))
747 | ```
748 |
749 | These can represent either a [date](#date), a `daytime` or a
750 | [time-of-day](#time-of-day) value, depending on the values of its slots.
751 |
752 |
753 | ### timestamp+
754 |
755 | ```lisp
756 | Function: (timestamp+ time amount unit &optional (timezone *default-timezone*)
757 | offset)
758 | ```
759 |
760 | Add the `amount` to the `time`
761 | using the specified `unit`.
762 |
763 | - `unit` may be one of ( `:nsec` `:sec` `:minute` `:hour` `:day` `:month` `:year`).
764 |
765 | The value of the parts of the timestamp of higher resolution than the
766 | `unit` will never be touched. If you want a precise number of seconds
767 | from a time, you should specify the offset in seconds.
768 |
769 | ### timestamp-
770 |
771 | ```lisp
772 | Function: (timestamp- time amount unit &optional (timezone *default-timezone*)
773 | offset)
774 | ```
775 |
776 | Subtract the `amount` from the `time`
777 | using the specified `unit`.
778 |
779 | - `unit` may be one of ( `:nsec` `:sec` `:minute` `:hour` `:day` `:month` `:year`).
780 |
781 | The value of the parts of the timestamp of higher resolution than the
782 | `unit` will never be touched. If you want a precise number of seconds
783 | from a time, you should specify the offset in seconds.
784 |
785 | ### timestamp-century
786 |
787 | ```lisp
788 | Function: (timestamp-century timestamp &key (timezone *default-timezone*))
789 | ```
790 |
791 | Returns the ordinal century upon which the timestamp falls. Ordinal time values start at 1, so the `(timestamp-century (now))` will return 21.
792 |
793 | ### timestamp-day
794 |
795 | ```lisp
796 | Function: (timestamp-day timestamp &key (timezone *default-timezone*))
797 | ```
798 |
799 | Returns the day of the month upon which the timestamp falls.
800 |
801 | ### timestamp-day-of-week
802 |
803 | ```lisp
804 | Function: (timestamp-day-of-week timestamp &key (timezone *default-timezone*)
805 | offset)
806 | ```
807 |
808 | This returns the index of the day of the week, starting at 0 which
809 | means Sunday.
810 |
811 | **Note:** "Day of the week" is ambigous and locale dependent.
812 |
813 | ### timestamp-decade
814 |
815 | ```lisp
816 | Function: (timestamp-decade timestamp &key (timezone *default-timezone*))
817 | ```
818 |
819 | Returns the cardinal decade upon which the timestamp falls. Ordinal time values start at 1.
820 |
821 | ### timestamp-difference
822 |
823 | ```lisp
824 | Function: (timestamp-difference time-a time-b)
825 | ```
826 |
827 | Returns the difference between time-a and time-b in seconds
828 |
829 | ### timestamp-hour
830 |
831 | ```lisp
832 | Function: (timestamp-hour timestamp &key (timezone *default-timezone*))
833 | ```
834 |
835 | ### timestamp-maximize-part
836 |
837 | ```lisp
838 | Function: (timestamp-maximize-part timestamp part &key
839 | (timezone *default-timezone*) into)
840 | ```
841 |
842 | Returns a timestamp with its parts maximized up to
843 | `part`. `part` can be any of (:nsec :sec :min
844 | :hour :day :month). If `into` is specified, it will be
845 | modified and returned, otherwise a new timestamp will be created.
846 |
847 | ### timestamp-maximum
848 |
849 | ```lisp
850 | Function: (timestamp-maximum time &rest times)
851 | ```
852 |
853 | Returns the latest timestamp
854 |
855 | ### timestamp-microsecond
856 |
857 | ```lisp
858 | Function: (timestamp-microsecond timestamp)
859 | ```
860 |
861 | ### timestamp-millennium
862 |
863 | ```lisp
864 | Function: (timestamp-millennium timestamp &key (timezone *default-timezone*))
865 | ```
866 |
867 | Returns the ordinal millennium upon which the timestamp falls. These start from 1, so the `(timestamp-millennium (now))` will return 3.
868 |
869 | ### timestamp-millisecond
870 |
871 | ```lisp
872 | Function: (timestamp-millisecond timestamp)
873 | ```
874 |
875 | ### timestamp-minimize-part
876 |
877 | ```lisp
878 | Function: (timestamp-minimize-part timestamp part &key
879 | (timezone *default-timezone*) into)
880 | ```
881 |
882 | Returns a timestamp with its parts minimized up to
883 | `part`. `part` can be any of (:nsec :sec :min
884 | :hour :day :month). If `into` is specified, it will be
885 | modified and returned, otherwise a new timestamp will be created.
886 |
887 |
888 | ### timestamp-minimum
889 |
890 | ```lisp
891 | Function: (timestamp-minimum time &rest times)
892 | ```
893 |
894 | Returns the earliest timestamp
895 |
896 | ### timestamp-minute
897 |
898 | ```lisp
899 | Function: (timestamp-minute timestamp &key (timezone *default-timezone*))
900 | ```
901 |
902 | ### timestamp-month
903 |
904 | ```lisp
905 | Function: (timestamp-month timestamp &key (timezone *default-timezone*))
906 | ```
907 |
908 | Returns the month upon which the timestamp falls.
909 |
910 | ### timestamp-second
911 |
912 | ```lisp
913 | Function: (timestamp-second timestamp &key (timezone *default-timezone*))
914 | ```
915 |
916 | ### timestamp-subtimezone
917 |
918 | ```lisp
919 | Function: (timestamp-subtimezone timestamp timezone)
920 | ```
921 |
922 | Return as multiple values the time zone as the number of seconds east of UTC, a boolean daylight-saving-p, and the customary abbreviation of the timezone.
923 |
924 | ### timestamp-to-universal
925 |
926 | ```lisp
927 | Function: (timestamp-to-universal timestamp)
928 | ```
929 |
930 | Return the UNIVERSAL-TIME corresponding to the [timestamp](#timestamp).
931 | This is the date/time specified in `timestamp`
932 | encoded as the number of seconds since January 1st, 1900 12:00am
933 | UTC.
934 |
935 | ### timestamp-to-unix
936 |
937 | ```lisp
938 | Function: (timestamp-to-unix timestamp)
939 | ```
940 |
941 | Return the Unix time corresponding to the [timestamp](#timestamp).
942 | This returns the date/time specified in `timestamp`
943 | encoded as the number of seconds since January 1st, 1970 12:00am
944 | UTC. It corresponds with the time received from the POSIX call
945 | `time()`.
946 |
947 |
948 | ### timestamp-week
949 |
950 | No documentation found for `timestamp-week`
951 |
952 | ### timestamp-whole-year-difference
953 |
954 | ```lisp
955 | Function: (timestamp-whole-year-difference time-a time-b)
956 | ```
957 |
958 | Returns the number of whole years elapsed between time-a and time-b.
959 |
960 | **Note:** This is useful for calculating anniversaries and birthdays.
961 |
962 | ### timestamp-year
963 |
964 | ```lisp
965 | Function: (timestamp-year timestamp &key (timezone *default-timezone*))
966 | ```
967 |
968 | Returns the cardinal year upon which the timestamp falls.
969 |
970 | ### timestamp/=
971 |
972 | ```lisp
973 | Function: (timestamp/= &rest timestamps)
974 | ```
975 |
976 | Returns T if no pair of timestamps is equal. Otherwise return NIL.
977 |
978 | ### timestamp<
979 |
980 | ```lisp
981 | Function: (timestamp< &rest times)
982 | ```
983 |
984 | ### timestamp<=
985 |
986 | ```lisp
987 | Function: (timestamp<= &rest times)
988 | ```
989 |
990 | ### timestamp=
991 |
992 | ```lisp
993 | Function: (timestamp= &rest times)
994 | ```
995 |
996 | ### timestamp>
997 |
998 | ```lisp
999 | Function: (timestamp> &rest times)
1000 | ```
1001 |
1002 | ### timestamp>=
1003 |
1004 | ```lisp
1005 | Function: (timestamp>= &rest times)
1006 | ```
1007 |
1008 | ### timezones-matching-subzone
1009 |
1010 | ```lisp
1011 | Function: (timezones-matching-subzone abbreviated-name timestamp)
1012 | ```
1013 |
1014 | Returns list of lists of active timezone, matched subzone and last transition time
1015 | for timezones that have subzone matching specified abbreviated-name as of [timestamp](#timestamp) moment if provided.
1016 |
1017 | ### to-rfc1123-timestring
1018 |
1019 | ```lisp
1020 | Function: (to-rfc1123-timestring timestamp)
1021 | ```
1022 |
1023 | ### to-rfc3339-timestring
1024 |
1025 | ```lisp
1026 | Function: (to-rfc3339-timestring timestamp)
1027 | ```
1028 |
1029 | ### today
1030 |
1031 | ```lisp
1032 | Function: (today)
1033 | ```
1034 |
1035 | Produces a [timestamp](#timestamp) instance that corresponds to today's date,
1036 | which is the midnight of the current day in the UTC zone.
1037 |
1038 | ### universal-to-timestamp
1039 |
1040 | ```lisp
1041 | Function: (universal-to-timestamp universal &key (nsec 0))
1042 | ```
1043 |
1044 | Produces a [timestamp](#timestamp) instance from the provided universal time
1045 | universal. Universal time is defined in the Common Lisp
1046 | Specification as the number of seconds since 1900-01-01T00:00:00Z.
1047 |
1048 | **Note:** Subsecond precision is not preserved.
1049 |
1050 | ### unix-to-timestamp
1051 |
1052 | ```lisp
1053 | Function: (unix-to-timestamp unix &key (nsec 0))
1054 | ```
1055 |
1056 | Produces a [timestamp](#timestamp) instance from the provided unix time unix. Unix time
1057 | is defined by POSIX as the number of seconds since 1970-01-01T00:00:00Z.
1058 |
1059 | ### with-decoded-timestamp
1060 |
1061 | ```lisp
1062 | Macro: (with-decoded-timestamp
1063 | (&key nsec sec minute hour day month year day-of-week daylight-p
1064 | timezone offset)
1065 | timestamp &body forms)
1066 | ```
1067 |
1068 | This macro binds variables to the decoded elements of [timestamp](#timestamp). The timezone argument is used for decoding the timestamp, and is not bound by the macro. The value of day-of-week starts from 0 which means Sunday.
1069 |
1070 | ### zone-name
1071 |
1072 | ```lisp
1073 | Function: (zone-name zone)
1074 | ```
1075 |
--------------------------------------------------------------------------------
/docs/quicklisp.md:
--------------------------------------------------------------------------------
1 | # quicklisp - Library Manager
2 |
3 | Version: 2020-01-04
4 |
5 | Licence: BSD-style
6 |
7 | Repository: [quicklisp/quicklisp-client - Github](https://github.com/quicklisp/quicklisp-client)
8 |
9 | *In case of any inaccuracies, ambiguities or suggestions, please [create an issue here](https://github.com/digikar99/common-lisp.readthedocs/issues).*
10 |
11 |
12 | ## GETTING STARTED
13 |
14 | ### Installation
15 |
16 |
17 | **Download**
18 |
19 | Do the equivalent steps on Windows and Mac OS:
20 |
21 | ```sh
22 | curl -O https://beta.quicklisp.org/quicklisp.lisp # download quicklisp.lisp
23 | curl -O https://beta.quicklisp.org/quicklisp.lisp.asc # download the PGP signature file
24 | gpg --verify quicklisp.lisp.asc quicklisp.lisp # verify it against the signing key
25 | ```
26 |
27 | As of 07 June 2020, Quicklisp release signing key has a fingerprint of `D7A3 489D DEFE 32B7 D0E7 CC61 3079 65AB 028B 5FF7`, an id of `028B5FF7`, and an email of `release@quicklisp.org`. See [here](https://www.quicklisp.org/beta/#installation) for the more recent details.
28 |
29 | **Installation**
30 |
31 | Load quicklisp.lisp: `sbcl --load quicklisp.lisp # or an equivalent command for your implementation` (optionally, you may want to `rlwrap sbcl --load quicklisp.lisp` for a better
32 | repl experience):
33 |
34 | ```lisp
35 | (quicklisp-quickstart:install)
36 | (ql:add-to-init-file) ; to automatically load quicklisp at implementation startup
37 | ;;; Note that ql acts as a nickname for the quicklisp-client package.
38 | ```
39 |
40 | `quicklisp-quickstart:install` also takes a couple keyword arguments (see `(describe 'quicklisp-quickstart:install)` - but unless you know what
41 | you are doing, it is recommended to leave them as they are.
42 |
43 | ### Loading after installation
44 |
45 | `(ql:add-to-init-file)` adds instructions to your implementations init-file (`.sbclrc` or
46 | equivalent) to load quicklisp on implementation startup.
47 |
48 | However, some runtime options of the implementation may disable loading the init-file -
49 | `sbcl --script` for instance. For these cases, you might want to `alias` (or equivalent)
50 | `alias sbcl-ql='rlwrap sbcl --noinform --load $HOME/quicklisp/setup.lisp'` in your `.bashrc`
51 | (or equivalent).
52 |
53 | ### A few useful functions and variables
54 |
55 | - [quickload](#quickload): `(ql:quickload '("alexandria" "bordeaux-threads"))` or `(ql:quickload "alexandria")`.
56 | - [system-apropos](#system-apropos): `(ql:system-apropos "postgres")`
57 | - [where-is-system](#where-is-system)
58 | - [\*local-project-directories\*](#local-project-directories): you may either want to have this variable modified from implementation init-file, or symlink `~/quicklisp/local-projects` to wherever your projects directory is. This is the location - as the name suggests - where quicklisp searches for local projects.
59 | - [uninstall](#uninstall)
60 | - [update-client](#update-client)
61 |
62 | You may also need to run `(asdf:clear-configuration)` to have [ASDF](https://common-lisp.net/project/asdf/asdf.html) reprocess its configuration files while loading a newer library. There is also the [ql:register-local-projects](#register-local-projects) that can help with the same.
63 |
64 | ### A note on quicklisp dists
65 |
66 | Besides being an ASDF system, quicklisp is also the name of a [dist](#dist). This distribution
67 | is released about once per month, with the guarantee that all systems in the distribution build together - note that this does not still imply that they *work* together. For these cases,
68 | you may want to [go back in dist time](http://blog.quicklisp.org/2011/08/going-back-in-dist-time.html). You might, additionally, want to learn about [qlot](https://github.com/fukamachi/qlot) that helps with version pinning - however, given the stability of Common Lisp, that translates to the stability for its (old but gold) libraries, it may be an overkill. But, YMMV.
69 |
70 | Also worth a read is [getting libraries into quicklisp](http://blog.quicklisp.org/2015/01/getting-library-into-quicklisp.html). (Hope you took note of the blog!)
71 |
72 | The once-per-month release nature of quicklisp can be an issue if you need to work with
73 | bleeding edge packages - for these cases, there exists [Ultralisp](https://ultralisp.org/) - which updates every 5 minutes! This is yet another distribution. Some useful functions for working with distributions include:
74 |
75 | - [install-dist](#install-dist)
76 | - [uninstall-dist](#uninstall-dist)
77 | - [update-dist](#update-dist): `(ql:update-dist "quicklisp")`
78 | - [find-dist](#find-dist)
79 | - [enabled-dists](#enabled-dists)
80 | - [enable](#enable)
81 | - [disable](#disable)
82 |
83 | ### More reading
84 |
85 | More reading about quicklisp is available on its [official page](https://www.quicklisp.org/beta/index.html).
86 |
87 |
88 | ## quicklisp-client: API REFERENCE
89 |
90 | Nickname: ql
91 |
92 |
93 | The Quicklisp client package, intended for end-user Quicklisp
94 | commands and configuration parameters.
95 |
96 |
97 | ### \*local-project-directories\*
98 |
99 | ```lisp
100 | Variable
101 | ```
102 |
103 | The default local projects directory.
104 |
105 |
106 | ### \*quickload-prompt\*
107 |
108 | ```lisp
109 | Variable
110 | ```
111 |
112 | When NIL, quickload systems without prompting for enter to
113 | continue, otherwise proceed directly without user intervention.
114 |
115 |
116 | ### \*quickload-verbose\*
117 |
118 | ```lisp
119 | Variable
120 | ```
121 |
122 | When NIL, show terse output when quickloading a system. Otherwise,
123 | show normal compile and load output.
124 |
125 |
126 | ### add-to-init-file
127 |
128 | ```lisp
129 | Function: (add-to-init-file &optional implementation-or-file)
130 | ```
131 |
132 | Add forms to the Lisp implementation's init file that will load
133 | quicklisp at CL startup.
134 |
135 | ### available-client-versions
136 |
137 | ```lisp
138 | Function: (available-client-versions)
139 | ```
140 |
141 |
142 |
143 | ### available-dist-versions
144 |
145 | ```lisp
146 | Function: (available-dist-versions name)
147 | ```
148 |
149 |
150 |
151 | ### bundle-systems
152 |
153 | ```lisp
154 | Function: (bundle-systems system-names &key include-local-projects to
155 | (overwrite t))
156 | ```
157 |
158 | In the directory `to`, construct a self-contained bundle of libraries
159 | based on `system-names`. For each system named, and its recursive
160 | required systems, unpack its release archive in TO/software/, and
161 | write a system index, compatible with the output of
162 | QL:[write-asdf-manifest-file](#write-asdf-manifest-file), to TO/system-index.txt. Write a loader
163 | script to TO/bundle.lisp that, when loaded via CL:LOAD, configures
164 | ASDF to load systems from the bundle before any other system.
165 |
166 | `system-names` must name systems provided directly by Quicklisp.
167 |
168 | If `include-local-projects` is true, each directory in
169 | QL:*LOCAL-PROJECT-DIRECTORIES* is copied into the bundle and loaded
170 | before any of the other bundled systems.
171 |
172 | ### client-url
173 |
174 | ```lisp
175 | Function: (client-url)
176 | ```
177 |
178 | Return an URL suitable for passing as the :URL argument to
179 | [install-client](#install-client) for the current local client installation.
180 |
181 | ### client-version
182 |
183 | ```lisp
184 | Function: (client-version)
185 | ```
186 |
187 | Return the version for the current local client installation. May
188 | or may not be suitable for passing as the :VERSION argument to
189 | [install-client](#install-client), depending on if it's a standard Quicklisp-provided
190 | client.
191 |
192 | ### config-value
193 |
194 | ```lisp
195 | Function: (config-value path)
196 | ```
197 |
198 |
199 |
200 | ### dist-url
201 |
202 | ```lisp
203 | Function: (dist-url name)
204 | ```
205 |
206 |
207 |
208 | ### dist-version
209 |
210 | ```lisp
211 | Function: (dist-version name)
212 | ```
213 |
214 |
215 |
216 | ### help
217 |
218 | ```lisp
219 | Function: (help)
220 | ```
221 |
222 |
223 |
224 | ### install-client
225 |
226 | ```lisp
227 | Function: (install-client &key url version)
228 | ```
229 |
230 |
231 |
232 | ### list-local-projects
233 |
234 | ```lisp
235 | Function: (list-local-projects)
236 | ```
237 |
238 | Return a list of pathnames to local project system files.
239 |
240 | ### list-local-systems
241 |
242 | ```lisp
243 | Function: (list-local-systems)
244 | ```
245 |
246 | Return a list of local project system names.
247 |
248 | ### local-projects-searcher
249 |
250 | ```lisp
251 | Function: (local-projects-searcher system-name)
252 | ```
253 |
254 | This function is added to ASDF:*SYSTEM-DEFINITION-SEARCH-FUNCTIONS*
255 | to use the local project directory and cache to find systems.
256 |
257 | ### provided-systems
258 |
259 | ```lisp
260 | Generic Function: (provided-systems object)
261 | ```
262 |
263 | Return a list of systems provided by `object`.
264 |
265 | ### qmerge
266 |
267 | ```lisp
268 | Function: (qmerge pathname)
269 | ```
270 |
271 | Return `pathname` merged with the base Quicklisp directory.
272 |
273 | ### quickload
274 |
275 | ```lisp
276 | Generic Function: (quickload systems &key verbose silent prompt explain
277 | &allow-other-keys)
278 | ```
279 |
280 | Load `systems` the quicklisp way. `systems` is a designator for a list
281 | of things to be loaded.
282 |
283 | ### register-local-projects
284 |
285 | ```lisp
286 | Function: (register-local-projects)
287 | ```
288 |
289 | Force a scan of the local projects directory to create the system
290 | file index.
291 |
292 | ### setup
293 |
294 | ```lisp
295 | Function: (setup)
296 | ```
297 |
298 |
299 |
300 | ### system-apropos
301 |
302 | ```lisp
303 | Generic Function: (system-apropos term)
304 | ```
305 |
306 |
307 |
308 | ### system-apropos-list
309 |
310 | ```lisp
311 | Generic Function: (system-apropos-list term)
312 | ```
313 |
314 |
315 |
316 | ### system-list
317 |
318 | ```lisp
319 | Function: (system-list)
320 | ```
321 |
322 |
323 |
324 | ### system-not-found
325 |
326 | ```lisp
327 | Condition
328 | ```
329 |
330 | This condition is signaled by QUICKLOAD when a
331 | system given to load is not available via ASDF or a Quicklisp
332 | dist.
333 |
334 | **Direct Slots**
335 |
336 | **ql-dist:name**
337 | ```lisp
338 | Initargs: :NAME
339 | Readers: SYSTEM-NOT-FOUND-NAME
340 | ```
341 |
342 | ### system-not-found-name
343 |
344 | ```lisp
345 | Generic Function: (system-not-found-name condition)
346 | ```
347 |
348 |
349 |
350 | ### uninstall
351 |
352 | ```lisp
353 | Function: (uninstall system-name)
354 | ```
355 |
356 |
357 |
358 | ### uninstall-dist
359 |
360 | ```lisp
361 | Function: (uninstall-dist name)
362 | ```
363 |
364 |
365 |
366 | ### update-all-dists
367 |
368 | ```lisp
369 | Function: (update-all-dists &key (prompt t))
370 | ```
371 |
372 |
373 |
374 | ### update-client
375 |
376 | ```lisp
377 | Function: (update-client &key (prompt t))
378 | ```
379 |
380 |
381 |
382 | ### update-dist
383 |
384 | ```lisp
385 | Function: (update-dist dist &key (prompt t))
386 | ```
387 |
388 |
389 |
390 | ### use-only-quicklisp-systems
391 |
392 | ```lisp
393 | Function: (use-only-quicklisp-systems)
394 | ```
395 |
396 |
397 |
398 | ### where-is-system
399 |
400 | ```lisp
401 | Function: (where-is-system name)
402 | ```
403 |
404 | Return the pathname to the source directory of ASDF system with the
405 | given `name`, or NIL if no system by that name can be found known.
406 |
407 | ### who-depends-on
408 |
409 | ```lisp
410 | Function: (who-depends-on system-name)
411 | ```
412 |
413 | Return a list of names of systems that depend on `system-name`.
414 |
415 | ### write-asdf-manifest-file
416 |
417 | ```lisp
418 | Function: (write-asdf-manifest-file output-file &key
419 | (if-exists :rename-and-delete) exclude-local-projects)
420 | ```
421 |
422 | Write a list of system file pathnames to `output-file`, one per line,
423 | in order of descending QL-DIST:PREFERENCE.
424 |
425 |
426 | ## ql-dist: API Reference
427 |
428 | Generic functions, variables, and classes for interacting with the
429 | dist system. Documented, exported symbols are intended for public
430 | use.
431 |
432 |
433 | ### \*dist-enumeration-functions\*
434 |
435 | ```lisp
436 | Variable
437 | ```
438 |
439 | [all-dists](#all-dists) calls each function in this list with no arguments, and
440 | appends the results into a list of dist objects, removing
441 | duplicates. Functions might be called just once for a batch of
442 | related operations; see [with-consistent-dists](#with-consistent-dists).
443 |
444 |
445 | ### all-dists
446 |
447 | ```lisp
448 | Function: (all-dists)
449 | ```
450 |
451 | Return a list of all known dists.
452 |
453 | ### archive-content-sha1
454 |
455 | ```lisp
456 | Generic Function: (archive-content-sha1 object)
457 | ```
458 |
459 |
460 |
461 | ### archive-md5
462 |
463 | ```lisp
464 | Generic Function: (archive-md5 object)
465 | ```
466 |
467 |
468 |
469 | ### archive-size
470 |
471 | ```lisp
472 | Generic Function: (archive-size object)
473 | ```
474 |
475 |
476 |
477 | ### archive-url
478 |
479 | ```lisp
480 | Generic Function: (archive-url release)
481 | ```
482 |
483 | Return the full URL for fetching the archive file of `release`.
484 |
485 | ### available-update
486 |
487 | ```lisp
488 | Generic Function: (available-update dist)
489 | ```
490 |
491 | If an update is available for `dist`, return the
492 | update as an uninstalled dist object. Otherwise, return NIL.
493 |
494 | ### available-versions
495 |
496 | ```lisp
497 | Generic Function: (available-versions object)
498 | ```
499 |
500 | Return a list of version information for `object`.
501 |
502 | ### available-versions-url
503 |
504 | ```lisp
505 | Generic Function: (available-versions-url object)
506 | ```
507 |
508 | Return the URL for the available versions data file of `object`.
509 |
510 | ### badly-sized-local-archive
511 |
512 | ```lisp
513 | Condition
514 | ```
515 |
516 |
517 | ### base-directory
518 |
519 | ```lisp
520 | Generic Function: (base-directory object)
521 | ```
522 |
523 | Return the base directory pathname of `object`.
524 |
525 | ### canonical-distinfo-url
526 |
527 | ```lisp
528 | Generic Function: (canonical-distinfo-url object)
529 | ```
530 |
531 |
532 |
533 | ### check-local-archive-file
534 |
535 | ```lisp
536 | Generic Function: (check-local-archive-file release)
537 | ```
538 |
539 | Check the local archive file of `release` for validity, including
540 | size and signature checks. Signals errors in the case of invalid files.
541 |
542 | ### clean
543 |
544 | ```lisp
545 | Generic Function: (clean object)
546 | ```
547 |
548 | Remove any unneeded files or directories related to
549 | `object`.
550 |
551 | ### dependency-tree
552 |
553 | ```lisp
554 | Generic Function: (dependency-tree system)
555 | ```
556 |
557 |
558 |
559 | ### disable
560 |
561 | ```lisp
562 | Generic Function: (disable object)
563 | ```
564 |
565 | Disable `object`.
566 |
567 | ### dist
568 |
569 | ```lisp
570 | Generic Function: (dist object)
571 | ```
572 |
573 | Return the dist of `object`.
574 |
575 | ```lisp
576 | Class
577 | ```
578 |
579 | **Direct Slots**
580 |
581 | **base-directory**
582 | ```lisp
583 | Initargs: :BASE-DIRECTORY
584 | Readers: BASE-DIRECTORY
585 | Writers: (SETF BASE-DIRECTORY)
586 | ```
587 | **name**
588 | ```lisp
589 | Initargs: :NAME
590 | Readers: NAME
591 | Writers: (SETF NAME)
592 | ```
593 | **version**
594 | ```lisp
595 | Initargs: :VERSION
596 | Readers: VERSION
597 | Writers: (SETF VERSION)
598 | ```
599 | **system-index-url**
600 | ```lisp
601 | Initargs: :SYSTEM-INDEX-URL
602 | Readers: SYSTEM-INDEX-URL
603 | Writers: (SETF SYSTEM-INDEX-URL)
604 | ```
605 | **release-index-url**
606 | ```lisp
607 | Initargs: :RELEASE-INDEX-URL
608 | Readers: RELEASE-INDEX-URL
609 | Writers: (SETF RELEASE-INDEX-URL)
610 | ```
611 | **available-versions-url**
612 | ```lisp
613 | Initargs: :AVAILABLE-VERSIONS-URL
614 | Readers: AVAILABLE-VERSIONS-URL
615 | Writers: (SETF AVAILABLE-VERSIONS-URL)
616 | ```
617 | **canonical-distinfo-url**
618 | ```lisp
619 | Initargs: :CANONICAL-DISTINFO-URL
620 | Readers: CANONICAL-DISTINFO-URL
621 | Writers: (SETF CANONICAL-DISTINFO-URL)
622 | ```
623 | **provided-systems**
624 | ```lisp
625 | Initargs: :PROVIDED-SYSTEMS
626 | Readers: PROVIDED-SYSTEMS
627 | Writers: (SETF PROVIDED-SYSTEMS)
628 | ```
629 | **provided-releases**
630 | ```lisp
631 | Initargs: :PROVIDED-RELEASES
632 | Readers: PROVIDED-RELEASES
633 | Writers: (SETF PROVIDED-RELEASES)
634 | ```
635 |
636 | ### enable
637 |
638 | ```lisp
639 | Generic Function: (enable object)
640 | ```
641 |
642 | Enable `object`.
643 |
644 | ### enabled-dists
645 |
646 | ```lisp
647 | Function: (enabled-dists)
648 | ```
649 |
650 | Return a list of all known dists for which [enabledp](#enabledp) returns true.
651 |
652 | ### enabledp
653 |
654 | ```lisp
655 | Generic Function: (enabledp object)
656 | ```
657 |
658 | Return true if `object` is enabled.
659 |
660 | ### ensure-installed
661 |
662 | ```lisp
663 | Generic Function: (ensure-installed object)
664 | ```
665 |
666 | Ensure that `object` is installed.
667 |
668 | ### ensure-local-archive-file
669 |
670 | ```lisp
671 | Generic Function: (ensure-local-archive-file release)
672 | ```
673 |
674 | If the archive file for `release` is not available locally, fetch it
675 | and return the pathname to it.
676 |
677 | ### find-asdf-system-file
678 |
679 | ```lisp
680 | Function: (find-asdf-system-file name)
681 | ```
682 |
683 | Return the ASDF system file in which the system named `name` is defined.
684 |
685 | ### find-dist
686 |
687 | ```lisp
688 | Function: (find-dist name)
689 | ```
690 |
691 |
692 |
693 | ### find-dist-or-lose
694 |
695 | ```lisp
696 | Function: (find-dist-or-lose name)
697 | ```
698 |
699 |
700 |
701 | ### find-release
702 |
703 | ```lisp
704 | Generic Function: (find-release name)
705 | ```
706 |
707 | Return a release with the given `name`, or NIL if no system is
708 | found. If multiple releases have the same name, the one with the
709 | highest preference is returned.
710 |
711 | ### find-release-in-dist
712 |
713 | ```lisp
714 | Generic Function: (find-release-in-dist release-name dist)
715 | ```
716 |
717 | Return a release with the given [name](#name) in `dist`, or NIL if no release
718 | is found.
719 |
720 | ### find-system
721 |
722 | ```lisp
723 | Generic Function: (find-system name)
724 | ```
725 |
726 | Return a system with the given `name`, or NIL if no system is
727 | found. If multiple systems have the same name, the one with the
728 | highest preference is returned.
729 |
730 | ### find-system-in-dist
731 |
732 | ```lisp
733 | Generic Function: (find-system-in-dist system-name dist)
734 | ```
735 |
736 | Return a system with the given [name](#name) in `dist`, or NIL if no system
737 | is found.
738 |
739 | ### forget-preference
740 |
741 | ```lisp
742 | Generic Function: (forget-preference object)
743 | ```
744 |
745 | Remove specific preference information for `object`.
746 |
747 | ### inhibit-subscription
748 |
749 | ```lisp
750 | Generic Function: (inhibit-subscription object)
751 | ```
752 |
753 | Inhibit subscription for `object`.
754 |
755 | ### initialize-release-index
756 |
757 | ```lisp
758 | Generic Function: (initialize-release-index dist)
759 | ```
760 |
761 | Initialize the release index of `dist`.
762 |
763 | ### initialize-system-index
764 |
765 | ```lisp
766 | Generic Function: (initialize-system-index dist)
767 | ```
768 |
769 | Initialize the system index of `dist`.
770 |
771 | ### install
772 |
773 | ```lisp
774 | Generic Function: (install object)
775 | ```
776 |
777 | Install `object`.
778 |
779 | ### install-dist
780 |
781 | ```lisp
782 | Function: (install-dist url &key (prompt t) replace)
783 | ```
784 |
785 |
786 |
787 | ### install-metadata-file
788 |
789 | ```lisp
790 | Generic Function: (install-metadata-file object)
791 | ```
792 |
793 | The pathname to a file describing the installation status of
794 | `object`.
795 |
796 | ### installed-releases
797 |
798 | ```lisp
799 | Generic Function: (installed-releases dist)
800 | ```
801 |
802 | Return a list of all releases installed for `dist`.
803 |
804 | ### installed-systems
805 |
806 | ```lisp
807 | Generic Function: (installed-systems dist)
808 | ```
809 |
810 | Return a list of all systems installed for `dist`.
811 |
812 | ### installedp
813 |
814 | ```lisp
815 | Generic Function: (installedp object)
816 | ```
817 |
818 | Return true if `object` is installed.
819 |
820 | ### invalid-local-archive
821 |
822 | ```lisp
823 | Condition
824 | ```
825 |
826 | **Direct Slots**
827 |
828 | **release**
829 | ```lisp
830 | Initargs: :RELEASE
831 | Readers: INVALID-LOCAL-ARCHIVE-RELEASE
832 | ```
833 |
834 | ### invalid-local-archive-file
835 |
836 | ```lisp
837 | Generic Function: (invalid-local-archive-file condition)
838 | ```
839 |
840 |
841 |
842 | ### invalid-local-archive-release
843 |
844 | ```lisp
845 | Generic Function: (invalid-local-archive-release condition)
846 | ```
847 |
848 |
849 |
850 | ### local-archive-file
851 |
852 | ```lisp
853 | Generic Function: (local-archive-file release)
854 | ```
855 |
856 | Return the pathname to where the archive file of `release` should be
857 | stored.
858 |
859 | ### metadata-name
860 |
861 | ```lisp
862 | Generic Function: (metadata-name object)
863 | ```
864 |
865 | The metadata-name of an object is used to form the pathname for a
866 | few different object metadata files.
867 |
868 | ### missing-local-archive
869 |
870 | ```lisp
871 | Condition
872 | ```
873 |
874 |
875 | ### name
876 |
877 | ```lisp
878 | Generic Function: (name object)
879 | ```
880 |
881 | Return the name of `object`.
882 |
883 | ### new-version-available-p
884 |
885 | ```lisp
886 | Generic Function: (new-version-available-p dist)
887 | ```
888 |
889 | Return true if a new version of `dist` is available.
890 |
891 | ### preference
892 |
893 | ```lisp
894 | Generic Function: (preference object)
895 | ```
896 |
897 | Returns a value used when comparing multiple systems or releases
898 | with the same name. Objects with higher preference are returned by
899 | [find-system](#find-system) and [find-release](#find-release).
900 |
901 | ### preference-file
902 |
903 | ```lisp
904 | Generic Function: (preference-file object)
905 | ```
906 |
907 | Return the file from which preference information is loaded for
908 | `object`.
909 |
910 | ### preference-parent
911 |
912 | ```lisp
913 | Generic Function: (preference-parent object)
914 | ```
915 |
916 | Return a value suitable for checking if `object` has no specific
917 | preference set.
918 |
919 | ### prefix
920 |
921 | ```lisp
922 | Generic Function: (prefix object)
923 | ```
924 |
925 |
926 |
927 | ### project-name
928 |
929 | ```lisp
930 | Generic Function: (project-name object)
931 | ```
932 |
933 |
934 |
935 | ### provided-releases
936 |
937 | ```lisp
938 | Generic Function: (provided-releases object)
939 | ```
940 |
941 | Return a list of releases provided by `object`.
942 |
943 | ### provided-systems
944 |
945 | ```lisp
946 | Generic Function: (provided-systems object)
947 | ```
948 |
949 | Return a list of systems provided by `object`.
950 |
951 | ### relative-to
952 |
953 | ```lisp
954 | Generic Function: (relative-to object pathname)
955 | ```
956 |
957 | Merge `pathname` with the base-directory of `object`.
958 |
959 | ### release
960 |
961 | ```lisp
962 | Generic Function: (release object)
963 | ```
964 |
965 | Return the release of `object`.
966 |
967 | ```lisp
968 | Class
969 | ```
970 |
971 | Instances of this class represent a snapshot of a project at some
972 | point in time, which might be from version control, or from an
973 | official release, or from some other source.
974 |
975 | **Direct Slots**
976 |
977 | **project-name**
978 | ```lisp
979 | Initargs: :PROJECT-NAME
980 | ```
981 | **dist**
982 | ```lisp
983 | Initargs: :DIST
984 | ```
985 | **provided-systems**
986 | ```lisp
987 | Initargs: :PROVIDED-SYSTEMS
988 | Readers: PROVIDED-SYSTEMS
989 | Writers: (SETF PROVIDED-SYSTEMS)
990 | ```
991 | **archive-url**
992 | ```lisp
993 | Initargs: :ARCHIVE-URL
994 | Readers: ARCHIVE-URL
995 | Writers: (SETF ARCHIVE-URL)
996 | ```
997 | **archive-size**
998 | ```lisp
999 | Initargs: :ARCHIVE-SIZE
1000 | Readers: ARCHIVE-SIZE
1001 | Writers: (SETF ARCHIVE-SIZE)
1002 | ```
1003 | **archive-md5**
1004 | ```lisp
1005 | Initargs: :ARCHIVE-MD5
1006 | Readers: ARCHIVE-MD5
1007 | Writers: (SETF ARCHIVE-MD5)
1008 | ```
1009 | **archive-content-sha1**
1010 | ```lisp
1011 | Initargs: :ARCHIVE-CONTENT-SHA1
1012 | Readers: ARCHIVE-CONTENT-SHA1
1013 | Writers: (SETF ARCHIVE-CONTENT-SHA1)
1014 | ```
1015 | **prefix**
1016 | ```lisp
1017 | Initargs: :PREFIX
1018 | ```
1019 | **system-files**
1020 | ```lisp
1021 | Initargs: :SYSTEM-FILES
1022 | Readers: SYSTEM-FILES
1023 | Writers: (SETF SYSTEM-FILES)
1024 | ```
1025 | **metadata-name**
1026 | ```lisp
1027 | Initargs: :METADATA-NAME
1028 | Readers: METADATA-NAME
1029 | Writers: (SETF METADATA-NAME)
1030 | ```
1031 |
1032 | ### release-index-url
1033 |
1034 | ```lisp
1035 | Generic Function: (release-index-url object)
1036 | ```
1037 |
1038 | Return the URL for the release index of `object`.
1039 |
1040 | ### required-systems
1041 |
1042 | ```lisp
1043 | Generic Function: (required-systems object)
1044 | ```
1045 |
1046 |
1047 |
1048 | ### short-description
1049 |
1050 | ```lisp
1051 | Generic Function: (short-description object)
1052 | ```
1053 |
1054 | Return a short string describing `object`.
1055 |
1056 | ### show-update-report
1057 |
1058 | ```lisp
1059 | Generic Function: (show-update-report old-dist new-dist)
1060 | ```
1061 |
1062 | Display a description of the update from `old-dist`
1063 | to `new-dist`.
1064 |
1065 | ### standard-dist-enumeration-function
1066 |
1067 | ```lisp
1068 | Function: (standard-dist-enumeration-function)
1069 | ```
1070 |
1071 | The default function used for producing a list of dist objects.
1072 |
1073 | ### subscribe
1074 |
1075 | ```lisp
1076 | Generic Function: (subscribe object)
1077 | ```
1078 |
1079 | Subscribe to updates of `object`, if possible. If no
1080 | updates are available, a condition of type [subscription-unavailable](#subscription-unavailable)
1081 | is raised.
1082 |
1083 | ### subscribedp
1084 |
1085 | ```lisp
1086 | Generic Function: (subscribedp object)
1087 | ```
1088 |
1089 | Return true if `object` is subscribed to updates.
1090 |
1091 | ### subscription-inhibited-p
1092 |
1093 | ```lisp
1094 | Generic Function: (subscription-inhibited-p object)
1095 | ```
1096 |
1097 | Return T if subscription to `object` is inhibited.
1098 |
1099 | ### subscription-inhibition-file
1100 |
1101 | ```lisp
1102 | Generic Function: (subscription-inhibition-file object)
1103 | ```
1104 |
1105 | The file whose presence indicates the inhibited
1106 | subscription status of `object`.
1107 |
1108 | ### subscription-unavailable
1109 |
1110 | ```lisp
1111 | Condition
1112 | ```
1113 |
1114 |
1115 | ### subscription-url
1116 |
1117 | ```lisp
1118 | Generic Function: (subscription-url object)
1119 | ```
1120 |
1121 |
1122 |
1123 | ### system
1124 |
1125 | ```lisp
1126 | Generic Function: (system object)
1127 | ```
1128 |
1129 | Return the system of `object`.
1130 |
1131 | ```lisp
1132 | Class
1133 | ```
1134 |
1135 | **Direct Slots**
1136 |
1137 | **name**
1138 | ```lisp
1139 | Initargs: :NAME
1140 | ```
1141 | **system-file-name**
1142 | ```lisp
1143 | Initargs: :SYSTEM-FILE-NAME
1144 | Readers: SYSTEM-FILE-NAME
1145 | Writers: (SETF SYSTEM-FILE-NAME)
1146 | ```
1147 | **release**
1148 | ```lisp
1149 | Initargs: :RELEASE
1150 | ```
1151 | **dist**
1152 | ```lisp
1153 | Initargs: :DIST
1154 | Readers: DIST
1155 | Writers: (SETF DIST)
1156 | ```
1157 | **required-systems**
1158 | ```lisp
1159 | Initargs: :REQUIRED-SYSTEMS
1160 | Readers: REQUIRED-SYSTEMS
1161 | Writers: (SETF REQUIRED-SYSTEMS)
1162 | ```
1163 | **metadata-name**
1164 | ```lisp
1165 | Initargs: :METADATA-NAME
1166 | Readers: METADATA-NAME
1167 | Writers: (SETF METADATA-NAME)
1168 | ```
1169 |
1170 | ### system-apropos
1171 |
1172 | ```lisp
1173 | Generic Function: (system-apropos term)
1174 | ```
1175 |
1176 |
1177 |
1178 | ### system-apropos-list
1179 |
1180 | ```lisp
1181 | Generic Function: (system-apropos-list term)
1182 | ```
1183 |
1184 |
1185 |
1186 | ### system-definition-searcher
1187 |
1188 | ```lisp
1189 | Function: (system-definition-searcher name)
1190 | ```
1191 |
1192 | Like [find-asdf-system-file](#find-asdf-system-file), but this function can be used in
1193 | ASDF:*SYSTEM-DEFINITION-SEARCH-FUNCTIONS*; it will only return system
1194 | file names if they match `name`.
1195 |
1196 | ### system-file-name
1197 |
1198 | ```lisp
1199 | Generic Function: (system-file-name object)
1200 | ```
1201 |
1202 |
1203 |
1204 | ### system-files
1205 |
1206 | ```lisp
1207 | Generic Function: (system-files object)
1208 | ```
1209 |
1210 |
1211 |
1212 | ### system-index-url
1213 |
1214 | ```lisp
1215 | Generic Function: (system-index-url object)
1216 | ```
1217 |
1218 | Return the URL for the system index of `object`.
1219 |
1220 | ### uninhibit-subscription
1221 |
1222 | ```lisp
1223 | Generic Function: (uninhibit-subscription object)
1224 | ```
1225 |
1226 | Remove inhibition of subscription for `object`.
1227 |
1228 | ### uninstall
1229 |
1230 | ```lisp
1231 | Generic Function: (uninstall object)
1232 | ```
1233 |
1234 | Uninstall `object`.
1235 |
1236 | ### unknown-dist
1237 |
1238 | ```lisp
1239 | Condition
1240 | ```
1241 |
1242 | **Direct Slots**
1243 |
1244 | **name**
1245 | ```lisp
1246 | Initargs: :NAME
1247 | Readers: :UNKNOWN-DIST-NAME
1248 | ```
1249 |
1250 | ### unsubscribe
1251 |
1252 | ```lisp
1253 | Generic Function: (unsubscribe object)
1254 | ```
1255 |
1256 | Unsubscribe from updates to `object`.
1257 |
1258 | ### update-in-place
1259 |
1260 | ```lisp
1261 | Generic Function: (update-in-place old-dist new-dist)
1262 | ```
1263 |
1264 | Update `old-dist` to `new-dist` in place.
1265 |
1266 | ### update-release-differences
1267 |
1268 | ```lisp
1269 | Generic Function: (update-release-differences old-dist new-dist)
1270 | ```
1271 |
1272 | Compare `old-dist` to `new-dist` and return three lists
1273 | as multiple values: new releases (present in `new-dist` but not
1274 | `old-dist`), changed releases (present in both dists but different in
1275 | some way), and removed releases (present in `old-dist` but not
1276 | `new-dist`). The list of changed releases is a list of two-element
1277 | lists, with each two-element list having first the old release
1278 | object and then the new release object.
1279 |
1280 | ### version
1281 |
1282 | ```lisp
1283 | Generic Function: (version object)
1284 | ```
1285 |
1286 |
1287 |
1288 | ### with-consistent-dists
1289 |
1290 | ```lisp
1291 | Macro: (with-consistent-dists &body body)
1292 | ```
1293 |
1294 | See CALL-WITH-CONSISTENT-DISTS.
1295 |
--------------------------------------------------------------------------------
/docs/unix-opts.md:
--------------------------------------------------------------------------------
1 | # unix-opts - cmd line argument parser
2 |
3 | Version: 0.1.7
4 |
5 | Licence: MIT
6 |
7 | Nickname: opts
8 |
9 | Repository: [libre-man/unix-opts](https://github.com/libre-man/unix-opts)
10 |
11 | See also: [awesome-cl#command-line-options-parsers](https://github.com/CodyReichert/awesome-cl#command-line-options-parsers)
12 |
13 | *This documentation was possible due to the excellent [official documentation and
14 | example](https://github.com/libre-man/unix-opts).*
15 |
16 | *In case of any inaccuracies, ambiguities or suggestions, please [create an issue here](https://github.com/digikar99/common-lisp.readthedocs/issues).*
17 |
18 | ***
19 |
20 | ## GETTING STARTED
21 |
22 | Consider the following command line options defined using [define-opts](#define-opts):
23 |
24 | ```lisp
25 | (opts:define-opts
26 | (:name :help
27 | :description "print this help text"
28 | :short #\h
29 | :long "help")
30 | (:name :verbose
31 | :description "verbose output"
32 | :short #\v
33 | :long "verbose")
34 | (:name :level
35 | :description "the program will run on LEVEL level"
36 | :short #\l
37 | :long "level"
38 | :required t
39 | :arg-parser #'parse-integer ; <- takes an argument, which we want to parse into integer
40 | :meta-var "LEVEL")
41 | (:name :output
42 | :description "redirect output to file FILE"
43 | :short #\o
44 | :long "output"
45 | :arg-parser #'identity ; <- takes an argument, but we keep it as the string
46 | :meta-var "FILE"))
47 | ```
48 |
49 | [describe](#describe) gets us the required "help text" (see the documentation for other
50 | options):
51 |
52 | ```lisp
53 | CL-USER> (opts:describe :prefix "Demonstrating REPL")
54 | Demonstrating REPL
55 |
56 | Available options:
57 | -h, --help print this help text
58 | -v, --verbose verbose output
59 | -l, --level LEVEL (Required) the program will run on LEVEL level
60 | -o, --output FILE redirect output to file FILE
61 | NIL
62 | ```
63 |
64 | Command line arguments can be processed with a call to [get-opts](#get-opts).
65 | For demonstration purposes, we use the REPL. See [this example
66 | directory](https://github.com/libre-man/unix-opts/tree/master/example)
67 | to see how this might be done in a script.
68 |
69 | ```lisp
70 | CL-USER> (opts:get-opts '())
71 | ; Evaluation aborted on #.
72 | CL-USER> (opts:get-opts '("--level" "2"))
73 | (:LEVEL 2)
74 | NIL
75 | CL-USER> (opts:get-opts '("--level" "2" "--help"))
76 | (:LEVEL 2 :HELP T)
77 | NIL
78 | ```
79 |
80 | `get-opts` can throw several conditions:
81 |
82 | - [unknown-option](#unknown-option)
83 | - [missing-arg](#missing-arg)
84 | - [arg-parser-failed](#arg-parser-failed)
85 | - [missing-required-option](#missing-required-option)
86 |
87 | Each of these has several restarts:
88 |
89 | - [use-value](#use-value)
90 | - [skip-option](#skip-option)
91 | - [reparse-arg](#reparse-arg)
92 |
93 | (See the documentation for [get-opts](#get-opts) for the details about each of these restarts.
94 | The Cookbook chapter on [Error and Exception
95 | Handling](https://lispcookbook.github.io/cl-cookbook/error_handling.html) should be helpful
96 | if you want to learn about them.)
97 |
98 | Thus, a typical way to use `get-opts` would be simply wrap the error in [handler-case]():
99 |
100 | ```lisp
101 | CL-USER> (handler-case (opts:get-opts '())
102 | (error (condition)
103 | (format t "~A" condition)
104 | (opts:describe)))
105 | missing required options: "--level"
106 | Available options:
107 | -h, --help print this help text
108 | -v, --verbose verbose output
109 | -l, --level LEVEL (Required) the program will run on LEVEL level
110 | -o, --output FILE redirect output to file FILE
111 |
112 | NIL
113 | ```
114 |
115 | You could use [getf](http://www.lispworks.com/documentation/lw50/CLHS/Body/f_getf.htm#getf)
116 | or [destructuring-bind](http://www.lispworks.com/documentation/HyperSpec/Body/m_destru.htm#destructuring-bind)
117 | to obtain the arguments you need:
118 |
119 | ```lisp
120 | CL-USER> (defun process-options (&rest options)
121 | (handler-case (opts:get-opts options)
122 | (error (condition) ; or you could case down on the various conditions above!
123 | (format t "~A" condition)
124 | (opts:describe))))
125 | PROCESS-OPTIONS
126 | CL-USER> (destructuring-bind (&key level help) (process-options "--level" "2" "--help")
127 | (if help
128 | (opts:describe)
129 | (format t "I see you've supplied level option, you want ~a level!~%" level)))
130 |
131 | Available options:
132 | -h, --help print this help text
133 | -v, --verbose verbose output
134 | -l, --level LEVEL (Required) the program will run on LEVEL level
135 | -o, --output FILE redirect output to file FILE
136 |
137 | NIL
138 | CL-USER> (destructuring-bind (&key level help) (process-options "--level" "2")
139 | (if help
140 | (opts:describe)
141 | (format t "I see you've supplied level option, you want ~a level!~%" level)))
142 | I see you've supplied level option, you want 2 level!
143 | NIL
144 | ```
145 |
146 | You could also [iterate:dsetq](../iterate/#dsetq) to bring the options to global space.
147 |
148 | ```lisp
149 | CL-USER> (destructuring-bind (&key verbose level help)
150 | (process-options "--level" "2" "--verbose")
151 | (if help
152 | (opts:describe) ; assume we have defined *level* and *verbose* previously
153 | (dsetq (*verbose* *level*) (list verbose level))))
154 | (T 2)
155 | CL-USER> *verbose*
156 | T
157 | CL-USER> *level*
158 | 2
159 | ```
160 |
161 | ## API REFERENCE
162 |
163 | ### arg-parser-failed
164 |
165 |
166 | ```lisp
167 | Condition
168 | ```
169 |
170 | This condition is thrown when some option OPTION wants
171 | an argument, it's given but cannot be parsed by argument parser.
172 |
173 | **Direct Slots**
174 |
175 | **raw-arg**
176 | ```lisp
177 | Initargs: :RAW-ARG
178 | Readers: RAW-ARG
179 | ```
180 | ### argv
181 |
182 | ```lisp
183 | Function: (argv)
184 | ```
185 | Return a list of program's arguments, including command used to execute
186 | the program as first elements of the list. Portable across implementations.
187 |
188 | ### define-opts
189 |
190 | ```lisp
191 | Macro: (define-opts &body descriptions)
192 | ```
193 | Define command line options. Arguments of this macro must be plists
194 | containing various parameters. Here we enumerate all allowed parameters:
195 |
196 | - **:name** - keyword that will be included in list returned by [get-opts](#get-opts) function if
197 | actual option is supplied by user.
198 |
199 | - **:description** - description of the option (it will be used in [describe](#describe)
200 | function). This argument is optional, but it's recommended to supply it.
201 |
202 | - **:short** - single character, short variant of the option. You may omit this
203 | argument if you supply `:long` variant of option.
204 |
205 | - **:long** - string, long variant of option. You may omit this argument if you
206 | supply `:short` variant of option.
207 |
208 | - **:arg-parser** - if actual option must take an argument, supply this argument, it
209 | must be a function that takes a string and parses it.
210 |
211 | - **:meta-var** - if actual option requires an argument, this is how it will be
212 | printed in option description.
213 |
214 | ### describe
215 |
216 | ```lisp
217 | Function: (describe &key prefix suffix usage-of args (stream *standard-output*))
218 | ```
219 | Return string describing options of the program that were defined with
220 | `define-opts` macro previously. You can supply `prefix` and `suffix` arguments
221 | that will be printed before and after options respectively. If `usage-of` is
222 | supplied, it should be a string, name of the program for "Usage: "
223 | section. This section is only printed if this name is given. If your program
224 | takes arguments (apart from options), you can specify how to print them in
225 | "Usage: " section with `args` option (should be a string designator). Output
226 | goes to `stream`.
227 |
228 | ### exit
229 |
230 | ```lisp
231 | Function: (exit &optional (status 0))
232 | ```
233 | Exit the program returning `status`.
234 |
235 | ### get-opts
236 |
237 | ```lisp
238 | Function: (get-opts &optional options)
239 | ```
240 | Parse command line options. If `options` is given, it should be a list to
241 | parse. If it's not given, the function will use `argv` function to get list
242 | of command line arguments.
243 |
244 | Return two values:
245 |
246 | * a list that contains keywords associated with command line options with
247 | `define-opts` macro, and
248 | * a list of free arguments.
249 |
250 | If some option requires an argument, you can use `getf` to
251 | test presence of the option and get its argument if the option is present.
252 |
253 | The parser may signal various conditions. Let's list them all specifying
254 | which restarts are available for every condition, and what kind of
255 | information the programmer can extract from the conditions.
256 |
257 | - [unknown-option](#unknown-option) is thrown when parser encounters unknown (not previously
258 | defined with `define-opts`) option. Use the `option` reader to get name of
259 | the option (string). Available restarts:
260 | - [use-value](#use-value): substitute the option and try again,
261 | - [skip-option](#skip-option): ignore the option.
262 |
263 | - [missing-arg](#missing-arg) is thrown when some option wants an argument, but there is no
264 | such argument given. Use the `option` reader to get name of the
265 | option (string). Available restarts:
266 | - [use-value](#use-value): supplied value will be used,
267 | - [skip-option](#skip-option): ignore the option.
268 |
269 | - [arg-parser-failed](#arg-parser-failed) is thrown when some option wants an argument, it's given
270 | but cannot be parsed by argument parser. Use the `option` reader to get name
271 | of the option (string) and `raw-arg` to get raw string representing the
272 | argument before parsing. Available restarts:
273 | - [use-value](#use-value): supplied value will be used,
274 | - [skip-option](#skip-option): ignore the option,
275 | - [reparse-arg](#reparse-arg): supplied string will be parsed instead.
276 |
277 | - [missing-required-option](#missing-required-option) is thrown when some option was required but was
278 | not given. Use the `missing-options` reader to get the list of options that
279 | are missing. Available restarts:
280 | - [use-value](#use-value): supplied list of values will be used,
281 | - [skip-option](#skip-option): ignore all these options, effectively binding them
282 | to `nil`
283 |
284 | ### missing-arg
285 |
286 |
287 | ```lisp
288 | Condition
289 | ```
290 |
291 | This condition is thrown when some option OPTION wants
292 | an argument, but there is no such argument given.
293 |
294 | ### missing-options
295 |
296 | ```lisp
297 | Generic Function: (missing-options condition)
298 | ```
299 |
300 |
301 | ### missing-required-option
302 |
303 |
304 | ```lisp
305 | Condition
306 | ```
307 |
308 | This condition is thrown when required options are missing.
309 |
310 | **Direct Slots**
311 |
312 | **missing-options**
313 | ```lisp
314 | Initargs: :MISSING-OPTIONS
315 | Readers: MISSING-OPTIONS
316 | ```
317 | ### option
318 |
319 | ```lisp
320 | Generic Function: (option condition)
321 | ```
322 |
323 |
324 |
325 | ```lisp
326 | Class
327 | ```
328 |
329 | representation of an option
330 |
331 | ### raw-arg
332 |
333 | ```lisp
334 | Generic Function: (raw-arg condition)
335 | ```
336 |
337 |
338 | ### reparse-arg
339 |
340 | ### skip-option
341 |
342 | ### unknown-option
343 |
344 |
345 | ```lisp
346 | Condition
347 | ```
348 |
349 | This condition is thrown when parser encounters
350 | unknown (not previously defined with `define-opts`) option.
351 |
352 | ### use-value
353 |
354 | ```lisp
355 | Function: (use-value value &optional condition)
356 | ```
357 | Transfer control and `value` to a restart named USE-VALUE, or
358 | return NIL if none exists.
359 |
--------------------------------------------------------------------------------
/docs/utilities.md:
--------------------------------------------------------------------------------
1 | # utilities - A collection of utility libraries
2 |
3 | A collection of smallish utility libraries.
4 |
5 | *In case of any inaccuracies, ambiguities or suggestions, please [create an issue here](https://github.com/cl-library-docs/common-lisp-libraries/issues).*
6 |
7 | ***
8 |
9 |
10 |
11 | ## PARSE-NUMBER
12 |
13 | Version: 1.7
14 |
15 | Licence: BSD 3-Clause
16 |
17 | Repository: [sharplispers/parse-number - Github](https://github.com/sharplispers/parse-number)
18 |
19 | PARSE-NUMBER is a library of functions which accept an arbitrary
20 | string and attempt to parse it, if possible into one of the standard
21 | Common Lisp number types without using the reader, or else signal an
22 | error of type `invalid-number`.
23 |
24 | ### invalid-number
25 |
26 | ```lisp
27 | Condition
28 | ```
29 |
30 | ### invalid-number-reason
31 |
32 | ```lisp
33 | Generic Function: (invalid-number-reason condition)
34 | ```
35 |
36 | ### invalid-number-value
37 |
38 | ```lisp
39 | Generic Function: (invalid-number-value condition)
40 | ```
41 |
42 | ### parse-number
43 |
44 | ```lisp
45 | Function: (parse-number string &key (start 0) (end NIL) (radix 10)
46 | ((:float-format *read-default-float-format*)
47 | *read-default-float-format*))
48 | ```
49 |
50 | ### parse-positive-real-number
51 |
52 | ```lisp
53 | Function: (parse-positive-real-number string &key (start 0) (end NIL)
54 | (radix 10)
55 | ((float-format *read-default-float-format*)
56 | *read-default-float-format*))
57 | ```
58 |
59 | ### parse-real-number
60 |
61 | ```lisp
62 | Function: (parse-real-number string &key (start 0) (end NIL) (radix 10)
63 | ((float-format *read-default-float-format*)
64 | *read-default-float-format*))
65 | ```
66 |
67 | ## SPLIT-SEQUENCE
68 |
69 | Version: 2.0.0
70 |
71 | Licence: MIT
72 |
73 | Repository: [sharplispers/split-sequence](https://github.com/sharplispers/split-sequence)
74 |
75 | ### split-sequence
76 |
77 | ```lisp
78 | Function: (split-sequence delimiter sequence &key (start 0) (end NIL)
79 | (from-end NIL) (count NIL) (remove-empty-subseqs NIL)
80 | (test (function eql) test-p) (test-not NIL test-not-p)
81 | (key (function identity)))
82 | ```
83 |
84 | Return a list of subsequences in seq delimited by delimiter.
85 | If `:remove-empty-subseqs` is NIL, empty subsequences will be included
86 | in the result; otherwise they will be discarded. All other keywords
87 | work analogously to those for [cl:substitute](http://www.lispworks.com/documentation/HyperSpec/Body/f_sbs_s.htm). In particular, the
88 | behaviour of `:from-end` is possibly different from other versions of
89 | this function; `:from-end` values of NIL and T are equivalent unless
90 | `:count` is supplied. `:count` limits the number of subseqs in the main
91 | resulting list. The second return value is an index suitable as an
92 | argument to [cl:subseq](http://www.lispworks.com/documentation/HyperSpec/Body/f_subseq.htm) into the sequence indicating where processing
93 | stopped.
94 |
95 | ### split-sequence-if
96 |
97 | ```lisp
98 | Function: (split-sequence-if predicate sequence &key (start 0) (end NIL)
99 | (from-end NIL) (count NIL) (remove-empty-subseqs NIL)
100 | (key (function identity)))
101 | ```
102 |
103 | Return a list of subsequences in seq delimited by items satisfying
104 | predicate.
105 | If `:remove-empty-subseqs` is NIL, empty subsequences will be included
106 | in the result; otherwise they will be discarded. All other keywords
107 | work analogously to those for [cl:substitute-if](http://www.lispworks.com/documentation/HyperSpec/Body/f_sbs_s.htm). In particular, the
108 | behaviour of `:from-end` is possibly different from other versions of
109 | this function; `:from-end` values of NIL and T are equivalent unless
110 | `:count` is supplied. `:count` limits the number of subseqs in the main
111 | resulting list. The second return value is an index suitable as an
112 | argument to [cl:subseq](http://www.lispworks.com/documentation/HyperSpec/Body/f_subseq.htm) into the sequence indicating where processing
113 | stopped.
114 |
115 | ### split-sequence-if-not
116 |
117 | ```lisp
118 | Function: (split-sequence-if-not predicate sequence &key (start 0) (end NIL)
119 | (from-end NIL) (count NIL) (remove-empty-subseqs NIL)
120 | (key (function identity)))
121 | ```
122 |
123 | Return a list of subsequences in seq delimited by items satisfying
124 | ([cl:complement](http://www.lispworks.com/documentation/HyperSpec/Body/f_comple.htm) predicate).
125 | If `:remove-empty-subseqs` is NIL, empty subsequences will be included
126 | in the result; otherwise they will be discarded. All other keywords
127 | work analogously to those for [cl:substitute-if-not](http://www.lispworks.com/documentation/HyperSpec/Body/f_sbs_s.htm). In particular,
128 | the behaviour of `:from-end` is possibly different from other versions
129 | of this function; `:from-end` values of NIL and T are equivalent unless
130 | `:count` is supplied. `:count` limits the number of subseqs in the main
131 | resulting list. The second return value is an index suitable as an
132 | argument to [cl:subseq](http://www.lispworks.com/documentation/HyperSpec/Body/f_subseq.htm) into the sequence indicating where processing
133 | stopped.
134 |
135 | ## TRIVIAL-TYPES
136 |
137 | Version: 0.1
138 |
139 | Licence: LLGPL
140 |
141 | Repository: [m2ym/trivial-types - Github](https://github.com/m2ym/trivial-types)
142 |
143 |
144 | TODO: This repository is archived; quickdocs points to this; a [branch of a fork](https://github.com/christophejunke/trivial-types/tree/patch-1) is ahead of this.
145 |
146 | TRIVIAL-TYPES provides missing but important type
147 | definitions such as `proper-list`, `association-list`, `property-list` and
148 | `tuple`.
149 |
150 | By using these types, you can keep type declarations more
151 | accurate. For example, you may write a class definition like:
152 |
153 | ```lisp
154 | (defclass person ()
155 | ((name :type string))
156 | ((age :type fixnum))
157 | ((friends :type list)))
158 | ```
159 |
160 | However, it is not obvious for anyone except you that FRIENDS slot has
161 | only a list of person. If you want declare `friends` slot more
162 | accurately,` proper-list` is the best for that:
163 |
164 | ```lisp
165 | (defclass person ()
166 | ((name :type string))
167 | ((age :type fixnum))
168 | ((friends :type (proper-list person))))
169 | ```
170 |
171 | In addition, TRIVIAL-TYPES also provides standard designators defined
172 | in ANSI standard such as `package-designator`. They are useful when you
173 | write a function that takes a package-oid argument like:
174 |
175 | ```lisp
176 | (defun list-external-symbols (package)
177 | (declare (package-designator package))
178 | (loop for symbol being the external-symbol of package
179 | collect symbol))
180 | ```
181 |
182 | An exhaustive list of provided types includes:
183 |
184 | - [association-list](#association-list-p)
185 | - character-designator
186 | - [file-associated-stream](#file-associated-stream-p)
187 | - file-position-designator
188 | - function-designator
189 | - list-designator
190 | - non-nil
191 | - package-designator
192 | - pathname-designator
193 | - [proper-list](#proper-list-p)
194 | - [property-list](#property-list-p)
195 | - stream-designator
196 | - string-designator
197 |
198 | ### association-list-p
199 |
200 | ```lisp
201 | Function: (association-list-p var)
202 | ```
203 |
204 | Returns true if OBJECT is an association list.
205 |
206 | Examples:
207 |
208 | ```lisp
209 | (association-list-p 1) => NIL
210 | (association-list-p '(1 2 3)) => NIL
211 | (association-list-p nil) => T
212 | (association-list-p '((foo))) => T
213 | (association-list-p '((:a . 1) (:b . 2))) => T
214 | ```
215 |
216 | ### file-associated-stream-p
217 |
218 | ```lisp
219 | Function: (file-associated-stream-p stream)
220 | ```
221 |
222 | Returns true if `stream` is a stream associated to a file.
223 |
224 | ### proper-list-p
225 |
226 | ```lisp
227 | Function: (proper-list-p object)
228 | ```
229 |
230 | Returns true if `object` is a proper list.
231 |
232 | Examples:
233 |
234 | ```lisp
235 | (proper-list-p 1) => NIL
236 | (proper-list-p '(1 . 2)) => NIL
237 | (proper-list-p nil) => T
238 | (proper-list-p '(1 2 3)) => T
239 | ```
240 |
241 | ### property-list-p
242 |
243 | ```lisp
244 | Function: (property-list-p object)
245 | ```
246 |
247 | Returns true if `object` is a property list.
248 |
249 | Examples:
250 |
251 | ```lisp
252 | (property-list-p 1) => NIL
253 | (property-list-p '(1 2 3)) => NIL
254 | (property-list-p '(foo)) => NIL
255 | (property-list-p nil) => T
256 | (property-list-p '(foo 1)) => T
257 | (property-list-p '(:a 1 :b 2)) => T
258 | ```
259 |
260 | ### tuple
261 |
262 | ```lisp
263 | Function: (tuple &rest args)
264 | ```
265 |
266 | Exactly same as LIST.
267 |
268 | ### tuplep
269 |
270 | ```lisp
271 | Function: (tuplep object)
272 | ```
273 |
274 | Returns true if `object` is a tuple, meaning a proper list.
275 |
276 | Examples:
277 |
278 | ```lisp
279 | (tuplep 1) => NIL
280 | (tuplep '(1 . 2)) => NIL
281 | (tuplep nil) => T
282 | (tuplep '(1 2 3)) => T
283 | ```
284 |
285 | ### type-expand
286 |
287 | ```lisp
288 | Function: (type-expand type-specifier &optional env)
289 | ```
290 |
291 | Expand `type-specifier` in the lexical environment `env`.
292 |
293 | ### type-specifier-p
294 |
295 | ```lisp
296 | Function: (type-specifier-p type-specifier)
297 | ```
298 |
299 | Returns true if `type-specifier` is a valid type specfiier.
300 |
301 |
302 | ## TRIVIAL-PACKAGE-LOCAL-NICKNAMES
303 |
304 | Version: 0.2
305 |
306 | Licence: Public Domain
307 |
308 | Repository: [phoe/trivial-package-local-nicknames](https://github.com/phoe/trivial-package-local-nicknames)
309 |
310 | A portability layer for package local nicknames.
311 |
312 | ### add-package-local-nickname
313 |
314 | ```lisp
315 | Function: (add-package-local-nickname local-nickname actual-package &optional
316 | (package-designator (sane-package)))
317 | ```
318 |
319 | Adds `local-nickname` for `actual-package` in the designated package, defaulting
320 | to current package. `local-nickname` must be a string designator, and
321 | `actual-package` must be a package designator.
322 |
323 | Returns the designated package.
324 |
325 | Signals a continuable error if `local-nickname` is already a package local
326 | nickname for a different package, or if `local-nickname` is one of "CL",
327 | "COMMON-LISP", or, "KEYWORD", or if `local-nickname` is a global name or
328 | nickname for the package to which the nickname would be added.
329 |
330 | When in the designated package, calls to FIND-PACKAGE with the `local-nickname`
331 | will return the package the designated `actual-package` instead. This also
332 | affects all implied calls to FIND-PACKAGE, including those performed by the
333 | reader.
334 |
335 | When printing a package prefix for a symbol with a package local nickname,
336 | local nickname is used instead of the real name in order to preserve
337 | print-read consistency.
338 |
339 | See also: [package-local-nicknames](#package-local-nicknames), [package-locally-nicknamed-by-list](#package-locally-nicknamed-by-list),
340 | [remove-package-local-nickname](#remove-package-local-nickname), and the DEFPACKAGE option :LOCAL-NICKNAMES.
341 |
342 | Experimental: interface subject to change.
343 |
344 | ### package-local-nicknames
345 |
346 | ```lisp
347 | Function: (package-local-nicknames package-designator)
348 | ```
349 |
350 | Returns an alist of (local-nickname . actual-package) describing the
351 | nicknames local to the designated package.
352 |
353 | When in the designated package, calls to FIND-PACKAGE with the any of the
354 | local-nicknames will return the corresponding actual-package instead. This
355 | also affects all implied calls to FIND-PACKAGE, including those performed by
356 | the reader.
357 |
358 | When printing a package prefix for a symbol with a package local nickname, the
359 | local nickname is used instead of the real name in order to preserve
360 | print-read consistency.
361 |
362 | See also: [add-package-local-nickname](#add-package-local-nickname), [package-locally-nicknamed-by-list](#package-locally-nicknamed-by-list),
363 | [remove-package-local-nickname](#remove-package-local-nickname), and the DEFPACKAGE option :LOCAL-NICKNAMES.
364 |
365 | Experimental: interface subject to change.
366 |
367 | ### package-locally-nicknamed-by-list
368 |
369 | ```lisp
370 | Function: (package-locally-nicknamed-by-list package-designator)
371 | ```
372 |
373 | Returns a list of packages which have a local nickname for the designated
374 | package.
375 |
376 | See also: [add-package-local-nickname](#add-package-local-nickname), [package-local-nicknames](#package-local-nicknames),
377 | [remove-package-local-nickname](#remove-package-local-nickname), and the DEFPACKAGE option :LOCAL-NICKNAMES.
378 |
379 | Experimental: interface subject to change.
380 |
381 | ### remove-package-local-nickname
382 |
383 | ```lisp
384 | Function: (remove-package-local-nickname old-nickname &optional
385 | (package-designator (sane-package)))
386 | ```
387 |
388 | If the designated package had `old-nickname` as a local nickname for
389 | another package, it is removed. Returns true if the nickname existed and was
390 | removed, and NIL otherwise.
391 |
392 | See also: [add-package-local-nickname](#add-package-local-nickname), [package-local-nicknames](#package-local-nicknames),
393 | [package-locally-nicknamed-by-list](#package-locally-nicknamed-by-list), and the DEFPACKAGE option :LOCAL-NICKNAMES.
394 |
395 | Experimental: interface subject to change.
396 |
397 |
--------------------------------------------------------------------------------
/emacs-utils.el:
--------------------------------------------------------------------------------
1 |
2 |
3 | ;; https://www.emacswiki.org/emacs/RegularExpression
4 |
5 | (defun quote-symbol-at-point ()
6 | (interactive)
7 | (beginning-of-thing 'symbol)
8 | (insert ?\`)
9 | (end-of-thing 'symbol)
10 | (insert ?`))
11 |
12 | (defun quote-keyword-at-point ()
13 | (interactive)
14 | (beginning-of-thing 'symbol)
15 | (backward-char)
16 | (insert ?\`)
17 | (forward-char)
18 | (end-of-thing 'symbol)
19 | (insert ?`))
20 |
21 | (global-set-key (kbd "") 'quote-keyword-at-point)
22 | (global-set-key (kbd "") 'quote-symbol-at-point)
23 |
24 |
--------------------------------------------------------------------------------
/mkdocs.yml:
--------------------------------------------------------------------------------
1 | site_name: common-lisp-libraries
2 | theme:
3 | name: readthedocs
4 | collapse_by_default: false
5 | highlightjs: true
6 | hljs_languages:
7 | - lisp
8 | navigation_depth: 4
9 | sticky_navigation: false
10 | prev_next_buttons_location: none
11 | include_search_page: true
12 | nav:
13 | - index: index.md
14 | - Defacto libraries:
15 | - asdf.md
16 | - alexandria.md
17 | - bordeaux-threads.md
18 | - cl-ppcre.md
19 | - cl-who.md
20 | - fiveam.md
21 | - hunchentoot.md
22 | - iterate.md
23 | - local-time.md
24 | - postmodern.md
25 | - quicklisp.md
26 | - usocket.md
27 | - utilities.md
28 | - Not yet defacto:
29 | - numcl.md
30 | - unix-opts.md
31 | plugins:
32 | - search
33 | extra_css: [extra.css]
--------------------------------------------------------------------------------
/requirements.txt:
--------------------------------------------------------------------------------
1 | mkdocs>=1.1
2 |
--------------------------------------------------------------------------------
/scratch/postmodern.lisp:
--------------------------------------------------------------------------------
1 | (in-package :cl-rtd)
2 |
3 | (reader:enable-reader-syntax 'get-val 'lambda)
4 |
5 | (defparameter md-file "~/ram-disk/postmodern.md")
6 |
7 | (defparameter file-contents (with-output-to-string (s)
8 | (iter (for line in-file md-file using 'read-line)
9 | (write-line line s))))
10 |
11 | (defun parse (file-contents)
12 | (let* ((body-list (cdr
13 | (ppcre:split
14 | `(:sequence (:flags :single-line-mode-p)
15 | #\newline
16 | (:register (:sequence
17 | (:non-greedy-repetition
18 | 0 nil (:inverted-char-class #\newline))))
19 | #\newline
20 | (:greedy-repetition 2 nil #\-)
21 | #\newline
22 | #\newline)
23 | file-contents)))
24 | (symbol-doc-ht (make-hash-table :test 'equal)))
25 | (ppcre:do-register-groups (title)
26 | (`(:sequence (:flags :single-line-mode-p)
27 | #\newline
28 | (:register (:sequence
29 | (:non-greedy-repetition
30 | 0 nil (:inverted-char-class #\newline))))
31 | #\newline
32 | (:greedy-repetition 2 nil #\-)
33 | #\newline
34 | #\newline)
35 | file-contents)
36 | (let ((symbol (str:replace-all "**" "*" [(str:split " " title) 1])))
37 | ;; (print symbol)
38 | ;; (print (car body-list))
39 | ;; (if (= (decf a) 0) (return-from parse nil))
40 | (if-let (doc [symbol-doc-ht symbol])
41 | (setf [symbol-doc-ht symbol] (str:concat doc (car body-list)))
42 | (setf [symbol-doc-ht symbol] (car body-list)))
43 | (setq body-list (cdr body-list))))
44 | symbol-doc-ht))
45 |
46 |
47 |
48 | (with-open-file (f "~/ram-disk/postmodern-md.md"
49 | :direction :output :if-exists :supersede :if-does-not-exist :create)
50 | (let ((symbol-doc-ht (parse file-contents)))
51 | (iter (for (key . val) in
52 | (sort (hash-table-alist symbol-doc-ht) λ(string< (car -) (car --))))
53 | (for symbol = (find-symbol (string-upcase key)
54 | :postmodern))
55 | (unless symbol (format t "~&~D was not found in package~%"
56 | (string-upcase key)))
57 | (for signature = (ignore-errors (swank/backend:arglist symbol)))
58 | (write-string
59 | (conc "### " (str:replace-all "*" "\\*" key)
60 | (when (fboundp symbol)
61 | (conc #\newline #\newline "```lisp" #\newline
62 | (cond ((macro-function symbol) "Macro")
63 | ((typep (fdefinition symbol)
64 | (find-class 'standard-generic-function))
65 | "Generic Function")
66 | (t "Function"))
67 | ": " (string-downcase (format nil "~D" (cons key signature)))
68 | #\newline "```" #\newline))
69 | #\newline
70 | val (string #\newline))
71 | f))))
72 |
--------------------------------------------------------------------------------
/src/.gitignore:
--------------------------------------------------------------------------------
1 | *.fasl
--------------------------------------------------------------------------------
/src/functions.lisp:
--------------------------------------------------------------------------------
1 | (in-package :cl-rtd)
2 |
3 | ;; This file gets the documentation of Functions, Macros and Generic Functions
4 | (reader:enable-reader-syntax 'get-val)
5 |
6 | (defun arglist-symbols (arg-list)
7 | (let ((special-symbols '(&optional &key)))
8 | (iter
9 | (for elt in arg-list)
10 | (for linear
11 | initially nil
12 | then (or linear (member elt special-symbols)))
13 | (cond ((member elt special-symbols) nil)
14 | (linear
15 | (collect (etypecase elt
16 | (symbol elt)
17 | (list (car elt)))))
18 | ((listp elt) (appending (arglist-symbols elt)))
19 | (t (collect elt))))))
20 |
21 | (defparameter *classes-are-significant* nil
22 | "If T, generic functions are not documented separately.")
23 | ;;; TODO: This should only disable listing accessors separately
24 |
25 | (defmethod format-documentation ((slot (eql 'function)) symbol
26 | &optional (docstring (documentation symbol slot)))
27 | (when (fboundp symbol)
28 | (let* ((arg-list (swank/backend:arglist symbol))
29 | (arg-symbols (arglist-symbols arg-list)))
30 | (ppcre-flet ((quote-args
31 | (let ((symbol-name (subseq target-string [reg-starts 0] [reg-ends 0])))
32 | (if (and (string-upcase-p symbol-name)
33 | (member (string-upcase symbol-name) arg-symbols
34 | :test 'string=))
35 | (conc "`" (string-downcase symbol-name) "`")
36 | symbol-name))))
37 | (apply #'conc
38 | (format nil "~%```lisp~%~A: ~A~%```~%"
39 | (cond ((macro-function symbol) "Macro")
40 | ((typep (fdefinition symbol)
41 | (find-class 'standard-generic-function))
42 | "Generic Function")
43 | (t "Function"))
44 | (map-tree (lm elt (typecase elt
45 | (keyword (string-downcase (format nil "~S" elt)))
46 | (string-designator (string-downcase elt))
47 | (t (write-to-string elt))))
48 | (cons symbol arg-list)))
49 | (when docstring
50 | (list #\newline
51 | (restart-case
52 | (-<> (ppcre:regex-replace-all "([^\\s^\(^\)^\.^\,^\;]*)"
53 | docstring #'quote-args)
54 | ;; Usually, docstring contain symbols in upcase formats. However,
55 | ;; quoted-and-downcased symbols "look nicer".
56 | ;; A docstring-ed symbol cannot contain a space and '(', ')' characters.
57 | ;; Also assume, full-stops and commas are due to english.
58 | (requote-with-backquote <>)
59 | ;; Some also contain symbols in `format'. We want them to be in `format`.
60 | ;; Ideally they should be hyperlinked elsewhere around the world!
61 | (hyperlink-samedoc-symbols <> symbol)
62 | ;; Too many links? Control using *blacklist-samedoc-symbols*
63 | ;; These functions should be separated
64 | (quote-self <> symbol))
65 | (continue-ignoring-errors () (format t "Errors on ~D~%" symbol)))
66 | #\newline)))))))
67 |
68 |
69 |
--------------------------------------------------------------------------------
/src/md-file.lisp:
--------------------------------------------------------------------------------
1 | ;; (handler-bind ((asdf/find-system:load-system-definition-error
2 | ;; (lambda (c)
3 | ;; (declare (ignore c))
4 | ;; (invoke-restart 'sb-impl::drop-them)))
5 | ;; (sb-int:package-at-variance-error
6 | ;; (lambda (c)
7 | ;; (declare (ignore c))
8 | ;; (invoke-restart 'sb-impl::drop-them))))
9 | ;; (ql:quickload '(:alexandria :str :iterate :reader :arrows :swank :closer-mop)))
10 |
11 | ;; (ql:quickload '(:alexandria :str :iterate :reader :simple-arrows :closer-mop))
12 |
13 | (in-package :cl-rtd)
14 |
15 | ;;; Our main function is the md-file function below.
16 | ;; Typical usage of the below function includes
17 | ;; (let ((*blacklist-samedoc-symbols* '(thread lock timeout)))
18 | ;; (md-file :bordeaux-threads "~/ram-disk/bordeaux-threads.md"))
19 |
20 | (defparameter *slots* '(function variable type))
21 |
22 | (defun documentation-exists-p (symbol)
23 | (or (some #'identity
24 | (mapcar (lm doc-slot (documentation symbol doc-slot))
25 | *slots*))
26 | (trivial-types:type-specifier-p symbol)
27 | (fboundp symbol)
28 | (boundp symbol)))
29 |
30 | (defun generate-package-documentation (&optional prologue-exists-p)
31 | (apply #'conc
32 | (unless prologue-exists-p
33 | (format nil "~%# ~a~%" (string-downcase *package-name*)))
34 | ;; Refer: http://www.lispworks.com/documentation/HyperSpec/Body/f_docume.htm
35 | ;; T for documentation merely specifies to get the documentation of the package
36 | (when-let (doc (documentation (find-package *package-name*) t))
37 | (format nil "~a~%~%" doc))
38 | (iter outer
39 | (for symbol in *samedoc-symbols*)
40 | ;; (for i below 5)
41 | (collect (format nil "~%### ~a~%" (let ((sym-name (string-downcase symbol)))
42 | (if (str:containsp "*" sym-name)
43 | (str:replace-all "*" "\\\*" sym-name)
44 | sym-name))))
45 | (if (not (documentation-exists-p symbol))
46 | (collect (format nil "~%No documentation found for `~a`~%"
47 | (string-downcase symbol)))
48 | (iter (for slot in *slots*)
49 | (for docstring = (documentation symbol slot))
50 | (when (and (eq slot 'function)
51 | (fboundp symbol)
52 | (typep (fdefinition symbol) 'generic-function)
53 | *classes-are-significant*)
54 | ;; If it's a generic function, we don't even reach the next lines.
55 | (next-iteration))
56 | ;; (print (list symbol slot))
57 | ;; (print (list 'documenting symbol slot));
58 | ;; Some classes may have no docstrings, but may have doc.
59 | ;; We do want to write the heading for such classes.
60 | (when-let (doc (format-documentation slot symbol docstring))
61 | (setq doc (if (ppcre:scan "(?s)^\\n*$" doc)
62 | "" doc)) ; remove spurious new lines
63 | (in outer (collect doc))))))))
64 |
65 | (defun prologue-file-path ()
66 | (let ((prologue-file-path (merge-pathnames (pathname (conc "../prologue/"
67 | (string-downcase *package-name*)
68 | ".md"))
69 | (asdf:component-pathname
70 | (asdf:find-system "cl-rtd")))))
71 | (if (uiop:file-exists-p prologue-file-path)
72 | prologue-file-path
73 | nil)))
74 |
75 | (defun md-file (package-keyword &optional (output-file (format nil "~A.md" package-keyword))
76 | &key classes-are-significant)
77 | "If CLASSES-ARE-SIGNIFICANT is T, generic functions are not documented separately."
78 |
79 | (let* ((symbols (iter (for symbol in-package package-keyword
80 | external-only t)
81 | (collect symbol)))
82 | (sorted-symbols (sort symbols #'string<))
83 | (*samedoc-symbols* (set-difference sorted-symbols *blacklist-samedoc-symbols*
84 | :test #'string=))
85 | (*package-name* (package-name package-keyword))
86 | (*classes-are-significant* classes-are-significant)
87 | (*print-length* nil)
88 | (prologue-file-path (prologue-file-path)))
89 | (when prologue-file-path
90 | (uiop:copy-file prologue-file-path output-file))
91 | (write-string-into-file (generate-package-documentation prologue-file-path)
92 | (string-downcase output-file)
93 | :if-exists (if prologue-file-path :append :supersede)
94 | :if-does-not-exist :create)
95 | t))
96 |
--------------------------------------------------------------------------------
/src/package.lisp:
--------------------------------------------------------------------------------
1 | (cl:in-package :cl-user)
2 |
3 | (defpackage :cl-rtd
4 | (:use :cl :alexandria :iterate :arrows)
5 | (:local-nicknames (:mop :closer-mop))
6 | (:export #:md-file))
7 |
8 | (in-package :cl-rtd)
9 |
10 | (defgeneric format-documentation (slot symbol &optional docstring))
11 |
12 | (defvar *samedoc-symbols* ()
13 | "List of symbols used for hyperlinking on the same page. This is bound in md-file.")
14 | (defvar *blacklist-samedoc-symbols* ()
15 | "List of symbols users may want to exclude for hyperlinking. This list is subtracted
16 | from *SAMEDOC-SYMBOLS* to obtain the final list.")
17 | (defvar *package-name* "")
18 |
19 | (reader+swank:enable-package-local-reader-syntax 'get-val)
20 |
--------------------------------------------------------------------------------
/src/types.lisp:
--------------------------------------------------------------------------------
1 | (in-package :cl-rtd)
2 |
3 | (defun split-and-clean-slots (slots-doc)
4 | (-<> (str:replace-all " " "4SPACES" slots-doc)
5 | (str:split " " <> :omit-nulls t)
6 | (mapcar (lm - (str:replace-all "4SPACES" " " -))
7 | <>)
8 | (remove-if (lm - (str:starts-with-p (conc *package-name* "::") -))
9 | <>)))
10 |
11 | (defun class-documentation (class)
12 | ;; Only slots are documented currently.
13 | (flet
14 | ((quote-slots (slots)
15 | (conc "**Direct Slots**" #\newline #\newline
16 | (with-output-to-string (s)
17 | (ppcre:do-register-groups (slot-name initarg reader writer)
18 | (*slot-splitting-regex*
19 | (ppcre:regex-replace-all (conc "(?-i)" *package-keyword* #\:)
20 | slots
21 | ""))
22 | (when (and slot-name (string/= "" slot-name))
23 | (write-string (conc "**" (string-downcase slot-name) "**"
24 | #\newline
25 | "```lisp" #\newline
26 | (or initarg "")
27 | (or reader "")
28 | (or writer "")
29 | "```" #\newline)
30 | s)))))))
31 | (let ((full-doc (with-output-to-string (*standard-output*) (describe class))))
32 | (if-let
33 | (return-value
34 | (ppcre:register-groups-bind (prologue direct-slots end)
35 | (`(:sequence (:flags :single-line-mode-p)
36 | (:register (:sequence (:greedy-repetition 0 nil :everything)
37 | "Direct slots:" #\newline))
38 | (:register (:sequence (:non-greedy-repetition
39 | 0 nil :everything)
40 | #\newline))
41 | (:register (:sequence #\newline
42 | (:greedy-repetition 0 nil :everything))))
43 | full-doc)
44 | (declare (ignore prologue end))
45 | (quote-slots direct-slots)))
46 | return-value
47 | ""))))
48 |
49 | (defun slot-splitting-regex ()
50 | `(:sequence
51 | (:flags :single-line-mode-p)
52 | (:register (:greedy-repetition 0 nil
53 | :non-whitespace-char-class))
54 | (:greedy-repetition
55 | 0 1 (:sequence #\newline " "
56 | (:register (:sequence "Initargs: "
57 | (:greedy-repetition
58 | 0 nil
59 | :non-whitespace-char-class)
60 | #\newline))))
61 | (:greedy-repetition
62 | 0 1 (:sequence " "
63 | (:register (:sequence "Readers: "
64 | (:greedy-repetition
65 | 0 nil
66 | :non-whitespace-char-class)
67 | #\newline))))
68 | (:greedy-repetition
69 | 0 1 (:sequence " "
70 | (:register (:sequence
71 | "Writers: "
72 | (:greedy-repetition
73 | 0 nil
74 | (:inverted-char-class #\newline))
75 | #\newline))))
76 | (:greedy-repetition
77 | 0 1 (:sequence " "
78 | (:register (:sequence
79 | "Documentation:"
80 | (:greedy-repetition
81 | 0 nil
82 | :everything)
83 | #\newline))))
84 | (:alternation :void (:sequence " " ,*package-name*))))
85 |
86 | (defun format-slot-documentation (slot-doc-list)
87 | (if-let (processed-doc-list
88 | (mapcar (lambda (slot-doc)
89 | ;; (write-string slot-doc)
90 | (with-output-to-string (s)
91 | (ppcre:register-groups-bind (slot-name initarg reader writer)
92 | ((slot-splitting-regex)
93 | (ppcre:regex-replace-all (conc "(?-i)" *package-name* #\:)
94 | slot-doc
95 | ""))
96 | (when (and slot-name (string/= "" slot-name))
97 | (write-string (conc "**" (string-downcase slot-name) "**"
98 | #\newline
99 | "```lisp" #\newline
100 | (or initarg "")
101 | (or reader "")
102 | (or writer "")
103 | "```" #\newline)
104 | s)))))
105 | slot-doc-list))
106 | (apply 'conc "**Direct Slots**" #\newline #\newline processed-doc-list)
107 | ""))
108 |
109 | (defun direct-slots-documentation (class)
110 | (declare (type class class))
111 | (let ((full-doc (with-output-to-string (*standard-output*) (describe class))))
112 | (ppcre:register-groups-bind (prologue direct-slots end)
113 | (`(:sequence (:flags :single-line-mode-p)
114 | (:register (:sequence (:greedy-repetition 0 nil :everything)
115 | "Direct slots:" #\newline))
116 | (:register (:sequence (:non-greedy-repetition
117 | 0 nil :everything)
118 | #\newline))
119 | (:register (:sequence #\newline
120 | (:greedy-repetition 0 nil :everything))))
121 | full-doc)
122 | (declare (ignore prologue end))
123 | direct-slots)))
124 |
125 | (defmethod format-documentation ((slot (eql 'type)) symbol
126 | &optional (docstring (documentation symbol slot)))
127 | (let ((class (ignore-errors (find-class symbol))))
128 | (when (trivial-types:type-specifier-p symbol)
129 | (funcall 'conc
130 | (format nil "~%```lisp~%~A~%```~%~%"
131 | (cond ((null class)
132 | "Type")
133 | ((typep class (find-class 'structure-class))
134 | "Structure")
135 | ((typep class (find-class 'standard-class))
136 | "Class")
137 | ((subtypep class (find-class 'condition))
138 | "Condition")
139 | ((typep class
140 | (find-class 'closer-mop:funcallable-standard-class))
141 | "Function")
142 | #+sbcl
143 | ((typep class (find-class 'sb-pcl:system-class))
144 | "System Class (SBCL)")
145 | (t (error "Non-exhaustive cases: ~D" class))))
146 | (when docstring
147 | (conc (requote-with-backquote docstring)
148 | #\newline
149 | #\newline))
150 | (when class
151 | (-> class
152 | direct-slots-documentation
153 | split-and-clean-slots
154 | format-slot-documentation
155 | (hyperlink-samedoc-symbols symbol)))))))
156 |
--------------------------------------------------------------------------------
/src/utilities.lisp:
--------------------------------------------------------------------------------
1 | (in-package :cl-rtd)
2 |
3 | (reader:enable-reader-syntax 'get-val)
4 |
5 | (defun map-tree (function tree)
6 | (cond ((null tree) ())
7 | ((listp tree)
8 | (cons (map-tree function (car tree))
9 | (map-tree function (cdr tree))))
10 | (t (funcall function tree))))
11 |
12 | (defun string-upcase-p (string)
13 | (every (lambda (char)
14 | (or (not (alpha-char-p char))
15 | (char= (char-upcase char) char)))
16 | string))
17 |
18 | (defmacro ppcre-flet (bindings &body body)
19 | `(flet (,@(loop for binding in bindings
20 | collect (destructuring-bind (name &body body) binding
21 | `(,name (target-string start end match-start match-end
22 | reg-starts reg-ends)
23 | (declare (ignorable target-string start end match-start match-end
24 | reg-starts reg-ends))
25 | ,@body))))
26 | ,@body))
27 |
28 | (defun conc (&rest strings/chars)
29 | (apply #'concatenate
30 | 'string
31 | (mapcar (lambda (elt)
32 | (etypecase elt
33 | (string elt)
34 | (character (string elt))
35 | (null "")))
36 | strings/chars)))
37 |
38 | (defmacro lm (&rest body-vars)
39 | `(lambda ,(butlast body-vars)
40 | ,@(last body-vars)))
41 |
42 | (define-constant +lisp-symbol-regex+
43 | `(:sequence (:register
44 | (:greedy-repetition 1 nil
45 | (:alternation (:char-class (:range #\A #\Z))
46 | #\-
47 | #\:
48 | #\*
49 | (:char-class (:range #\0 #\9))))))
50 | :test 'equal)
51 |
52 | (define-constant +quoted-lisp-symbol-regex+
53 | `(:sequence #\`
54 | (:register
55 | (:greedy-repetition 1 nil
56 | (:alternation (:char-class (:range #\A #\Z))
57 | #\-
58 | #\:
59 | #\*
60 | (:char-class (:range #\0 #\9)))))
61 | #\`)
62 | :test 'equal)
63 |
64 | (defun requote-with-backquote (string)
65 | "Converts quoted of `format' to `format`."
66 | (ppcre-flet ((%requote-with-backquote
67 | (conc (subseq target-string [reg-starts 0] (1- [reg-ends 0])) "`")))
68 | (ppcre:regex-replace-all "(\\`[^\\s^\(^\)]*')" string #'%requote-with-backquote)))
69 |
70 | (defun hyperlink-samedoc-symbols (string current-symbol)
71 | "Converts SYMBOL or `symbol` to [symbol](#symbol) if SYMBOL is in *SAMEDOC-SYMBOLS*."
72 | (ppcre-flet ((%hyperlink-samedoc-symbols
73 | (let* ((potential-symbol-name (subseq target-string [reg-starts 0] [reg-ends 0]))
74 | (potential-symbol (ignore-errors (read-from-string
75 | (string-upcase potential-symbol-name))))
76 | (downcased (string-downcase potential-symbol-name)))
77 | (if (and (symbolp potential-symbol)
78 | (member potential-symbol *samedoc-symbols*
79 | :test #'string=)
80 | ;; avoid hyperlinking to the same function
81 | (string/= potential-symbol current-symbol))
82 | (format nil "[~A](#~A)"
83 | (str:replace-all "*" "\\*"
84 | (str:replace-all "\\*" "*" downcased))
85 | (string-trim '(#\*)
86 | (string-downcase (symbol-name potential-symbol))))
87 | potential-symbol-name))))
88 | (-<> (ppcre:regex-replace-all +lisp-symbol-regex+ string
89 | #'%hyperlink-samedoc-symbols)
90 | (ppcre:regex-replace-all +quoted-lisp-symbol-regex+ <>
91 | #'%hyperlink-samedoc-symbols))))
92 |
93 | (defun quote-self (string current-symbol)
94 | (ppcre-flet ((%quote-self
95 | (let* ((symbol-name (subseq target-string [reg-starts 0] [reg-ends 0]))
96 | (downcased (string-downcase symbol-name)))
97 | (if (string= (string-upcase symbol-name) current-symbol)
98 | (format nil "`~A`" downcased)
99 | symbol-name))))
100 | (ppcre:regex-replace-all +lisp-symbol-regex+ string
101 | #'%quote-self)))
102 |
103 |
--------------------------------------------------------------------------------
/src/variables.lisp:
--------------------------------------------------------------------------------
1 | (in-package :cl-rtd)
2 |
3 | (defmethod format-documentation ((slot (eql 'variable)) symbol
4 | &optional (docstring (documentation symbol slot)))
5 | (apply #'conc
6 | (ecase (introspect-environment:variable-information symbol)
7 | (:constant
8 | (format nil "~%```lisp~%Constant: ~A~%```~%" (symbol-value symbol)))
9 | (:special
10 | (if (boundp symbol)
11 | (format nil "~%```lisp~%Variable~%Default Value: ~S~%```~%"
12 | (symbol-value symbol))
13 | (format nil "~%```lisp~%Variable~%Default Unbound~%```~%")))
14 | (:symbol-macro
15 | (format nil "~%```lisp~%Symbol Macro~%Expansion: ~S~%```~%"
16 | (macroexpand-1 symbol)))
17 | ((nil)))
18 | (when docstring
19 | (list #\newline
20 | (hyperlink-samedoc-symbols docstring symbol)
21 | #\newline))))
22 |
--------------------------------------------------------------------------------