Simplifying chibi docs with \procedure and \macro utils.

This commit is contained in:
Alex Shinn 2014-02-02 16:26:19 +09:00
parent 87bc0f0106
commit e5c243ee10
16 changed files with 198 additions and 177 deletions

View file

@ -6,14 +6,14 @@
;;> the compiler, and other core types less commonly ;;> the compiler, and other core types less commonly
;;> needed in user code, plus related utilities. ;;> needed in user code, plus related utilities.
;;> \subsubsection{Analysis and Expansion} ;;> \section{Analysis and Expansion}
;;> \subsubsubsection{\scheme{(analyze x [env])}} ;;> \procedure{(analyze x [env])}
;;> Expands and analyzes the expression \var{x} and returns the ;;> Expands and analyzes the expression \var{x} and returns the
;;> resulting AST. ;;> resulting AST.
;;> \subsubsubsection{\scheme{(optimize ast)}} ;;> \procedure{(optimize ast)}
;;> Runs an optimization pass on \var{ast} and returns the ;;> Runs an optimization pass on \var{ast} and returns the
;;> resulting simplified expression. ;;> resulting simplified expression.
@ -109,7 +109,7 @@
((opcode? x) (cond ((opcode-name x) => string->symbol) (else x))) ((opcode? x) (cond ((opcode-name x) => string->symbol) (else x)))
(else x))))) (else x)))))
;;> \subsubsection{Types} ;;> \section{Types}
;;> All objects have an associated type, and types may have parent ;;> All objects have an associated type, and types may have parent
;;> types. When using ;;> types. When using
@ -169,15 +169,15 @@
;;> \item{\scheme{exception?}} ;;> \item{\scheme{exception?}}
;;> ] ;;> ]
;;> \subsubsubsection{\scheme{(type-of x)}} ;;> \procedure{(type-of x)}
;;> Returns the type of any object \var{x}. ;;> Returns the type of any object \var{x}.
;;> \subsubsubsection{\scheme{(type-name type)}} ;;> \procedure{(type-name type)}
;;> Returns the name of type \var{type}. ;;> Returns the name of type \var{type}.
;;> \subsubsubsection{\scheme{(type-parent type)}} ;;> \procedure{(type-parent type)}
;;> Returns the immediate parent of type \var{type}, ;;> Returns the immediate parent of type \var{type},
;;> or \scheme{#f} for a type with no parent. ;;> or \scheme{#f} for a type with no parent.
@ -188,21 +188,21 @@
(> (vector-length v) 1) (> (vector-length v) 1)
(vector-ref v (- (vector-length v) 2))))) (vector-ref v (- (vector-length v) 2)))))
;;> \subsubsubsection{\scheme{(type-cpl type)}} ;;> \procedure{(type-cpl type)}
;;> Returns the class precedence list of type \var{type} as a ;;> Returns the class precedence list of type \var{type} as a
;;> vector, or \scheme{#f} for a type with no parent. ;;> vector, or \scheme{#f} for a type with no parent.
;;> \subsubsubsection{\scheme{(type-slots type)}} ;;> \procedure{(type-slots type)}
;;> Returns the slot list of type \var{type}. ;;> Returns the slot list of type \var{type}.
;;> \subsubsection{Accessors} ;;> \section{Accessors}
;;> This section describes additional accessors on AST and other core ;;> This section describes additional accessors on AST and other core
;;> types. ;;> types.
;;> \subsubsubsection{Procedures} ;;> \subsection{Procedures}
;;> \itemlist[ ;;> \itemlist[
;;> \item{\scheme{(procedure-code f)} - the compiled bytecode object} ;;> \item{\scheme{(procedure-code f)} - the compiled bytecode object}
@ -216,7 +216,7 @@
(define (procedure-name-set! x name) (define (procedure-name-set! x name)
(bytecode-name-set! (procedure-code x) name)) (bytecode-name-set! (procedure-code x) name))
;;> \subsubsubsection{Macros} ;;> \subsection{Macros}
;;> \itemlist[ ;;> \itemlist[
;;> \item{\scheme{(macro-procedure f)} - the macro procedure} ;;> \item{\scheme{(macro-procedure f)} - the macro procedure}
@ -224,7 +224,7 @@
;;> \item{\scheme{(macro-source f)} - the source location the macro was defined in} ;;> \item{\scheme{(macro-source f)} - the source location the macro was defined in}
;;> ] ;;> ]
;;> \subsubsubsection{Bytecode Objects} ;;> \subsection{Bytecode Objects}
;;> \itemlist[ ;;> \itemlist[
;;> \item{\scheme{(bytecode-name bc)} - the macro procedure} ;;> \item{\scheme{(bytecode-name bc)} - the macro procedure}
@ -232,7 +232,7 @@
;;> \item{\scheme{(bytecode-source bc)} - the source location the procedure was defined in} ;;> \item{\scheme{(bytecode-source bc)} - the source location the procedure was defined in}
;;> ] ;;> ]
;;> \subsubsubsection{Syntactic Closures} ;;> \subsection{Syntactic Closures}
;;> \itemlist[ ;;> \itemlist[
;;> \item{\scheme{(syntactic-closure-env sc)}} ;;> \item{\scheme{(syntactic-closure-env sc)}}
@ -243,7 +243,7 @@
;;> Return the environment, free variables, and expression ;;> Return the environment, free variables, and expression
;;> associated with \var{sc} respectively. ;;> associated with \var{sc} respectively.
;;> \subsubsubsection{Exceptions} ;;> \subsection{Exceptions}
;;> \itemlist[ ;;> \itemlist[
;;> \item{\scheme{(exception-kind exn)}} ;;> \item{\scheme{(exception-kind exn)}}
@ -254,7 +254,7 @@
;;> Return the kind, message, and irritants ;;> Return the kind, message, and irritants
;;> associated with \var{exn} respectively. ;;> associated with \var{exn} respectively.
;;> \subsubsubsection{Lambdas} ;;> \subsection{Lambdas}
;;> \itemlist[ ;;> \itemlist[
;;> \item{\scheme{(lambda-name lam)} - the name of the lambda, if known} ;;> \item{\scheme{(lambda-name lam)} - the name of the lambda, if known}
@ -281,7 +281,7 @@
;;> \item{\scheme{(lambda-source-set! lam x)}} ;;> \item{\scheme{(lambda-source-set! lam x)}}
;;> ] ;;> ]
;;> \subsubsubsection{Conditionals} ;;> \subsection{Conditionals}
;;> \itemlist[ ;;> \itemlist[
;;> \item{\scheme{(cnd-test cnd)} - the test for the conditional} ;;> \item{\scheme{(cnd-test cnd)} - the test for the conditional}
@ -292,14 +292,14 @@
;;> \item{\scheme{(cnd-fail-set! cnd x)}} ;;> \item{\scheme{(cnd-fail-set! cnd x)}}
;;> ] ;;> ]
;;> \subsubsubsection{Sequences} ;;> \subsection{Sequences}
;;> \itemlist[ ;;> \itemlist[
;;> \item{\scheme{(seq-ls seq)} - the list of sequence expressions} ;;> \item{\scheme{(seq-ls seq)} - the list of sequence expressions}
;;> \item{\scheme{(seq-ls-set! seq x)}} ;;> \item{\scheme{(seq-ls-set! seq x)}}
;;> ] ;;> ]
;;> \subsubsubsection{References} ;;> \subsection{References}
;;> \itemlist[ ;;> \itemlist[
;;> \item{\scheme{(ref-name ref)} - the name of the referenced variable} ;;> \item{\scheme{(ref-name ref)} - the name of the referenced variable}
@ -308,7 +308,7 @@
;;> \item{\scheme{(ref-cell-set! ref x)}} ;;> \item{\scheme{(ref-cell-set! ref x)}}
;;> ] ;;> ]
;;> \subsubsubsection{Mutations} ;;> \subsection{Mutations}
;;> \itemlist[ ;;> \itemlist[
;;> \item{\scheme{(set-var set)} - a reference to the mutated variable} ;;> \item{\scheme{(set-var set)} - a reference to the mutated variable}
@ -317,14 +317,14 @@
;;> \item{\scheme{(set-value-set! set x)}} ;;> \item{\scheme{(set-value-set! set x)}}
;;> ] ;;> ]
;;> \subsubsubsection{Literals} ;;> \subsection{Literals}
;;> \itemlist[ ;;> \itemlist[
;;> \item{\scheme{(lit-value lit)} - the literal value} ;;> \item{\scheme{(lit-value lit)} - the literal value}
;;> \item{\scheme{(lit-value-set! lit x)}} ;;> \item{\scheme{(lit-value-set! lit x)}}
;;> ] ;;> ]
;;> \subsubsubsection{Pairs} ;;> \subsection{Pairs}
;;> \itemlist[ ;;> \itemlist[
;;> \item{\scheme{(pair-source x)}} ;;> \item{\scheme{(pair-source x)}}
@ -335,28 +335,28 @@
;;> Source info is represented as another pair whose \var{car} is ;;> Source info is represented as another pair whose \var{car} is
;;> the source file name and whose \var{cdr} is the line number. ;;> the source file name and whose \var{cdr} is the line number.
;;> \subsubsection{Miscellaneous Utilities} ;;> \section{Miscellaneous Utilities}
;;> \subsubsubsection{\scheme{(gc)}} ;;> \procedure{(gc)}
;;> Force a garbage collection. ;;> Force a garbage collection.
;;> \subsubsubsection{\scheme{(object-size x)}} ;;> \procedure{(object-size x)}
;;> Returns the heap space directly used by \var{x}, not ;;> Returns the heap space directly used by \var{x}, not
;;> counting any elements of \var{x}. ;;> counting any elements of \var{x}.
;;> \subsubsubsection{\scheme{(integer->immediate n)}} ;;> \procedure{(integer->immediate n)}
;;> Returns the interpretation of the integer \var{n} as ;;> Returns the interpretation of the integer \var{n} as
;;> an immediate object, useful for debugging. ;;> an immediate object, useful for debugging.
;;> \subsubsubsection{\scheme{(string-contains str pat)}} ;;> \procedure{(string-contains str pat)}
;;> Returns the first string cursor of \var{pat} in \var{str}, ;;> Returns the first string cursor of \var{pat} in \var{str},
;;> of \scheme{#f} if it's not found. ;;> of \scheme{#f} if it's not found.
;;> \subsubsubsection{\scheme{(atomically expr)}} ;;> \procedure{(atomically expr)}
;;> Run \var{expr} atomically, disabling yields. Ideally should only be ;;> Run \var{expr} atomically, disabling yields. Ideally should only be
;;> used for brief, deterministic expressions. If used incorrectly (e.g. ;;> used for brief, deterministic expressions. If used incorrectly (e.g.

View file

@ -1,30 +1,8 @@
;; Copyright (c) 2005-2009 Alex Shinn. All rights reserved. ;; Copyright (c) 2005-2014 Alex Shinn. All rights reserved.
;; BSD-style license: http://synthcode.com/license.txt ;; BSD-style license: http://synthcode.com/license.txt
;; Procedure: base64-encode-string str ;;> RFC 3548 base64 encoding and decoding utilities.
;; Return a base64 encoded representation of string according to the ;;> This API is compatible with the Gauche library rfc.base64.
;; official base64 standard as described in RFC3548.
;; Procedure: base64-decode-string str
;; Return a base64 decoded representation of string, also interpreting
;; the alternate 62 & 63 valued characters as described in RFC3548.
;; Other out-of-band characters are silently stripped, and = signals
;; the end of the encoded string. No errors will be raised.
;; Procedure: base64-encode [port]
;; Procedure: base64-decode [port]
;; Variations of the above which read and write to ports.
;; Procedure: base64-encode-header enc str [start-col max-col nl]
;; Return a base64 encoded representation of string as above,
;; wrapped in =?ENC?B?...?= as per RFC1522, split across multiple
;; MIME-header lines as needed to keep each lines length less than
;; MAX-COL. The string is encoded as is, and the encoding ENC is
;; just used for the prefix, i.e. you are responsible for ensuring
;; STR is already encoded according to ENC. The optional argument
;; NL is the newline separator, defaulting to CRLF.
;; This API is compatible with the Gauche library rfc.base64.
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; string utils ;; string utils
@ -103,6 +81,11 @@
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; decoding ;; decoding
;;> Return a base64 decoded representation of string, also interpreting
;;> the alternate 62 & 63 valued characters as described in RFC3548.
;;> Other out-of-band characters are silently stripped, and = signals
;;> the end of the encoded string. No errors will be raised.
;; Create a result buffer with the maximum possible length for the ;; Create a result buffer with the maximum possible length for the
;; input, and pass it to the internal base64-decode-string! utility. ;; input, and pass it to the internal base64-decode-string! utility.
;; If the resulting length used is exact, we can return that buffer, ;; If the resulting length used is exact, we can return that buffer,
@ -199,9 +182,8 @@
(extract-bit-field 4 2 b3)))) (extract-bit-field 4 2 b3))))
(+ j 2)))))) (+ j 2))))))
;; General port decoder: work in single blocks at a time to avoid ;;> Variation of the above to read and write to ports.
;; allocating memory (crucial for Scheme implementations that don't
;; allow large strings).
(define (base64-decode . o) (define (base64-decode . o)
(let ((in (if (pair? o) (car o) (current-input-port))) (let ((in (if (pair? o) (car o) (current-input-port)))
(out (if (and (pair? o) (pair? (cdr o))) (out (if (and (pair? o) (pair? (cdr o)))
@ -253,6 +235,9 @@
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; encoding ;; encoding
;;> Return a base64 encoded representation of string according to the
;;> official base64 standard as described in RFC3548.
(define (base64-encode-string str) (define (base64-encode-string str)
(let* ((len (string-length str)) (let* ((len (string-length str))
(quot (quotient len 3)) (quot (quotient len 3))
@ -307,6 +292,8 @@
(string-set! res (+ j 3) (enc (bitwise-and #b111111 b3))) (string-set! res (+ j 3) (enc (bitwise-and #b111111 b3)))
(lp (+ i 3) (+ j 4))))))) (lp (+ i 3) (+ j 4)))))))
;;> Variation of the above to read and write to ports.
(define (base64-encode . o) (define (base64-encode . o)
(let ((in (if (pair? o) (car o) (current-input-port))) (let ((in (if (pair? o) (car o) (current-input-port)))
(out (if (and (pair? o) (pair? (cdr o))) (out (if (and (pair? o) (pair? (cdr o)))
@ -322,6 +309,15 @@
(if (= n 2048) (if (= n 2048)
(lp))))))) (lp)))))))
;;> Return a base64 encoded representation of the string \var{str} as
;;> above, wrapped in =?ENC?B?...?= as per RFC1522, split across
;;> multiple MIME-header lines as needed to keep each lines length
;;> less than \var{max-col}. The string is encoded as is, and the
;;> encoding \var{enc} is just used for the prefix, i.e. you are
;;> responsible for ensuring \var{str} is already encoded according to
;;> \var{enc}. The optional argument \var{nl} is the newline
;;> separator, defaulting to \var{crlf}.
(define (base64-encode-header encoding str . o) (define (base64-encode-header encoding str . o)
(define (round4 i) (arithmetic-shift (arithmetic-shift i -2) 2)) (define (round4 i) (arithmetic-shift (arithmetic-shift i -2) 2))
(let ((start-col (if (pair? o) (car o) 0)) (let ((start-col (if (pair? o) (car o) 0))

View file

@ -1,5 +1,5 @@
;; Additional accessors ;;> \section{Additional accessors}
(define (bytevector-u16-ref-le str i) (define (bytevector-u16-ref-le str i)
(+ (bytevector-u8-ref str i) (+ (bytevector-u8-ref str i)
@ -21,7 +21,7 @@
(arithmetic-shift (bytevector-u8-ref str (+ i 2)) 8) (arithmetic-shift (bytevector-u8-ref str (+ i 2)) 8)
(bytevector-u8-ref str (+ i 3)))) (bytevector-u8-ref str (+ i 3))))
;; Integer conversion ;;> \section{Integer conversion}
(define (integer->bytevector n) (define (integer->bytevector n)
(cond (cond
@ -49,7 +49,9 @@
(+ (arithmetic-shift n 8) (+ (arithmetic-shift n 8)
(bytevector-u8-ref bv i))))))) (bytevector-u8-ref bv i)))))))
;; Hex string conversion (big-endian, guaranteed padded to even length) ;;> \section{Hex string conversion}
;;> Big-endian conversion, guaranteed padded to even length.
(define (integer->hex-string n) (define (integer->hex-string n)
(let* ((res (number->string n 16)) (let* ((res (number->string n 16))

View file

@ -11,7 +11,7 @@
;;> loading these collections from files while allowing extensions ;;> loading these collections from files while allowing extensions
;;> such as configurations from command-line options. ;;> such as configurations from command-line options.
;;> \subsubsection{Background} ;;> \section{Background}
;;> ;;>
;;> As any application grows to sufficient complexity, it acquires ;;> As any application grows to sufficient complexity, it acquires
;;> options and behaviors that one may want to modify at startup or ;;> options and behaviors that one may want to modify at startup or
@ -40,7 +40,7 @@
;;> users of a group or whole system are likely to want to share, then ;;> users of a group or whole system are likely to want to share, then
;;> it makes sense to cascade multiple config files. ;;> it makes sense to cascade multiple config files.
;;> \subsubsection{Syntax} ;;> \section{Syntax}
;;> ;;>
;;> With any other language there is a question of config file syntax, ;;> With any other language there is a question of config file syntax,
;;> and a few popular choices exist such as .ini syntax. With Scheme ;;> and a few popular choices exist such as .ini syntax. With Scheme
@ -71,7 +71,7 @@
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;> \subsubsection{Interface} ;;> \section{Interface}
;;> Returns true iff \var{x} is a config object. ;;> Returns true iff \var{x} is a config object.
@ -112,7 +112,7 @@
(define (alist? x) (define (alist? x)
(and (list? x) (every pair? x))) (and (list? x) (every pair? x)))
;;> \subsubsubsection{\rawcode{(assoc-get alist key [equal? [default]])}} ;;> \procedure{(assoc-get alist key [equal? [default]])}
;;> Utility analogous to \scheme{conf-get} on a pure alist. Returns ;;> Utility analogous to \scheme{conf-get} on a pure alist. Returns
;;> the value of the cell in \var{alist} whose car is \var{equal?} to ;;> the value of the cell in \var{alist} whose car is \var{equal?} to
@ -138,7 +138,7 @@
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; Loading from files. ;; Loading from files.
;;> \subsubsubsection{\rawcode{(conf-load file [conf])}} ;;> \procedure{(conf-load file [conf])}
;;> Loads the config file \var{file}, prepending to \var{conf} if ;;> Loads the config file \var{file}, prepending to \var{conf} if
;;> provided. ;;> provided.
@ -168,7 +168,7 @@
(lp (cdr ls) (conf-load path res)) (lp (cdr ls) (conf-load path res))
(lp (cdr ls) res)))))))) (lp (cdr ls) res))))))))
;;> \subsubsubsection{\rawcode{(conf-load-cascaded config-path file [include-keyword])}} ;;> \procedure{(conf-load-cascaded config-path file [include-keyword])}
;;> Similar to conf-load-in-path, but also recursively loads any ;;> Similar to conf-load-in-path, but also recursively loads any
;;> "include" config files, indicated by a top-level ;;> "include" config files, indicated by a top-level
@ -230,7 +230,7 @@
(or (assq key (conf-alist config)) (or (assq key (conf-alist config))
(search (conf-parent config)))))))) (search (conf-parent config))))))))
;;> \subsubsubsection{\rawcode{(conf-get config key [default])}} ;;> \procedure{(conf-get config key [default])}
;;> Basic config lookup - retrieves the value from \var{config} ;;> Basic config lookup - retrieves the value from \var{config}
;;> associated with \var{key}. If not present, return \var{default}. ;;> associated with \var{key}. If not present, return \var{default}.
@ -247,7 +247,7 @@
(cadr cell) (cadr cell)
(cdr cell))))) (cdr cell)))))
;;> \subsubsubsection{\rawcode{(conf-get-list config key [default])}} ;;> \procedure{(conf-get-list config key [default])}
;;> Equivalent to \scheme{conf-get} but coerces its result to a list ;;> Equivalent to \scheme{conf-get} but coerces its result to a list
;;> as described in the syntax section. ;;> as described in the syntax section.
@ -338,7 +338,7 @@
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;> \subsubsection{Config Verification} ;;> \section{Config Verification}
(define (conf-default-warn . args) (define (conf-default-warn . args)
(for-each (for-each

View file

@ -92,10 +92,13 @@
(list (append (map cons vars vals) (car env)))) (list (append (map cons vars vals) (car env))))
(define (make-default-doc-env) (define (make-default-doc-env)
`(((section . ,(expand-section 'h1)) `(((title . ,(expand-section 'h1))
(subsection . ,(expand-section 'h2)) (section . ,(expand-section 'h2))
(subsubsection . ,(expand-section 'h3)) (subsection . ,(expand-section 'h3))
(subsubsubsection . ,(expand-section 'h4)) (subsubsection . ,(expand-section 'h4))
(subsubsubsection . ,(expand-section 'h5))
(procedure . ,expand-procedure)
(macro . ,expand-macro)
(centered . center) (centered . center)
(smaller . small) (smaller . small)
(larger . large) (larger . large)
@ -240,6 +243,12 @@
(else (else
sxml))) sxml)))
(define (expand-procedure sxml env)
((expand-section 'h3) `(,(car sxml) (rawcode ,@(cdr sxml))) env))
(define (expand-macro sxml env)
(expand-procedure sxml env))
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; adjustments for html ;; adjustments for html
@ -252,9 +261,18 @@
(match x (match x
(('div ('a ('@ ('name . name)) . _) (('div ('a ('@ ('name . name)) . _)
((and h (or 'h1 'h2 'h3 'h4 'h5 'h6)) . section)) ((and h (or 'h1 'h2 'h3 'h4 'h5 'h6)) . section))
`((,(header-index h) (let* ((raw-text (sxml-strip (cons h section)))
(a (@ (href . ,(string-append "#" name))) (text (if (string-prefix? "(" raw-text)
,(sxml-strip (cons h section)))))) (let ((end (string-find
raw-text
(lambda (ch)
(or (char-whitespace? ch)
(eqv? ch #\)))))))
(substring raw-text 1 end))
raw-text)))
`((,(header-index h)
(a (@ (href . ,(string-append "#" name)))
,text)))))
((a . b) ((a . b)
(append (extract-contents a) (extract-contents b))) (append (extract-contents a) (extract-contents b)))
(else (else
@ -282,9 +300,9 @@
(style (@ (type . "text/css")) (style (@ (type . "text/css"))
" "
body {color: #000; background-color: #FFF} body {color: #000; background-color: #FFF}
div#menu {font-size: smaller; position: absolute; top: 50px; left: 0; width: 180px; height: 100%} div#menu {font-size: smaller; position: absolute; top: 50px; left: 0; width: 190px; height: 100%}
div#main {position: absolute; top: 0; left: 200px; width: 520px; height: 100%} div#main {position: absolute; top: 0; left: 200px; width: 540px; height: 100%}
div#notes {position: relative; top: 2em; left: 550px; max-width: 200px; height: 0px; font-size: smaller;} div#notes {position: relative; top: 2em; left: 570px; max-width: 200px; height: 0px; font-size: smaller;}
div#footer {padding-bottom: 50px} div#footer {padding-bottom: 50px}
.result { color: #000; background-color: #FFEADF; width: 100%; padding: 3px} .result { color: #000; background-color: #FFEADF; width: 100%; padding: 3px}
.command { color: #000; background-color: #FFEADF; width: 100%; padding: 5px} .command { color: #000; background-color: #FFEADF; width: 100%; padding: 5px}
@ -293,7 +311,11 @@ div#footer {padding-bottom: 50px}
"\n") "\n")
(body (body
(div (@ (id . "menu")) (div (@ (id . "menu"))
,(get-contents (extract-contents x))) ,(let ((contents (get-contents (extract-contents x))))
(match contents
(('ol (li y sections ...))
sections)
(else contents))))
(div (@ (id . "main")) (div (@ (id . "main"))
,@(map (lambda (x) ,@(map (lambda (x)
(if (and (pair? x) (eq? 'title (car x))) (if (and (pair? x) (eq? 'title (car x)))
@ -469,7 +491,10 @@ div#footer {padding-bottom: 50px}
(define section-number (define section-number
(let ((sections '(section subsection subsubsection subsubsubsection))) (let ((sections '(section subsection subsubsection subsubsubsection)))
(lambda (x) (length (or (memq x sections) '()))))) (lambda (x)
(cond ((memq x sections) => length)
((memq x '(procedure macro)) (section-number 'subsection))
(else 0)))))
(define (section>=? x n) (define (section>=? x n)
(and (pair? x) (and (pair? x)
@ -479,7 +504,7 @@ div#footer {padding-bottom: 50px}
(define (extract-sxml tag x) (define (extract-sxml tag x)
(and (pair? x) (and (pair? x)
(cond ((eq? tag (car x)) x) (cond ((if (pair? tag) (memq (car x) tag) (eq? tag (car x))) x)
((memq (car x) '(div)) ((memq (car x) '(div))
(any (lambda (y) (extract-sxml tag y)) (sxml-body x))) (any (lambda (y) (extract-sxml tag y)) (sxml-body x)))
(else #f)))) (else #f))))
@ -536,14 +561,15 @@ div#footer {padding-bottom: 50px}
(let lp ((ls orig-ls) (rev-pre '())) (let lp ((ls orig-ls) (rev-pre '()))
(cond (cond
((or (null? ls) ((or (null? ls)
(section>=? (car ls) (section-number 'subsubsubsection))) (section>=? (car ls) (section-number 'subsection)))
`(,@(reverse rev-pre) `(,@(reverse rev-pre)
,@(if (and (pair? ls) ,@(if (and (pair? ls)
(section-describes? (section-describes?
(extract-sxml 'subsubsubsection (car ls)) (extract-sxml '(subsection procedure macro)
(car ls))
name)) name))
'() '()
`((subsubsubsection `((subsection
tag: ,(write-to-string name) tag: ,(write-to-string name)
(rawcode (rawcode
,@(if (eq? 'const: (caar sig)) ,@(if (eq? 'const: (caar sig))

View file

@ -16,7 +16,7 @@
(let-syntax ((call)) (let-syntax ((call))
. body)))))) . body))))))
;;> \subsubsubsection{\scheme{(define-method (name params ...) body ...)}} ;;> \macro{(define-method (name params ...) body ...)}
;;> Each parameter should be either a single identifier or a list of the form ;;> Each parameter should be either a single identifier or a list of the form
;;> \scheme{(param type)} where \var{param} is the parameter name and ;;> \scheme{(param type)} where \var{param} is the parameter name and

View file

@ -3,14 +3,14 @@
;;> runtime memory usage doesn't give a good idea of how to optimize ;;> runtime memory usage doesn't give a good idea of how to optimize
;;> that usage, so this module is provided for profiling. ;;> that usage, so this module is provided for profiling.
;;> \subsubsubsection{(heap-stats)} ;;> \procedure{(heap-stats)}
;;> Returns an alist summarizing all heap allocated objects. The ;;> Returns an alist summarizing all heap allocated objects. The
;;> \var{car} of each cell is the type-name, and the \var{cdr} is the ;;> \var{car} of each cell is the type-name, and the \var{cdr} is the
;;> count of objects of that type in the heap. Garbage is collected ;;> count of objects of that type in the heap. Garbage is collected
;;> before the counts are taken. ;;> before the counts are taken.
;;> \subsubsubsection{(heap-dump [depth])} ;;> \procedure{(heap-dump [depth])}
;;> Returns the same value as \scheme{(heap-stats)}, but also prints ;;> Returns the same value as \scheme{(heap-stats)}, but also prints
;;> all objects on the heap as it runs. \var{depth} indicates the ;;> all objects on the heap as it runs. \var{depth} indicates the

View file

@ -39,7 +39,7 @@
(display str out) (display str out)
(newline out))) (newline out)))
;;> \subsubsubsection{(write-string str [out [start [end]]])} ;;> \procedure{(write-string str [out [start [end]]])}
;;> Writes the characters from \var{start} to \var{end} of string ;;> Writes the characters from \var{start} to \var{end} of string
;;> \var{str} to output port \var{out}, where \var{start} defaults ;;> \var{str} to output port \var{out}, where \var{start} defaults
@ -60,7 +60,7 @@
(display (substring str start end) out)))) (display (substring str start end) out))))
(display str out)))) (display str out))))
;;> \subsubsubsection{(read-line [in [n]])} ;;> \procedure{(read-line [in [n]])}
;;> Read a line from the input port \var{in}, defaulting to ;;> Read a line from the input port \var{in}, defaulting to
;;> \scheme{(current-input-port)}, and return the result as ;;> \scheme{(current-input-port)}, and return the result as
@ -109,7 +109,7 @@
(else (else
res))))))) res)))))))
;;> \subsubsubsection{(read-string n [in])} ;;> \procedure{(read-string n [in])}
;;> Reads \var{n} characters from input-port \var{in}, ;;> Reads \var{n} characters from input-port \var{in},
;;> defaulting to \scheme{(current-input-port)}, and ;;> defaulting to \scheme{(current-input-port)}, and
@ -140,7 +140,7 @@
(port-line in))) (port-line in)))
(cadr res))))))) (cadr res)))))))
;;> \subsubsubsection{(read-string! str n [in])} ;;> \procedure{(read-string! str n [in])}
;;> Reads \var{n} characters from port \var{in}, which ;;> Reads \var{n} characters from port \var{in}, which
;;> defaults to \scheme{(current-input-port)}, and writes ;;> defaults to \scheme{(current-input-port)}, and writes

