Merge branch 'master' into new_ui

db4
Slava Pestov 2009-01-27 06:34:19 -06:00
commit 8b6ae748b9
47 changed files with 629 additions and 451 deletions

View File

@ -53,7 +53,8 @@ ARTICLE: { "concurrency" "synchronous-sends" } "Synchronous sends"
{ $subsection reply-synchronous }
"An example:"
{ $example
"USING: concurrency.messaging kernel threads ;"
"USING: concurrency.messaging kernel prettyprint threads ;"
"IN: scratchpad"
": pong-server ( -- )"
" receive [ \"pong\" ] dip reply-synchronous ;"
"[ pong-server t ] \"pong-server\" spawn-server"

View File

@ -11,7 +11,7 @@ HELP: eval>string
{ $description "Evaluates the Factor code in " { $snippet "str" } " with " { $link output-stream } " rebound to a string output stream, then outputs the resulting string." } ;
ARTICLE: "eval" "Evaluating strings at runtime"
"Evaluating strings at runtime:"
"The " { $vocab-link "eval" } " vocabulary implements support for evaluating strings at runtime."
{ $subsection eval }
{ $subsection eval>string } ;

View File

@ -0,0 +1,4 @@
IN: eval.tests
USING: eval tools.test ;
[ "4\n" ] [ "USING: math prettyprint ; 2 2 + ." eval>string ] unit-testv

View File

@ -1,14 +1,24 @@
! Copyright (C) 2008 Slava Pestov.
! Copyright (C) 2008, 2009 Slava Pestov.
! See http://factorcode.org/license.txt for BSD license.
USING: splitting parser compiler.units kernel namespaces
debugger io.streams.string ;
debugger io.streams.string fry ;
IN: eval
: parse-string ( str -- )
[ string-lines parse-lines ] with-compilation-unit ;
: (eval) ( str -- )
parse-string call ;
: eval ( str -- )
[ string-lines parse-fresh ] with-compilation-unit call ;
[ (eval) ] with-file-vocabs ;
: (eval>string) ( str -- output )
[
"quiet" on
parser-notes off
'[ _ (eval) ] try
] with-string-writer ;
: eval>string ( str -- output )
[
parser-notes off
[ [ eval ] keep ] try drop
] with-string-writer ;
[ (eval>string) ] with-file-vocabs ;

View File

@ -92,22 +92,22 @@ link-no-follow? off
[ "<p>=</p><h2>foo</h2>" ] [ "===foo==" convert-farkup ] unit-test
[ "<h1>foo</h1><p>=</p>" ] [ "=foo==" convert-farkup ] unit-test
[ "<pre><span class='KEYWORD3'>int</span> <span class='FUNCTION'>main</span><span class='OPERATOR'>(</span><span class='OPERATOR'>)</span>\n</pre>" ]
[ "<pre><span class=\"KEYWORD3\">int</span> <span class=\"FUNCTION\">main</span><span class=\"OPERATOR\">(</span><span class=\"OPERATOR\">)</span></pre>" ]
[ "[c{int main()}]" convert-farkup ] unit-test
[ "<p><img src='lol.jpg'/></p>" ] [ "[[image:lol.jpg]]" convert-farkup ] unit-test
[ "<p><img src='lol.jpg' alt='teh lol'/></p>" ] [ "[[image:lol.jpg|teh lol]]" convert-farkup ] unit-test
[ "<p><a href='http://lol.com'>http://lol.com</a></p>" ] [ "[[http://lol.com]]" convert-farkup ] unit-test
[ "<p><a href='http://lol.com'>haha</a></p>" ] [ "[[http://lol.com|haha]]" convert-farkup ] unit-test
[ "<p><a href='Foo/Bar'>Bar</a></p>" ] [ "[[Foo/Bar]]" convert-farkup ] unit-test
[ "<p><img src=\"lol.jpg\"/></p>" ] [ "[[image:lol.jpg]]" convert-farkup ] unit-test
[ "<p><img src=\"lol.jpg\" alt=\"teh lol\"/></p>" ] [ "[[image:lol.jpg|teh lol]]" convert-farkup ] unit-test
[ "<p><a href=\"http://lol.com\">http://lol.com</a></p>" ] [ "[[http://lol.com]]" convert-farkup ] unit-test
[ "<p><a href=\"http://lol.com\">haha</a></p>" ] [ "[[http://lol.com|haha]]" convert-farkup ] unit-test
[ "<p><a href=\"Foo/Bar\">Bar</a></p>" ] [ "[[Foo/Bar]]" convert-farkup ] unit-test
"/wiki/view/" relative-link-prefix [
[ "<p><a href='/wiki/view/Foo/Bar'>Bar</a></p>" ] [ "[[Foo/Bar]]" convert-farkup ] unit-test
[ "<p><a href=\"/wiki/view/Foo/Bar\">Bar</a></p>" ] [ "[[Foo/Bar]]" convert-farkup ] unit-test
] with-variable
[ ] [ "[{}]" convert-farkup drop ] unit-test
[ "<pre>hello\n</pre>" ] [ "[{hello}]" convert-farkup ] unit-test
[ "<pre>hello</pre>" ] [ "[{hello}]" convert-farkup ] unit-test
[
"<p>Feature comparison:\n<table><tr><td>a</td><td>Factor</td><td>Java</td><td>Lisp</td></tr><tr><td>Coolness</td><td>Yes</td><td>No</td><td>No</td></tr><tr><td>Badass</td><td>Yes</td><td>No</td><td>No</td></tr><tr><td>Enterprise</td><td>Yes</td><td>Yes</td><td>No</td></tr><tr><td>Kosher</td><td>Yes</td><td>No</td><td>Yes</td></tr></table></p>"
@ -118,15 +118,15 @@ link-no-follow? off
] [ "Feature comparison:\n\n|a|Factor|Java|Lisp|\n|Coolness|Yes|No|No|\n|Badass|Yes|No|No|\n|Enterprise|Yes|Yes|No|\n|Kosher|Yes|No|Yes|\n" convert-farkup ] unit-test
[
"<p>This wiki is written in <a href='Factor'>Factor</a> and is hosted on a <a href='http://linode.com'>http://linode.com</a> virtual server.</p>"
"<p>This wiki is written in <a href=\"Factor\">Factor</a> and is hosted on a <a href=\"http://linode.com\">http://linode.com</a> virtual server.</p>"
] [
"This wiki is written in [[Factor]] and is hosted on a [[http://linode.com|http://linode.com]] virtual server."
convert-farkup
] unit-test
[ "<p><a href='a'>a</a> <a href='b'>c</a></p>" ] [ "[[a]] [[b|c]]" convert-farkup ] unit-test
[ "<p><a href=\"a\">a</a> <a href=\"b\">c</a></p>" ] [ "[[a]] [[b|c]]" convert-farkup ] unit-test
[ "<p><a href='C%2b%2b'>C++</a></p>" ] [ "[[C++]]" convert-farkup ] unit-test
[ "<p><a href=\"C%2b%2b\">C++</a></p>" ] [ "[[C++]]" convert-farkup ] unit-test
[ "<p>&lt;foo&gt;</p>" ] [ "<foo>" convert-farkup ] unit-test
@ -138,10 +138,10 @@ link-no-follow? off
[ "<hr/>" ] [ "___" convert-farkup ] unit-test
[ "<hr/>\n" ] [ "___\n" convert-farkup ] unit-test
[ "<p>before:\n<pre><span class='OPERATOR'>{</span> <span class='DIGIT'>1</span> <span class='DIGIT'>2</span> <span class='DIGIT'>3</span> <span class='OPERATOR'>}</span> <span class='DIGIT'>1</span> tail\n</pre></p>" ]
[ "<p>before:\n<pre><span class=\"OPERATOR\">{</span> <span class=\"DIGIT\">1</span> <span class=\"DIGIT\">2</span> <span class=\"DIGIT\">3</span> <span class=\"OPERATOR\">}</span> <span class=\"DIGIT\">1</span> tail</pre></p>" ]
[ "before:\n[factor{{ 1 2 3 } 1 tail}]" convert-farkup ] unit-test
[ "<p><a href='Factor'>Factor</a>-rific!</p>" ]
[ "<p><a href=\"Factor\">Factor</a>-rific!</p>" ]
[ "[[Factor]]-rific!" convert-farkup ] unit-test
[ "<p>[ factor { 1 2 3 }]</p>" ]
@ -163,7 +163,7 @@ link-no-follow? off
convert-farkup string>xml-chunk
"a" deep-tag-named "href" swap at url-decode ;
[ "Trader Joe's" ] [ "[[Trader Joe's]]" check-link-escaping ] unit-test
[ "Trader Joe\"s" ] [ "[[Trader Joe\"s]]" check-link-escaping ] unit-test
[ "<foo>" ] [ "[[<foo>]]" check-link-escaping ] unit-test
[ "&blah;" ] [ "[[&blah;]]" check-link-escaping ] unit-test
[ "C++" ] [ "[[C++]]" check-link-escaping ] unit-test
[ "C++" ] [ "[[C++]]" check-link-escaping ] unit-test

View File

@ -2,8 +2,9 @@
! See http://factorcode.org/license.txt for BSD license.
USING: accessors arrays combinators html.elements io
io.streams.string kernel math namespaces peg peg.ebnf
sequences sequences.deep strings xml.entities
vectors splitting xmode.code2html urls.encoding ;
sequences sequences.deep strings xml.entities xml.interpolate
vectors splitting xmode.code2html urls.encoding xml.data
xml.writer ;
IN: farkup
SYMBOL: relative-link-prefix
@ -74,6 +75,7 @@ inline-code = "%" (!("%" | nl).)+ "%"
=> [[ second >string inline-code boa ]]
link-content = (!("|"|"]").)+
=> [[ >string ]]
image-link = "[[image:" link-content "|" link-content "]]"
=> [[ [ second >string ] [ fourth >string ] bi image boa ]]
@ -146,7 +148,7 @@ named-code
simple-code
= "[{" (!("}]").)+ "}]"
=> [[ second f swap code boa ]]
=> [[ second >string f swap code boa ]]
code = named-code | simple-code
@ -163,66 +165,78 @@ stand-alone
{ [ dup [ 127 > ] contains? ] [ drop invalid-url ] }
{ [ dup first "/\\" member? ] [ drop invalid-url ] }
{ [ CHAR: : over member? ] [ dup absolute-url? [ drop invalid-url ] unless ] }
[ relative-link-prefix get prepend ]
} cond ;
[ relative-link-prefix get prepend "" like ]
} cond url-encode ;
: escape-link ( href text -- href-esc text-esc )
[ check-url ] dip escape-string ;
: write-link ( href text -- xml )
[ check-url link-no-follow? get "true" and ] dip
[XML <a href=<-> nofollow=<->><-></a> XML] ;
: write-link ( href text -- )
escape-link
[ <a url-encode =href link-no-follow? get [ "true" =nofollow ] when a> ]
[ write </a> ]
bi* ;
: write-image-link ( href text -- )
: write-image-link ( href text -- xml )
disable-images? get [
2drop
<strong> "Images are not allowed" write </strong>
[XML <strong>Images are not allowed</strong> XML]
] [
escape-link
[ <img url-encode =src ] [ [ =alt ] unless-empty img/> ] bi*
[ check-url ] [ f like ] bi*
[XML <img src=<-> alt=<->/> XML]
] if ;
: render-code ( string mode -- string' )
[ string-lines ] dip
[
<pre>
htmlize-lines
</pre>
] with-string-writer write ;
: render-code ( string mode -- xml )
[ string-lines ] dip htmlize-lines
[XML <pre><-></pre> XML] ;
GENERIC: (write-farkup) ( farkup -- )
: <foo.> ( string -- ) <foo> write ;
: </foo.> ( string -- ) </foo> write ;
: in-tag. ( obj quot string -- ) [ <foo.> call ] keep </foo.> ; inline
M: heading1 (write-farkup) [ child>> (write-farkup) ] "h1" in-tag. ;
M: heading2 (write-farkup) [ child>> (write-farkup) ] "h2" in-tag. ;
M: heading3 (write-farkup) [ child>> (write-farkup) ] "h3" in-tag. ;
M: heading4 (write-farkup) [ child>> (write-farkup) ] "h4" in-tag. ;
M: strong (write-farkup) [ child>> (write-farkup) ] "strong" in-tag. ;
M: emphasis (write-farkup) [ child>> (write-farkup) ] "em" in-tag. ;
M: superscript (write-farkup) [ child>> (write-farkup) ] "sup" in-tag. ;
M: subscript (write-farkup) [ child>> (write-farkup) ] "sub" in-tag. ;
M: inline-code (write-farkup) [ child>> (write-farkup) ] "code" in-tag. ;
M: list-item (write-farkup) [ child>> (write-farkup) ] "li" in-tag. ;
M: unordered-list (write-farkup) [ child>> (write-farkup) ] "ul" in-tag. ;
M: ordered-list (write-farkup) [ child>> (write-farkup) ] "ol" in-tag. ;
M: paragraph (write-farkup) [ child>> (write-farkup) ] "p" in-tag. ;
M: link (write-farkup) [ href>> ] [ text>> ] bi write-link ;
M: image (write-farkup) [ href>> ] [ text>> ] bi write-image-link ;
M: code (write-farkup) [ string>> ] [ mode>> ] bi render-code ;
M: line (write-farkup) drop <hr/> ;
M: line-break (write-farkup) drop <br/> nl ;
M: table-row (write-farkup) ( obj -- )
child>> [ [ [ (write-farkup) ] "td" in-tag. ] each ] "tr" in-tag. ;
M: table (write-farkup) [ child>> (write-farkup) ] "table" in-tag. ;
M: string (write-farkup) escape-string write ;
M: vector (write-farkup) [ (write-farkup) ] each ;
M: f (write-farkup) drop ;
GENERIC: (write-farkup) ( farkup -- xml )
: write-farkup ( string -- )
: farkup-inside ( farkup name -- xml )
<simple-name> swap T{ attrs } swap
child>> (write-farkup) 1array <tag> ;
M: heading1 (write-farkup) "h1" farkup-inside ;
M: heading2 (write-farkup) "h2" farkup-inside ;
M: heading3 (write-farkup) "h3" farkup-inside ;
M: heading4 (write-farkup) "h4" farkup-inside ;
M: strong (write-farkup) "strong" farkup-inside ;
M: emphasis (write-farkup) "em" farkup-inside ;
M: superscript (write-farkup) "sup" farkup-inside ;
M: subscript (write-farkup) "sub" farkup-inside ;
M: inline-code (write-farkup) "code" farkup-inside ;
M: list-item (write-farkup) "li" farkup-inside ;
M: unordered-list (write-farkup) "ul" farkup-inside ;
M: ordered-list (write-farkup) "ol" farkup-inside ;
M: paragraph (write-farkup) "p" farkup-inside ;
M: table (write-farkup) "table" farkup-inside ;
M: link (write-farkup)
[ href>> ] [ text>> ] bi write-link ;
M: image (write-farkup)
[ href>> ] [ text>> ] bi write-image-link ;
M: code (write-farkup)
[ string>> ] [ mode>> ] bi render-code ;
M: line (write-farkup)
drop [XML <hr/> XML] ;
M: line-break (write-farkup)
drop [XML <br/> XML] ;
M: table-row (write-farkup)
child>>
[ (write-farkup) [XML <td><-></td> XML] ] map
[XML <tr><-></tr> XML] ;
M: string (write-farkup) ;
M: vector (write-farkup) [ (write-farkup) ] map ;
M: f (write-farkup) ;
: farkup>xml ( string -- xml )
parse-farkup (write-farkup) ;
: write-farkup ( string -- )
farkup>xml write-xml-chunk ;
: convert-farkup ( string -- string' )
parse-farkup [ (write-farkup) ] with-string-writer ;
[ write-farkup ] with-string-writer ;

View File

@ -1,4 +1,4 @@
! Copyright (C) 2006, 2008 Slava Pestov.
! Copyright (C) 2006, 2009 Slava Pestov.
! See http://factorcode.org/license.txt for BSD license.
USING: fry accessors sequences parser kernel help help.markup
help.topics words strings classes tools.vocabs namespaces make
@ -6,21 +6,24 @@ io io.streams.string prettyprint definitions arrays vectors
combinators combinators.short-circuit splitting debugger
hashtables sorting effects vocabs vocabs.loader assocs editors
continuations classes.predicate macros math sets eval
vocabs.parser words.symbol values ;
vocabs.parser words.symbol values grouping unicode.categories
sequences.deep ;
IN: help.lint
: check-example ( element -- )
rest [
but-last "\n" join 1vector
[
use [ clone ] change
[ eval>string ] with-datastack
] with-scope peek "\n" ?tail drop
] keep
peek assert= ;
SYMBOL: vocabs-quot
: check-examples ( word element -- )
nip \ $example swap elements [ check-example ] each ;
: check-example ( element -- )
[
rest [
but-last "\n" join 1vector
[ (eval>string) ] with-datastack
peek "\n" ?tail drop
] keep
peek assert=
] vocabs-quot get call ;
: check-examples ( element -- )
\ $example swap elements [ check-example ] each ;
: extract-values ( element -- seq )
\ $values swap elements dup empty? [
@ -64,8 +67,13 @@ IN: help.lint
]
} 2|| [ "$values don't match stack effect" throw ] unless ;
: check-see-also ( word element -- )
nip \ $see-also swap elements [
: check-nulls ( element -- )
\ $values swap elements
null swap deep-member?
[ "$values should not contain null" throw ] when ;
: check-see-also ( element -- )
\ $see-also swap elements [
rest dup prune [ length ] bi@ assert=
] each ;
@ -79,43 +87,78 @@ IN: help.lint
] each ;
: check-rendering ( element -- )
[ print-topic ] with-string-writer drop ;
[ print-content ] with-string-writer drop ;
: check-strings ( str -- )
[
"\n\t" intersects?
[ "Paragraph text should not contain \\n or \\t" throw ] when
] [
" " swap subseq?
[ "Paragraph text should not contain double spaces" throw ] when
] bi ;
: check-whitespace ( str1 str2 -- )
[ " " tail? ] [ " " head? ] bi* or
[ "Missing whitespace between strings" throw ] unless ;
: check-bogus-nl ( element -- )
{ { $nl } { { $nl } } } [ head? ] with contains?
[ "Simple element should not begin with a paragraph break" throw ] when ;
: check-elements ( element -- )
{
[ check-bogus-nl ]
[ [ string? ] filter [ check-strings ] each ]
[ [ simple-element? ] filter [ check-elements ] each ]
[ 2 <clumps> [ [ string? ] all? ] filter [ first2 check-whitespace ] each ]
} cleave ;
: check-markup ( element -- )
{
[ check-elements ]
[ check-rendering ]
[ check-examples ]
[ check-modules ]
} cleave ;
: all-word-help ( words -- seq )
[ word-help ] filter ;
TUPLE: help-error topic error ;
TUPLE: help-error error topic ;
C: <help-error> help-error
M: help-error error.
"In " write dup topic>> pprint nl
error>> error. ;
[ "In " write topic>> pprint nl ]
[ error>> error. ]
bi ;
: check-something ( obj quot -- )
flush [ <help-error> , ] recover ; inline
flush '[ _ assert-depth ] swap '[ _ <help-error> , ] recover ; inline
: check-word ( word -- )
[ with-file-vocabs ] vocabs-quot set
dup word-help [
[
dup word-help '[
_ _ {
[ check-examples ]
[ check-values ]
[ check-see-also ]
[ [ check-rendering ] [ check-modules ] bi* ]
} 2cleave
] assert-depth
dup '[
_ dup word-help
[ check-values ]
[ nip [ check-nulls ] [ check-see-also ] [ check-markup ] tri ] 2bi
] check-something
] [ drop ] if ;
: check-words ( words -- ) [ check-word ] each ;
: check-article-title ( article -- )
article-title first LETTER?
[ "Article title must begin with a capital letter" throw ] unless ;
: check-article ( article -- )
[
dup article-content
'[ _ check-rendering _ check-modules ]
assert-depth
[ with-interactive-vocabs ] vocabs-quot set
dup '[
_
[ check-article-title ]
[ article-content check-markup ] bi
] check-something ;
: files>vocabs ( -- assoc )
@ -135,7 +178,7 @@ M: help-error error.
] keep ;
: check-about ( vocab -- )
[ vocab-help [ article drop ] when* ] check-something ;
dup '[ _ vocab-help [ article drop ] when* ] check-something ;
: check-vocab ( vocab -- seq )
"Checking " write dup write "..." print

