diff --git a/collects/scribble/basic.ss b/collects/scribble/basic.ss index c9b9775d62..5da997d9bf 100644 --- a/collects/scribble/basic.ss +++ b/collects/scribble/basic.ss @@ -89,7 +89,24 @@ (make-element 'bold (decode-content str))) (define (tt . str) - (make-element 'tt (decode-content str))) + (let ([l (decode-content str)]) + (let ([l (let ([m (and (pair? l) + (string? (car l)) + (regexp-match-positions #rx"^ +" (car l)))]) + (if m + (cons (hspace (- (cdar m) (caar m))) + (cons + (substring (car l) (cdar m)) + (cdr l))) + l))]) + (if (andmap string? l) + (make-element 'tt l) + (make-element #f (map (lambda (s) + (if (or (string? s) + (symbol? s)) + (make-element 'tt (list s)) + s)) + l)))))) (define (span-class classname . str) (make-element classname (decode-content str))) diff --git a/collects/scribble/latex-render.ss b/collects/scribble/latex-render.ss index 9b2e87be12..ce08830006 100644 --- a/collects/scribble/latex-render.ss +++ b/collects/scribble/latex-render.ss @@ -54,6 +54,7 @@ (define-color "schemestdout" "OutputColor") (define-color "schememeta" "IdentifierColor") (define-color "schememod" "black") + (define-color "schemereader" "black") (define-color "schemevariablecol" "IdentifierColor") (printf "\\newcommand{\\schemevariable}[1]{{\\schemevariablecol{\\textsl{#1}}}}\n") (define-color "schemeerrorcol" "red") diff --git a/collects/scribble/scheme.ss b/collects/scribble/scheme.ss index ac59fc5c39..74622b0a24 100644 --- a/collects/scribble/scheme.ss +++ b/collects/scribble/scheme.ss @@ -22,7 +22,7 @@ (struct just-context (val ctx))) (define no-color "schemeplain") - (define reader-color "schemeplain") + (define reader-color "schemereader") (define keyword-color "schemekeyword") (define comment-color "schemecomment") (define paren-color "schemeparen") @@ -253,7 +253,7 @@ [(and (pair? (syntax-e c)) (memq (syntax-e (car (syntax-e c))) '(quote quasiquote unquote unquote-splicing - syntax unsyntax))) + quasisyntax syntax unsyntax unsyntax-splicing))) (advance c init-line!) (let-values ([(str quote-delta) (case (syntax-e (car (syntax-e c))) @@ -262,7 +262,9 @@ [(unquote-splicing) (values ",@" -1)] [(quasiquote) (values "`" +1)] [(syntax) (values "#'" 0)] - [(unsyntax) (values "#," 0)])]) + [(quasisyntax) (values "#`" 0)] + [(unsyntax) (values "#," 0)] + [(unsyntax-splicing) (values "#,@" 0)])]) (out str (if (positive? (+ quote-depth quote-delta)) value-color reader-color)) @@ -308,7 +310,9 @@ c)]) (cond [(and (syntax? l) - (pair? (syntax-e l))) + (pair? (syntax-e l)) + (not (memq (syntax-e (car (syntax-e l))) + '(quote unquote syntax unsyntax quasiquote quasiunsyntax)))) (lloop (syntax-e l))] [(or (null? l) (and (syntax? l) @@ -318,6 +322,7 @@ ((loop init-line! quote-depth) (car l)) (lloop (cdr l))] [else + (advance l init-line! -2) (out ". " (if (positive? quote-depth) value-color paren-color)) (set! src-col (+ src-col 3)) diff --git a/collects/scribble/scribble.css b/collects/scribble/scribble.css index a4406c927d..76a9151e24 100644 --- a/collects/scribble/scribble.css +++ b/collects/scribble/scribble.css @@ -238,6 +238,10 @@ background-color: #eeeeee; } + .schemereader { + font-family: Courier; font-size: 80%; + } + .schemeparen { color: #843c24; font-family: Courier; font-size: 80%; diff --git a/collects/scribblings/reference/data.scrbl b/collects/scribblings/reference/data.scrbl index 155574b04b..a4985df0b9 100644 --- a/collects/scribblings/reference/data.scrbl +++ b/collects/scribblings/reference/data.scrbl @@ -67,14 +67,13 @@ object, @scheme[#f] otherwise. See also @secref["mz:model-eq"].} @guideintro["guide:symbols"]{symbols} A symbol is like an immutable string, but symbols are normally -@index["interned symbols"]{@defterm{interned}}, so that two symbols -with the same character content are normally @scheme[eq?]. All symbols -produced by the default reader (see @secref["mz:parse-symbol"]) are -interned. +@deftech{interned}, so that two symbols with the same character +content are normally @scheme[eq?]. All symbols produced by the default +reader (see @secref["mz:parse-symbol"]) are interned. @index['("symbols" "generating")]{@index['("symbols" "unique")]{The}} two procedures @scheme[string->uninterned-symbol] and @scheme[gensym] -generate @idefterm{uninterned symbols}, i.e., a symbols that are not +generate @deftech{uninterned} symbols, i.e., symbols that are not @scheme[eq?], @scheme[eqv?], or @scheme[equal?] to any other symbol, although they may print the same as other symbols. @@ -98,22 +97,23 @@ ephemeron key (see @secref["mz:ephemerons"]). @examples[(symbol->string 'Apple)] -@defproc[(string->symbol [str string?]) symbol?]{Returns an interned - symbol whose characters are the same as in @scheme[str].} +@defproc[(string->symbol [str string?]) symbol?]{Returns an + @tech{interned} symbol whose characters are the same as in + @scheme[str].} @examples[(string->symbol "Apple") (string->symbol "1")] @defproc[(string->uninterned-symbol [str string?]) symbol?]{Like @scheme[(string->symbol str)], but the resulting symbol is a new - uninterned symbol. Calling @scheme[string->uninterned-symbol] twice - with the same @scheme[str] returns two distinct symbols.} + @tech{uninterned} symbol. Calling @scheme[string->uninterned-symbol] + twice with the same @scheme[str] returns two distinct symbols.} @examples[(string->uninterned-symbol "Apple") (eq? 'a (string->uninterned-symbol "a"))] @defproc[(gensym [base (or/c string? symbol?) "g"]) symbol?]{Returns a - new uninterned symbol with an automatically-generated name. The + new @tech{uninterned} symbol with an automatically-generated name. The optional @scheme[base] argument is a prefix symbol or string.} @examples[(gensym "apple")] @@ -122,7 +122,39 @@ ephemeron key (see @secref["mz:ephemerons"]). @include-section["regexps.scrbl"] @; ------------------------------------------------------------ -@section[#:tag "keywords"]{Keywords} +@section[#:tag "mz:keywords"]{Keywords} + +@guideintro["guide:keywords"]{keywords} + +A keyword is like an @tech{interned} symbol, but its printed form +starts with @litchar{#:}, and a keyword cannot be used as an +identifier. Furthermore, a keyword by itself is not a valid +expression, though a keyword can be @scheme[quote]d to form an +expression that produces the symbol. + +Two keywords are @scheme[eq?] if and only if they print the same. + +Like symbols, keywords are only weakly held by the internal keyword +table; see @secref["mz:symbols"] for more information. + +@item{@defproc[(keyword? [v any/c]) any] returns @scheme[#t] if @scheme[v] is a +keyword, @scheme[#f] otherwise.} + +@defproc[(keyword->string [keyword keyword?]) string?]{ + +Returns a string for the @scheme[display]ed form of @scheme[keyword], +not including the leading @litchar{#:}.} + +@defproc[(string->keyword [str string?]) keyword]{ + +Returns a keyword whose @scheme[display]ed form is the same as that of +@scheme[str], but with a leading @litchar{#:}.} + +@defproc[(keywordstring] and @scheme[string "/Note/: *This is _not_ a pipe*." + #,(tt "@text{@it{Note}: @bf{This is @ul{not} a pipe}.}")) + (let* ([formatter (lambda (fmt) + (lambda args (format fmt (apply string-append args))))] + [bf (formatter "*~a*")] + [it (formatter "/~a/")] + [ul (formatter "_~a_")] + [text string-append]) + @text{@it{Note}: @bf{This is @ul{not} a pipe}.})) ] If you want to see the expression that is actually being read, you can @@ -310,15 +319,15 @@ This is particularly useful with strings, which can be used to include arbitrary text. @scribble-examples|==={ - @foo{This @"}" is a closing brace} + @foo{@"}" is a closing brace} }===| Note that the escaped string is (intentionally) merged with the rest of the text. This works for @litchar["@"] too: @scribble-examples|==={ - @foo{The command prefix is @"@".} - @foo{@"@foo{bar}" reads as (foo "bar")} + @foo{Command prefix: @"@".} + @foo{@"@f{b}" -> (f "b")} }===| @subsubsub*section{Alternative Body Syntax} @@ -340,7 +349,7 @@ prefixed with a @litchar["|"]: @foo|{Maze |@bar{is} Life!}| - @foo|{Works for |@bar|{subforms}| too}| + @foo|{|@bar|{subforms}| ok}| }===| Note that the subform uses its own delimiters, @litchar["{...}"] or @@ -357,8 +366,8 @@ in reverse order with paren-like characters (@litchar["("], @litchar["["], @litchar["<"]) mirrored. @scribble-examples|==={ - @foo|<<<{Some @x{more} |@{text}|.}>>>| - @foo|!!{Blah |!!@bold{blah}...}!!| + @foo|<<<{@x{m} |@{t}|.}>>>| + @foo|!!{B |!!@bold{b}...}!!| }===| Finally, remember that you can use an expression escape with a Scheme @@ -430,7 +439,7 @@ rules for @"@"-forms), and @litchar["@;..."] is a line-comment. @scribble-examples|==={ @foo{First line@;{there is still a - newline at this point;} + newline here;} Second line} }===| @@ -439,10 +448,8 @@ of the line @italic{and} all following spaces (or tabs). Using this, you can get further control of the subforms. @scribble-examples|==={ - @foo{This is @; - a pretty long @; - single string-@; - argument.} + @foo{A long single-@; + string arg.} }===| Note how this is different from using @litchar["@||"]s in that strings @@ -467,7 +474,7 @@ A single newline that follows an open brace or precedes a closing brace is discarded, unless there are only newlines in the body; other newlines are read as a @scheme["\n"] string -@;FIXME empty lines are ignored in generated HTML output +@;FIXME empty lines are ignored in generated HTML output (with IE?) @scribble-examples|==={ @foo{bar } @@ -497,20 +504,23 @@ In the parsed S-expression syntax, a single newline string is used for all newlines; you can use @scheme[eq?] to identify this line. This can be used to identify newlines in the original @nonterm{text-body}. -@; FIXME: need to show printout here (with the scribble syntax) -@schemeblock[ +@; FIXME: unfortunate code duplication (again): +@interaction[ +(eval:alts + (let ([nl (car #, @tt["@'{"] + #, @tt[" }"])]) + (for-each (lambda (x) (display (if (eq? x nl) "\n... " x))) + #, @tt["@`{foo"] + #, @elem[@tt[" @"] @scheme[,@(list "bar" "\n" "baz")]] + #, @tt[" blah}}"]) + (newline)) (let ([nl (car @'{ })]) (for-each (lambda (x) (display (if (eq? x nl) "\n... " x))) @`{foo @,@(list "bar" "\n" "baz") blah}) - (newline)) - --prints--> - foo - ... bar - baz - ... blah + (newline))) ] Spaces at the beginning of body lines do not appear in the resulting @@ -543,7 +553,6 @@ syntax object used for indentation). This makes sense when formatting structured code as well as text (see the last example in the following block). -@;FIXME: last example too long, messes up output @scribble-examples|==={ @foo{bar baz @@ -560,8 +569,8 @@ block). @foo{ bar baz bbb} - @text{Some text@footnote{And a - footnote comment.}. More text.} + @text{Text@note{And + note.}. More.} }===| Note that each @"@"-form is parsed to an S-expression that has its own @@ -634,28 +643,33 @@ To implement a verbatim environment you need to drop indentation strings, and use the original newline strings instead of the single-newline string. Here is an example of this. -@; FIXME: need to show evaluation here (with the scribble syntax) -@schemeblock[ +@; FIXME: a bit of code duplication here +@def+int[ (define-syntax (verb stx) (syntax-case stx () [(_ cmd item ...) - ;;FIXME: show a "#`" in the rendering of the following line - #`(cmd . - ;;FIXME: the next line should begin with a #, - ,(let loop ([items (syntax->list #'(item ...))]) - (if (null? items) - '() - (let* ([fst (car items)] - [prop (syntax-property fst 'scribble)] - [rst (loop (cdr items))]) - (cond [(not prop) (cons fst rst)] - [(eq? prop 'indentation) rst] - [else (cons (datum->syntax-object - fst (cadr prop) fst) - rst)])))))])) + #`(cmd + #,@(let loop ([items (syntax->list #'(item ...))]) + (if (null? items) + '() + (let* ([fst (car items)] + [prop (syntax-property fst 'scribble)] + [rst (loop (cdr items))]) + (cond [(not prop) (cons fst rst)] + [(eq? prop 'indentation) rst] + [else (cons (datum->syntax-object + fst (cadr prop) fst) + rst)])))))])) +(eval:alts + + (code:line + #, @tt["@verb[string-append]{"] + #, @tt[" foo"] + #, @tt[" bar"] + #, @tt["}"]) + @verb[string-append]{ foo bar - } - --> "foo\n bar" + }) ]