View file

@ -124,7 +124,7 @@
. rest)))) . rest))))
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;> \subsubsection{Iterators} ;;> \section{Iterators}
;; Each gets passed two lists, those items left of the macro and those to ;; Each gets passed two lists, those items left of the macro and those to
;; the right, followed by a NEXT and REST continuation. ;; the right, followed by a NEXT and REST continuation.
@ -172,7 +172,7 @@
() ()
. rest)))) . rest))))
;;> \subsubsubsection{\scheme{(for elts [pairs] (in-lists lol [cdr [done?]]))}} ;;> \macro{(for elts [pairs] (in-lists lol [cdr [done?]]))}
;;> Iterator from Taylor R. Campbell. If you know the number of lists ;;> Iterator from Taylor R. Campbell. If you know the number of lists
;;> ahead of time it's much more efficient to iterate over each one ;;> ahead of time it's much more efficient to iterate over each one
@ -215,12 +215,12 @@
(%in-idx < (lambda (x i) (- i 1)) (lambda (x) (- (length x) 1)) (lambda (x) 0) ref tmp seq next . rest)))) (%in-idx < (lambda (x i) (- i 1)) (lambda (x) (- (length x) 1)) (lambda (x) 0) ref tmp seq next . rest))))
)))) ))))
;;> \subsubsubsection{\scheme{(for var [index] (in-vector vec))}} ;;> \macro{(for var [index] (in-vector vec))}
;;> \subsubsubsection{\scheme{(for var [index] (in-vector-reverse vec))}} ;;> \macro{(for var [index] (in-vector-reverse vec))}
(define-in-indexed in-vector in-vector-reverse vector-length vector-ref) (define-in-indexed in-vector in-vector-reverse vector-length vector-ref)
;;> \subsubsubsection{\scheme{(for ch [cursor] (in-string str))}} ;;> \macro{(for ch [cursor] (in-string str))}
(define-syntax in-string (define-syntax in-string
(syntax-rules () (syntax-rules ()
@ -229,7 +229,7 @@
string-cursor-start string-cursor-end string-cursor-ref string-cursor-start string-cursor-end string-cursor-ref
tmp s next . rest)))) tmp s next . rest))))
;;> \subsubsubsection{\scheme{(for ch [cursor] (in-string-reverse str))}} ;;> \macro{(for ch [cursor] (in-string-reverse str))}
(define-syntax in-string-reverse (define-syntax in-string-reverse
(syntax-rules () (syntax-rules ()
@ -258,7 +258,7 @@
. rest)) . rest))
)) ))
;;> \subsubsubsection{\scheme{(for ch (in-port [input-port [reader [eof?]]]))}} ;;> \macro{(for ch (in-port [input-port [reader [eof?]]]))}
(define-syntax in-port (define-syntax in-port
(syntax-rules () (syntax-rules ()
@ -278,7 +278,7 @@
() ()
. rest)))) . rest))))
;;> \subsubsubsection{\scheme{(for ch (in-file [input-port [reader [eof?]]]))}} ;;> \macro{(for ch (in-file [input-port [reader [eof?]]]))}
(define-syntax in-file (define-syntax in-file
(syntax-rules () (syntax-rules ()
@ -296,7 +296,7 @@
((dummy (close-input-port p))) ((dummy (close-input-port p)))
. rest)))) . rest))))
;;> \subsubsubsection{\scheme{(for x (up-from [start] [(to limit)] [(by step)]))}} ;;> \macro{(for x (up-from [start] [(to limit)] [(by step)]))}
(define-syntax up-from (define-syntax up-from
(syntax-rules (to by) (syntax-rules (to by)
@ -322,7 +322,7 @@
(next ((s start)) ((var s (+ var 1))) () () () . rest)) (next ((s start)) ((var s (+ var 1))) () () () . rest))
)) ))
;;> \subsubsubsection{\scheme{(for x (down-from [start] [(to limit)] [(by step)]))}} ;;> \macro{(for x (down-from [start] [(to limit)] [(by step)]))}
(define-syntax down-from (define-syntax down-from
(syntax-rules (to by) (syntax-rules (to by)
@ -371,14 +371,14 @@
((var (final cursor))) ((var (final cursor)))
. rest)))) . rest))))
;;> \subsubsubsection{\scheme{(for x [pair] (listing expr))}} ;;> \macro{(for x [pair] (listing expr))}
(define-syntax listing (define-syntax listing
(syntax-rules () (syntax-rules ()
((listing args next . rest) ((listing args next . rest)
(accumulating (cons reverse '()) args next . rest)))) (accumulating (cons reverse '()) args next . rest))))
;;> \subsubsubsection{\scheme{(for x [pair] (listing-reverse expr))}} ;;> \macro{(for x [pair] (listing-reverse expr))}
(define-syntax listing-reverse (define-syntax listing-reverse
(syntax-rules () (syntax-rules ()
@ -388,28 +388,28 @@
(define (append-reverse rev tail) (define (append-reverse rev tail)
(if (null? rev) tail (append-reverse (cdr rev) (cons (car rev) tail)))) (if (null? rev) tail (append-reverse (cdr rev) (cons (car rev) tail))))
;;> \subsubsubsection{\scheme{(for x [pair] (appending expr))}} ;;> \macro{(for x [pair] (appending expr))}
(define-syntax appending (define-syntax appending
(syntax-rules () (syntax-rules ()
((appending args next . rest) ((appending args next . rest)
(accumulating (append-reverse reverse '()) args next . rest)))) (accumulating (append-reverse reverse '()) args next . rest))))
;;> \subsubsubsection{\scheme{(for x [pair] (appending-reverse expr))}} ;;> \macro{(for x [pair] (appending-reverse expr))}
(define-syntax appending-reverse (define-syntax appending-reverse
(syntax-rules () (syntax-rules ()
((appending-reverse args next . rest) ((appending-reverse args next . rest)
(accumulating (append-reverse (lambda (x) x) '()) args next . rest)))) (accumulating (append-reverse (lambda (x) x) '()) args next . rest))))
;;> \subsubsubsection{\scheme{(for x (summing expr))}} ;;> \macro{(for x (summing expr))}
(define-syntax summing (define-syntax summing
(syntax-rules () (syntax-rules ()
((summing args next . rest) ((summing args next . rest)
(accumulating (+ (lambda (x) x) 0) args next . rest)))) (accumulating (+ (lambda (x) x) 0) args next . rest))))
;;> \subsubsubsection{\scheme{(for x (multiplying expr))}} ;;> \macro{(for x (multiplying expr))}
(define-syntax multiplying (define-syntax multiplying
(syntax-rules () (syntax-rules ()

View file

@ -14,7 +14,7 @@
;;> patterns - patterns in which the same identifier occurs multiple ;;> patterns - patterns in which the same identifier occurs multiple
;;> times, tail patterns after ellipsis, and the experimental tree patterns. ;;> times, tail patterns after ellipsis, and the experimental tree patterns.
;;> \subsubsection{Patterns} ;;> \section{Patterns}
;;> Patterns are written to look like the printed representation of ;;> Patterns are written to look like the printed representation of
;;> the objects they match. The basic usage is ;;> the objects they match. The basic usage is
@ -239,10 +239,10 @@
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;> \subsubsection{Syntax} ;;> \section{Syntax}
;;> \subsubsubsection{\rawcode{(match expr (pattern . body) ...)\br{} ;;> \macro{(match expr (pattern . body) ...)\br{}
;;> (match expr (pattern (=> failure) . body) ...)}} ;;> (match expr (pattern (=> failure) . body) ...)}
;;> The result of \var{expr} is matched against each \var{pattern} in ;;> The result of \var{expr} is matched against each \var{pattern} in
;;> turn, according to the pattern rules described in the previous ;;> turn, according to the pattern rules described in the previous
@ -846,7 +846,7 @@
((_ loop (v ...) ((pat expr) . rest) . body) ((_ loop (v ...) ((pat expr) . rest) . body)
(match-named-let loop (v ... (pat expr tmp)) rest . body)))) (match-named-let loop (v ... (pat expr tmp)) rest . body))))
;;> \subsubsubsection{\rawcode{(match-let* ((var value) ...) body ...)}} ;;> \macro{(match-let* ((var value) ...) body ...)}
;;> Similar to \scheme{match-let}, but analogously to \scheme{let*} ;;> Similar to \scheme{match-let}, but analogously to \scheme{let*}
;;> matches and binds the variables in sequence, with preceding match ;;> matches and binds the variables in sequence, with preceding match

View file

@ -2,8 +2,7 @@
;; Copyright (c) 2004-2014 Alex Shinn. All rights reserved. ;; Copyright (c) 2004-2014 Alex Shinn. All rights reserved.
;; BSD-style license: http://synthcode.com/license.txt ;; BSD-style license: http://synthcode.com/license.txt
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;;> Prime and number theoretic utilities.
;; Number theoretic utilities
;;> Returns a pair whose car is the power of 2 in the factorization of ;;> Returns a pair whose car is the power of 2 in the factorization of
;;> n, and whose cdr is the product of all remaining primes. ;;> n, and whose cdr is the product of all remaining primes.

View file

@ -2,9 +2,9 @@
;; Copyright (c) 2003-2013 Alex Shinn. All rights reserved. ;; Copyright (c) 2003-2013 Alex Shinn. All rights reserved.
;; BSD-style license: http://synthcode.com/license.txt ;; BSD-style license: http://synthcode.com/license.txt
;; Memory and persistent caching with various levels of control, based ;;> Memory and persistent caching with various levels of control, based
;; on a combination of lru-cache from Hato and an older memoization ;;> on a combination of lru-cache from Hato and an older memoization
;; library for Gauche. ;;> library for Gauche.
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; types ;; types

View file

@ -11,7 +11,7 @@
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; association lists ;; association lists
;;> \subsubsubsection{\scheme{(assq-ref ls key [default])}} ;;> \procedure{(assq-ref ls key [default])}
;;> Returns the \scheme{cdr} of the cell in \var{ls} whose ;;> Returns the \scheme{cdr} of the cell in \var{ls} whose
;;> \scheme{car} is \scheme{eq?} to \var{key}, or \var{default} ;;> \scheme{car} is \scheme{eq?} to \var{key}, or \var{default}
;;> if not found. Useful for retrieving values associated with ;;> if not found. Useful for retrieving values associated with
@ -73,9 +73,9 @@
str) str)
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;> \subsubsection{RFC2822 Headers} ;;> \section{RFC2822 Headers}
;;> \subsubsubsection{\scheme{(mime-header-fold kons knil [source [limit [kons-from]]])}} ;;> \procedure{(mime-header-fold kons knil [source [limit [kons-from]]])}
;;> ;;>
;;> Performs a fold operation on the MIME headers of source which can be ;;> Performs a fold operation on the MIME headers of source which can be
;;> either a string or port, and defaults to current-input-port. \var{kons} ;;> either a string or port, and defaults to current-input-port. \var{kons}
@ -139,7 +139,7 @@
(else (else
(out first-line knil 0))))) (out first-line knil 0)))))
;;> \subsubsubsection{\scheme{(mime-headers->list [source])}} ;;> \procedure{(mime-headers->list [source])}
;;> Return an alist of the MIME headers from source with headers all ;;> Return an alist of the MIME headers from source with headers all
;;> downcased. ;;> downcased.
@ -163,7 +163,7 @@
(substring s (+ i 1) (string-length s))))) (substring s (+ i 1) (string-length s)))))
(cons (string->symbol (string-downcase-ascii (string-trim s))) "")))) (cons (string->symbol (string-downcase-ascii (string-trim s))) ""))))
;;> \subsubsubsection{\scheme{(mime-parse-content-type str)}} ;;> \procedure{(mime-parse-content-type str)}
;;> Parses \var{str} as a Content-Type style-value returning the list ;;> Parses \var{str} as a Content-Type style-value returning the list
;;> \scheme{(type (attr . val) ...)}. ;;> \scheme{(type (attr . val) ...)}.
@ -179,7 +179,7 @@
(cons (caar res) (cdr res)) (cons (caar res) (cdr res))
res))) res)))
;;> \subsubsubsection{\scheme{(mime-decode-header str)}} ;;> \procedure{(mime-decode-header str)}
;;> Replace all occurrences of RFC1522 =?ENC?...?= escapes in \var{str} with ;;> Replace all occurrences of RFC1522 =?ENC?...?= escapes in \var{str} with
;;> the appropriate decoded and charset converted value. ;;> the appropriate decoded and charset converted value.
@ -250,9 +250,9 @@
(lambda (x) (next (mime-convert-part x cte enc))) (lambda (x) (next (mime-convert-part x cte enc)))
(lambda (x) (final (mime-convert-part x cte enc))))) (lambda (x) (final (mime-convert-part x cte enc)))))
;;> \subsubsection{RFC2045 MIME Encoding} ;;> \section{RFC2045 MIME Encoding}
;;> \subsubsubsection{\scheme{(mime-message-fold src kons knil [down up headers])}} ;;> \procedure{(mime-message-fold src kons knil [down up headers])}
;;> Performs a tree fold operation on the given string or port ;;> Performs a tree fold operation on the given string or port
;;> \var{src} as a MIME body corresponding to the headers give in ;;> \var{src} as a MIME body corresponding to the headers give in
;;> \var{headers}. If \var{headers} are false or not provided they ;;> \var{headers}. If \var{headers} are false or not provided they
@ -339,7 +339,7 @@
(lambda (x) (next (kons parent-headers headers x seed))) (lambda (x) (next (kons parent-headers headers x seed)))
(lambda (x) (final (kons parent-headers headers x seed))))))))))) (lambda (x) (final (kons parent-headers headers x seed)))))))))))
;;> \subsubsubsection{\scheme{(mime-message->sxml [src [headers]])}} ;;> \procedure{(mime-message->sxml [src [headers]])}
;;> ;;>
;;> Parse the given source as a MIME message and return ;;> Parse the given source as a MIME message and return
;;> the result as an SXML object of the form: ;;> the result as an SXML object of the form:

View file

@ -1,45 +1,19 @@
;; quoted-printable.scm -- RFC2045 implementation ;; quoted-printable.scm -- RFC2045 implementation
;; Copyright (c) 2005-2009 Alex Shinn. All rights reserved. ;; Copyright (c) 2005-2014 Alex Shinn. All rights reserved.
;; BSD-style license: http://synthcode.com/license.txt ;; BSD-style license: http://synthcode.com/license.txt
;; Procedure: quoted-printable-encode-string str [start-col max-col] ;;> RFC 2045 quoted printable encoding and decoding utilities. This
;; Return a quoted-printable encoded representation of string ;;> API is backwards compatible with the Gauche library
;; according to the official standard as described in RFC2045. ;;> rfc.quoted-printable.
;;
;; ? and _ are always encoded for compatibility with RFC1522 encoding,
;; and soft newlines are inserted as necessary to keep each lines
;; length less than MAX-COL (default 76). The starting column may be
;; overridden with START-COL (default 0).
;; Procedure: quoted-printable-decode-string str [mime?] ;;> \schemeblock{
;; Return a quoted-printable decoded representation of string. If ;;> (define (mime-encode-header header value charset)
;; MIME? is specified and true, _ will be decoded as as space in ;;> (let ((prefix (string-append header ": "))
;; accordance with RFC1522. No errors will be raised on invalid ;;> (str (ces-convert value "UTF8" charset)))
;; input. ;;> (string-append
;;> prefix
;; Procedure: quoted-printable-encode [port start-col max-col] ;;> (quoted-printable-encode-header charset str (string-length prefix)))))
;; Procedure: quoted-printable-decode [port start-col max-col] ;;> }
;; Variations of the above which read and write to ports.
;; Procedure: quoted-printable-encode-header enc str [start-col max-col]
;; Return a quoted-printable encoded representation of string as
;; above, wrapped in =?ENC?Q?...?= as per RFC1522, split across
;; multiple MIME-header lines as needed to keep each lines length less
;; than MAX-COL. The string is encoded as is, and the encoding ENC is
;; just used for the prefix, i.e. you are responsible for ensuring STR
;; is already encoded according to ENC.
;; Example:
;; (define (mime-encode-header header value charset)
;; (let ((prefix (string-append header ": "))
;; (str (ces-convert value "UTF8" charset)))
;; (string-append
;; prefix
;; (quoted-printable-encode-header charset str (string-length prefix)))))
;; This API is backwards compatible with the Gauche library
;; rfc.quoted-printable.
(define *default-max-col* 76) (define *default-max-col* 76)
@ -69,6 +43,14 @@
(string-set! buf (+ col 2) (hex (bitwise-and c #b1111))) (string-set! buf (+ col 2) (hex (bitwise-and c #b1111)))
(lp (+ i 1) (+ col 3) res))))))))) (lp (+ i 1) (+ col 3) res)))))))))
;;> Return a quoted-printable encoded representation of the input
;;> according to the official standard as described in RFC2045.
;;>
;;> ? and _ are always encoded for compatibility with RFC1522
;;> encoding, and soft newlines are inserted as necessary to keep each
;;> lines length less than \var{max-col} (default 76). The starting
;;> column may be overridden with \var{start-col} (default 0).
(define (quoted-printable-encode-string . o) (define (quoted-printable-encode-string . o)
(let ((src (if (pair? o) (car o) (current-input-port))) (let ((src (if (pair? o) (car o) (current-input-port)))
(start-col (if (and (pair? o) (pair? (cdr o))) (cadr o) 0)) (start-col (if (and (pair? o) (pair? (cdr o))) (cadr o) 0))
@ -78,9 +60,19 @@
(qp-encode (if (string? src) src (read-string #f src)) (qp-encode (if (string? src) src (read-string #f src))
start-col max-col "=\r\n"))) start-col max-col "=\r\n")))
;;> Variation of the above to read and write to ports.
(define (quoted-printable-encode . o) (define (quoted-printable-encode . o)
(display (apply (quoted-printable-encode-string o)))) (display (apply (quoted-printable-encode-string o))))
;;> Return a quoted-printable encoded representation of string as
;;> above, wrapped in =?ENC?Q?...?= as per RFC1522, split across
;;> multiple MIME-header lines as needed to keep each lines length
;;> less than \var{max-col}. The string is encoded as is, and the
;;> encoding \var{enc} is just used for the prefix, i.e. you are
;;> responsible for ensuring \var{str} is already encoded according to
;;> \var{enc}.
(define (quoted-printable-encode-header encoding . o) (define (quoted-printable-encode-header encoding . o)
(let ((src (if (pair? o) (car o) (current-input-port))) (let ((src (if (pair? o) (car o) (current-input-port)))
(start-col (if (and (pair? o) (pair? (cdr o))) (cadr o) 0)) (start-col (if (and (pair? o) (pair? (cdr o))) (cadr o) 0))
@ -99,6 +91,11 @@
start-col effective-max-col separator) start-col effective-max-col separator)
"?=")))) "?="))))
;;> Return a quoted-printable decoded representation of \var{str}. If
;;> \var{mime-header?} is specified and true, _ will be decoded as as
;;> space in accordance with RFC1522. No errors will be raised on
;;> invalid input.
(define (quoted-printable-decode-string . o) (define (quoted-printable-decode-string . o)
(define (hex? c) (or (char-numeric? c) (<= 65 (char->integer c) 70))) (define (hex? c) (or (char-numeric? c) (<= 65 (char->integer c) 70)))
(define (unhex1 c) (define (unhex1 c)
@ -152,6 +149,7 @@
(write-char c out) (write-char c out)
(lp (+ i 1))))))))))))) (lp (+ i 1)))))))))))))
;;> Variation of the above to read and write to ports.
(define (quoted-printable-decode . o) (define (quoted-printable-decode . o)
(display (apply quoted-printable-decode-string o))) (display (apply quoted-printable-decode-string o)))