View File

@ -94,7 +94,7 @@ $nl
"For example, we'd like it to identify the following as a palindrome:"
{ $code "\"A man, a plan, a canal: Panama.\"" }
"However, right now, the simplistic algorithm we use says this is not a palindrome:"
{ $example "\"A man, a plan, a canal: Panama.\" palindrome?" "f" }
{ $unchecked-example "\"A man, a plan, a canal: Panama.\" palindrome?" "f" }
"We would like it to output " { $link t } " there. We can encode this requirement with a unit test that we add to " { $snippet "palindrome-tests.factor" } ":"
{ $code "[ t ] [ \"A man, a plan, a canal: Panama.\" palindrome? ] unit-test" }
"If you now run unit tests, you will see a unit test failure:"
@ -106,12 +106,12 @@ $nl
"Start by pushing a character on the stack; notice that characters are really just integers:"
{ $code "CHAR: a" }
"Now, use the " { $link Letter? } " word to test if it is an alphabetical character, upper or lower case:"
{ $example "Letter? ." "t" }
{ $unchecked-example "Letter? ." "t" }
"This gives the expected result."
$nl
"Now try with a non-alphabetical character:"
{ $code "CHAR: #" }
{ $example "Letter? ." "f" }
{ $unchecked-example "Letter? ." "f" }
"What we want to do is given a string, remove all characters which do not match the " { $link Letter? } " predicate. Let's push a string on the stack:"
{ $code "\"A man, a plan, a canal: Panama.\"" }
"Now, place a quotation containing " { $link Letter? } " on the stack; quoting code places it on the stack instead of executing it immediately:"

View File

