commit 5175a23e64690530f76d69024a2bedf7d7b35aae
parent 1de817fdf84c6bd80348d6e9f95ecee81265210c
Author: Eli Barzilay <eli@racket-lang.org>
Date: Mon, 9 Jul 2007 05:12:59 +0000
updated screibble reader docs
svn: r6865
original commit: 6355ad12f4eaaf9816643837fa560eb4f2395a76
Diffstat:
4 files changed, 556 insertions(+), 389 deletions(-)
diff --git a/collects/scribble/doc.txt b/collects/scribble/doc.txt
@@ -113,7 +113,7 @@ use Scheme's `quote'.
'@foo{bar}
-** Concrete Syntax: The Command Part
+** The Command Part
Besides being a Scheme identifier, the <cmd> part of an @-form can
have Scheme punctuation prefixes, which will end up wrapping the
@@ -145,7 +145,7 @@ contains, say, just strings:
If the command part begins with a ";" (with no newline between the "@"
and the ";"), then the construct is a comment. There are two comment
forms, one for arbitrary-text and possibly nested comments, and
-another one for a line comments:
+another one for line comments:
@;{<anything> ...}
@@ -156,8 +156,9 @@ the description of the body syntax below. In the second form, all
text from the "@;" to the end of the line *and* all following spaces
(or tabs) are part of the comment (similar to "%" comments in TeX).
- @foo{bar @; comment --reads-as--> (foo "bar baz")
- baz}
+ @foo{bar @; comment --reads-as--> (foo "bar bazblah")
+ baz@;
+ blah}
Tip: if you're editing in a Scheme-aware editor (like DrScheme or
Emacs), it is useful to comment out blocks like this:
@@ -183,7 +184,7 @@ in the command itself, which can lead to things like:
@@foo{bar}{baz} --reads-as--> ((foo "bar") "baz")
-** Concrete Syntax: The Datum Part
+** The Datum Part
The datum part can contains arbitrary Scheme expressions, which are
simply stacked before the body text arguments:
@@ -211,14 +212,14 @@ keyword-value arguments that precede the body of text arguments.
@foo[#:style 'big]{bar} --reads-as--> (foo #:style 'big "bar")
-** Concrete Syntax: The Body Part
+** The Body Part
The syntax of the body part is intended to be as convenient as
possible for free text. It can contain almost any text -- the only
-characters with special meaning is "@" for sub forms, and "}" for the
-end of the text. In addition, a "{" is allowed as part of the text,
-and it makes the matching "}" be part of the text too -- so balanced
-braces are valid text.
+characters with special meaning is "@" for sub-@-forms, and "}" for
+the end of the text. In addition, a "{" is allowed as part of the
+text, and it makes the matching "}" be part of the text too -- so
+balanced braces are valid text.
@foo{f{o}o} --reads-as--> (foo "f{o}o")
@foo{{{}}{}} --reads-as--> (foo "{{}}{}")
@@ -269,19 +270,19 @@ of the text. This works for "@" too:
--reads-as-->
(foo "@foo{bar} reads as (foo \"bar\")")
-* Concrete Syntax: Alternative Body Syntax
+* Alternative Body Syntax
-In addition, there is an alternative syntax for the body, one that
-specifies a new marker for its end: use "|{" for the opening marker to
-have the text terminated by a "}|".
+In addition to the above, there is an alternative syntax for the body,
+one that specifies a new marker for its end: use "|{" for the opening
+marker to have the text terminated by a "}|".
@foo|{...}|
--reads-as-->
(foo "...")
- @foo|{close with "}", open with "{"}|
+ @foo|{"}" closes, "{" opens}|
--reads-as-->
- (foo "close with \"}\", open with \"{\"")
+ (foo "\"}\" closes, \"{\" opens")
@foo|{Nesting |{is}| ok}|
--reads-as-->
@@ -325,7 +326,7 @@ string for confusing situations. This works well when you only need
to quote short pieces, and the above works well when you have larger
multi-line body texts.
-* Concrete Syntax: Scheme Expression Escapes
+* Scheme Expression Escapes
In some cases, you may want to use a Scheme identifier (or a number or
a boolean etc.) in a position that touches the following text; in
@@ -344,7 +345,7 @@ or datum part when you use this form.
@foo{foo@|(f 1)|{bar}} --reads-as--> (foo "foo" (f 1) "{bar}")
@foo{foo@|bar|[1]{baz}} --reads-as--> (foo "foo" bar "[1]{baz}")
-This works for string expressions too, but not that unlike the above,
+This works for string expressions too, but note that unlike the above,
the string is (intentionally) not merged with the rest of the text:
@foo{x@"y"z} --reads-as--> (foo "xyz")
@@ -370,7 +371,7 @@ is little point in Scheme code that uses braces.
@|{blah}| --reads-as--> ("blah")
-* Concrete Syntax: Comments
+* Comments
As noted above, there are two kinds of Scribble comments: "@;{...}" is
a (nestable) comment for a whole body of text (following the same
@@ -396,7 +397,7 @@ get further control of the subforms.
Note how this is different from using "@||"s in that strings around it
are not merged.
-* Concrete Syntax: Spaces, Newlines, and Indentation
+* Spaces, Newlines, and Indentation
The Scribble syntax treats spaces and newlines in a special way is
meant to be sensible for dealing with text. As mentioned above,
@@ -410,9 +411,9 @@ for spaces between a "{" and text, or between text and a "}".
@foo{ bar --reads-as--> (foo " bar" "\n" "baz ")
baz }
-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 "\n" string
+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 "\n" string
@foo{bar --reads-as--> (foo "bar")
}
@@ -603,3 +604,4 @@ Here is an example of this.
foo
bar
}
+ --> "foo\n bar"
diff --git a/collects/scribblings/scribble/reader.scrbl b/collects/scribblings/scribble/reader.scrbl
@@ -68,72 +68,79 @@ identifier with bars (@schemefont["|@foo|"]).
Of course, @litchar["@"] is not treated specially in Scheme strings,
character constants, etc.
-Roughly, a form matching the grammar above is read as
+Roughly, a form matching the above grammar is read as
@schemeblock[
-(#, @nonterm{cmd} #, @kleenestar{@nonterm{datum}} #, @kleenestar{@nonterm{parsed-body}})
+ (#, @nonterm{cmd}
+ #, @kleenestar{@nonterm{datum}}
+ #, @kleenestar{@nonterm{parsed-body}})
]
where @nonterm{parsed-body} is the translation of each
-@nonterm{text-body} in the input.
-
-Thus, the initial @nonterm{cmd} determines the Scheme code that
-the input is translated into. The common case is when @nonterm{cmd} is a
-Scheme identifier, which generates a plain Scheme form.
-
-A @nonterm{text-body} is either a sequence of characters without
-@litchar["@"] or newlines, a newline by itself, or the translation of a
-@at form. Note that the syntax for @at forms is the same in a
-@nonterm{text-body} context as in a Scheme context. A
-@nonterm{text-body} that isn't a @at form is converted to a string for
-its @nonterm{parsed-body}:
-
-@scribble-examples[
-#<<EOS
-@foo{bar baz
- blah}
-EOS
-
-#f
-
-#<<EOS
-@foo{bar @baz[3]
- blah}
-EOS
-
-#f
-
-#<<EOS
-@foo{bar @baz{3}
- blah}
-EOS
-
-#f
-
-#<<EOS
-@foo{bar @baz[2 3]{4 5}
- blah}
-EOS
-
+@nonterm{text-body} in the input. Thus, the initial @nonterm{cmd}
+determines the Scheme code that the input is translated into. The
+common case is when @nonterm{cmd} is a Scheme identifier, which
+generates a plain Scheme form.
+
+A @nonterm{text-body} is made of text, newlines, and nested
+@"@"-forms. Note that the syntax for @"@"-forms is the same in a
+@nonterm{text-body} context as in a Scheme context. A
+@nonterm{text-body} that isn't an @"@"-form is converted to a string
+expression for its @nonterm{parsed-body}, and newlines are converted
+to @scheme["\n"] expressions.
+
+@scribble-examples|==={
+ @foo{bar baz
+ blah}
+ @foo{bar @baz[3]
+ blah}
+ @foo{bar @baz{3}
+ blah}
+ @foo{bar @baz[2 3]{4 5}
+ blah}
+}===|
+
+Note that spaces are not allowed before a @litchar["["] or a
+@litchar["{"], or they will be part of the following text (or Scheme
+code). (More on using braces in body texts below.)
+
+@scribble-examples|==={
+ @foo{bar @baz[2 3] {4 5}}
+}===|
+
+When the above @"@"-forms appear in a Scheme expression context, the
+lexical environment must provide bindings for @scheme[foo] (as a procedure or
+a macro).
+
+@; FIXME: need to show evaluation here (with the scribble syntax)
+@schemeblock[
+ (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}.})
+ --> "/Note/: *This is _not_ a pipe*."
]
-When the above @at forms appear in a Scheme expression context,
-the surrounding context must provide a binding for @scheme[foo]
-(either as a procedure or macro). To just see the read result for a
-@at form, you can always use Scheme's @scheme[quote]:
+If you want to see the expression that is actually being read, you can
+use Scheme's @scheme[quote].
-@scribble-examples[(list @litchar["'@foo{bar}"] @scheme['(foo "bar")])]
+@scribble-examples|==={
+ '@foo{bar}
+}===|
@; - - - - - - - - - - - - - - - - - - - - - - - -
@subsection{The Command Part}
-Besides being a Scheme identifier, the @nonterm{cmd} part of an @at
-form can have Scheme punctuation prefixes, which will end up wrapping
-the @italic{whole} expression.
+Besides being a Scheme identifier, the @nonterm{cmd} part of an
+@"@"-form can have Scheme punctuation prefixes, which will end up
+wrapping the @italic{whole} expression.
-@scribble-examples[
- "@`',@foo{blah}"
-]
+@scribble-examples|==={
+ @`',@foo{blah}
+}===|
When writing Scheme code, this means that @litchar["@`',@foo{blah}"]
is exactly the same as @litchar["`@',@foo{blah}"] and
@@ -141,30 +148,24 @@ is exactly the same as @litchar["`@',@foo{blah}"] and
construct can appear in body texts with the same meaning, whereas the
other two would not work (see below).
-Even after Scheme punctuation, the @nonterm{cmd} itself is not limited
-to a Scheme identifier; it can be any Scheme expression.
+After the optional punctuation prefix, the @nonterm{cmd} itself is not
+limited to identifiers; it can be @italic{any} Scheme expression.
-@scribble-examples[
- "@(lambda (x) x){blah}"
-]
+@scribble-examples|==={
+ @(lambda (x) x){blah}
+ @`(unquote foo){blah}
+}===|
In addition, the command can be omitted altogether, which will omit it
from the translation, resulting in an S-expression that usually
contains, say, just strings:
-@scribble-examples[
-#<<EOS
+@scribble-examples|==={
@{foo bar
baz}
-EOS
-
-#f
-
-#<<EOS
@'{foo bar
baz}
-EOS
-]
+}===|
If the command part begins with a @litchar{;} (with no newline between
the @litchar["@"] and the @litchar{;}), then the construct is a
@@ -172,332 +173,489 @@ comment. There are two comment forms, one for arbitrary-text and
possibly nested comments, and another one for line comments:
@schemeblock[
-#, @BNF-seq[@litchar["@;"] @kleenestar{@nonterm{whitespace}} @litchar["{"] @kleenestar{@nonterm{any}} @litchar["@"]]
+#, @BNF-seq[@litchar["@;{"] @kleenestar{@nonterm{any}} @litchar["}"]]
-#, @BNF-seq[@litchar["@;"] @kleenestar{@nonterm{anythign-else-without-newline}}]
+#, @BNF-seq[@litchar["@;"] @kleenestar{@nonterm{anything-else-without-newline}}]
]
In the first form, the commented body must still parse correctly; see
-the description of the body syntax below.
-
-Tip: if you're editing in some Scheme-mode, it is useful to comment out
-blocks like this:
+the description of the body syntax below. In the second form, all
+text from the @litchar["@;"] to the end of the line @italic{and} all
+following spaces (or tabs) are part of the comment (similar to
+@litchar["%"] comments in TeX).
-@verbatim[#<<EOS
- @;
- {
- ...
- }
-EOS
-]
+@scribble-examples|==={
+ @foo{bar @; comment
+ baz@;
+ blah}
+}===|
-or
+Tip: if you're editing in a Scheme-aware editor (like DrScheme or
+Emacs), it is useful to comment out blocks like this:
-@verbatim[#<<EOS
+@verbatim["
@;{
...
;}
-EOS
-]
+"]
-otherwise you will probably confuse the editor into treating the file as
-having imbalanced parenthesis.
+so the editor does not treat the file as having unbalanced
+parenthesis.
-If only the @nonterm{cmd} part is specified of an @at form, then the
+If only the @nonterm{cmd} part of an @"@"-form is specified, then the
result is the command part only, without an extra set of parenthesis.
-This makes it suitable for Scheme escapes in body texts. More below,
-in the description of the body part.
+This makes it suitable for Scheme escapes in body texts. (More on this
+below, in the description of the body part.)
+
+@scribble-examples|==={
+ @foo{x @y z}
+ @foo{x @(* y 2) z}
+ @{@foo bar}
+}===|
Finally, note that there are currently no special rules for using
@litchar["@"] in the command itself, which can lead to things like:
-@scribble-examples[
- "@@foo{bar}{baz}"
-]
-
-You should not rely on such behavior, since @litchar["@@"] might be used
-differently in the future (e.g., making @litchar["@@"] be ``@at'' in a
-body text).
+@scribble-examples|==={
+ @@foo{bar}{baz}
+}===|
@subsection{The Datum Part}
The datum part can contains arbitrary Scheme expressions, which
are simply stacked before the body text arguments:
-@scribble-examples[
- "@foo[1 (* 2 3)]{bar}"
- "@foo[@bar{...}]{blah}"
-]
+@scribble-examples|==={
+ @foo[1 (* 2 3)]{bar}
+ @foo[@bar{...}]{blah}
+}===|
-@italic{This following is going to be removed, I think...}
+The body part can still be omitted, which is essentially an
+alternative syntax for plain (non-textual) S-expressions:
-But there is one change that makes it easy to use for keyword/values:
-@litchar{=} is a terminating character in the textual scope, and it if
-there is a @BNF-seq[@nonterm{identifier} @litchar{=} @nonterm{expr}]
-sequence (spaces optional), then it is converted to
-@schemefont{#:}@nonterm{identifier} @nonterm{expr}.
+@scribble-examples|==={
+ @foo[bar]
+ @foo{bar @f[x] baz}
+}===|
-@scribble-examples[
- "@foo[(* 2 3) a=b]{bar}"
-]
+The datum part can be empty, which makes no difference, except when
+the body is omitted. It is more common, however, to use an empty body
+for the same purpose.
-@subsection{The Body Part}
+@scribble-examples|==={
+ @foo[]{bar}
+ @foo[]
+ @foo
+ @foo{}
+}===|
-The syntax of the body part is intended to be as convenient as
-possible for writing free text. It can contain almost any text---the
-only character with special meaning is @litchar["@"]. In addition,
-@litchar["{"], @litchar["}"], @litchar["|"], and @litchar["\\"] can
-have special meanings, but only in a few contexts. As described
-above, the text turns to a sequence of string arguments for the
-resulting form. Spaces at the beginning of lines are discarded (but
-see the information about indentation below), and newlines turn to
-individual @scheme["\n"] strings. (Spaces are preserved on a
-single-line text.) As part of trying to do the ``right thing,'' an
-empty line at the beginning and at the end are discarded, so:
-
-@scribble-examples[
-#<<EOS
- @foo{
- bar
- }
-EOS
+The most common use of the datum part is for Scheme forms that expect
+keyword-value arguments that precede the body of text arguments.
-#f
+@scribble-examples|==={
+ @foo[#:style 'big]{bar}
+}===|
- "@foo{bar}"
- "@foo{ bar }"
-]
+@subsection{The Body Part}
+
+The syntax of the body part is intended to be as convenient as
+possible for free text. It can contain almost any text---the only
+characters with special meaning is @litchar["@"] for sub-@"@"-forms,
+and @litchar["}"] for the end of the text. In addition, a
+@litchar["{"] is allowed as part of the text, and it makes the
+matching @litchar["}"] be part of the text too---so balanced braces
+are valid text.
+
+@scribble-examples|==={
+ @foo{f{o}o}
+ @foo{{{}}{}}
+}===|
+
+As described above, the text turns to a sequence of string arguments
+for the resulting form. Spaces at the beginning and end of lines are
+discarded, and newlines turn to individual @scheme["\n"] strings
+(i.e., they are not merged with other body parts). (See also the
+information about newlines and indentation below.) Spaces are
+@italic{not} discarded if they appear after the open @litchar["{"]
+(before the closing @litchar["}"]) when there is also text that
+follows (precedes) it; specifically, they are preserved in a
+single-line body.
+
+@scribble-examples|==={
+ @foo{bar}
+ @foo{ bar }
+ @foo[1]{ bar }
+}===|
If @litchar["@"] appears in a body, then it is interpreted as Scheme
-code, which means that the @|at|-reader will be applied recursively,
-and the resulting syntax will appear as an argument, among other
+code, which means that the @"@"-reader is applied recursively, and the
+resulting syntax appears as part of the S-expression, among other
string contents.
-@scribble-examples[
- "@foo{a @bar{b} c}"
-]
-
-If the nested @at construct has only a command---no body part---then
-it does not appear in a subform. Given that the command part can be
-any Scheme expression, this makes @at a general escape to arbitrary
-Scheme code.
-
-@scribble-examples[
- "@foo{a @bar c}"
- "@foo{a @(bar 2) c}"
-]
+@scribble-examples|==={
+ @foo{a @bar{b} c}
+}===|
+
+If the nested @"@" construct has only a command---no body or datum
+parts---it will not appear in a subform. Given that the command part
+can be any Scheme expression, this makes @"@" a general escape to
+arbitrary Scheme code.
+
+@scribble-examples|==={
+ @foo{a @bar c}
+ @foo{a @(bar 2) c}
+}===|
+
+This is particularly useful with strings, which can be used to include
+arbitrary text.
+
+@scribble-examples|==={
+ @foo{This @"}" 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")}
+}===|
+
+@subsubsub*section{Alternative Body Syntax}
+
+In addition to the above, there is an alternative syntax for the body,
+one that specifies a new marker for its end: use @litchar["|{"] for
+the opening marker to have the text terminated by a @litchar["}|"].
+
+@scribble-examples|==={
+ @foo|{...}|
+ @foo|{"}" closes, "{" opens}|
+ @foo|{Nesting |{is}| ok}|
+}===|
+
+This applies to sub-@"@"-forms too---the @litchar["@"] must be
+prefixed with a @litchar["|"]:
+
+@scribble-examples|==={
+ @foo|{Maze
+ |@bar{is}
+ Life!}|
+ @foo|{Works for |@bar|{subforms}| too}|
+}===|
+
+Note that the subform uses its own delimiters, @litchar["{...}"] or
+@litchar["|{...}|"]. This means that you can copy and paste Scribble
+text with @"@"-forms freely, just prefix the @litchar["@"] if the
+immediate surrounding text has a prefix.
+
+For even better control, you can add characters in the opening
+delimiter, between the @litchar["|"] and the @litchar["{"].
+Characters that are put there (non alphanumeric ASCII characters only,
+excluding @litchar["{"] and @litchar["@"]) should also be used for
+sub-@"@"-forms, and the end-of-body marker should have these characters
+in reverse order with paren-like characters (@litchar["("],
+@litchar["["], @litchar["<"]) mirrored.
+
+@scribble-examples|==={
+ @foo|<<<{Some @x{more} |@{text}|.}>>>|
+ @foo|!!{Blah |!!@bold{blah}...}!!|
+}===|
+
+Finally, remember that you can use an expression escape with a Scheme
+string for confusing situations. This works well when you only need
+to quote short pieces, and the above works well when you have larger
+multi-line body texts.
+
+@subsubsub*section{Scheme Expression Escapes}
In some cases, you may want to use a Scheme identifier (or a number or
-a boolean) in a position that touches other text that can make an
-identifier; in these situations you should surround the Scheme
-identifier (or number or boolean) by a pair of @litchar["|"]. The
-text inside the bars is parsed as a Scheme expression, but if that
-fails, it is used as a quoted identifier; do not rely on this
-behavior, and avoid using whitespace inside the bars. Also, if bars
-are used, then no body text is used even if they are followed by
-braces (see the next paragraph).
-
-@scribble-examples[
- "@foo{foo @bar foo}"
- "@foo{foo@bar.}"
- "@foo{foo@|bar|.}"
- "@foo{foo@3.}"
- "@foo{foo@|3|.}"
- "@foo{foo@|(f 1)|{bar}.}"
-]
-
-Braces are only problematic because a @litchar["}"] is used to mark
-the end of the text. They are therefore allowed, as long as they are
-balanced.
-
-@scribble-examples[
- "@foo{f{o}o}"
-]
-
-There is also an alternative syntax for the body, one that specifies a
-new marker for the end: use @litchar["|{"] for the openning marker,
-optionally with additional characters between them (excluding
-@litchar["{"], whitespace, and alphanumerics); the matching closing
-marker should be the mirrored form of the openning marker (reverse the
-characters and swap round, square, curly, and angle parentheses).
-
-@scribble-examples[
- "@foo|{...}|"
- "@foo|{foo{{{bar}|"
- "@foo|<{{foo{{{bar}}>|"
-]
-
-More simply, if you get into too much trouble with special characters
-in a body, then it's often a good idea to use the Scheme part,
-instead.
-
-@scribble-examples[
- "@foo[\"}\"]"
- "@foo[\"@literally{}\"]"
-]
-
-@; - - - - - - - - - - - - - - - - - - - - - - - -
-@subsubsub*section{Quoting in Body Texts}
-
-To quote braces or @at, precede them with a backslash. Note that this
-is an irregular use of backslash quoting! To use @litchar["\\@"] in
-your text, simply precede it with a backslash. The general rule is
-that to use N backslashes-and-a-special-character, you should precede
-it with one extra backslash. Any other use of a backslash (one that
-is not followed by more back-slashes and a special character) is
-preserved in the text as usual.
-
-@scribble-examples[
- "@foo{b\\@ar}"
- "@foo{b\\\\@ar}"
- "@foo{b\\\\\\@ar}"
- "@foo{b\\@\\@ar}"
- "@foo{b\\ar}"
- "@foo{b\\\\ar}"
-]
-
-@; - - - - - - - - - - - - - - - - - - - - - - - -
-@subsubsub*section{Newlines and Indentation}
-
-When indentation is used, all-space indentation string syntaxes are
-perpended to the beginning of each line. The rule for adding these
-string is:
+a boolean etc.) in a position that touches the following text; in
+these situations you should surround the escaped Scheme expression by
+a pair of @litchar["|"] characters. The text inside the bars is
+parsed as a Scheme expression.
+
+@scribble-examples|==={
+ @foo{foo@bar.}
+ @foo{foo@|bar|.}
+ @foo{foo@3.}
+ @foo{foo@|3|.}
+}===|
+
+This form is a generic Scheme expression escape, there is no body text
+or datum part when you use this form.
+
+@scribble-examples|==={
+ @foo{foo@|(f 1)|{bar}}
+ @foo{foo@|bar|[1]{baz}}
+}===|
+
+This works for string expressions too, but note that unlike the above,
+the string is (intentionally) not merged with the rest of the text:
+
+@scribble-examples|==={
+ @foo{x@"y"z}
+ @foo{x@|"y"|z}
+}===|
+
+Expression escapes also work with @italic{any} number of expressions,
+
+@scribble-examples|==={
+ @foo{x@|1 (+ 2 3) 4|y}
+ @foo{x@|*
+ *|y}
+}===|
+
+It seems that @litchar["@||"] has no purpose---but remember that these escapes
+are never merged with the surrounding text, which can be useful when
+you want to control the sub expressions in the form.
+
+@scribble-examples|==={
+ @foo{Alice@||Bob@|
+ |Carol}
+}===|
+
+Note that @litchar["@|{...}|"] can be parsed as either an escape expression or
+as a no-command @"@"-form. The latter is used in this case (since there
+is little point in Scheme code that uses braces.
+
+@scribble-examples|==={
+ @|{blah}|
+}===|
+
+@subsubsub*section{Comments}
+
+As noted above, there are two kinds of Scribble comments: @litchar["@;{...}"] is
+a (nestable) comment for a whole body of text (following the same
+rules for @"@"-forms), and @litchar["@;..."] is a line-comment.
+
+@scribble-examples|==={
+ @foo{First line@;{there is still a
+ newline at this point;}
+ Second line}
+}===|
+
+One useful property of line-comments is that they continue to the end
+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.}
+}===|
+
+Note how this is different from using @litchar["@||"]s in that strings
+around it are not merged.
+
+@subsubsub*section{Spaces, Newlines, and Indentation}
+
+The Scribble syntax treats spaces and newlines in a special way is
+meant to be sensible for dealing with text. As mentioned above,
+spaces at the beginning and end of body lines are discarded, except
+for spaces between a @litchar["{"] and text, or between text and a
+@litchar["}"].
+
+@scribble-examples|==={
+ @foo{bar}
+ @foo{ bar }
+ @foo{ bar
+ baz }
+}===|
-@itemize{
+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
- @item{A spaces-string is added to each line according to its distance from
- the leftmost syntax object;}
+@;FIXME empty lines are ignored in generated HTML output
+@scribble-examples|==={
+ @foo{bar
+ }
+ @foo{
+ bar
+ }
+ @foo{
- @item{The first string is not prepended with indentation if it appears on
- the first line of output.}
+ bar
-}
+ }
+ @foo{
+ bar
-@scribble-examples[
-#<<EOS
-@foo{
- bar
baz
- bbb}
-EOS
-
-#f
-
-#<<EOS
-@foo{bar
- baz
- bbb}
-EOS
-
-#f
+ }
+ @foo{
+ }
+ @foo{
-#<<EOS
-@foo{ bar
- baz
- bbb}
-EOS
+ }
+ @foo{ bar
+ baz }
+}===|
-#f
+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}.
-#<<EOS
-@foo{bar
- baz
- bbb}
-EOS
+@; FIXME: need to show printout here (with the scribble syntax)
+@schemeblock[
+ (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
+]
-#f
+Spaces at the beginning of body lines do not appear in the resulting
+S-expressions, but the column of each line is noticed, and all-space
+indentation strings are added so the result has the same indentation.
+A indentation string is added to each line according to its distance
+from the leftmost syntax object (except for empty lines). (Note: if
+you try these examples on a mzscheme REPL, you should be aware that
+the reader does not know about the "@litchar["> "]" prompt.)
-#<<EOS
+@scribble-examples|==={
+ @foo{
+ bar
+ baz
+ blah
+ }
+ @foo{
+ begin
+ x++;
+ end}
+ @foo{
+ a
+ b
+ c}
+}===|
+
+If the first string came from the openning @litchar["{"] line, it is
+not prepended with an indentation (but it can affect the leftmost
+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
+ bbb}
@foo{ bar
+ baz
+ bbb}
+ @foo{bar
baz
bbb}
-EOS
-
-#f
-
-#<<EOS
-@foo{ bar
- baz
+ @foo{ bar
+ baz
bbb}
-EOS
-]
-
-Additional notes:
-
-@itemize{
+ @foo{ bar
+ baz
+ bbb}
+ @text{Some text@footnote{And a
+ footnote comment.}. More text.}
+}===|
+
+Note that each @"@"-form is parsed to an S-expression that has its own
+indentation. This means that Scribble source can be indented like
+code, but if indentation matters then you may need to apply
+indentation of the outer item to all lines of the inner one. For
+example, in
+
+@litchar/lines|==={
+ @code{
+ begin
+ i = 1, r = 1
+ @bold{while i < n do
+ r *= i++
+ done}
+ end
+ }
+}===|
- @item{You can identify indentation strings at the syntax level by the fact
- that they have the same location information as the following syntax
- object.}
+a formatter will need to apply the 2-space indentation to the
+rendering of the @scheme[bold] body.
- @item{This mechanism depends on line and column number information
- (@scheme[use-at-readtable] turns them on for the current input port);}
+Note that to get a first-line text to be counted as a leftmost line,
+line and column accounting should be on for the input port
+(@scheme[use-at-readtable] turns them on for the current input port).
+Without this,
- @item{To use this mechanism with nested commands that should preserve
- indentation, you will need to do some additional work since the nested
- use will have only its own indentation;}
+@litchar/lines|==={
+ @foo{x1
+ x2
+ x3}
+}===|
- @item{When using it on a command-line, you note that the reader is not aware
- of the ``> '' prompt, which might lead to confusing results.}
+will not have 2-space indentations in the parsed S-expression if
+source accounting is not on, but
-}
+@litchar/lines|==={
+ @foo{x1
+ x2
+ x3}
+}===|
-@italic{The following is likely to change.}
+will (due to the last line). Pay attention to this, as it can be a
+problem with Scheme code, for example:
-For situations where spaces at the beginning of lines matter (various
-verbatim environments), you should begin a line with a @litchar["|"].
-It has no other special meaning -- so to use a @litchar["|"] as the
-first character in the text, simply use another before it.
+@litchar/lines|==={
+ @code{(define (foo x)
+ (+ x 1))}
+}===|
-@scribble-examples[
-#<<EOS
-@code{
- |(define (foo x)
- | |error|)
-}
-EOS
-]
+For rare situations where spaces at the beginning (or end) of lines
+matter, you can begin (or end) a line with a "@||".
-In other situations, newlines matter; you might want to avoid a
-newline token in some place. To avoid a newline and still break the
-source line, use a line comment. As in TeX, these will consume text
-up-to and including the end of the line and all following whitespace.
-
-@bold{@italic{The following examples from the original docs didn't
-work. They have been changed!}}
-
-@scribble-examples[
-#<<EOS
-@foo{bar @;
- baz@;
- !}
-EOS
-] @bold{The "!" above used to be a "."}
-
-A @litchar["|"] that follows this is still used for marking the
-beginning of the text:
-
-@scribble-examples[
-#<<EOS
-@foo{bar @;
- baz@;
- ? .}
-EOS
-] @bold{The "?" above used to be a "|", which is surely part of the point.}
-
-
-@; ------------------------------------------------------------------------
-@subsection{How To Use the Reader}
-
-The reader can be used in any way you want. All you need is to use
-function names that you bind. You can even use quasi-quotes, skipping
-the need for functions, for example:
-
-@verbatim[
-#<<EOS
- > (define (important . text) @`b{@u{@big{@,@text}}})
- > (important @`p{An important announcement!
- Read it!})
- (b (u (big (p "An important announcement!" "\n" "Read it!"))))
-EOS
+@scribble-examples|==={
+ @foo{
+ @|| bar @||
+ @|| baz}
+}===|
+
+Finally, you might be need a verbatim-like environment, where the
+parsed body matches exactly the textual source. To make this
+possible, the @"@"-parser uses syntax properties on the resulting
+syntax values. All items that are not physically in the Scribble
+source---newlines and indentation-spaces---have a 'scribble property.
+An indentation string will have @scheme['indentation] as the value of
+this property, and a newline will have a @scheme['(newline S)] value
+where S is the original newline string including spaces that precede
+and follow it (which includes the indentation for the following item).
+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[
+ (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)])))))]))
+ @verb[string-append]{
+ foo
+ bar
+ }
+ --> "foo\n bar"
]
diff --git a/collects/scribblings/scribble/scribble.scrbl b/collects/scribblings/scribble/scribble.scrbl
@@ -23,7 +23,7 @@ The layers are:
@itemize{
@item{@file{reader.ss}: a reader that extends the syntax of Scheme
- with @at forms for conveniently embedding a mixin of text and
+ with @"@"-forms for conveniently embedding a mixin of text and
escapes. See @secref["reader"].}
@item{@file{struct.ss}: a set of document datatypes, which define the
diff --git a/collects/scribblings/scribble/utils.ss b/collects/scribblings/scribble/utils.ss
@@ -6,21 +6,17 @@
(prefix scribble: (lib "reader.ss" "scribble"))
(lib "string.ss"))
- (provide at
- litchar/lines
- scribble-examples)
+ (provide scribble-examples litchar/lines)
- (define at "@")
-
- (define (litchar/lines s)
- (let ([strs (regexp-split #rx"\n" s)])
+ (define (litchar/lines . strs)
+ (let ([strs (regexp-split #rx"\n" (apply string-append strs))])
(if (= 1 (length strs))
- (litchar s)
- (make-table
- #f
- (map (lambda (s)
- (list (make-flow (list (make-paragraph (list (litchar s)))))))
- strs)))))
+ (litchar (car strs))
+ (make-table
+ #f
+ (map (lambda (s)
+ (list (make-flow (list (make-paragraph (list (litchar s)))))))
+ strs)))))
(define (as-flow e)
(make-flow (list (if (flow-element? e)
@@ -72,20 +68,31 @@
p)]))
(define (scribble-examples . lines)
- (make-table
- #f
- (map (lambda (line)
- (let ([line (if (string? line)
- (list (litchar/lines line)
- (scheme:to-paragraph
- (let ([p (open-input-string line)])
- (port-count-lines! p)
- (if (regexp-match? #rx"\n" line)
- ((norm-spacing 0) (scribble:read-syntax #f p))
- (scribble:read p)))))
- line)])
- (list (as-flow spacer)
- (as-flow (if line (car line) ""))
- (as-flow (if line (make-paragraph (list spacer "reads as" spacer)) ""))
- (as-flow (if line (cadr line) "")))))
- lines))))
+ (define reads-as (make-paragraph (list spacer "reads as" spacer)))
+ (let* ([lines (apply string-append lines)]
+ [p (open-input-string lines)])
+ (port-count-lines! p)
+ (let loop ([r '()] [newlines? #f])
+ (regexp-match? #px#"^[[:space:]]*" p)
+ (let* ([p1 (file-position p)]
+ [stx (scribble:read-syntax #f p)]
+ [p2 (file-position p)])
+ (if (not (eof-object? stx))
+ (let ([str (substring lines p1 p2)])
+ (loop (cons (list str stx) r)
+ (or newlines? (regexp-match? #rx#"\n" str))))
+ (let* ([r (reverse! r)]
+ [r (if newlines?
+ (cdr (apply append! (map (lambda (x) (list #f x)) r)))
+ r)])
+ (make-table
+ #f
+ (map (lambda (x)
+ (let ([@expr (if x (litchar/lines (car x)) "")]
+ [sexpr (if x
+ (scheme:to-paragraph
+ ((norm-spacing 0) (cadr x)))
+ "")]
+ [reads-as (if x reads-as "")])
+ (map as-flow (list spacer @expr reads-as sexpr))))
+ r)))))))))