View file

@ -44,7 +44,7 @@
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; test interface ;; test interface
;;> \subsubsubsection{\scheme{(test [name] expect expr)}} ;;> \macro{(test [name] expect expr)}
;;> Evaluate \var{expr} and check that it is \scheme{equal?} ;;> Evaluate \var{expr} and check that it is \scheme{equal?}
;;> to \var{expect}. \var{name} is used in reporting, and ;;> to \var{expect}. \var{name} is used in reporting, and
@ -68,7 +68,7 @@
((test a ...) ((test a ...)
(test-syntax-error 'test "test requires 2 or 3 arguments" (test a ...))))) (test-syntax-error 'test "test requires 2 or 3 arguments" (test a ...)))))
;;> \subsubsubsection{\scheme{(test-equal equal [name] expect expr)}} ;;> \macro{(test-equal equal [name] expect expr)}
;;> Equivalent to test, using \var{equal} for comparison instead of ;;> Equivalent to test, using \var{equal} for comparison instead of
;;> \scheme{equal?}. ;;> \scheme{equal?}.
@ -79,7 +79,7 @@
(parameterize ((current-test-comparator equal)) (parameterize ((current-test-comparator equal))
(test . args))))) (test . args)))))
;;> \subsubsubsection{\scheme{(test-assert [name] expr)}} ;;> \macro{(test-assert [name] expr)}
;;> Like \scheme{test} but evaluates \var{expr} and checks that it's true. ;;> Like \scheme{test} but evaluates \var{expr} and checks that it's true.
@ -93,7 +93,7 @@
(test-syntax-error 'test-assert "1 or 2 arguments required" (test-syntax-error 'test-assert "1 or 2 arguments required"
(test a ...))))) (test a ...)))))
;;> \subsubsubsection{\scheme{(test-not [name] expr)}} ;;> \macro{(test-not [name] expr)}
;;> Like \scheme{test} but evaluates \var{expr} and checks that it's false. ;;> Like \scheme{test} but evaluates \var{expr} and checks that it's false.
@ -102,7 +102,7 @@
((_ expr) (test-assert (not expr))) ((_ expr) (test-assert (not expr)))
((_ name expr) (test-assert name (not expr))))) ((_ name expr) (test-assert name (not expr)))))
;;> \subsubsubsection{\scheme{(test-values [name] expect expr)}} ;;> \macro{(test-values [name] expect expr)}
;;> Like \scheme{test} but \var{expect} and \var{expr} can both ;;> Like \scheme{test} but \var{expect} and \var{expr} can both
;;> return multiple values. ;;> return multiple values.
@ -115,7 +115,7 @@
(test name (call-with-values (lambda () expect) (lambda results results)) (test name (call-with-values (lambda () expect) (lambda results results))
(call-with-values (lambda () expr) (lambda results results)))))) (call-with-values (lambda () expr) (lambda results results))))))
;;> \subsubsubsection{\scheme{(test-error [name] expr)}} ;;> \macro{(test-error [name] expr)}
;;> Like \scheme{test} but evaluates \var{expr} and checks that it ;;> Like \scheme{test} but evaluates \var{expr} and checks that it
;;> raises an error. ;;> raises an error.
@ -148,7 +148,7 @@
(var-values . ,(list vars ...)) (var-values . ,(list vars ...))
(key . val) ...))))) (key . val) ...)))))
;;> \subsubsubsection{\scheme{(test-exit)}} ;;> \macro{(test-exit)}
;;> Exits with a failure status if any tests have failed, ;;> Exits with a failure status if any tests have failed,
;;> and a successful status otherwise. ;;> and a successful status otherwise.

