Merge branch 'master' of git:plt
This commit is contained in:
commit
4537240f1f
|
@ -123,8 +123,8 @@
|
|||
(define cwd (path->string (current-directory)))
|
||||
(define (rewrite s)
|
||||
(regexp-replace** ([rev "<current-rev>"]
|
||||
[home "<home>"]
|
||||
[tmp "<tmp>"]
|
||||
[home "<home>"]
|
||||
[cwd "<cwd>"])
|
||||
s))
|
||||
|
||||
|
|
|
@ -1798,6 +1798,7 @@ path/s is either such a string or a list of them.
|
|||
"collects/tests/scribble" responsible (eli mflatt)
|
||||
"collects/tests/srfi" responsible (noel chongkai jay)
|
||||
"collects/tests/srpersist" responsible (unknown)
|
||||
"collects/tests/slatex" responsible (jay sstrickl)
|
||||
"collects/tests/syntax-color" responsible (sowens mflatt)
|
||||
"collects/tests/test-engine" responsible (kathyg)
|
||||
"collects/tests/unstable/generics.ss" responsible (jay)
|
||||
|
|
|
@ -1,12 +1,18 @@
|
|||
|
||||
(module slatex-wrapper scheme/base
|
||||
(require mzlib/file
|
||||
scheme/contract
|
||||
mzlib/process
|
||||
mzlib/sendevent
|
||||
"slatex.ss")
|
||||
|
||||
(provide slatex latex pdf-slatex pdf-latex slatex/no-latex
|
||||
filename->latex-filename)
|
||||
(provide/contract
|
||||
[slatex (string? . -> . boolean?)]
|
||||
[pdf-slatex (string? . -> . boolean?)]
|
||||
[slatex/no-latex (string? . -> . boolean?)]
|
||||
[latex (string? . -> . boolean?)]
|
||||
[pdf-latex (string? . -> . boolean?)]
|
||||
[filename->latex-filename (string? . -> . string?)])
|
||||
|
||||
(define (add-suffix p s)
|
||||
(path->string
|
||||
|
|
63
collects/tests/slatex/test.rkt
Normal file
63
collects/tests/slatex/test.rkt
Normal file
|
@ -0,0 +1,63 @@
|
|||
#lang racket
|
||||
(require slatex/slatex-wrapper
|
||||
tests/eli-tester
|
||||
scheme/runtime-path)
|
||||
|
||||
(define-runtime-path slatex-file-pth '(lib "slatex"))
|
||||
(define slatex-pth (path-only slatex-file-pth))
|
||||
|
||||
(define tmp-file (build-path (current-directory) "test.tex")
|
||||
#;(make-temporary-file "slatex~a.tex" #f (current-directory)))
|
||||
|
||||
(test
|
||||
(putenv "TEXINPUTS" (format "~a:" (path->string slatex-pth)))
|
||||
tmp-file
|
||||
|
||||
(with-output-to-file tmp-file #:exists 'truncate/replace
|
||||
(lambda ()
|
||||
(display #<<END
|
||||
\documentclass{article}
|
||||
\usepackage{slatex}
|
||||
%
|
||||
%That was LaTeX2e. If you use
|
||||
%LaTeX2.09, or LaTeX2e in
|
||||
%2.09 compatibility mode, use
|
||||
%
|
||||
%\documentstyle[slatex]{article}
|
||||
%
|
||||
%or
|
||||
%
|
||||
%\documentstyle{article}
|
||||
%\input slatex.sty
|
||||
\begin{document}
|
||||
|
||||
In Scheme, the expression
|
||||
\scheme|(set! x 42)| returns
|
||||
an unspecified value, rather
|
||||
than \scheme'42'. However,
|
||||
one could get a \scheme{set!}
|
||||
of the latter style with:
|
||||
|
||||
\begin{schemedisplay}
|
||||
(define-syntax setq
|
||||
(syntax-rules ()
|
||||
[(setq x a)
|
||||
(begin (set! x a)
|
||||
x)]))
|
||||
\end{schemedisplay}
|
||||
|
||||
\end{document}
|
||||
END
|
||||
)))
|
||||
|
||||
(slatex (path->string tmp-file))
|
||||
|
||||
(with-handlers ([exn:fail:filesystem? void])
|
||||
(delete-file (path-replace-suffix tmp-file #".aux")))
|
||||
(with-handlers ([exn:fail:filesystem? void])
|
||||
(delete-file (path-replace-suffix tmp-file #".log")))
|
||||
(with-handlers ([exn:fail:filesystem? void])
|
||||
(delete-file (path-replace-suffix tmp-file #".dvi")))
|
||||
|
||||
(delete-file tmp-file))
|
||||
|
|
@ -301,6 +301,73 @@
|
|||
#f "127.0.0.1" 80 "127.0.0.1"))
|
||||
(list "Jay" (make-date 10 6) (make-date 10 8))))))
|
||||
|
||||
; Multiple value formlets
|
||||
(local [(define (date->xml m d)
|
||||
(format "~a/~a" m d))
|
||||
(define (submit t)
|
||||
`(input ([type "submit"]) ,t))
|
||||
(define date-formlet
|
||||
(formlet
|
||||
(div
|
||||
"Month:" ,{input-int . => . month}
|
||||
"Day:" ,{input-int . => . day})
|
||||
(values month day)))
|
||||
|
||||
(define travel-formlet
|
||||
(formlet
|
||||
(div
|
||||
"Name:" ,{input-string . => . name}
|
||||
(div
|
||||
"Arrive:" ,{date-formlet . => . (values arrive-m arrive-d)}
|
||||
"Depart:" ,{date-formlet . => . (values depart-m depart-d)})
|
||||
,@(list "1" "2" "3")
|
||||
,(submit "Submit"))
|
||||
(values name arrive-m arrive-d depart-m depart-d)))
|
||||
|
||||
(define-syntax-rule (check-equal?/values actual-expr expected-expr)
|
||||
(call-with-values (lambda () actual-expr)
|
||||
(lambda actual
|
||||
(call-with-values (lambda () expected-expr)
|
||||
(lambda expected
|
||||
(check-equal? actual expected))))))]
|
||||
(test-suite
|
||||
"Date (values)"
|
||||
|
||||
(test-case "date->xml"
|
||||
(check-equal? (date->xml 1 2)
|
||||
"1/2"))
|
||||
(test-case "date-formlet"
|
||||
(check-equal? (formlet-display date-formlet)
|
||||
'((div () "Month:" (input ((name "input_0") (type "text"))) "Day:" (input ((name "input_1") (type "text")))))))
|
||||
(test-case "travel-formlet"
|
||||
(check-equal? (formlet-display travel-formlet)
|
||||
'((div
|
||||
()
|
||||
"Name:"
|
||||
(input ((name "input_0") (type "text")))
|
||||
(div
|
||||
()
|
||||
"Arrive:"
|
||||
(div () "Month:" (input ((name "input_1") (type "text"))) "Day:" (input ((name "input_2") (type "text"))))
|
||||
"Depart:"
|
||||
(div () "Month:" (input ((name "input_3") (type "text"))) "Day:" (input ((name "input_4") (type "text")))))
|
||||
"1"
|
||||
"2"
|
||||
"3"
|
||||
(input ((type "submit")) "Submit")))))
|
||||
(test-case "travel-formlet (proc)"
|
||||
(check-equal?/values (formlet-process travel-formlet
|
||||
(make-request #"GET" (string->url "http://test.com")
|
||||
empty
|
||||
(delay
|
||||
(list (make-binding:form #"input_0" #"Jay")
|
||||
(make-binding:form #"input_1" #"10")
|
||||
(make-binding:form #"input_2" #"6")
|
||||
(make-binding:form #"input_3" #"10")
|
||||
(make-binding:form #"input_4" #"8")))
|
||||
#f "127.0.0.1" 80 "127.0.0.1"))
|
||||
(values "Jay" 10 6 10 8)))))
|
||||
|
||||
))
|
||||
|
||||
(require schemeunit/text-ui)
|
||||
|
|
|
@ -13,13 +13,11 @@
|
|||
|
||||
(define (cross f p)
|
||||
(lambda (i)
|
||||
(let*-values ([(x1 g i) (f i)]
|
||||
[(x2 q i) (p i)])
|
||||
(let*-values ([(x1 a1 i) (f i)]
|
||||
[(x2 a2 i) (p i)])
|
||||
(values (append x1 x2)
|
||||
(lambda (env)
|
||||
(let ([ge (g env)]
|
||||
[qe (q env)])
|
||||
(ge qe)))
|
||||
(call-with-values (lambda () (a2 env)) (a1 env)))
|
||||
i))))
|
||||
|
||||
;; This is gross because OCaml auto-curries
|
||||
|
@ -70,23 +68,25 @@
|
|||
(define xexpr-forest/c
|
||||
(listof pretty-xexpr/c))
|
||||
|
||||
(define (formlet/c c)
|
||||
(define-syntax-rule (formlet/c* c)
|
||||
(integer? . -> .
|
||||
(values xexpr-forest/c
|
||||
((listof binding?) . -> . (coerce-contract 'formlet/c c))
|
||||
((listof binding?) . -> . c)
|
||||
integer?)))
|
||||
(define formlet*/c (formlet/c* any))
|
||||
(define (formlet/c . c)
|
||||
(formlet/c* (apply values (map (curry coerce-contract 'formlet/c) c))))
|
||||
|
||||
(define alpha any/c)
|
||||
(define beta any/c)
|
||||
|
||||
(provide/contract
|
||||
[xexpr-forest/c contract?]
|
||||
[formlet/c (any/c . -> . contract?)]
|
||||
[formlet*/c contract?]
|
||||
[formlet/c (() () #:rest (listof any/c) . ->* . contract?)]
|
||||
[pure (alpha
|
||||
. -> . (formlet/c alpha))]
|
||||
[cross ((formlet/c (alpha . -> . beta))
|
||||
(formlet/c alpha)
|
||||
. -> . (formlet/c beta))]
|
||||
[cross ((formlet/c procedure?) formlet*/c . -> . formlet*/c)]
|
||||
[cross* (((formlet/c (() () #:rest (listof alpha) . ->* . beta)))
|
||||
() #:rest (listof (formlet/c alpha))
|
||||
. ->* . (formlet/c beta))]
|
||||
|
@ -95,4 +95,4 @@
|
|||
[text (string? . -> . (formlet/c procedure?))]
|
||||
[tag-xexpr (symbol? (listof (list/c symbol? string?)) (formlet/c alpha) . -> . (formlet/c alpha))]
|
||||
[formlet-display ((formlet/c alpha) . -> . xexpr-forest/c)]
|
||||
[formlet-process ((formlet/c alpha) request? . -> . alpha)])
|
||||
[formlet-process (formlet*/c request? . -> . any)])
|
||||
|
|
|
@ -4,9 +4,9 @@
|
|||
"lib.ss")
|
||||
|
||||
(provide/contract
|
||||
[send/formlet (((formlet/c any/c))
|
||||
[send/formlet ((formlet*/c)
|
||||
(#:wrap (pretty-xexpr/c . -> . response/c))
|
||||
. ->* . any/c)])
|
||||
. ->* . any)])
|
||||
|
||||
(define (send/formlet f
|
||||
#:wrap
|
||||
|
@ -23,7 +23,7 @@
|
|||
,@(formlet-display f)))))))
|
||||
|
||||
(provide/contract
|
||||
[embed-formlet (embed/url/c (formlet/c any/c) . -> . pretty-xexpr/c)])
|
||||
[embed-formlet (embed/url/c formlet*/c . -> . pretty-xexpr/c)])
|
||||
|
||||
(define (embed-formlet embed/url f)
|
||||
`(form ([action ,(embed/url
|
||||
|
|
|
@ -1,44 +1,52 @@
|
|||
#lang scheme
|
||||
(require (for-syntax scheme)
|
||||
(require (for-syntax scheme syntax/parse)
|
||||
"lib.ss"
|
||||
(for-syntax "lib.ss"))
|
||||
|
||||
(define-syntax (#%# stx) (raise-syntax-error '#%# "Only allowed inside formlet" stx))
|
||||
|
||||
(define-for-syntax (cross-of stx)
|
||||
(syntax-case stx (unquote unquote-splicing => #%#)
|
||||
[s (string? (syntax->datum #'s))
|
||||
(syntax/loc stx empty)]
|
||||
[,(formlet . => . name) (syntax/loc stx name)]
|
||||
[,e (syntax/loc stx empty)]
|
||||
[,@e (syntax/loc stx empty)]
|
||||
[(#%# n ...)
|
||||
(quasisyntax/loc stx (list #,@(map cross-of (syntax->list #'(n ...)))))]
|
||||
[(t ([k v] ...) n ...)
|
||||
(quasisyntax/loc stx (list #,@(map cross-of (syntax->list #'(n ...)))))]
|
||||
[(t n ...)
|
||||
(quasisyntax/loc stx (list #,@(map cross-of (syntax->list #'(n ...)))))]))
|
||||
(syntax-parse
|
||||
stx
|
||||
#:literals (unquote unquote-splicing => #%# values)
|
||||
[s:str
|
||||
(syntax/loc stx empty)]
|
||||
[,(formlet . => . (values name:id ...)) (syntax/loc stx (vector name ...))]
|
||||
[,(formlet . => . name:id) (syntax/loc stx name)]
|
||||
[,e (syntax/loc stx empty)]
|
||||
[,@e (syntax/loc stx empty)]
|
||||
[(#%# n ...)
|
||||
(quasisyntax/loc stx (list #,@(map cross-of (syntax->list #'(n ...)))))]
|
||||
[(t ([k v] ...) n ...)
|
||||
(quasisyntax/loc stx (list #,@(map cross-of (syntax->list #'(n ...)))))]
|
||||
[(t n ...)
|
||||
(quasisyntax/loc stx (list #,@(map cross-of (syntax->list #'(n ...)))))]))
|
||||
|
||||
(define-for-syntax (circ-of stx)
|
||||
(syntax-case stx (unquote unquote-splicing => #%#)
|
||||
[s (string? (syntax->datum #'s))
|
||||
(syntax/loc stx (text s))]
|
||||
[,(formlet . => . name) (syntax/loc stx formlet)]
|
||||
[,e (syntax/loc stx (xml e))]
|
||||
[,@e (syntax/loc stx (xml-forest e))]
|
||||
[(#%# n ...)
|
||||
(let ([n-cross (map cross-of (syntax->list #'(n ...)))])
|
||||
(quasisyntax/loc stx
|
||||
(cross*
|
||||
(pure (match-lambda*
|
||||
[(list #,@n-cross)
|
||||
(list #,@n-cross)]))
|
||||
#,@(map circ-of (syntax->list #'(n ...))))))]
|
||||
[(t ([k v] ...) n ...)
|
||||
(quasisyntax/loc stx
|
||||
(tag-xexpr `t `([k v] ...)
|
||||
(syntax-parse
|
||||
stx
|
||||
#:literals (unquote unquote-splicing => #%# values)
|
||||
[s:str
|
||||
(syntax/loc stx (text s))]
|
||||
[,(formlet . => . (values name:id ...)) (syntax/loc stx (cross (pure (lambda (name ...) (vector name ...))) formlet))]
|
||||
[,(formlet . => . name:id) (syntax/loc stx formlet)]
|
||||
[,e (syntax/loc stx (xml e))]
|
||||
[,@e (syntax/loc stx (xml-forest e))]
|
||||
[(#%# n ...)
|
||||
(let ([n-cross (map cross-of (syntax->list #'(n ...)))])
|
||||
(quasisyntax/loc stx
|
||||
(cross*
|
||||
(pure (match-lambda*
|
||||
[(list #,@n-cross)
|
||||
(list #,@n-cross)]))
|
||||
#,@(map circ-of (syntax->list #'(n ...))))))]
|
||||
[(t ([k v] ...) n ...)
|
||||
(quasisyntax/loc stx
|
||||
(tag-xexpr `t `([k v] ...)
|
||||
#,(circ-of (syntax/loc stx (#%# n ...)))))]
|
||||
[(t n ...)
|
||||
(quasisyntax/loc stx
|
||||
(tag-xexpr `t empty
|
||||
[(t n ...)
|
||||
(quasisyntax/loc stx
|
||||
(tag-xexpr `t empty
|
||||
#,(circ-of (syntax/loc stx (#%# n ...)))))]))
|
||||
|
||||
(define-syntax (formlet stx)
|
||||
|
@ -48,4 +56,22 @@
|
|||
(cross (pure (match-lambda [#,(cross-of #'q) e]))
|
||||
#,(circ-of #'q)))]))
|
||||
|
||||
(provide formlet)
|
||||
(provide formlet #%#)
|
||||
|
||||
(require "input.ss")
|
||||
(define date-formlet
|
||||
(formlet
|
||||
(div
|
||||
"Month:" ,{input-int . => . month}
|
||||
"Day:" ,{input-int . => . day})
|
||||
(values month day)))
|
||||
|
||||
(define travel-formlet
|
||||
(formlet
|
||||
(div
|
||||
"Name:" ,{input-string . => . name}
|
||||
(div
|
||||
"Arrive:" ,{date-formlet . => . (values arrive-m arrive-d)}
|
||||
"Depart:" ,{date-formlet . => . (values depart-m depart-d)})
|
||||
,@(list "1" "2" "3"))
|
||||
(values name arrive-m arrive-d depart-m depart-d)))
|
||||
|
|
|
@ -110,9 +110,15 @@ Most users will want to use the syntactic shorthand for creating @tech{formlet}s
|
|||
@tech{formlet} given by @scheme[_formlet-expr]; the result of this processing this formlet is
|
||||
available in the @scheme[yields-expr] as @scheme[_name].
|
||||
|
||||
@scheme[,{_formlet-expr . => . (values _name ...)}] embeds the
|
||||
@tech{formlet} given by @scheme[_formlet-expr]; the results of this processing this formlet is
|
||||
available in the @scheme[yields-expr] as @scheme[_name ...].
|
||||
|
||||
@scheme[(#%# _xexpr ...)] renders an @xexpr forest.
|
||||
}
|
||||
|
||||
@defidform[#%#]{Only allowed inside @scheme[formlet].}
|
||||
|
||||
}
|
||||
|
||||
@section{Functional Usage}
|
||||
|
@ -128,10 +134,10 @@ types. Refer to @secref["input-formlets"] for example low-level formlets using t
|
|||
Equivalent to @scheme[(listof xexpr/c)]
|
||||
}
|
||||
|
||||
@defproc[(formlet/c [content any/c]) contract?]{
|
||||
@defproc[(formlet/c [content any/c] ...) contract?]{
|
||||
Equivalent to @scheme[(integer? . -> .
|
||||
(values xexpr-forest/c
|
||||
((listof binding?) . -> . (coerce-contract 'formlet/c content))
|
||||
((listof binding?) . -> . (values (coerce-contract 'formlet/c content) ...))
|
||||
integer?))].
|
||||
|
||||
A @tech{formlet}'s internal representation is a function from an initial input number
|
||||
|
@ -139,16 +145,20 @@ types. Refer to @secref["input-formlets"] for example low-level formlets using t
|
|||
input number.
|
||||
}
|
||||
|
||||
@defthing[formlet*/c contract?]{
|
||||
Equivalent to @scheme[(formlet/c any/c ...)].
|
||||
}
|
||||
|
||||
@defproc[(pure [value any/c]) (formlet/c any/c)]{
|
||||
Constructs a @tech{formlet} that has no rendering and always returns @scheme[value] in
|
||||
the processing stage.
|
||||
}
|
||||
|
||||
@defproc[(cross [f (formlet/c (any/c . -> . any/c))]
|
||||
[g (formlet/c any/c)])
|
||||
(formlet/c any/c)]{
|
||||
@defproc[(cross [f (formlet/c procedure?)]
|
||||
[g (formlet/c any/c ...)])
|
||||
(formlet/c any/c ...)]{
|
||||
Constructs a @tech{formlet} with a rendering equal to the concatenation of the renderings of @tech{formlet}s @scheme[f] and @scheme[g];
|
||||
a processing stage that applies @scheme[g]'s processing result to @scheme[f]'s processing result.
|
||||
a processing stage that applies @scheme[g]'s processing results to @scheme[f]'s processing result.
|
||||
}
|
||||
|
||||
@defproc[(cross* [f (formlet/c (() () #:rest (listof any/c) . ->* . any/c))]
|
||||
|
@ -185,9 +195,9 @@ types. Refer to @secref["input-formlets"] for example low-level formlets using t
|
|||
Renders @scheme[f].
|
||||
}
|
||||
|
||||
@defproc[(formlet-process [f (formlet/c any/c)]
|
||||
@defproc[(formlet-process [f (formlet/c any/c ...)]
|
||||
[r request?])
|
||||
any/c]{
|
||||
(values any/c ...)]{
|
||||
Runs the processing stage of @scheme[f] on the bindings in @scheme[r].
|
||||
}
|
||||
|
||||
|
@ -310,13 +320,13 @@ These @tech{formlet}s are the main combinators for form input.
|
|||
|
||||
A few utilities are provided for using @tech{formlet}s in Web applications.
|
||||
|
||||
@defproc[(send/formlet [f (formlet/c any/c)]
|
||||
@defproc[(send/formlet [f (formlet/c any/c ...)]
|
||||
[#:wrap wrapper
|
||||
(xexpr/c . -> . response/c)
|
||||
(lambda (form-xexpr)
|
||||
`(html (head (title "Form Entry"))
|
||||
(body ,form-xexpr)))])
|
||||
any/c]{
|
||||
(values any/c ...)]{
|
||||
Uses @scheme[send/suspend] to send @scheme[f]'s rendering (wrapped in a FORM tag whose action is
|
||||
the continuation URL (wrapped again by @scheme[wrapper])) to the client.
|
||||
When the form is submitted, the request is passed to the
|
||||
|
@ -324,7 +334,7 @@ A few utilities are provided for using @tech{formlet}s in Web applications.
|
|||
}
|
||||
|
||||
@defproc[(embed-formlet [embed/url embed/url/c]
|
||||
[f (formlet/c any/c)])
|
||||
[f (formlet/c any/c ...)])
|
||||
xexpr/c]{
|
||||
Like @scheme[send/formlet], but for use with @scheme[send/suspend/dispatch].
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue
Block a user