diff options
-rw-r--r-- | COPYING | 26 | ||||
-rwxr-xr-x | chicken-heredoc.scm | 60 | ||||
-rwxr-xr-x | chicken-scratch.scm | 78 |
3 files changed, 104 insertions, 60 deletions
diff --git a/COPYING b/COPYING new file mode 100644 index 0000000..b6a7248 --- /dev/null +++ b/COPYING | |||
@@ -0,0 +1,26 @@ | |||
1 | Copyright 2023 Case Duckworth | ||
2 | |||
3 | Redistribution and use in source and binary forms, with or without modification, | ||
4 | are permitted provided that the following conditions are met: | ||
5 | |||
6 | 1. Redistributions of source code must retain the above copyright notice, this | ||
7 | list of conditions and the following disclaimer. | ||
8 | |||
9 | 2. Redistributions in binary form must reproduce the above copyright notice, | ||
10 | this list of conditions and the following disclaimer in the documentation | ||
11 | and/or other materials provided with the distribution. | ||
12 | |||
13 | 3. Neither the name of the copyright holder nor the names of its contributors | ||
14 | may be used to endorse or promote products derived from this software without | ||
15 | specific prior written permission. | ||
16 | |||
17 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS “AS IS” AND | ||
18 | ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED | ||
19 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE | ||
20 | DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR | ||
21 | ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES | ||
22 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; | ||
23 | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON | ||
24 | ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | ||
25 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS | ||
26 | SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. \ No newline at end of file | ||
diff --git a/chicken-heredoc.scm b/chicken-heredoc.scm deleted file mode 100755 index e0e55ad..0000000 --- a/chicken-heredoc.scm +++ /dev/null | |||
@@ -1,60 +0,0 @@ | |||
1 | #!/bin/sh | ||
2 | #| -*- scheme -*- | ||
3 | exec csi -ss "$0" "$@" | ||
4 | heredocs for chicken | ||
5 | idea-https://git.sr.ht/~evhan/beaker/tree/master/item/aux/generate-wiki-page.scm | ||
6 | |# | ||
7 | |||
8 | (import (only (chicken irregex) | ||
9 | irregex-replace/all | ||
10 | irregex-search) | ||
11 | (only (chicken io) | ||
12 | read-string) | ||
13 | (only (chicken port) | ||
14 | make-concatenated-port) | ||
15 | (only (chicken random) | ||
16 | pseudo-random-real) | ||
17 | (only (chicken time) | ||
18 | current-seconds)) | ||
19 | |||
20 | (define filestr | ||
21 | (make-parameter #f)) | ||
22 | |||
23 | (define def-end | ||
24 | (make-parameter "&def-end")) | ||
25 | |||
26 | (define (randomizer #!optional str) | ||
27 | (let ((base (number->string (+ (current-seconds) | ||
28 | (pseudo-random-real))))) | ||
29 | (if (and str (irregex-search base str)) | ||
30 | (randomizer str) | ||
31 | base))) | ||
32 | |||
33 | (define-syntax def | ||
34 | (syntax-rules () | ||
35 | ((def var val) | ||
36 | ;; I'm pretty sure this only works in CHICKEN. | ||
37 | (begin (set! var val) | ||
38 | (def-end))))) | ||
39 | |||
40 | (define (heredoc-expand file) | ||
41 | (let* ((delim (string-append "END-" (randomizer))) | ||
42 | (template (make-concatenated-port | ||
43 | (open-input-string (string-append "#<#" delim "\n")) | ||
44 | (open-input-file file) | ||
45 | (open-input-string (string-append "\n" delim "\n")))) | ||
46 | (expanded (open-output-string)) | ||
47 | (str (begin | ||
48 | (display (eval (read template)) expanded) | ||
49 | (get-output-string expanded)))) | ||
50 | (irregex-replace/all `(seq ,(def-end) (* "\n")) | ||
51 | str | ||
52 | ""))) | ||
53 | |||
54 | (define (main args) | ||
55 | (for-each (lambda (f) | ||
56 | ;; Is this overkill? Maybe.... | ||
57 | (parameterize ((filestr (with-input-from-file f read-string))) | ||
58 | (parameterize ((def-end (randomizer (filestr)))) | ||
59 | (display (heredoc-expand f))))) | ||
60 | args)) | ||
diff --git a/chicken-scratch.scm b/chicken-scratch.scm new file mode 100755 index 0000000..e47ad67 --- /dev/null +++ b/chicken-scratch.scm | |||
@@ -0,0 +1,78 @@ | |||
1 | ;;; CHICKEN-SCRATCH --- heredocs for CHICKEN | ||
2 | ;; written by Case Duckworth <acdw@acdw.net> off an idea by evhan | ||
3 | ;; Licensed under BSD-3. See COPYING for details. | ||
4 | |||
5 | ;; CHICKEN has "Multiline string constants with embedded expressions" syntax, | ||
6 | ;; which is basically shell here-doc syntax but schemier and with a real | ||
7 | ;; programming langugage to embed. evhan's beaker tool (which is great, btw) | ||
8 | ;; uses this facility to do a quick-and-dirty templating for wiki generation. I | ||
9 | ;; realized that I could use the same facility for the same kind of | ||
10 | ;; heredoc-style templating I have done in various other SSGs like unk and | ||
11 | ;; vienna, but with scheme. Thus, CHICKEN-SCRATCH was born. | ||
12 | |||
13 | ;; USAGE | ||
14 | |||
15 | ;; `expand-string' is the main entry point to this module. It takes a string and | ||
16 | ;; returns a string with all #( ... ) forms expanded according to the CHICKEN | ||
17 | ;; rules. `expand-port' is a port version of `expand-string'. | ||
18 | |||
19 | ;; To enable truly invisible definitions within the expanded string, the `def' | ||
20 | ;; macro is provided which performs a `set!' on its variables, then returns a | ||
21 | ;; string guaranteed not to be in the input string, which is then filtered out | ||
22 | ;; in the expanded string. | ||
23 | |||
24 | ;; Finally, to enable CHICKEN-SCRATCH to be used in a shebang, if the first line | ||
25 | ;; of the input string begins with #!, it's deleted from the input. | ||
26 | |||
27 | (module chicken-scratch | ||
28 | (expand-string | ||
29 | expand-port | ||
30 | def | ||
31 | %def/replacer) | ||
32 | |||
33 | (import scheme | ||
34 | (chicken base) | ||
35 | (only (chicken io) | ||
36 | read-string) | ||
37 | (only (chicken irregex) | ||
38 | irregex-replace | ||
39 | irregex-replace/all | ||
40 | irregex-search) | ||
41 | (only (chicken port) | ||
42 | make-concatenated-port) | ||
43 | (only (chicken random) | ||
44 | pseudo-random-real)) | ||
45 | |||
46 | (define %def/replacer (make-parameter #f)) | ||
47 | |||
48 | (define (expand-string str) | ||
49 | (parameterize ((%def/replacer (random-string-not-in str))) | ||
50 | (let* ((delim (random-string-not-in str)) | ||
51 | (template (make-concatenated-port | ||
52 | (open-input-string (string-append "#<#" delim "\n")) | ||
53 | (open-input-string (irregex-replace "^#!.*\n" str "")) | ||
54 | (open-input-string (string-append "\n" delim "\n")))) | ||
55 | (expanded (open-output-string)) | ||
56 | (output (begin | ||
57 | (display (eval (read template)) expanded) | ||
58 | (get-output-string expanded)))) | ||
59 | (irregex-replace/all `(seq ,(%def/replacer) (* "\n")) | ||
60 | output | ||
61 | "")))) | ||
62 | |||
63 | (define (expand-port #!optional port) | ||
64 | (let ((port (or port (current-input-port)))) | ||
65 | (expand-string (read-string #f port)))) | ||
66 | |||
67 | (define-syntax def | ||
68 | (syntax-rules () | ||
69 | ((def var val) | ||
70 | ;; I think this only works in CHICKEN. | ||
71 | (begin (set! var val) | ||
72 | (%def/replacer))))) | ||
73 | |||
74 | (define (random-string-not-in str) | ||
75 | (let ((attempt (number->string (pseudo-random-real)))) | ||
76 | (if (irregex-search attempt str) | ||
77 | (random-string-not-in str) | ||
78 | attempt)))) | ||