View file

@ -20,7 +20,7 @@
;;> Accessors for the URI type. ;;> Accessors for the URI type.
;;/ ;;/
;;> \subsubsubsection{\scheme{(make-uri scheme [user host port path query fragment])}} ;;> \procedure{(make-uri scheme [user host port path query fragment])}
(define (make-uri scheme . o) (define (make-uri scheme . o)
(let* ((user (if (pair? o) (car o) #f)) (let* ((user (if (pair? o) (car o) #f))
@ -209,7 +209,7 @@
res res
(cons (substring-cursor str from to) res))) (cons (substring-cursor str from to) res)))
;;> \subsubsubsection{\scheme{(uri-encode str [plus?])}} ;;> \procedure{(uri-encode str [plus?])}
;;> Return the URI encoded version of the string \var{str}, ;;> Return the URI encoded version of the string \var{str},
;;> using hex escapes as needed and replacing spaces with "+" ;;> using hex escapes as needed and replacing spaces with "+"
@ -243,7 +243,7 @@
(lp next next (cons (encode-1 ch) (lp next next (cons (encode-1 ch)
(collect str from to res))))))))) (collect str from to res)))))))))
;;> \subsubsubsection{\scheme{(uri-decode str [plus?])}} ;;> \procedure{(uri-decode str [plus?])}
;;> Decodes any URI hex escapes in the given string, and ;;> Decodes any URI hex escapes in the given string, and
;;> translates any pluses ("+") to space iff the optional ;;> translates any pluses ("+") to space iff the optional
@ -277,7 +277,7 @@
(else (else
(lp from next res)))))))) (lp from next res))))))))
;;> \subsubsubsection{\scheme{(uri-query->alist str [plus?])}} ;;> \procedure{(uri-query->alist str [plus?])}
;;> Parses the query part of a URI as a delimited list of ;;> Parses the query part of a URI as a delimited list of
;;> URI encoded \rawcode{VAR=VALUE} pairs, decodes them and ;;> URI encoded \rawcode{VAR=VALUE} pairs, decodes them and
@ -299,7 +299,7 @@
(cons (uri-decode (substring-cursor str i j) plus?) #f)))) (cons (uri-decode (substring-cursor str i j) plus?) #f))))
(lp (+ j 1) (cons cell res))))))) (lp (+ j 1) (cons cell res)))))))
;;> \subsubsubsection{\scheme{(uri-alist->query ls [plus?])}} ;;> \procedure{(uri-alist->query ls [plus?])}
;;> The reverse of the above, formats the alist as a URI ;;> The reverse of the above, formats the alist as a URI
;;> query string. ;;> query string.