@ -31,7 +31,7 @@ TUPLE: color red green blue ;
] with-string-writer
] unit-test
[ "<input type='hidden' name='red' value='<jimmy>'/>" ] [
[ "<input value=\"&lt;jimmy>\" name=\"red\" type=\"hidden\"/>" ] [
[
"red" hidden render
] with-string-writer
@ -39,13 +39,13 @@ TUPLE: color red green blue ;
[ ] [ "'jimmy'" "red" set-value ] unit-test
[ "<input type='text' size='5' name='red' value='&apos;jimmy&apos;'/>" ] [
[ "<input value=\"&apos;jimmy&apos;\" name=\"red\" size=\"5\" type=\"text\"/>" ] [
[
"red" <field> 5 >>size render
] with-string-writer
] unit-test
[ "<input type='password' size='5' name='red' value=''/>" ] [
[ "<input value=\"\" name=\"red\" size=\"5\" type=\"password\"/>" ] [
[
"red" <password> 5 >>size render
] with-string-writer
@ -105,7 +105,7 @@ TUPLE: color red green blue ;
[ ] [ t "delivery" set-value ] unit-test
[ "<input type='checkbox' name='delivery' checked='true'>Delivery</input>" ] [
[ "<input type=\"checkbox\" checked=\"true\" name=\"delivery\">Delivery</input>" ] [
[
"delivery"
<checkbox>
@ -116,7 +116,7 @@ TUPLE: color red green blue ;
[ ] [ f "delivery" set-value ] unit-test
[ "<input type='checkbox' name='delivery'>Delivery</input>" ] [
[ "<input type=\"checkbox\" name=\"delivery\">Delivery</input>" ] [
[
"delivery"
<checkbox>
@ -133,7 +133,7 @@ M: link-test link-href drop "http://www.apple.com/foo&bar" ;
[ ] [ link-test "link" set-value ] unit-test
[ "<a href='http://www.apple.com/foo&amp;bar'>&lt;Link Title&gt;</a>" ] [
[ "<a href=\"http://www.apple.com/foo&amp;bar\">&lt;Link Title&gt;</a>" ] [
[ "link" link new render ] with-string-writer
] unit-test
@ -149,7 +149,7 @@ M: link-test link-href drop "http://www.apple.com/foo&bar" ;
[ ] [ "java" "mode" set-value ] unit-test
[ "<span class='KEYWORD3'>int</span> x <span class='OPERATOR'>=</span> <span class='DIGIT'>4</span>;\n" ] [
[ "<span class=\"KEYWORD3\">int</span> x <span class=\"OPERATOR\">=</span> <span class=\"DIGIT\">4</span>;" ] [
[ "code" <code> "mode" >>mode render ] with-string-writer
] unit-test
@ -163,6 +163,8 @@ M: link-test link-href drop "http://www.apple.com/foo&bar" ;
[ t ] [
[ "object" inspector render ] with-string-writer
USING: splitting sequences ;
"\"" split "'" join ! replace " with ' for now
[ "object" value [ describe ] with-html-writer ] with-string-writer
=
] unit-test

View File

@ -4,12 +4,12 @@ USING: accessors kernel namespaces io math.parser assocs classes
classes.tuple words arrays sequences splitting mirrors
hashtables combinators continuations math strings inspector
fry locals calendar calendar.format xml.entities
validators urls present
xmode.code2html lcs.diff2html farkup
validators urls present xml.writer xml.interpolate xml
xmode.code2html lcs.diff2html farkup io.streams.string
html.elements html.streams html.forms ;
IN: html.components
GENERIC: render* ( value name renderer -- )
GENERIC: render* ( value name renderer -- xml )
: render ( name renderer -- )
prepare-value
@ -19,38 +19,36 @@ GENERIC: render* ( value name renderer -- )
[ f swap ]
if
] 2dip
render*
render* write-xml-chunk
[ render-error ] when* ;
<PRIVATE
: render-input ( value name type -- )
<input =type =name present =value input/> ;
: render-input ( value name type -- xml )
[XML <input value=<-> name=<-> type=<->/> XML] ;
PRIVATE>
SINGLETON: label
M: label render* 2drop present escape-string write ;
M: label render*
2drop present ;
SINGLETON: hidden
M: hidden render* drop "hidden" render-input ;
M: hidden render*
drop "hidden" render-input ;
: render-field ( value name size type -- )
<input
=type
[ present =size ] when*
=name
present =value
input/> ;
: render-field ( value name size type -- xml )
[XML <input value=<-> name=<-> size=<-> type=<->/> XML] ;
TUPLE: field size ;
: <field> ( -- field )
field new ;
M: field render* size>> "text" render-field ;
M: field render*
size>> "text" render-field ;
TUPLE: password size ;
@ -67,14 +65,12 @@ TUPLE: textarea rows cols ;
: <textarea> ( -- renderer )
textarea new ;
M: textarea render*
<textarea
[ rows>> [ present =rows ] when* ]
[ cols>> [ present =cols ] when* ] bi
=name
textarea>
present escape-string write
</textarea> ;
M: textarea render* ( value name area -- xml )
rot [ [ rows>> ] [ cols>> ] bi ] dip
[XML <textarea
name=<->
rows=<->
cols=<->><-></textarea> XML] ;
! Choice
TUPLE: choice size multiple choices ;
@ -82,24 +78,23 @@ TUPLE: choice size multiple choices ;
: <choice> ( -- choice )
choice new ;
: render-option ( text selected? -- )
<option [ "selected" =selected ] when option>
present escape-string write
</option> ;
: render-option ( text selected? -- xml )
"selected" and swap
[XML <option selected=<->><-></option> XML] ;
: render-options ( options selected -- )
'[ dup _ member? render-option ] each ;
: render-options ( value choice -- xml )
[ choices>> value ] [ multiple>> ] bi
[ swap ] [ swap 1array ] if
'[ dup _ member? render-option ] map ;
M: choice render*
<select
swap =name
dup size>> [ present =size ] when*
dup multiple>> [ "true" =multiple ] when
select>
[ choices>> value ] [ multiple>> ] bi
[ swap ] [ swap 1array ] if
render-options
</select> ;
M:: choice render* ( value name choice -- xml )
choice size>> :> size
choice multiple>> "true" and :> multiple
value choice render-options :> contents
[XML <select
name=<-name->
size=<-size->
multiple=<-multiple->><-contents-></select> XML] ;
! Checkboxes
TUPLE: checkbox label ;
@ -108,13 +103,10 @@ TUPLE: checkbox label ;
checkbox new ;
M: checkbox render*
<input
"checkbox" =type
swap =name
swap [ "true" =checked ] when
input>
label>> escape-string write
</input> ;
[ "true" and ] [ ] [ label>> ] tri*
[XML <input
type="checkbox"
checked=<-> name=<->><-></input> XML] ;
! Link components
GENERIC: link-title ( obj -- string )
@ -129,10 +121,9 @@ M: url link-href ;
TUPLE: link target ;
M: link render*
nip
<a target>> [ =target ] when* dup link-href =href a>
link-title present escape-string write
</a> ;
nip swap
[ target>> ] [ [ link-href ] [ link-title ] bi ] bi*
[XML <a target=<-> href=<->><-></a> XML] ;
! XMode code component
TUPLE: code mode ;
@ -161,7 +152,7 @@ M: farkup render*
nip
[ no-follow>> [ string>boolean link-no-follow? set ] when* ]
[ disable-images>> [ string>boolean disable-images? set ] when* ]
[ parsed>> string>boolean [ (write-farkup) ] [ write-farkup ] if ]
[ parsed>> string>boolean [ (write-farkup) ] [ farkup>xml ] if ]
tri
] with-scope ;
@ -169,7 +160,8 @@ M: farkup render*
SINGLETON: inspector
M: inspector render*
2drop [ describe ] with-html-writer ;
2drop [ [ describe ] with-html-writer ] with-string-writer
string>xml-chunk ;
! Diff component
SINGLETON: comparison
@ -180,4 +172,4 @@ M: comparison render*
! HTML component
SINGLETON: html
M: html render* 2drop write ;
M: html render* 2drop string>xml-chunk ;

View File

@ -1,7 +1,7 @@
! Copyright (C) 2004, 2008 Mackenzie Straight, Doug Coleman.
! See http://factorcode.org/license.txt for BSD license.
USING: alien alien.c-types arrays destructors io io.backend io.buffers
io.files io.ports io.binary io.timeouts io.encodings.8-bit
USING: alien alien.c-types arrays destructors io io.backend
io.buffers io.files io.ports io.binary io.timeouts
windows.errors strings kernel math namespaces sequences windows
windows.kernel32 windows.shell32 windows.types windows.winsock
splitting continuations math.bitwise system accessors ;
@ -51,6 +51,4 @@ HOOK: add-completion io-backend ( port -- )
: default-security-attributes ( -- obj )
"SECURITY_ATTRIBUTES" <c-object>
"SECURITY_ATTRIBUTES" heap-size
over set-SECURITY_ATTRIBUTES-nLength ;
M: windows console-encoding windows-1252 ;
over set-SECURITY_ATTRIBUTES-nLength ;

View File

@ -1,44 +1,42 @@
! Copyright (C) 2008 Slava Pestov
! See http://factorcode.org/license.txt for BSD license.
USING: lcs html.elements kernel ;
USING: lcs xml.interpolate xml.writer kernel strings ;
FROM: accessors => item>> ;
FROM: io => write ;
FROM: sequences => each if-empty ;
FROM: xml.entities => escape-string ;
FROM: sequences => each if-empty when-empty map ;
IN: lcs.diff2html
GENERIC: diff-line ( obj -- )
GENERIC: diff-line ( obj -- xml )
: write-item ( item -- )
item>> [ "&nbsp;" ] [ escape-string ] if-empty write ;
: item-string ( item -- string )
item>> [ CHAR: no-break-space 1string ] when-empty ;
M: retain diff-line
<tr>
dup [
<td "retain" =class td>
write-item
</td>
] bi@
</tr> ;
item-string
[XML <td class="retain"><-></td> XML]
dup [XML <tr><-><-></tr> XML] ;
M: insert diff-line
<tr>
<td> </td>
<td "insert" =class td>
write-item
</td>
</tr> ;
item-string [XML
<tr>
<td> </td>
<td class="insert"><-></td>
</tr>
XML] ;
M: delete diff-line
<tr>
<td "delete" =class td>
write-item
</td>
<td> </td>
</tr> ;
item-string [XML
<tr>
<td class="delete"><-></td>
<td> </td>
</tr>
XML] ;
: htmlize-diff ( diff -- )
<table "100%" =width "comparison" =class table>
<tr> <th> "Old" write </th> <th> "New" write </th> </tr>
[ diff-line ] each
</table> ;
: htmlize-diff ( diff -- xml )
[ diff-line ] map
[XML
<table width="100%" class="comparison">
<tr><th>Old</th><th>New</th></tr>
<->
</table>
XML] ;

View File

@ -134,6 +134,7 @@ $nl
}
"In a word with locals, literals expand into code which constructs the literal, and so every invocation pushes a new object:"
{ $example
"USE: locals"
"IN: scratchpad"
"TUPLE: person first-name last-name ;"
":: ordinary-word-test ( -- tuple )"

View File

@ -6,7 +6,7 @@ ARTICLE: "complex-numbers-zero" "Embedding of real numbers in complex numbers"
"Constructing a complex number with an imaginary component equal to an integer zero simply returns the real number corresponding to the real component:"
{ $example "USING: math prettyprint ;" "C{ 1 2 } C{ 3 -2 } + ." "4" }
"Constructing a complex number with an imaginary component equal to floating point zero will still output a new complex number, however:"
{ $example "USING: math prettyprint ;" "C{ 0.0 2.0 } C{ 0.0 1.0 } * ." "C{ 2.0 0.0 }" }
{ $example "USING: math prettyprint ;" "C{ 0.0 2.0 } C{ 0.0 1.0 } * ." "C{ -2.0 0.0 }" }
"Unlike math, where all real numbers are also complex numbers, Factor only considers a number to be a complex number if its imaginary part is non-zero. However, complex number operations are fully supported for real numbers; they are treated as having an imaginary part of zero." ;
ARTICLE: "complex-numbers" "Complex numbers"

View File

@ -5,8 +5,8 @@ ARTICLE: "math.libm" "C standard library math functions"
"The words in the " { $vocab-link "math.libm" } " vocabulary call C standard library math functions. They are used to implement words in the " { $vocab-link "math.functions" } " vocabulary."
$nl
"They can be called directly, however there is little reason to do so, since they only implement real-valued functions, and in some cases place restrictions on the domain:"
{ $example "2 acos ." "C{ 0.0 1.316957896924817 }" }
{ $example "2 facos ." "0.0/0.0" }
{ $example "USE: math.functions" "2 acos ." "C{ 0.0 1.316957896924817 }" }
{ $example "USE: math.libm" "2 facos ." "0.0/0.0" }
"Trigonometric functions:"
{ $subsection fcos }
{ $subsection fsin }

View File

@ -21,7 +21,7 @@ $nl
ARTICLE: "inference-combinators" "Combinator stack effects"
"Without further information, one cannot say what the stack effect of " { $link call } " is; it depends on the given quotation. If the inferencer encounters a " { $link call } " without further information, a " { $link literal-expected } " error is raised."
{ $example "[ dup call ] infer." "... an error ..." }
{ $example "[ dup call ] infer." "Literal value expected\n\nType :help for debugging help." }
"On the other hand, the stack effect of applying " { $link call } " to a literal quotation or a " { $link curry } " of a literal quotation is easy to compute; it behaves as if the quotation was substituted at that point:"
{ $example "[ [ 2 + ] call ] infer." "( object -- object )" }
"Consider a combinator such as " { $link keep } ". The combinator itself does not have a stack effect, because it applies " { $link call } " to a potentially arbitrary quotation. However, since the combinator is declared " { $link POSTPONE: inline } ", a given usage of it can have a stack effect:"
@ -35,7 +35,15 @@ $nl
"Here is an example where the stack effect cannot be inferred:"
{ $code ": foo 0 [ + ] ;" "[ foo reduce ] infer." }
"However if " { $snippet "foo" } " was declared " { $link POSTPONE: inline } ", everything would work, since the " { $link reduce } " combinator is also " { $link POSTPONE: inline } ", and the inferencer can see the literal quotation value at the point it is passed to " { $link call } ":"
{ $example ": foo 0 [ + ] ; inline" "[ foo reduce ] infer." "( object -- object )" } ;
{ $example ": foo 0 [ + ] ; inline" "[ foo reduce ] infer." "( object -- object )" }
"Passing a literal quotation on the data stack through an inlined recursive combinator nullifies its literal status. For example, the following will not infer:"
{ $example
"[ [ reverse ] swap [ reverse ] map swap call ] infer." "Literal value expected\n\nType :help for debugging help."
}
"To make this work, pass the quotation on the retain stack instead:"
{ $example
"[ [ reverse ] [ [ reverse ] map ] dip call ] infer." "( object -- object )"
} ;
ARTICLE: "inference-branches" "Branch stack effects"
"Conditionals such as " { $link if } " and combinators built on " { $link if } " present a problem, in that if the two branches leave the stack at a different height, it is not clear what the stack effect should be. In this case, inference throws a " { $link unbalanced-branches-error } "."
@ -58,12 +66,14 @@ $nl
$nl
"If a recursive word takes quotation parameters from the stack and calls them, it must be declared " { $link POSTPONE: inline } " (as documented in " { $link "inference-combinators" } ") as well as " { $link POSTPONE: recursive } "."
$nl
"Furthermore, the input parameters which are quotations must be annotated in the stack effect. For example,"
{ $see loop }
"An inline recursive word cannot pass a quotation through the recursive call. For example, the following will not infer:"
{ $code ": foo ( a b c -- d e f ) [ f foo drop ] when 2dup call ; inline" "[ 1 [ 1+ ] foo ] infer." }
"Furthermore, the input parameters which are quotations must be annotated in the stack effect. For example, the following will not infer:"
{ $example ": bad ( quot -- ) [ call ] keep foo ; inline recursive" "[ [ ] bad ] infer." "Literal value expected\n\nType :help for debugging help." }
"The following is correct:"
{ $example ": good ( quot: ( -- ) -- ) [ call ] keep good ; inline recursive" "[ [ ] good ] infer." "( -- )" }
"An inline recursive word cannot pass a quotation on the data stack through the recursive call. For example, the following will not infer:"
{ $example ": bad ( ? quot: ( ? -- ) -- ) 2dup [ not ] dip bad call ; inline recursive" "[ [ drop ] bad ] infer." "Literal value expected\n\nType :help for debugging help." }
"However a small change can be made:"
{ $example ": foo ( a b c -- d ) [ 2dup f foo drop ] when call ; inline" "[ 1 [ 1+ ] t foo ] infer." "( -- object )" }
{ $example ": good ( ? quot: ( ? -- ) -- ) [ good ] 2keep [ not ] dip call ; inline recursive" "[ [ drop ] good ] infer." "( object -- )" }
"An inline recursive word must have a fixed stack effect in its base case. The following will not infer:"
{ $code
": foo ( quot ? -- ) [ f foo ] [ call ] if ; inline"

View File

@ -3,7 +3,7 @@
USING: accessors kernel xml arrays math generic http.client
combinators hashtables namespaces io base64 sequences strings
calendar xml.data xml.writer xml.utilities assocs math.parser
debugger calendar.format math.order ;
debugger calendar.format math.order xml.interpolate ;
IN: xml-rpc
! * Sending RPC requests
@ -15,56 +15,70 @@ GENERIC: item>xml ( object -- xml )
M: integer item>xml
dup 31 2^ neg 31 2^ 1 - between?
[ "Integers must fit in 32 bits" throw ] unless
number>string "i4" build-tag ;
number>string [XML <i4><-></i4> XML] ;
UNION: boolean t POSTPONE: f ;
M: boolean item>xml
"1" "0" ? "boolean" build-tag ;
"1" "0" ? [XML <boolean><-></boolean> XML] ;
M: float item>xml
number>string "double" build-tag ;
number>string [XML <double><-></double> XML] ;
M: string item>xml ! This should change < and &
"string" build-tag ;
M: string item>xml
[XML <string><-></string> XML] ;
: struct-member ( name value -- tag )
swap dup string?
[ "Struct member name must be string" throw ] unless
"name" build-tag swap
item>xml "value" build-tag
2array "member" build-tag* ;
over string? [ "Struct member name must be string" throw ] unless
item>xml
[XML
<member>
<name><-></name>
<value><-></value>
</member>
XML] ;
M: hashtable item>xml
[ struct-member ] { } assoc>map
"struct" build-tag* ;
[XML <struct><-></struct> XML] ;
M: array item>xml
[ item>xml "value" build-tag ] map
"data" build-tag* "array" build-tag ;
[ item>xml [XML <value><-></value> XML] ] map
[XML <array><data><-></data></array> XML] ;
TUPLE: base64 string ;
C: <base64> base64
M: base64 item>xml
string>> >base64 "base64" build-tag ;
string>> >base64
[XML <base64><-></base64> XML] ;
: params ( seq -- xml )
[ item>xml "value" build-tag "param" build-tag ] map
"params" build-tag* ;
[ item>xml [XML <param><value><-></value></param> XML] ] map
[XML <params><-></params> XML] ;
: method-call ( name seq -- xml )
params [ "methodName" build-tag ] dip
2array "methodCall" build-tag* build-xml ;
params
<XML
<methodCall>
<methodName><-></methodName>
<->
</methodCall>
XML> ;
: return-params ( seq -- xml )
params "methodResponse" build-tag build-xml ;
params <XML <methodResponse><-></methodResponse> XML> ;
: return-fault ( fault-code fault-string -- xml )
[ "faultString" set "faultCode" set ] H{ } make-assoc item>xml
"value" build-tag "fault" build-tag "methodResponse" build-tag
build-xml ;
<XML
<methodResponse>
<fault>
<value><-></value>
</fault>
</methodResponse>
XML> ;
TUPLE: rpc-method name params ;

View File

@ -4,7 +4,7 @@ IN: xml.data
ABOUT: "xml.data"
ARTICLE: "xml.data" "XML data types"
{ $vocab-link "xml.data" } " defines a simple document object model for XML. Everything is simply a tuple and can be manipulated as such."
"The " { $vocab-link "xml.data" } " vocabulary defines a simple document object model for XML. Everything is simply a tuple and can be manipulated as such."
{ $subsection { "xml.data" "classes" } }
{ $subsection { "xml.data" "constructors" } }
"Simple words for manipulating names:"
@ -49,7 +49,7 @@ ARTICLE: { "xml.data" "constructors" } "XML data constructors"
{ $subsection <notation-decl> } ;
HELP: tag
{ $class-description "tuple representing an XML tag, delegating to a " { $link
{ $class-description "Tuple representing an XML tag, delegating to a " { $link
name } ", containing the slots attrs (an alist of names to strings) and children (a sequence). Tags implement the sequence protocol by acting like a sequence of its chidren, and the assoc protocol by acting like its attributes." }
{ $see-also <tag> name contained-tag xml } ;
@ -58,32 +58,32 @@ HELP: <tag>
{ "attrs" "an alist of names to strings" }
{ "children" sequence }
{ "tag" tag } }
{ $description "constructs an XML " { $link tag } " with the name (not a string) and tag attributes specified in attrs and children specified" }
{ $description "Constructs an XML " { $link tag } " with the name (not a string) and tag attributes specified in attrs and children specified." }
{ $see-also tag <contained-tag> } ;
HELP: name
{ $class-description "represents an XML name, with the fields space (a string representing the namespace, as written in the document, tag (a string of the actual name of the tag) and url (a string of the URL that the namespace points to)" }
{ $class-description "Represents an XML name, with the fields space (a string representing the namespace, as written in the document, tag (a string of the actual name of the tag) and url (a string of the URL that the namespace points to)." }
{ $see-also <name> tag } ;
HELP: <name>
{ $values { "space" "a string" } { "main" "a string" } { "url" "a string" }
{ "name" "an XML tag name" } }
{ $description "creates a name tuple with the name-space space and the tag-name tag and the tag-url url." }
{ $description "Creates a name tuple with the namespace prefix space, the the given main part of the name, and the namespace URL given by url." }
{ $see-also name <tag> } ;
HELP: contained-tag
{ $class-description "delegates to tag representing a tag like <a/> with no contents. The tag attributes are accessed with tag-attrs" }
{ $class-description "This is a subclass of " { $link tag } " consisting of tags with no body, like " { $snippet "<a/>" } "." }
{ $see-also tag <contained-tag> } ;
HELP: <contained-tag>
{ $values { "name" "an XML tag name" }
{ "attrs" "an alist from names to strings" }
{ "tag" tag } }
{ $description "creates an empty tag (like <a/>) with the specified name and tag attributes. This delegates to tag" }
{ $description "Creates an empty tag (like " { $snippet "<a/>" } ") with the specified name and tag attributes." }
{ $see-also contained-tag <tag> } ;
HELP: xml
{ $class-description "tuple representing an XML document, delegating to the main tag, containing the fields prolog (the header <?xml...?>), before (whatever comes between the prolog and the main tag) and after (whatever comes after the main tag)" }
{ $class-description "Tuple representing an XML document, delegating to the main tag, containing the fields prolog (the header " { $snippet "<?xml...?>" } "), before (whatever comes between the prolog and the main tag) and after (whatever comes after the main tag)." }
{ $see-also <xml> tag prolog } ;
HELP: <xml>
@ -159,35 +159,35 @@ HELP: <element-decl>
{ $description "Creates an element declaration object, of the class " { $link element-decl } } ;
HELP: attlist-decl
{ $class-description "Describes the class of element declarations, like <!ATTLIST pre xml:space (preserve) #FIXED 'preserve'>." } ;
{ $class-description "Describes the class of element declarations, like " { $snippet "<!ATTLIST pre xml:space (preserve) #FIXED 'preserve'>" } "." } ;
HELP: <attlist-decl>
{ $values { "name" name } { "att-defs" string } { "attlist-decl" attlist-decl } }
{ $description "Creates an element declaration object, of the class " { $link attlist-decl } } ;
HELP: entity-decl
{ $class-description "Describes the class of element declarations, like <!ENTITY foo 'bar'>." } ;
{ $class-description "Describes the class of element declarations, like " { $snippet "<!ENTITY foo 'bar'>" } "." } ;
HELP: <entity-decl>
{ $values { "name" name } { "def" string } { "pe?" "t or f" } { "entity-decl" entity-decl } }
{ $description "Creates an entity declaration object, of the class " { $link entity-decl } ". The pe? slot should be t if the object is a DTD-internal entity, like <!ENTITY % foo 'bar'> and f if the object is like <!ENTITY foo 'bar'>, that is, it can be used outside of the DTD." } ;
{ $description "Creates an entity declaration object, of the class " { $link entity-decl } ". The pe? slot should be t if the object is a DTD-internal entity, like " { $snippet "<!ENTITY % foo 'bar'>" } " and f if the object is like " { $snippet "<!ENTITY foo 'bar'>" } ", that is, it can be used outside of the DTD." } ;
HELP: system-id
{ $class-description "Describes the class of system identifiers within an XML DTD directive, such as <!DOCTYPE greeting " { $emphasis "SYSTEM 'hello.dtd'" } ">" } ;
{ $class-description "Describes the class of system identifiers within an XML DTD directive, such as " { $snippet "<!DOCTYPE greeting " { $emphasis "SYSTEM 'hello.dtd'" } ">" } } ;
HELP: <system-id>
{ $values { "system-literal" string } { "system-id" system-id } }
{ $description "Constructs a " { $link system-id } " tuple." } ;
HELP: public-id
{ $class-description "Describes the class of public identifiers within an XML DTD directive, such as <!DOCTYPE open-hatch " { $emphasis "PUBLIC '-//Textuality//TEXT Standard open-hatch boilerplate//EN' 'http://www.textuality.com/boilerplate/OpenHatch.xml'" } ">" } ;
{ $class-description "Describes the class of public identifiers within an XML DTD directive, such as " { $snippet "<!DOCTYPE open-hatch " { $emphasis "PUBLIC '-//Textuality//TEXT Standard open-hatch boilerplate//EN' 'http://www.textuality.com/boilerplate/OpenHatch.xml'" } ">" } } ;
HELP: <public-id>
{ $values { "pubid-literal" string } { "system-literal" string } { "public-id" public-id } }
{ $description "Constructs a " { $link system-id } " tuple." } ;
HELP: notation-decl
{ $class-description "Describes the class of element declarations, like <!NOTATION jpg SYSTEM './jpgviewer'>." } ;
{ $class-description "Describes the class of element declarations, like " { $snippet "<!NOTATION jpg SYSTEM './jpgviewer'>" } "." } ;
HELP: <notation-decl>
{ $values { "name" string } { "id" id } { "notation-decl" notation-decl } }

View File

@ -216,3 +216,6 @@ M: xml like
PREDICATE: contained-tag < tag children>> not ;
PREDICATE: open-tag < tag children>> ;
UNION: xml-data
tag comment string directive instruction ;

View File

@ -3,16 +3,15 @@
USING: kernel namespaces xml.tokenize xml.state xml.name
xml.data accessors arrays make xml.char-classes fry assocs sequences
math xml.errors sets combinators io.encodings io.encodings.iana
unicode.case xml.dtd strings xml.entities ;
unicode.case xml.dtd strings xml.entities unicode.categories ;
IN: xml.elements
: take-interpolated ( quot -- interpolated )
interpolating? get [
drop get-char CHAR: > =
[ next f ] [
pass-blank " \t\r\n-" take-to
pass-blank "->" expect
] if <interpolated>
[ next f ]
[ "->" take-string [ blank? ] trim ]
if <interpolated>
] [ call ] if ; inline
: interpolate-quote ( -- interpolated )

View File

@ -16,6 +16,7 @@ IN: xml.entities
{ CHAR: & "&amp;" }
{ CHAR: ' "&apos;" }
{ CHAR: " "&quot;" }
{ CHAR: < "&lt;" }
} ;
: escape-string-by ( str table -- escaped )

View File

@ -10,44 +10,68 @@ HELP: notags
{ $class-description "XML parsing error describing the case where an XML document contains no main tag, or any tags at all" } ;
HELP: extra-attrs
{ $class-description "XML parsing error describing the case where the XML prolog (<?xml ...?>) contains attributes other than the three allowed ones, standalone, version and encoding. Contains one slot, attrs, which is a hashtable of all the extra attributes' names. Delegates to " { $link parsing-error } "." } ;
{ $class-description "XML parsing error describing the case where the XML prolog (" { $snippet "<?xml ...?>" } ") contains attributes other than the three allowed ones, standalone, version and encoding. Contains one slot, attrs, which is a hashtable of all the extra attributes' names. Delegates to " { $link xml-error-at } "." } ;
HELP: nonexist-ns
{ $class-description "XML parsing error describing the case where a namespace doesn't exist but it is used in a tag. Contains one slot, name, which contains the name of the undeclared namespace, and delegates to " { $link parsing-error } "." } ;
{ $class-description "XML parsing error describing the case where a namespace doesn't exist but it is used in a tag. Contains one slot, name, which contains the name of the undeclared namespace, and delegates to " { $link xml-error-at } "." } ;
HELP: not-yes/no
{ $class-description "XML parsing error used to describe the case where standalone is set in the XML prolog to something other than 'yes' or 'no'. Delegates to " { $link parsing-error } " and contains one slot, text, which contains offending value." } ;
{ $class-description "XML parsing error used to describe the case where standalone is set in the XML prolog to something other than 'yes' or 'no'. Delegates to " { $link xml-error-at } " and contains one slot, text, which contains offending value." } ;
HELP: unclosed
{ $class-description "XML parsing error used to describe the case where the XML document contains classes which are not closed by the end of the document. Contains one slot, tags, a sequence of names." } ;
HELP: mismatched
{ $class-description "XML parsing error describing mismatched tags, eg <a></c>. Contains two slots: open is the name of the opening tag and close is the name of the closing tag. Delegates to " { $link parsing-error } " showing the location of the closing tag" } ;
{ $class-description "XML parsing error describing mismatched tags, eg " { $snippet "<a></c>" } ". Contains two slots: open is the name of the opening tag and close is the name of the closing tag. Delegates to " { $link xml-error-at } " showing the location of the closing tag" } ;
HELP: expected
{ $class-description "XML parsing error describing when an expected token was not present. Delegates to " { $link parsing-error } ". Contains two slots, should-be, which has the expected string, and was, which has the actual string." } ;
{ $class-description "XML parsing error describing when an expected token was not present. Delegates to " { $link xml-error-at } ". Contains two slots, should-be, which has the expected string, and was, which has the actual string." } ;
HELP: no-entity
{ $class-description "XML parsing error describing the use of an undefined entity in a case where standalone is marked yes. Delegates to " { $link parsing-error } ". Contains one slot, thing, containing a string representing the entity." } ;
{ $class-description "XML parsing error describing the use of an undefined entity in a case where standalone is marked yes. Delegates to " { $link xml-error-at } ". Contains one slot, thing, containing a string representing the entity." } ;
HELP: pre/post-content
{ $class-description "describes the error where a non-whitespace string is used before or after the main tag in an XML document. Contains two slots: string contains the offending string, and pre? is t if it occured before the main tag and f if it occured after" } ;
{ $class-description "Describes the error where a non-whitespace string is used before or after the main tag in an XML document. Contains two slots: string contains the offending string, and pre? is t if it occured before the main tag and f if it occured after" } ;
HELP: unclosed-quote
{ $class-description "describes the error where a quotation for an attribute value is opened but not closed before the end of the document." } ;
{ $class-description "Describes the error where a quotation for an attribute value is opened but not closed before the end of the document." } ;
HELP: bad-name
{ $class-description "describes the error where a name is used, for example in an XML tag or attribute key, which is invalid." } ;
{ $class-description "Describes the error where a name is used, for example in an XML tag or attribute key, which is invalid." } ;
HELP: quoteless-attr
{ $class-description "describes the error where an attribute of an XML tag is missing quotes around a value." } ;
{ $class-description "Describes the error where an attribute of an XML tag is missing quotes around a value." } ;
HELP: xml-parse-error
{ $class-description "the exception class that all parsing errors in XML documents are in." } ;
HELP: disallowed-char
{ $class-description "Describes the error where a disallowed character occurs in an XML document." } ;
HELP: missing-close
{ $class-description "Describes the error where a particular closing token is missing." } ;
HELP: unexpected-end
{ $class-description "Describes the error where a document unexpectedly ends, and the XML parser expected it to continue." } ;
HELP: duplicate-attr
{ $class-description "Describes the error where there is more than one attribute of the same key." } ;
HELP: bad-cdata
{ $class-description "Describes the error where CDATA is used outside of the main tag of an XML document." } ;
HELP: text-w/]]>
{ $class-description "Describes the error where a text node contains the literal string " { $snippet "]]>" } " which is disallowed." } ;
HELP: attr-w/<
{ $class-description "Describes the error where an attribute value contains the literal character " { $snippet "<" } " which is disallowed." } ;
HELP: misplaced-directive
{ $class-description "Describes the error where an internal DTD directive is used outside of a DOCTYPE or DTD file, or where a DOCTYPE occurs somewhere other than before the main tag of an XML document." } ;
HELP: xml-error
{ $class-description "The exception class that all parsing errors in XML documents are in." } ;
ARTICLE: "xml.errors" "XML parsing errors"
{ $vocab-link "xml.errors" } " provides a rich and highly inspectable set of parsing errors. All XML errors are described by the union class " { $link xml-parse-error } " but there are many classes contained in that:"
"The " { $vocab-link "xml.errors" } " vocabulary provides a rich and highly inspectable set of parsing errors. All XML errors are described by the union class " { $link xml-error } " but there are many classes contained in that:"
{ $subsection multitags }
{ $subsection notags }
{ $subsection extra-attrs }
@ -61,7 +85,15 @@ ARTICLE: "xml.errors" "XML parsing errors"
{ $subsection unclosed-quote }
{ $subsection bad-name }
{ $subsection quoteless-attr }
"Additionally, most of these errors are a kind of " { $link parsing-error } " which provides more information"
{ $subsection disallowed-char }
{ $subsection missing-close }
{ $subsection unexpected-end }
{ $subsection duplicate-attr }
{ $subsection bad-cdata }
{ $subsection text-w/]]> }
{ $subsection attr-w/< }
{ $subsection misplaced-directive }
"Additionally, most of these errors are a kind of " { $link xml-error-at } " which provides more information"
$nl
"Note that, in parsing an XML document, only the first error is reported." ;

View File

@ -27,12 +27,16 @@ T{ pre/post-content f "x" t } "x<y/>" xml-error-test
T{ versionless-prolog f 1 8 } "<?xml?><x/>" xml-error-test
T{ unclosed-quote f 1 13 } "<x value='/>" xml-error-test
T{ bad-name f 1 3 "-" } "<-/>" xml-error-test
T{ quoteless-attr f 1 12 } "<x value=<->/>" xml-error-test
T{ quoteless-attr f 1 10 } "<x value=3/>" xml-error-test
T{ attr-w/< f 1 11 } "<x value='<'/>" xml-error-test
T{ text-w/]]> f 1 6 } "<x>]]></x>" xml-error-test
T{ duplicate-attr f 1 21 T{ name { space "" } { main "this" } } V{ "a" "b" } } "<x this='a' this='b'/>" xml-error-test
T{ bad-cdata f 1 3 } "<![CDATA[]]><x/>" xml-error-test
T{ bad-cdata f 1 7 } "<x/><![CDATA[]]>" xml-error-test
T{ pre/post-content f "&" t } "&32;<x/>" xml-error-test
T{ pre/post-content f "&" t } "&#32;<x/>" xml-error-test
T{ bad-doctype f 1 17 "a" } "<!DOCTYPE foo [ a ]><x/>" xml-error-test
T{ bad-doctype f 1 22 T{ opener { name T{ name f "" "foo" "" } } { attrs T{ attrs } } } } "<!DOCTYPE foo [ <foo> ]><x/>" xml-error-test
T{ disallowed-char f 1 3 1 } "<x>\u000001</x>" xml-error-test
T{ missing-close f 1 9 } "<!-- foo" xml-error-test
T{ misplaced-directive f 1 9 "ENTITY" } "<!ENTITY foo 'bar'><x/>" xml-error-test

View File

@ -5,22 +5,22 @@ debugger sequences xml.state accessors summary
namespaces io.streams.string ;
IN: xml.errors
TUPLE: parsing-error line column ;
TUPLE: xml-error-at line column ;
: parsing-error ( class -- obj )
: xml-error-at ( class -- obj )
new
get-line >>line
get-column >>column ;
M: parsing-error summary ( obj -- str )
M: xml-error-at summary ( obj -- str )
[
"Parsing error" print
"XML parsing error" print
"Line: " write dup line>> .
"Column: " write column>> .
] with-string-writer ;
TUPLE: expected < parsing-error should-be was ;
TUPLE: expected < xml-error-at should-be was ;
: expected ( should-be was -- * )
\ expected parsing-error
\ expected xml-error-at
swap >>was
swap >>should-be throw ;
M: expected summary ( obj -- str )
@ -30,26 +30,26 @@ M: expected summary ( obj -- str )
"Token present: " write was>> print
] with-string-writer ;
TUPLE: unexpected-end < parsing-error ;
: unexpected-end ( -- * ) \ unexpected-end parsing-error throw ;
TUPLE: unexpected-end < xml-error-at ;
: unexpected-end ( -- * ) \ unexpected-end xml-error-at throw ;
M: unexpected-end summary ( obj -- str )
[
call-next-method write
"File unexpectedly ended." print
] with-string-writer ;
TUPLE: missing-close < parsing-error ;
: missing-close ( -- * ) \ missing-close parsing-error throw ;
TUPLE: missing-close < xml-error-at ;
: missing-close ( -- * ) \ missing-close xml-error-at throw ;
M: missing-close summary ( obj -- str )
[
call-next-method write
"Missing closing token." print
] with-string-writer ;
TUPLE: disallowed-char < parsing-error char ;
TUPLE: disallowed-char < xml-error-at char ;
: disallowed-char ( char -- * )
\ disallowed-char parsing-error swap >>char throw ;
\ disallowed-char xml-error-at swap >>char throw ;
M: disallowed-char summary
[ call-next-method ]
@ -72,10 +72,10 @@ M: pre/post-content summary ( obj -- str )
" the main tag." print
] with-string-writer ;
TUPLE: no-entity < parsing-error thing ;
TUPLE: no-entity < xml-error-at thing ;
: no-entity ( string -- * )
\ no-entity parsing-error swap >>thing throw ;
\ no-entity xml-error-at swap >>thing throw ;
M: no-entity summary ( obj -- str )
[
@ -83,10 +83,10 @@ M: no-entity summary ( obj -- str )
"Entity does not exist: &" write thing>> write ";" print
] with-string-writer ;
TUPLE: mismatched < parsing-error open close ;
TUPLE: mismatched < xml-error-at open close ;
: mismatched ( open close -- * )
\ mismatched parsing-error swap >>close swap >>open throw ;
\ mismatched xml-error-at swap >>close swap >>open throw ;
M: mismatched summary ( obj -- str )
[
@ -96,10 +96,10 @@ M: mismatched summary ( obj -- str )
"Closing tag: </" write close>> print-name ">" print
] with-string-writer ;
TUPLE: unclosed < parsing-error tags ;
TUPLE: unclosed < xml-error-at tags ;
: unclosed ( -- * )
\ unclosed parsing-error
\ unclosed xml-error-at
xml-stack get rest-slice [ first name>> ] map >>tags
throw ;
@ -111,10 +111,10 @@ M: unclosed summary ( obj -- str )
tags>> [ " <" write print-name ">" print ] each
] with-string-writer ;
TUPLE: bad-uri < parsing-error string ;
TUPLE: bad-uri < xml-error-at string ;
: bad-uri ( string -- * )
\ bad-uri parsing-error swap >>string throw ;
\ bad-uri xml-error-at swap >>string throw ;
M: bad-uri summary ( obj -- str )
[
@ -122,10 +122,10 @@ M: bad-uri summary ( obj -- str )
"Bad URI:" print string>> .
] with-string-writer ;
TUPLE: nonexist-ns < parsing-error name ;
TUPLE: nonexist-ns < xml-error-at name ;
: nonexist-ns ( name-string -- * )
\ nonexist-ns parsing-error swap >>name throw ;
\ nonexist-ns xml-error-at swap >>name throw ;
M: nonexist-ns summary ( obj -- str )
[
@ -133,10 +133,10 @@ M: nonexist-ns summary ( obj -- str )
"Namespace " write name>> write " has not been declared" print
] with-string-writer ;
TUPLE: unopened < parsing-error ; ! this should give which tag was unopened
TUPLE: unopened < xml-error-at ; ! this should give which tag was unopened
: unopened ( -- * )
\ unopened parsing-error throw ;
\ unopened xml-error-at throw ;
M: unopened summary ( obj -- str )
[
@ -144,10 +144,10 @@ M: unopened summary ( obj -- str )
"Closed an unopened tag" print
] with-string-writer ;
TUPLE: not-yes/no < parsing-error text ;
TUPLE: not-yes/no < xml-error-at text ;
: not-yes/no ( text -- * )
\ not-yes/no parsing-error swap >>text throw ;
\ not-yes/no xml-error-at swap >>text throw ;
M: not-yes/no summary ( obj -- str )
[
@ -157,10 +157,10 @@ M: not-yes/no summary ( obj -- str )
] with-string-writer ;
! this should actually print the names
TUPLE: extra-attrs < parsing-error attrs ;
TUPLE: extra-attrs < xml-error-at attrs ;
: extra-attrs ( attrs -- * )
\ extra-attrs parsing-error swap >>attrs throw ;
\ extra-attrs xml-error-at swap >>attrs throw ;
M: extra-attrs summary ( obj -- str )
[
@ -169,10 +169,10 @@ M: extra-attrs summary ( obj -- str )
attrs>> .
] with-string-writer ;
TUPLE: bad-version < parsing-error num ;
TUPLE: bad-version < xml-error-at num ;
: bad-version ( num -- * )
\ bad-version parsing-error swap >>num throw ;
\ bad-version xml-error-at swap >>num throw ;
M: bad-version summary ( obj -- str )
[
@ -185,10 +185,10 @@ ERROR: notags ;
M: notags summary ( obj -- str )
drop "XML document lacks a main tag" ;
TUPLE: bad-prolog < parsing-error prolog ;
TUPLE: bad-prolog < xml-error-at prolog ;
: bad-prolog ( prolog -- * )
\ bad-prolog parsing-error swap >>prolog throw ;
\ bad-prolog xml-error-at swap >>prolog throw ;
M: bad-prolog summary ( obj -- str )
[
@ -197,10 +197,10 @@ M: bad-prolog summary ( obj -- str )
prolog>> write-prolog nl
] with-string-writer ;
TUPLE: capitalized-prolog < parsing-error name ;
TUPLE: capitalized-prolog < xml-error-at name ;
: capitalized-prolog ( name -- capitalized-prolog )
\ capitalized-prolog parsing-error swap >>name throw ;
\ capitalized-prolog xml-error-at swap >>name throw ;
M: capitalized-prolog summary ( obj -- str )
[
@ -210,10 +210,10 @@ M: capitalized-prolog summary ( obj -- str )
" instead of <?xml...?>" print
] with-string-writer ;
TUPLE: versionless-prolog < parsing-error ;
TUPLE: versionless-prolog < xml-error-at ;
: versionless-prolog ( -- * )
\ versionless-prolog parsing-error throw ;
\ versionless-prolog xml-error-at throw ;
M: versionless-prolog summary ( obj -- str )
[
@ -221,10 +221,10 @@ M: versionless-prolog summary ( obj -- str )
"XML prolog lacks a version declaration" print
] with-string-writer ;
TUPLE: bad-directive < parsing-error dir ;
TUPLE: bad-directive < xml-error-at dir ;
: bad-directive ( directive -- * )
\ bad-directive parsing-error swap >>dir throw ;
\ bad-directive xml-error-at swap >>dir throw ;
M: bad-directive summary ( obj -- str )
[
@ -233,26 +233,26 @@ M: bad-directive summary ( obj -- str )
dir>> write
] with-string-writer ;
TUPLE: bad-decl < parsing-error ;
TUPLE: bad-decl < xml-error-at ;
: bad-decl ( -- * )
\ bad-decl parsing-error throw ;
\ bad-decl xml-error-at throw ;
M: bad-decl summary ( obj -- str )
call-next-method "\nExtra content in directive" append ;
TUPLE: bad-external-id < parsing-error ;
TUPLE: bad-external-id < xml-error-at ;
: bad-external-id ( -- * )
\ bad-external-id parsing-error throw ;
\ bad-external-id xml-error-at throw ;
M: bad-external-id summary ( obj -- str )
call-next-method "\nBad external ID" append ;
TUPLE: misplaced-directive < parsing-error dir ;
TUPLE: misplaced-directive < xml-error-at dir ;
: misplaced-directive ( directive -- * )
\ misplaced-directive parsing-error swap >>dir throw ;
\ misplaced-directive xml-error-at swap >>dir throw ;
M: misplaced-directive summary ( obj -- str )
[
@ -261,86 +261,82 @@ M: misplaced-directive summary ( obj -- str )
dir>> write-xml-chunk nl
] with-string-writer ;
TUPLE: bad-name < parsing-error name ;
TUPLE: bad-name < xml-error-at name ;
: bad-name ( name -- * )
\ bad-name parsing-error swap >>name throw ;
\ bad-name xml-error-at swap >>name throw ;
M: bad-name summary ( obj -- str )
[ call-next-method ]
[ "Invalid name: " swap name>> "\n" 3append ]
bi append ;
TUPLE: unclosed-quote < parsing-error ;
TUPLE: unclosed-quote < xml-error-at ;
: unclosed-quote ( -- * )
\ unclosed-quote parsing-error throw ;
\ unclosed-quote xml-error-at throw ;
M: unclosed-quote summary
call-next-method
"XML document ends with quote still open\n" append ;
TUPLE: quoteless-attr < parsing-error ;
TUPLE: quoteless-attr < xml-error-at ;
: quoteless-attr ( -- * )
\ quoteless-attr parsing-error throw ;
\ quoteless-attr xml-error-at throw ;
M: quoteless-attr summary
call-next-method "Attribute lacks quotes around value\n" append ;
TUPLE: attr-w/< < parsing-error ;
TUPLE: attr-w/< < xml-error-at ;
: attr-w/< ( value -- * )
\ attr-w/< parsing-error throw ;
\ attr-w/< xml-error-at throw ;
M: attr-w/< summary
call-next-method
"Attribute value contains literal <" append ;
TUPLE: text-w/]]> < parsing-error ;
TUPLE: text-w/]]> < xml-error-at ;
: text-w/]]> ( text -- * )
\ text-w/]]> parsing-error throw ;
\ text-w/]]> xml-error-at throw ;
M: text-w/]]> summary
call-next-method
"Text node contains ']]>'" append ;
TUPLE: duplicate-attr < parsing-error key values ;
TUPLE: duplicate-attr < xml-error-at key values ;
: duplicate-attr ( key values -- * )
\ duplicate-attr parsing-error
\ duplicate-attr xml-error-at
swap >>values swap >>key throw ;
M: duplicate-attr summary
call-next-method "\nDuplicate attribute" append ;
TUPLE: bad-cdata < parsing-error ;
TUPLE: bad-cdata < xml-error-at ;
: bad-cdata ( -- * )
\ bad-cdata parsing-error throw ;
\ bad-cdata xml-error-at throw ;
M: bad-cdata summary
call-next-method "\nCDATA occurs before or after main tag" append ;
TUPLE: not-enough-characters < parsing-error ;
TUPLE: not-enough-characters < xml-error-at ;
: not-enough-characters ( -- * )
\ not-enough-characters parsing-error throw ;
\ not-enough-characters xml-error-at throw ;
M: not-enough-characters summary ( obj -- str )
[
call-next-method write
"Not enough characters" print
] with-string-writer ;
TUPLE: bad-doctype < parsing-error contents ;
TUPLE: bad-doctype < xml-error-at contents ;
: bad-doctype ( contents -- * )
\ bad-doctype parsing-error swap >>contents throw ;
\ bad-doctype xml-error-at swap >>contents throw ;
M: bad-doctype summary
call-next-method "\nDTD contains invalid object" append ;
UNION: xml-parse-error
multitags notags extra-attrs nonexist-ns bad-decl
not-yes/no unclosed mismatched expected no-entity
bad-prolog versionless-prolog capitalized-prolog
bad-directive bad-name unclosed-quote quoteless-attr
attr-w/< text-w/]]> duplicate-attr ;
UNION: xml-error
multitags notags pre/post-content xml-error-at ;

View File

@ -0,0 +1,58 @@
USING: help.markup help.syntax present multiline ;
IN: xml.interpolate
ABOUT: "xml.interpolate"
ARTICLE: "xml.interpolate" "XML literal interpolation"
"The " { $vocab-link "xml.interpolate" } " vocabulary provides a convenient syntax for generating XML documents and chunks. It defines the following parsing words:"
{ $subsection POSTPONE: <XML }
{ $subsection POSTPONE: [XML }
"For a description of the common syntax of these two, see"
{ $subsection { "xml.interpolate" "in-depth" } } ;
HELP: <XML
{ $syntax "<XML <?xml version=\"1.0\"?><document>...</document> XML>" }
{ $description "This syntax allows the interpolation of XML documents. When evaluated, there is an XML document on the stack. For more information about XML interpolation, see " { $link { "xml.interpolate" "in-depth" } } "." } ;
HELP: [XML
{ $syntax "[XML foo <x>...</x> bar <y>...</y> baz XML]" }
{ $description "This syntax allows the interpolation of XML chunks. When evaluated, there is a sequence of XML elements (tags, strings, comments, etc) on the stack. For more information about XML interpolation, see " { $link { "xml.interpolate" "in-depth" } } "." } ;
ARTICLE: { "xml.interpolate" "in-depth" } "XML interpolation syntax"
"XML interpolation has two forms for each of the words " { $link POSTPONE: <XML } " and " { $link POSTPONE: [XML } ": a fry-like form and a locals form. To splice locals in, use the syntax " { $snippet "<-variable->" } ". To splice something in from the stack, in the style of " { $vocab-link "fry" } ", use the syntax " { $snippet "<->" } ". An XML interpolation form may only use one of these styles."
$nl
"These forms can be used where a tag might go, as in " { $snippet "[XML <foo><-></foo> XML]" } " or where an attribute might go, as in " { $snippet "[XML <foo bar=<->/> XML]" } ". When an attribute is spliced in, it is not included if the value is " { $snippet "f" } " and if the value is not a string, the value is put through " { $link present } ". Here is an example of the fry style of XML interpolation:"
{ $example
{" "one two three" " " split
[ [XML <item><-></item> XML] ] map
<XML <doc><-></doc> XML> pprint-xml>string "}
{" <' <?xml version="1.0" encoding="UTF-8"?>
<doc>
<item>
one
</item>
<item>
two
</item>
<item>
three
</item>
</doc>'> "} }
"Here is an example of the locals version:"
{ $example
{" [let |
number [ 3 ]
false [ f ]
url [ URL" http://factorcode.org/" ]
string [ "hello" ]
word [ \ drop ] |
<XML
<x
number=<-number->
false=<-false->
url=<-url->
string=<-string->
word=<-word-> />
XML> pprint-xml>string ] "}
{" <' <?xml version="1.0" encoding="UTF-8"?>
<x number="3" url="http://factorcode.org/" string="hello" word="drop"/>'> "} } ;

View File

@ -2,12 +2,12 @@
! See http://factorcode.org/license.txt for BSD license.
USING: tools.test xml.interpolate multiline kernel assocs
sequences accessors xml.writer xml.interpolate.private
locals splitting ;
locals splitting urls ;
IN: xml.interpolate.tests
[ "a" "c" { "a" "c" f } ] [
"<?xml version='1.0'?><x><-a-><b val=<-c->/><-></x>"
interpolated-doc
string>doc
[ second var>> ]
[ fourth "val" swap at var>> ]
[ extract-variables ] tri
@ -44,3 +44,9 @@ IN: xml.interpolate.tests
[ [XML <item><-></item> XML] ] map
<XML <doc><-></doc> XML> pprint-xml>string
] unit-test
[ {" <?xml version="1.0" encoding="UTF-8"?>
<x number="3" url="http://factorcode.org/" string="hello" word="drop"/>"} ]
[ 3 f URL" http://factorcode.org/" "hello" \ drop
<XML <x number=<-> false=<-> url=<-> string=<-> word=<->/> XML>
pprint-xml>string ] unit-test

View File

@ -3,21 +3,24 @@
USING: xml xml.state kernel sequences fry assocs xml.data
accessors strings make multiline parser namespaces macros
sequences.deep generalizations locals words combinators
math ;
math present arrays ;
IN: xml.interpolate
<PRIVATE
: interpolated-chunk ( string -- chunk )
: string>chunk ( string -- chunk )
t interpolating? [ string>xml-chunk ] with-variable ;
: interpolated-doc ( string -- xml )
: string>doc ( string -- xml )
t interpolating? [ string>xml ] with-variable ;
DEFER: interpolate-sequence
: interpolate-attrs ( table attrs -- attrs )
swap '[ dup interpolated? [ var>> _ at ] when ] assoc-map ;
swap '[
dup interpolated?
[ var>> _ at dup [ present ] when ] when
] assoc-map [ nip ] assoc-filter ;
: interpolate-tag ( table tag -- tag )
[ nip name>> ]
@ -27,8 +30,10 @@ DEFER: interpolate-sequence
GENERIC: push-item ( item -- )
M: string push-item , ;
M: object push-item , ;
M: sequence push-item % ;
M: xml-data push-item , ;
M: object push-item present , ;
M: sequence push-item
[ dup array? [ % ] [ , ] if ] each ;
GENERIC: interpolate-item ( table item -- )
M: object interpolate-item nip , ;
@ -48,6 +53,8 @@ M: tag (each-interpolated)
swap attrs>> values
[ interpolated? ] filter
swap each ;
M: xml (each-interpolated)
[ body>> ] dip (each-interpolated) ;
M: object (each-interpolated) 2drop ;
: each-interpolated ( xml quot -- )
@ -59,10 +66,10 @@ M: object (each-interpolated) 2drop ;
] each-interpolated doc ;
MACRO: interpolate-xml ( string -- doc )
interpolated-doc number<-> '[ _ interpolate-xml-doc ] ;
string>doc number<-> '[ _ interpolate-xml-doc ] ;
MACRO: interpolate-chunk ( string -- chunk )
interpolated-chunk number<-> '[ _ interpolate-sequence ] ;
string>chunk number<-> '[ _ interpolate-sequence ] ;
: >search-hash ( seq -- hash )
[ dup search ] H{ } map>assoc ;
@ -70,19 +77,22 @@ MACRO: interpolate-chunk ( string -- chunk )
: extract-variables ( xml -- seq )
[ [ var>> , ] each-interpolated ] { } make ;
: nenum ( ... n -- assoc )
narray <enum> ; inline
: collect ( accum seq -- accum )
{
{ [ dup [ ] all? ] [ >search-hash parsed ] } ! locals
{ [ dup [ not ] all? ] [ ! fry
length parsed \ narray parsed \ <enum> parsed
length parsed \ nenum parsed
] }
[ drop "XML interpolation contains both fry and locals" throw ] ! mixed
} cond ;
: parse-def ( accum delimiter word -- accum )
[
parse-multiline-string
[ interpolated-chunk extract-variables collect ] keep
parse-multiline-string but-last
[ string>chunk extract-variables collect ] keep
parsed
] dip parsed ;

View File

@ -22,7 +22,7 @@ SYMBOL: xml-file
xml-file get T{ name f "" "this" "http://d.de" } swap at
] unit-test
[ t ] [ xml-file get children>> second contained-tag? ] unit-test
[ "<a></b>" string>xml ] [ xml-parse-error? ] must-fail-with
[ "<a></b>" string>xml ] [ xml-error? ] must-fail-with
[ T{ comment f "This is where the fun begins!" } ] [
xml-file get before>> [ comment? ] find nip
] unit-test

View File

@ -155,6 +155,9 @@ M: directive write-xml-chunk
M: instruction write-xml-chunk
"<?" write text>> write "?>" write ;
M: number write-xml-chunk
"Numbers are not allowed in XML" throw ;
M: sequence write-xml-chunk
[ write-xml-chunk ] each ;

View File

@ -1,48 +1,45 @@
USING: xmode.tokens xmode.marker xmode.catalog kernel
USING: xmode.tokens xmode.marker xmode.catalog kernel locals
html.elements io io.files sequences words io.encodings.utf8
namespaces xml.entities accessors ;
namespaces xml.entities accessors xml.interpolate locals xml.writer ;
IN: xmode.code2html
: htmlize-tokens ( tokens -- )
: htmlize-tokens ( tokens -- xml )
[
[ str>> ] [ id>> ] bi [
<span name>> =class span> escape-string write </span>
] [
escape-string write
] if*
] each ;
name>> swap
[XML <span class=<->><-></span> XML]
] [ ] if*
] map ;
: htmlize-line ( line-context line rules -- line-context' )
: htmlize-line ( line-context line rules -- line-context' xml )
tokenize-line htmlize-tokens ;
: htmlize-lines ( lines mode -- )
f swap load-mode [ htmlize-line nl ] curry reduce drop ;
: htmlize-lines ( lines mode -- xml )
f -rot load-mode [ htmlize-line ] curry map nip ;
: default-stylesheet ( -- )
<style>
"resource:basis/xmode/code2html/stylesheet.css"
utf8 file-contents escape-string write
</style> ;
: default-stylesheet ( -- xml )
"resource:basis/xmode/code2html/stylesheet.css"
utf8 file-contents
[XML <style><-></style> XML] ;
: htmlize-stream ( path stream -- )
lines swap
<html>
:: htmlize-stream ( path stream -- xml )
stream lines
[ "" ] [ first find-mode path swap htmlize-lines ]
if-empty :> input
default-stylesheet :> stylesheet
<XML <html>
<head>
default-stylesheet
<title> dup escape-string write </title>
<-stylesheet->
<title><-path-></title>
</head>
<body>
<pre>
over empty?
[ 2drop ]
[ over first find-mode htmlize-lines ] if
</pre>
<pre><-input-></pre>
</body>
</html> ;
</html> XML> ;
: htmlize-file ( path -- )
dup utf8 [
dup ".html" append utf8 [
input-stream get htmlize-stream
input-stream get htmlize-stream write-xml
] with-file-writer
] with-file-reader ;

View File

@ -21,7 +21,7 @@ ARTICLE: "enums" "Enumerations"
{ $subsection enum }
{ $subsection <enum> }
"Inverting a permutation using enumerations:"
{ $example "USING: assocs sorting prettyprint ;" ": invert <enum> >alist sort-values keys ;" "{ 2 0 4 1 3 } invert ." "{ 1 3 0 4 2 }" } ;
{ $example "USING: assocs sorting prettyprint ;" "IN: scratchpad" ": invert ( perm -- perm' )" " <enum> >alist sort-values keys ;" "{ 2 0 4 1 3 } invert ." "{ 1 3 0 4 2 }" } ;
HELP: enum
{ $class-description "An associative structure which wraps a sequence and maps integers to the corresponding elements of the sequence."
@ -405,11 +405,12 @@ HELP: search-alist
{ $values
{ "key" object } { "alist" "an array of key/value pairs" }
{ "pair/f" "a key/value pair" } { "i/f" integer } }
{ $description "Performs an in-order traversal of a " { $snippet "alist" } " and stops when the key is matched or the end of the " { $snippet "alist" } " has been reached. If there is no match, both outputs are " { $link f } "." }
{ $examples { $example "USING: prettyprint assocs kernel ;"
{ $description "Iterates over " { $snippet "alist" } " and stops when the key is matched or the end of the " { $snippet "alist" } " has been reached. If there is no match, both outputs are " { $link f } "." }
{ $notes "This word is used to implement " { $link at* } " and " { $link set-at } " on sequences, and should not be called direclty." }
{ $examples { $example "USING: prettyprint assocs.private kernel ;"
"3 { { 1 2 } { 3 4 } } search-alist [ . ] bi@"
"{ 3 4 }\n1"
} { $example "USING: prettyprint assocs kernel ;"
} { $example "USING: prettyprint assocs.private kernel ;"
"6 { { 1 2 } { 3 4 } } search-alist [ . ] bi@"
"f\nf"
}

View File

@ -38,6 +38,9 @@ M: assoc assoc-like drop ;
: substituter ( assoc -- quot )
[ dupd at* [ nip ] [ drop ] if ] curry ; inline
: with-assoc ( assoc quot: ( value key -- assoc ) -- quot: ( key value -- ) )
curry [ swap ] prepose ; inline
PRIVATE>
: assoc-find ( assoc quot -- key value ? )
@ -81,7 +84,7 @@ PRIVATE>
M: assoc assoc-clone-like ( assoc exemplar -- newassoc )
[ dup assoc-size ] dip new-assoc
[ [ swapd set-at ] curry assoc-each ] keep ;
[ [ set-at ] with-assoc assoc-each ] keep ;
: keys ( assoc -- keys )
[ drop ] { } assoc>map ;
@ -93,7 +96,7 @@ M: assoc assoc-clone-like ( assoc exemplar -- newassoc )
[ at* ] 2keep delete-at ;
: rename-at ( newkey key assoc -- )
[ delete-at* ] keep [ swapd set-at ] curry [ 2drop ] if ;
[ delete-at* ] keep [ set-at ] with-assoc [ 2drop ] if ;
: assoc-empty? ( assoc -- ? )
assoc-size 0 = ;
@ -102,7 +105,7 @@ M: assoc assoc-clone-like ( assoc exemplar -- newassoc )
[ length 1- ] keep (assoc-stack) ; flushable
: assoc-subset? ( assoc1 assoc2 -- ? )
[ swapd at* [ = ] [ 2drop f ] if ] curry assoc-all? ;
[ at* [ = ] [ 2drop f ] if ] with-assoc assoc-all? ;
: assoc= ( assoc1 assoc2 -- ? )
[ assoc-subset? ] [ swap assoc-subset? ] 2bi and ;
@ -114,7 +117,7 @@ M: assoc assoc-clone-like ( assoc exemplar -- newassoc )
swap [ nip key? ] curry assoc-filter ;
: update ( assoc1 assoc2 -- )
swap [ swapd set-at ] curry assoc-each ;
swap [ set-at ] with-assoc assoc-each ;
: assoc-union ( assoc1 assoc2 -- union )
[ [ [ assoc-size ] bi@ + ] [ drop ] 2bi new-assoc ] 2keep

View File

@ -10,18 +10,6 @@ ARTICLE: "singletons" "Singleton classes"
{ $subsection singleton-class? }
{ $subsection singleton-class } ;
HELP: SINGLETON:
{ $syntax "SINGLETON: class" }
{ $values
{ "class" "a new singleton to define" }
}
{ $description
"Defines a new singleton class. The class word itself is the sole instance of the singleton class."
}
{ $examples
{ $example "USING: classes.singleton kernel io ;" "IN: scratchpad" "SINGLETON: foo\nGENERIC: bar ( obj -- )\nM: foo bar drop \"a foo!\" print ;\nfoo bar" "a foo!" }
} ;
HELP: define-singleton-class
{ $values { "word" "a new word" } }
{ $description

View File

@ -14,15 +14,11 @@ HOOK: init-io io-backend ( -- )
HOOK: (init-stdio) io-backend ( -- stdin stdout stderr )
HOOK: console-encoding os ( -- encoding )
M: object console-encoding utf8 ;
: init-stdio ( -- )
(init-stdio)
[ console-encoding <decoder> input-stream set-global ]
[ console-encoding <encoder> output-stream set-global ]
[ console-encoding <encoder> error-stream set-global ] tri* ;
[ utf8 <decoder> input-stream set-global ]
[ utf8 <encoder> output-stream set-global ]
[ utf8 <encoder> error-stream set-global ] tri* ;
HOOK: io-multiplex io-backend ( us -- )

View File

@ -1 +0,0 @@
Daniel Ehrenberg

View File

@ -1,11 +0,0 @@
USING: help.syntax help.markup ;
IN: io.encodings.binary
HELP: binary
{ $class-description "Encoding descriptor for binary I/O." } ;
ARTICLE: "io.encodings.binary" "Binary encoding"
"Making an encoded stream with the binary encoding is a no-op; streams with this encoding deal with byte-arrays, not strings."
{ $subsection binary } ;
ABOUT: "io.encodings.binary"

View File

@ -1,8 +0,0 @@
! Copyright (C) 2008 Daniel Ehrenberg.
! See http://factorcode.org/license.txt for BSD license.
USING: io.encodings kernel ;
IN: io.encodings.binary
SINGLETON: binary
M: binary <encoder> drop ;
M: binary <decoder> drop ;

View File

@ -1 +0,0 @@
Dummy encoding for binary I/O

View File

@ -1 +0,0 @@
text

View File

@ -888,9 +888,9 @@ $nl
"Here is an array containing the " { $link f } " class:"
{ $example "{ POSTPONE: f } ." "{ POSTPONE: f }" }
"The " { $link f } " object is an instance of the " { $link f } " class:"
{ $example "f class ." "POSTPONE: f" }
{ $example "USE: classes" "f class ." "POSTPONE: f" }
"The " { $link f } " class is an instance of " { $link word } ":"
{ $example "\\ f class ." "word" }
{ $example "USE: classes" "\\ f class ." "word" }
"On the other hand, " { $link t } " is just a word, and there is no class which it is a unique instance of."
{ $example "t \\ t eq? ." "t" }
"Many words which search collections confuse the case of no element being present with an element being found equal to " { $link f } ". If this distinction is imporant, there is usually an alternative word which can be used; for example, compare " { $link at } " with " { $link at* } "." ;

View File

@ -1,6 +1,7 @@
! Copyright (C) 2004, 2008 Slava Pestov.
! See http://factorcode.org/license.txt for BSD license.
USING: kernel.private slots.private classes.tuple.private ;
USING: kernel.private slots.private math.private
classes.tuple.private ;
IN: kernel
DEFER: dip
@ -154,7 +155,6 @@ TUPLE: identity-tuple ;
M: identity-tuple equal? 2drop f ;
USE: math.private
: = ( obj1 obj2 -- ? )
2dup eq? [ 2drop t ] [
2dup both-fixnums? [ 2drop f ] [ equal? ] if

View File

@ -4,10 +4,10 @@ IN: math.integers
ARTICLE: "integers" "Integers"
{ $subsection integer }
"Integers come in two varieties -- fixnums and bignums. Fixnums fit in a machine word and are faster to manipulate; if the result of a fixnum operation is too large to fit in a fixnum, the result is upgraded to a bignum. Here is an example where two fixnums are multiplied yielding a bignum:"
{ $example "134217728 class ." "fixnum" }
{ $example "128 class ." "fixnum" }
{ $example "USE: classes" "134217728 class ." "fixnum" }
{ $example "USE: classes" "128 class ." "fixnum" }
{ $example "134217728 128 * ." "17179869184" }
{ $example "134217728 128 * class ." "bignum" }
{ $example "USE: classes" "1 128 shift class ." "bignum" }
"Integers can be entered using a different base; see " { $link "syntax-numbers" } "."
$nl
"Integers can be tested for, and real numbers can be converted to integers:"

View File

@ -321,8 +321,8 @@ ARTICLE: "number-protocol" "Number protocol"
"Math operations obey certain numerical upgrade rules. If one of the inputs is a bignum and the other is a fixnum, the latter is first coerced to a bignum; if one of the inputs is a float, the other is coerced to a float."
$nl
"Two examples where you should note the types of the inputs and outputs:"
{ $example "3 >fixnum 6 >bignum * class ." "bignum" }
{ $example "1/2 2.0 + ." "4.5" }
{ $example "USE: classes" "3 >fixnum 6 >bignum * class ." "bignum" }
{ $example "1/2 2.0 + ." "2.5" }
"The following usual operations are supported by all numbers."
{ $subsection + }
{ $subsection - }

View File

@ -57,7 +57,7 @@ SYMBOL: auto-use?
dup vocabulary>>
[ (use+) ]
[ amended-use get dup [ push ] [ 2drop ] if ]
[ "Added “" "” vocabulary to search path" surround note. ]
[ "Added \"" "\" vocabulary to search path" surround note. ]
tri
] [ create-in ] if ;
@ -160,6 +160,7 @@ SYMBOL: interactive-vocabs
"definitions"
"editors"
"help"
"help.lint"
"inspector"
"io"
"io.files"
@ -203,7 +204,7 @@ SYMBOL: interactive-vocabs
SYMBOL: print-use-hook
print-use-hook global [ [ ] or ] change-at
!
: parse-fresh ( lines -- quot )
[
V{ } clone amended-use set

View File

@ -352,6 +352,18 @@ HELP: SYMBOLS:
{ $description "Creates a new symbol for every token until the " { $snippet ";" } "." }
{ $examples { $example "USING: prettyprint ;" "IN: scratchpad" "SYMBOLS: foo bar baz ;\nfoo . bar . baz ." "foo\nbar\nbaz" } } ;
HELP: SINGLETON:
{ $syntax "SINGLETON: class" }
{ $values
{ "class" "a new singleton to define" }
}
{ $description
"Defines a new singleton class. The class word itself is the sole instance of the singleton class."
}
{ $examples
{ $example "USING: classes.singleton kernel io ;" "IN: singleton-demo" "USE: prettyprint SINGLETON: foo\nGENERIC: bar ( obj -- )\nM: foo bar drop \"a foo!\" print ;\nfoo bar" "a foo!" }
} ;
HELP: SINGLETONS:
{ $syntax "SINGLETONS: words... ;" }
{ $values { "words" "a sequence of new words to define" } }

View File

@ -11,7 +11,7 @@ name words
main help
source-loaded? docs-loaded? ;
! sources-loaded? slot is one of these two
! sources-loaded? slot is one of these three
SYMBOL: +parsing+
SYMBOL: +running+
SYMBOL: +done+

View File

@ -1,18 +1,21 @@
! Copyright (C) 2009 Jose Antonio Ortega Ruiz.
! See http://factorcode.org/license.txt for BSD license.
USING: accessors io io.encodings.utf8 io.servers.connection kernel
listener math ;
USING: accessors debugger io io.encodings.utf8 io.servers.connection
kernel listener math namespaces ;
IN: fuel.remote
<PRIVATE
: start-listener ( -- )
[ [ print-error-and-restarts ] error-hook set listener ] with-scope ;
: server ( port -- server )
<threaded-server>
"tty-server" >>name
utf8 >>encoding
swap local-server >>insecure
[ listener ] >>handler
[ start-listener ] >>handler
f >>timeout ;
: print-banner ( -- )