From 9b3964c5d68b9201847c74bd13dac468595e6863 Mon Sep 17 00:00:00 2001
From: Slava Pestov
Date: Sat, 14 Jun 2008 00:30:51 -0500
Subject: [PATCH 01/71] Add disable images option
---
extra/farkup/farkup.factor | 21 +++++++++++++--------
1 file changed, 13 insertions(+), 8 deletions(-)
diff --git a/extra/farkup/farkup.factor b/extra/farkup/farkup.factor
index d5110de02d..321648136a 100755
--- a/extra/farkup/farkup.factor
+++ b/extra/farkup/farkup.factor
@@ -7,6 +7,7 @@ sequences.deep unicode.categories ;
IN: farkup
SYMBOL: relative-link-prefix
+SYMBOL: disable-images?
SYMBOL: link-no-follow?
r , r>
+ " href=\"" , >r , r> "\"" ,
link-no-follow? get [ " nofollow=\"true\"" , ] when
- "\">" , , "" ,
+ ">" , , "" ,
] { } make ;
: make-image-link ( href alt -- seq )
- escape-link
- [
- "
" , ]
- { } make ;
+ disable-images? get [
+ 2drop "Images are not allowed"
+ ] [
+ escape-link
+ [
+ "
" ,
+ ] { } make
+ ] if ;
MEMO: image-link ( -- parser )
[
From 51bfaf249b59905147977806b952b40c6644fb94 Mon Sep 17 00:00:00 2001
From: Slava Pestov
Date: Sat, 14 Jun 2008 00:31:00 -0500
Subject: [PATCH 02/71] Unit test fix
---
extra/furnace/sessions/sessions-tests.factor | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/extra/furnace/sessions/sessions-tests.factor b/extra/furnace/sessions/sessions-tests.factor
index e959cae76a..a97ba091c0 100755
--- a/extra/furnace/sessions/sessions-tests.factor
+++ b/extra/furnace/sessions/sessions-tests.factor
@@ -65,7 +65,7 @@ M: foo call-responder*
[
[ ] [
- empty-session
+ empty-session
123 >>id session set
] unit-test
From 2c3121cf472cb4412e61145ebb4d2e75d49a45d9 Mon Sep 17 00:00:00 2001
From: Slava Pestov
Date: Sat, 14 Jun 2008 00:31:10 -0500
Subject: [PATCH 03/71] Add support for some attributes to farkup tag
---
extra/html/components/components.factor | 14 ++++++++++++--
extra/html/templates/chloe/chloe.factor | 2 +-
2 files changed, 13 insertions(+), 3 deletions(-)
diff --git a/extra/html/components/components.factor b/extra/html/components/components.factor
index 42d89811c1..6e1a25f5f5 100644
--- a/extra/html/components/components.factor
+++ b/extra/html/components/components.factor
@@ -200,10 +200,20 @@ M: code render*
[ string-lines ] [ drop ] [ mode>> value ] tri* htmlize-lines ;
! Farkup component
-SINGLETON: farkup
+TUPLE: farkup no-follow disable-images ;
+
+: string>boolean ( string -- boolean )
+ {
+ { "true" [ t ] }
+ { "false" [ f ] }
+ } case ;
M: farkup render*
- 2drop string-lines "\n" join convert-farkup write ;
+ [
+ [ no-follow>> [ string>boolean link-no-follow? set ] when* ]
+ [ disable-images>> [ string>boolean disable-images? set ] when* ] bi
+ drop string-lines "\n" join convert-farkup write
+ ] with-scope ;
! Inspector component
SINGLETON: inspector
diff --git a/extra/html/templates/chloe/chloe.factor b/extra/html/templates/chloe/chloe.factor
index 08d6b873fc..936c06ae7e 100644
--- a/extra/html/templates/chloe/chloe.factor
+++ b/extra/html/templates/chloe/chloe.factor
@@ -98,12 +98,12 @@ CHLOE: if dup if-satisfied? [ process-tag-children ] [ drop ] if ;
CHLOE-SINGLETON: label
CHLOE-SINGLETON: link
-CHLOE-SINGLETON: farkup
CHLOE-SINGLETON: inspector
CHLOE-SINGLETON: comparison
CHLOE-SINGLETON: html
CHLOE-SINGLETON: hidden
+CHLOE-TUPLE: farkup
CHLOE-TUPLE: field
CHLOE-TUPLE: textarea
CHLOE-TUPLE: password
From f0a37253f2d123e5ea313be7403641a50cbba4b9 Mon Sep 17 00:00:00 2001
From: Slava Pestov
Date: Sat, 14 Jun 2008 00:31:24 -0500
Subject: [PATCH 04/71] Disable comments, make links nofollow in blog posts
---
extra/webapps/blogs/view-post.xml | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/extra/webapps/blogs/view-post.xml b/extra/webapps/blogs/view-post.xml
index 55bdd2e806..d8d4df10b2 100644
--- a/extra/webapps/blogs/view-post.xml
+++ b/extra/webapps/blogs/view-post.xml
@@ -37,7 +37,7 @@
-
+
Delete Comment
From 2d35ea233ff5860245dc1df0da1f006dcc737cb0 Mon Sep 17 00:00:00 2001
From: Slava Pestov
Date: Sat, 14 Jun 2008 00:44:23 -0500
Subject: [PATCH 05/71] Fix missing rest parameters
---
extra/webapps/blogs/blogs.factor | 2 ++
1 file changed, 2 insertions(+)
diff --git a/extra/webapps/blogs/blogs.factor b/extra/webapps/blogs/blogs.factor
index 38bf065e56..d0c651c71f 100644
--- a/extra/webapps/blogs/blogs.factor
+++ b/extra/webapps/blogs/blogs.factor
@@ -116,6 +116,7 @@ M: comment entity-url
: ( -- action )
+ "author" >>rest
[ validate-author ] >>init
[ "Recent Posts by " "author" value append ] >>title
[ list-posts ] >>entries
@@ -123,6 +124,7 @@ M: comment entity-url
: ( -- action )
+ "id" >>rest
[ validate-integer-id "id" value post "post" set-value ] >>init
[ "post" value feed-entry-title ] >>title
[ "post" value entity-url ] >>url
From 23f957850535953071464461b40ad5c7ecfb0b98 Mon Sep 17 00:00:00 2001
From: Slava Pestov
Date: Sat, 14 Jun 2008 02:45:04 -0500
Subject: [PATCH 06/71] Remove micro-pessimization
---
extra/io/ports/ports.factor | 6 ++----
1 file changed, 2 insertions(+), 4 deletions(-)
diff --git a/extra/io/ports/ports.factor b/extra/io/ports/ports.factor
index b761ecaf5b..f54cd2e9b3 100755
--- a/extra/io/ports/ports.factor
+++ b/extra/io/ports/ports.factor
@@ -98,11 +98,9 @@ TUPLE: output-port < buffered-port ;
: ( handle -- output-port )
output-port ;
-: can-write? ( len buffer -- ? )
- [ buffer-fill + ] keep buffer-capacity <= ;
-
: wait-to-write ( len port -- )
- tuck buffer>> can-write? [ drop ] [ stream-flush ] if ;
+ tuck buffer>> buffer-capacity <=
+ [ drop ] [ stream-flush ] if ;
M: output-port stream-write1
dup check-disposed
From faa96f887bbc37492b7a1df3c3ad815c91ac3c71 Mon Sep 17 00:00:00 2001
From: Slava Pestov
Date: Sat, 14 Jun 2008 02:45:26 -0500
Subject: [PATCH 07/71] Log rotation
---
extra/http/server/server.factor | 5 ++++-
extra/logging/logging.factor | 8 +++-----
extra/webapps/factor-website/factor-website.factor | 4 ++++
3 files changed, 11 insertions(+), 6 deletions(-)
diff --git a/extra/http/server/server.factor b/extra/http/server/server.factor
index 4ad44554f5..095b52171c 100755
--- a/extra/http/server/server.factor
+++ b/extra/http/server/server.factor
@@ -13,7 +13,7 @@ io.encodings.ascii
io.encodings.binary
io.streams.limited
io.timeouts
-fry logging calendar urls
+fry logging logging.insomniac calendar urls
http
http.server.responses
html.elements
@@ -140,4 +140,7 @@ LOG: httpd-hit NOTICE
: httpd-main ( -- )
8888 httpd ;
+: httpd-insomniac ( -- )
+ "http.server" { httpd-hit } schedule-insomniac ;
+
MAIN: httpd-main
diff --git a/extra/logging/logging.factor b/extra/logging/logging.factor
index f46fcf6c53..5168e7fcd2 100755
--- a/extra/logging/logging.factor
+++ b/extra/logging/logging.factor
@@ -42,11 +42,9 @@ SYMBOL: log-service
message ( obj -- inputs>message )
- dup one-string-array? [ first ] [
+ dup array? [ dup length 1 = [ first ] when ] when
+ dup string? [
[
string-limit off
1 line-limit set
@@ -54,7 +52,7 @@ PREDICATE: one-string-array < array
0 margin set
unparse
] with-scope
- ] if ;
+ ] unless ;
PRIVATE>
diff --git a/extra/webapps/factor-website/factor-website.factor b/extra/webapps/factor-website/factor-website.factor
index fa598c0948..04fc0487b8 100644
--- a/extra/webapps/factor-website/factor-website.factor
+++ b/extra/webapps/factor-website/factor-website.factor
@@ -3,6 +3,7 @@
USING: accessors kernel sequences assocs io.files io.sockets
io.server
namespaces db db.tuples db.sqlite smtp
+logging.insomniac
http.server
http.server.dispatchers
furnace.alloy
@@ -61,10 +62,13 @@ TUPLE: factor-website < dispatcher ;
: init-factor-website ( -- )
"factorcode.org" 25 smtp-server set-global
"todo@factorcode.org" lost-password-from set-global
+ "website@factorcode.org" insomniac-sender set-global
+ "slava@factorcode.org" insomniac-recipients set-global
init-factor-db
main-responder set-global ;
: start-factor-website ( -- )
test-db start-expiring
test-db start-update-task
+ httpd-insomniac
8812 httpd ;
From 4e4731ec67fdbdcdce5f557d434e0de634d99a97 Mon Sep 17 00:00:00 2001
From: Slava Pestov
Date: Sat, 14 Jun 2008 02:45:34 -0500
Subject: [PATCH 08/71] Fix rollback
---
extra/webapps/wiki/revisions.xml | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/extra/webapps/wiki/revisions.xml b/extra/webapps/wiki/revisions.xml
index 97a051cd96..0e1af75a8f 100644
--- a/extra/webapps/wiki/revisions.xml
+++ b/extra/webapps/wiki/revisions.xml
@@ -16,7 +16,7 @@
|
|
- Rollback |
+ Rollback |
From 9516d781542f44754e38c6b411ddac10b02bd1c2 Mon Sep 17 00:00:00 2001
From: Slava Pestov
Date: Sat, 14 Jun 2008 04:00:40 -0500
Subject: [PATCH 09/71] Fix bootstrap
---
extra/io/ports/ports-docs.factor | 4 ----
1 file changed, 4 deletions(-)
diff --git a/extra/io/ports/ports-docs.factor b/extra/io/ports/ports-docs.factor
index 7420cac115..47485193cf 100755
--- a/extra/io/ports/ports-docs.factor
+++ b/extra/io/ports/ports-docs.factor
@@ -64,7 +64,3 @@ HELP: (wait-to-read)
HELP: wait-to-read
{ $values { "port" input-port } { "eof?" "a boolean" } }
{ $description "If the port's buffer has unread data, returns immediately, otherwise suspends the current thread until some data is available for reading. If the buffer was empty and no more data could be read, outputs " { $link t } " to indicate end-of-file; otherwise outputs " { $link f } "." } ;
-
-HELP: can-write?
-{ $values { "len" "a positive integer" } { "buffer" buffer } { "?" "a boolean" } }
-{ $description "Tests if the port's output buffer can accomodate " { $snippet "len" } " bytes. If the buffer is empty, this always outputs " { $link t } ", since in that case the buffer will be grown automatically." } ;
From a2fa1369b04c867720ffcd360fa0c3016a225560 Mon Sep 17 00:00:00 2001
From: Slava Pestov
Date: Sat, 14 Jun 2008 04:00:57 -0500
Subject: [PATCH 10/71] Furnace fixes
---
extra/furnace/actions/actions.factor | 2 +-
extra/furnace/furnace.factor | 3 ++-
extra/furnace/sessions/sessions.factor | 8 ++++++--
3 files changed, 9 insertions(+), 4 deletions(-)
diff --git a/extra/furnace/actions/actions.factor b/extra/furnace/actions/actions.factor
index 2b3144fd27..9cc1880cc3 100755
--- a/extra/furnace/actions/actions.factor
+++ b/extra/furnace/actions/actions.factor
@@ -76,7 +76,7 @@ TUPLE: action rest authorize init display validate submit ;
: handle-post ( action -- response )
'[
- form-nesting-key params get at " " split
+ form-nesting-key params get at " " split harvest
[ , (handle-post) ]
[ swap '[ , , nest-values ] ] reduce
call
diff --git a/extra/furnace/furnace.factor b/extra/furnace/furnace.factor
index 2645146fbf..a51841d4ad 100644
--- a/extra/furnace/furnace.factor
+++ b/extra/furnace/furnace.factor
@@ -109,7 +109,8 @@ SYMBOL: exit-continuation
[ drop f ] [ "," split [ dup value ] H{ } map>assoc ] if ;
: a-url-path ( tag -- string )
- [ "href" required-attr ] [ "rest" optional-attr value ] bi
+ [ "href" required-attr ]
+ [ "rest" optional-attr dup [ value ] when ] bi
[ [ "/" ?tail drop "/" ] dip present 3append ] when* ;
: a-url ( tag -- url )
diff --git a/extra/furnace/sessions/sessions.factor b/extra/furnace/sessions/sessions.factor
index ab971d24d0..4be7403e39 100755
--- a/extra/furnace/sessions/sessions.factor
+++ b/extra/furnace/sessions/sessions.factor
@@ -2,7 +2,7 @@
! See http://factorcode.org/license.txt for BSD license.
USING: assocs kernel math.intervals math.parser namespaces
random accessors quotations hashtables sequences continuations
-fry calendar combinators destructors alarms io.server
+fry calendar combinators combinators.lib destructors alarms io.server
db db.tuples db.types
http http.server http.server.dispatchers http.server.filters
html.elements
@@ -69,7 +69,11 @@ TUPLE: sessions < server-state-manager domain verify? ;
: touch-session ( session -- )
sessions get touch-state ;
-: remote-host ( -- string ) remote-address get host>> ;
+: remote-host ( -- string )
+ {
+ [ request get "x-forwarded-for" header ]
+ [ remote-address get host>> ]
+ } 0|| ;
: empty-session ( -- session )
f
From 198b1a0d56510f8ac75af900c8ec4338223f3b43 Mon Sep 17 00:00:00 2001
From: Slava Pestov
Date: Sat, 14 Jun 2008 04:01:07 -0500
Subject: [PATCH 11/71] Clean up quadratic
---
extra/math/quadratic/quadratic.factor | 8 ++++----
1 file changed, 4 insertions(+), 4 deletions(-)
diff --git a/extra/math/quadratic/quadratic.factor b/extra/math/quadratic/quadratic.factor
index 2253582623..60929b92cb 100644
--- a/extra/math/quadratic/quadratic.factor
+++ b/extra/math/quadratic/quadratic.factor
@@ -3,13 +3,13 @@
USING: kernel math math.functions ;
IN: math.quadratic
-: monic ( c b a -- c' b' ) tuck / >r / r> ;
+: monic ( c b a -- c' b' ) tuck [ / ] 2bi@ ;
: discriminant ( c b -- b d ) tuck sq 4 / swap - sqrt ;
-: critical ( b d -- -b/2 d ) >r -2 / r> ;
+: critical ( b d -- -b/2 d ) [ -2 / ] dip ;
-: +- ( x y -- x+y x-y ) [ + ] 2keep - ;
+: +- ( x y -- x+y x-y ) [ + ] [ - ] 2bi ;
: quadratic ( c b a -- alpha beta )
#! Solve a quadratic equation ax^2 + bx + c = 0
@@ -17,4 +17,4 @@ IN: math.quadratic
: qeval ( x c b a -- y )
#! Evaluate ax^2 + bx + c
- >r pick * r> roll sq * + + ;
+ [ pick * ] dip roll sq * + + ;
From 149e4345c6d581e2088bc9a8bab2cb32f9d8cf8d Mon Sep 17 00:00:00 2001
From: Slava Pestov
Date: Sat, 14 Jun 2008 04:01:16 -0500
Subject: [PATCH 12/71] Add sanity checks
---
extra/html/components/components.factor | 7 +++++--
1 file changed, 5 insertions(+), 2 deletions(-)
diff --git a/extra/html/components/components.factor b/extra/html/components/components.factor
index 6e1a25f5f5..7355cd153d 100644
--- a/extra/html/components/components.factor
+++ b/extra/html/components/components.factor
@@ -10,9 +10,12 @@ IN: html.components
SYMBOL: values
-: value ( name -- value ) values get at ;
+: check-value-name ( name -- name )
+ dup string? [ "Value name not a string" throw ] unless ;
-: set-value ( value name -- ) values get set-at ;
+: value ( name -- value ) check-value-name values get at ;
+
+: set-value ( value name -- ) check-value-name values get set-at ;
: blank-values ( -- ) H{ } clone values set ;
From 501588ab76622b3ab7882a4d385b0c628706e597 Mon Sep 17 00:00:00 2001
From: Slava Pestov
Date: Sat, 14 Jun 2008 04:01:25 -0500
Subject: [PATCH 13/71] add x-forwarded-for logging
---
extra/http/server/server.factor | 10 ++++++++--
1 file changed, 8 insertions(+), 2 deletions(-)
diff --git a/extra/http/server/server.factor b/extra/http/server/server.factor
index 095b52171c..03822ec854 100755
--- a/extra/http/server/server.factor
+++ b/extra/http/server/server.factor
@@ -78,9 +78,15 @@ main-responder global [ <404> or ] change-at
LOG: httpd-hit NOTICE
+LOG: httpd-header NOTICE
+
+: log-header ( headers name -- )
+ tuck header 2array httpd-header ;
+
: log-request ( request -- )
- [ method>> ] [ url>> [ host>> ] [ path>> ] bi ] bi
- 3array httpd-hit ;
+ [ [ method>> ] [ url>> [ host>> ] [ path>> ] bi ] bi 3array httpd-hit ]
+ [ { "user-agent" "x-forwarded-for" } [ log-header ] with each ]
+ bi ;
: split-path ( string -- path )
"/" split harvest ;
From 5692d28ce5cdd47aff5cc906c08706bedf2b466b Mon Sep 17 00:00:00 2001
From: Slava Pestov
Date: Sat, 14 Jun 2008 04:06:43 -0500
Subject: [PATCH 14/71] Fix compile error
---
extra/editors/vim/vim.factor | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/extra/editors/vim/vim.factor b/extra/editors/vim/vim.factor
index 9ce256868b..8ec94a7fd6 100755
--- a/extra/editors/vim/vim.factor
+++ b/extra/editors/vim/vim.factor
@@ -6,11 +6,11 @@ SYMBOL: vim-path
SYMBOL: vim-detach
SYMBOL: vim-editor
-HOOK: vim-command vim-editor
+HOOK: vim-command vim-editor ( file line -- array )
TUPLE: vim ;
-M: vim vim-command ( file line -- array )
+M: vim vim-command
[
vim-path get , swap , "+" swap number>string append ,
] { } make ;
From b8380711e459fb27cd36d6f5c70c4662d2f79133 Mon Sep 17 00:00:00 2001
From: Slava Pestov
Date: Sat, 14 Jun 2008 04:11:30 -0500
Subject: [PATCH 15/71] Clean up editors.vim/gvim a bit
---
extra/editors/gvim/gvim.factor | 6 +++---
extra/editors/vim/vim.factor | 4 ++--
2 files changed, 5 insertions(+), 5 deletions(-)
diff --git a/extra/editors/gvim/gvim.factor b/extra/editors/gvim/gvim.factor
index 62150bdf49..240af7d8ef 100755
--- a/extra/editors/gvim/gvim.factor
+++ b/extra/editors/gvim/gvim.factor
@@ -3,14 +3,14 @@ namespaces sequences system combinators
editors.vim editors.gvim.backend vocabs.loader ;
IN: editors.gvim
-TUPLE: gvim ;
+SINGLETON: gvim
M: gvim vim-command ( file line -- string )
- [ "\"" % gvim-path % "\" \"" % swap % "\" +" % # ] "" make ;
+ [ gvim-path , swap , "+" swap number>string append , ] { } make ;
t vim-detach set-global ! don't block the ui
-T{ gvim } vim-editor set-global
+gvim vim-editor set-global
{
{ [ os unix? ] [ "editors.gvim.unix" ] }
diff --git a/extra/editors/vim/vim.factor b/extra/editors/vim/vim.factor
index 8ec94a7fd6..29c16f7cc3 100755
--- a/extra/editors/vim/vim.factor
+++ b/extra/editors/vim/vim.factor
@@ -8,7 +8,7 @@ SYMBOL: vim-detach
SYMBOL: vim-editor
HOOK: vim-command vim-editor ( file line -- array )
-TUPLE: vim ;
+SINGLETON: vim
M: vim vim-command
[
@@ -23,4 +23,4 @@ M: vim vim-command
"vim" vim-path set-global
[ vim-location ] edit-hook set-global
-T{ vim } vim-editor set-global
+vim vim-editor set-global
From bd7bee867b15c35be5477a4874c27d1806d12af3 Mon Sep 17 00:00:00 2001
From: Slava Pestov
Date: Sat, 14 Jun 2008 04:18:29 -0500
Subject: [PATCH 16/71] Fix test failure
---
extra/html/components/components-tests.factor | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/extra/html/components/components-tests.factor b/extra/html/components/components-tests.factor
index 2ae120b527..8ec3a58611 100644
--- a/extra/html/components/components-tests.factor
+++ b/extra/html/components/components-tests.factor
@@ -156,7 +156,7 @@ M: link-test link-href drop "http://www.apple.com/foo&bar" ;
[ ] [ "-foo\n-bar" "farkup" set-value ] unit-test
[ "" ] [
- [ "farkup" farkup render ] with-string-writer
+ [ "farkup" T{ farkup } render ] with-string-writer
] unit-test
[ ] [ { 1 2 3 } "object" set-value ] unit-test
From 5b4809e49d36d9ab8129912c874ed0c69525ff2e Mon Sep 17 00:00:00 2001
From: Slava Pestov
Date: Sat, 14 Jun 2008 04:21:52 -0500
Subject: [PATCH 17/71] Remove dead code
---
extra/editors/gvim/gvim.factor | 2 --
extra/editors/vim/vim-docs.factor | 4 +---
extra/editors/vim/vim.factor | 6 +-----
3 files changed, 2 insertions(+), 10 deletions(-)
diff --git a/extra/editors/gvim/gvim.factor b/extra/editors/gvim/gvim.factor
index 240af7d8ef..041f3db675 100755
--- a/extra/editors/gvim/gvim.factor
+++ b/extra/editors/gvim/gvim.factor
@@ -8,8 +8,6 @@ SINGLETON: gvim
M: gvim vim-command ( file line -- string )
[ gvim-path , swap , "+" swap number>string append , ] { } make ;
-t vim-detach set-global ! don't block the ui
-
gvim vim-editor set-global
{
diff --git a/extra/editors/vim/vim-docs.factor b/extra/editors/vim/vim-docs.factor
index 020117564d..cf42884084 100644
--- a/extra/editors/vim/vim-docs.factor
+++ b/extra/editors/vim/vim-docs.factor
@@ -11,7 +11,5 @@ $nl
"USE: vim"
"\"c:\\\\program files\\\\vim\\\\vim70\\\\gvim\" vim-path set-global"
}
-"On Unix, you may omit the last line if " { $snippet "\"vim\"" } " is in your " { $snippet "$PATH" } "."
-$nl
-"If you are running the terminal version of Vim, you want it to block Factor until exiting, but for GVim the opposite is desired, so that one can work in Factor and GVim concurrently. The " { $link vim-detach } " global variable can be set to " { $link t } " to detach the Vim process. The default is " { $link f } "." ;
+"On Unix, you may omit the last line if " { $snippet "\"vim\"" } " is in your " { $snippet "$PATH" } "." ;
diff --git a/extra/editors/vim/vim.factor b/extra/editors/vim/vim.factor
index 29c16f7cc3..bfbb8f15a5 100755
--- a/extra/editors/vim/vim.factor
+++ b/extra/editors/vim/vim.factor
@@ -3,7 +3,6 @@ namespaces parser prettyprint sequences editors accessors ;
IN: editors.vim
SYMBOL: vim-path
-SYMBOL: vim-detach
SYMBOL: vim-editor
HOOK: vim-command vim-editor ( file line -- array )
@@ -16,10 +15,7 @@ M: vim vim-command
] { } make ;
: vim-location ( file line -- )
- vim-command
- swap >>command
- vim-detach get-global [ t >>detached ] when
- try-process ;
+ vim-command try-process ;
"vim" vim-path set-global
[ vim-location ] edit-hook set-global
From 10477bf7dd3c9b60341ab65da76313797ba0ebae Mon Sep 17 00:00:00 2001
From: Eduardo Cavazos
Date: Sat, 14 Jun 2008 13:09:54 -0500
Subject: [PATCH 18/71] newfx: a few additions
---
extra/newfx/newfx.factor | 7 ++++++-
1 file changed, 6 insertions(+), 1 deletion(-)
diff --git a/extra/newfx/newfx.factor b/extra/newfx/newfx.factor
index be30dfe370..0504744240 100644
--- a/extra/newfx/newfx.factor
+++ b/extra/newfx/newfx.factor
@@ -189,4 +189,9 @@ METHOD: as-mutate { object object assoc } set-at ;
! A note about the 'mutate' qualifier. Other words also technically mutate
! their primary object. However, the 'mutate' qualifier is supposed to
-! indicate that this is the main objective of the word, as a side effect.
\ No newline at end of file
+! indicate that this is the main objective of the word, as a side effect.
+
+: adjoin ( seq elt -- seq ) over sets:adjoin ;
+: adjoin-on ( elt seq -- seq ) sets:adjoin ;
+: adjoined ( set elt -- set ) swap sets:adjoin ;
+: adjoined-on ( elt set -- ) sets:adjoin ;
\ No newline at end of file
From a36307a11b7f4d4a1cb60cb7d4a33d2910a70916 Mon Sep 17 00:00:00 2001
From: Eduardo Cavazos
Date: Sat, 14 Jun 2008 14:44:32 -0500
Subject: [PATCH 19/71] newfx: minor fix
---
extra/newfx/newfx.factor | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/extra/newfx/newfx.factor b/extra/newfx/newfx.factor
index 0504744240..e7d92bba58 100644
--- a/extra/newfx/newfx.factor
+++ b/extra/newfx/newfx.factor
@@ -192,6 +192,6 @@ METHOD: as-mutate { object object assoc } set-at ;
! indicate that this is the main objective of the word, as a side effect.
: adjoin ( seq elt -- seq ) over sets:adjoin ;
-: adjoin-on ( elt seq -- seq ) sets:adjoin ;
-: adjoined ( set elt -- set ) swap sets:adjoin ;
+: adjoin-on ( elt seq -- seq ) tuck sets:adjoin ;
+: adjoined ( set elt -- ) swap sets:adjoin ;
: adjoined-on ( elt set -- ) sets:adjoin ;
\ No newline at end of file
From 094cb776fb8dd994ca8bd60dccd0870cbcabdd4e Mon Sep 17 00:00:00 2001
From: Eduardo Cavazos
Date: Sat, 14 Jun 2008 14:45:37 -0500
Subject: [PATCH 20/71] dns.server: add CNAME to rr->rdata-names
---
extra/dns/server/server.factor | 7 ++++---
1 file changed, 4 insertions(+), 3 deletions(-)
diff --git a/extra/dns/server/server.factor b/extra/dns/server/server.factor
index de36d661aa..7d52ff9e88 100644
--- a/extra/dns/server/server.factor
+++ b/extra/dns/server/server.factor
@@ -50,9 +50,10 @@ IN: dns.server
: rr->rdata-names ( rr -- names/f )
{
- { [ dup type>> NS = ] [ rdata>> {1} ] }
- { [ dup type>> MX = ] [ rdata>> exchange>> {1} ] }
- { [ t ] [ drop f ] }
+ { [ dup type>> NS = ] [ rdata>> {1} ] }
+ { [ dup type>> MX = ] [ rdata>> exchange>> {1} ] }
+ { [ dup type>> CNAME = ] [ rdata>> {1} ] }
+ { [ t ] [ drop f ] }
}
cond ;
From b8f1d71d2eb6874ae81a42fdef1855bd8eb6ac75 Mon Sep 17 00:00:00 2001
From: Eduardo Cavazos
Date: Sat, 14 Jun 2008 15:48:07 -0500
Subject: [PATCH 21/71] dns.server: do work in separate thread
---
extra/dns/server/server.factor | 19 +++++++++++--------
1 file changed, 11 insertions(+), 8 deletions(-)
diff --git a/extra/dns/server/server.factor b/extra/dns/server/server.factor
index 7d52ff9e88..b556780805 100644
--- a/extra/dns/server/server.factor
+++ b/extra/dns/server/server.factor
@@ -1,8 +1,8 @@
-USING: kernel combinators sequences sets math
+USING: kernel combinators sequences sets math threads
io.sockets unicode.case accessors
combinators.cleave combinators.lib
- newfx
+ newfx fry
dns dns.util dns.misc ;
IN: dns.server
@@ -204,15 +204,18 @@ DEFER: query->rrs
! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
-: loop ( -- )
- socket receive
- swap
+: (handle-request) ( byte-array addr-spec -- )
+ >r
parse-message
find-answer
message->ba
- swap
- socket send
- loop ;
+ r>
+ socket send ;
+
+: handle-request ( byte-array addr-spec -- )
+ '[ , , (handle-request) ] in-thread ;
+
+: loop ( -- ) socket receive handle-request loop ;
! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
From 3e6a6c2195b29c7ce3d3ec84ce14ca346c756984 Mon Sep 17 00:00:00 2001
From: Eduardo Cavazos
Date: Sat, 14 Jun 2008 16:05:38 -0500
Subject: [PATCH 22/71] newfx: minor fix
---
extra/newfx/newfx.factor | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/extra/newfx/newfx.factor b/extra/newfx/newfx.factor
index e7d92bba58..37c738cd6a 100644
--- a/extra/newfx/newfx.factor
+++ b/extra/newfx/newfx.factor
@@ -1,11 +1,12 @@
-USING: kernel sequences assocs qualified circular ;
+USING: kernel sequences assocs qualified circular sets ;
USING: math multi-methods ;
QUALIFIED: sequences
QUALIFIED: assocs
QUALIFIED: circular
+QUALIFIED: sets
IN: newfx
From 229ad789071e2485eef9773deeb528d521faa835 Mon Sep 17 00:00:00 2001
From: Slava Pestov
Date: Sun, 15 Jun 2008 00:32:48 -0500
Subject: [PATCH 23/71] Slight cleanup
---
core/assocs/assocs.factor | 21 ++++++++++-----------
core/sequences/sequences.factor | 7 ++++---
extra/sequences/lib/lib.factor | 3 ---
3 files changed, 14 insertions(+), 17 deletions(-)
diff --git a/core/assocs/assocs.factor b/core/assocs/assocs.factor
index c875475278..f56ac810d9 100755
--- a/core/assocs/assocs.factor
+++ b/core/assocs/assocs.factor
@@ -20,26 +20,25 @@ GENERIC: assoc-clone-like ( assoc exemplar -- newassoc )
GENERIC: >alist ( assoc -- newassoc )
+: (assoc-each) ( assoc quot -- seq quot' )
+ >r >alist r> [ first2 ] prepose ; inline
+
: assoc-find ( assoc quot -- key value ? )
- >r >alist r> [ first2 ] prepose find swap
- [ first2 t ] [ drop f f f ] if ; inline
+ (assoc-each) find swap [ first2 t ] [ drop f f f ] if ; inline
: key? ( key assoc -- ? ) at* nip ; inline
: assoc-each ( assoc quot -- )
- [ f ] compose assoc-find 3drop ; inline
-
-: (assoc>map) ( quot accum -- quot' )
- [ push ] curry compose ; inline
+ (assoc-each) each ; inline
: assoc>map ( assoc quot exemplar -- seq )
- >r over assoc-size
- [ (assoc>map) assoc-each ] keep
- r> like ; inline
+ >r accumulator >r assoc-each r> r> like ; inline
+
+: assoc-map-as ( assoc quot exemplar -- newassoc )
+ >r [ 2array ] compose V{ } assoc>map r> assoc-like ; inline
: assoc-map ( assoc quot -- newassoc )
- over >r [ 2array ] compose V{ } assoc>map r> assoc-like ;
- inline
+ over assoc-map-as ; inline
: assoc-push-if ( key value quot accum -- )
>r 2keep r> roll
diff --git a/core/sequences/sequences.factor b/core/sequences/sequences.factor
index cb33552693..02a7191f0a 100755
--- a/core/sequences/sequences.factor
+++ b/core/sequences/sequences.factor
@@ -419,10 +419,11 @@ PRIVATE>
: interleave ( seq between quot -- )
[ (interleave) ] 2curry >r dup length swap r> 2each ; inline
+: accumulator ( quot -- quot' vec )
+ V{ } clone [ [ push ] curry compose ] keep ; inline
+
: unfold ( pred quot tail -- seq )
- V{ } clone [
- swap >r [ push ] curry compose r> while
- ] keep { } like ; inline
+ swap accumulator >r swap while r> { } like ; inline
: follow ( obj quot -- seq )
>r [ dup ] r> [ keep ] curry [ ] unfold nip ; inline
diff --git a/extra/sequences/lib/lib.factor b/extra/sequences/lib/lib.factor
index ed4c337a92..56488818ab 100755
--- a/extra/sequences/lib/lib.factor
+++ b/extra/sequences/lib/lib.factor
@@ -201,9 +201,6 @@ USE: continuations
>r >r 0 max r> r>
[ length tuck min >r min r> ] keep subseq ;
-: accumulator ( quot -- quot vec )
- V{ } clone [ [ push ] curry compose ] keep ; inline
-
! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
! List the positions of obj in seq
From 292a6fdb0d9af33c193e37881260ab7327527db3 Mon Sep 17 00:00:00 2001
From: Slava Pestov
Date: Sun, 15 Jun 2008 02:37:28 -0500
Subject: [PATCH 24/71] Fix typo
---
extra/cords/cords.factor | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/extra/cords/cords.factor b/extra/cords/cords.factor
index f5cc89f8d5..a7f4246826 100644
--- a/extra/cords/cords.factor
+++ b/extra/cords/cords.factor
@@ -1,4 +1,4 @@
-! Copysecond (C) 2008 Slava Pestov.
+! Copyright (C) 2008 Slava Pestov.
! See http://factorcode.org/license.txt for BSD license.
USING: accessors assocs sequences sorting math math.order
arrays combinators kernel ;
From 0f2da40977fbf6160d3e2908ddad1b3cf43c43c7 Mon Sep 17 00:00:00 2001
From: Slava Pestov
Date: Sun, 15 Jun 2008 02:37:37 -0500
Subject: [PATCH 25/71] Better error message
---
extra/io/launcher/launcher.factor | 13 +++++++++----
1 file changed, 9 insertions(+), 4 deletions(-)
diff --git a/extra/io/launcher/launcher.factor b/extra/io/launcher/launcher.factor
index 131cadfaf0..bd90072039 100755
--- a/extra/io/launcher/launcher.factor
+++ b/extra/io/launcher/launcher.factor
@@ -4,7 +4,7 @@ USING: system kernel namespaces strings hashtables sequences
assocs combinators vocabs.loader init threads continuations
math accessors concurrency.flags destructors
io io.backend io.timeouts io.pipes io.pipes.private io.encodings
-io.streams.duplex io.ports ;
+io.streams.duplex io.ports debugger prettyprint inspector ;
IN: io.launcher
TUPLE: process < identity-tuple
@@ -131,11 +131,16 @@ HOOK: run-process* io-backend ( process -- handle )
run-detached
dup detached>> [ dup wait-for-process drop ] unless ;
-ERROR: process-failed code ;
+ERROR: process-failed process code ;
+
+M: process-failed error.
+ dup "Process exited with error code " write code>> . nl
+ "Launch descriptor:" print nl
+ process>> describe ;
: try-process ( desc -- )
- run-process wait-for-process dup zero?
- [ drop ] [ process-failed ] if ;
+ run-process dup wait-for-process dup zero?
+ [ 2drop ] [ process-failed ] if ;
HOOK: kill-process* io-backend ( handle -- )
From 0ab3f1f436d11f860dad64c71f6f35d9f44d9182 Mon Sep 17 00:00:00 2001
From: Slava Pestov
Date: Sun, 15 Jun 2008 02:38:12 -0500
Subject: [PATCH 26/71] New html.forms abstraction fixes some problems; clean
up some code
---
extra/furnace/actions/actions.factor | 67 ++++++-----
extra/furnace/auth/login/login.factor | 8 +-
extra/furnace/flash/flash.factor | 4 +-
extra/furnace/furnace.factor | 5 +-
extra/html/components/components-tests.factor | 21 ++--
extra/html/components/components.factor | 89 +++------------
extra/html/forms/forms-tests.factor | 67 +++++++++++
extra/html/forms/forms.factor | 106 ++++++++++++++++++
extra/html/templates/chloe/chloe-tests.factor | 10 +-
extra/html/templates/chloe/chloe.factor | 3 +-
extra/http/http-tests.factor | 3 +-
extra/validators/validators-tests.factor | 64 -----------
extra/validators/validators.factor | 54 +--------
extra/webapps/blogs/blogs.factor | 12 +-
extra/webapps/pastebin/pastebin.factor | 13 ++-
extra/webapps/planet/planet.factor | 6 +-
extra/webapps/todo/todo.factor | 5 +-
extra/webapps/user-admin/edit-user.xml | 4 +-
extra/webapps/user-admin/user-admin.factor | 38 +++++--
19 files changed, 310 insertions(+), 269 deletions(-)
create mode 100644 extra/html/forms/forms-tests.factor
create mode 100644 extra/html/forms/forms.factor
diff --git a/extra/furnace/actions/actions.factor b/extra/furnace/actions/actions.factor
index 9cc1880cc3..4b431c83bc 100755
--- a/extra/furnace/actions/actions.factor
+++ b/extra/furnace/actions/actions.factor
@@ -8,6 +8,7 @@ http.server
http.server.responses
furnace
furnace.flash
+html.forms
html.elements
html.components
html.components
@@ -20,10 +21,10 @@ SYMBOL: params
SYMBOL: rest
: render-validation-messages ( -- )
- validation-messages get
+ form get errors>>
dup empty? [ drop ] [
- [ - message>> escape-string write
] each
+ [ - escape-string write
] each
] if ;
@@ -37,8 +38,21 @@ TUPLE: action rest authorize init display validate submit ;
: ( -- action )
action new-action ;
-: flashed-variables ( -- seq )
- { validation-messages named-validation-messages } ;
+: set-nested-form ( form name -- )
+ dup empty? [
+ drop form set
+ ] [
+ dup length 1 = [
+ first set-value
+ ] [
+ unclip [ set-nested-form ] nest-form
+ ] if
+ ] if ;
+
+: restore-validation-errors ( -- )
+ form fget [
+ nested-forms fget set-nested-form
+ ] when* ;
: handle-get ( action -- response )
'[
@@ -46,25 +60,12 @@ TUPLE: action rest authorize init display validate submit ;
{
[ init>> call ]
[ authorize>> call ]
- [ drop flashed-variables restore-flash ]
+ [ drop restore-validation-errors ]
[ display>> call ]
} cleave
] [ drop <400> ] if
] with-exit-continuation ;
-: validation-failed ( -- * )
- post-request? [ f ] [ <400> ] if exit-with ;
-
-: (handle-post) ( action -- response )
- '[
- , dup submit>> [
- [ validate>> call ]
- [ authorize>> call ]
- [ submit>> call ]
- tri
- ] [ drop <400> ] if
- ] with-exit-continuation ;
-
: param ( name -- value )
params get at ;
@@ -74,24 +75,29 @@ TUPLE: action rest authorize init display validate submit ;
revalidate-url-key param
dup [ >url [ same-host? ] keep and ] when ;
+: validation-failed ( -- * )
+ post-request? revalidate-url and
+ [
+ nested-forms-key param " " split harvest nested-forms set
+ { form nested-forms }
+ ] [ <400> ] if*
+ exit-with ;
+
: handle-post ( action -- response )
'[
- form-nesting-key params get at " " split harvest
- [ , (handle-post) ]
- [ swap '[ , , nest-values ] ] reduce
- call
- ] with-exit-continuation
- [
- revalidate-url
- [ flashed-variables ] [ <403> ] if*
- ] unless* ;
+ , dup submit>> [
+ [ validate>> call ]
+ [ authorize>> call ]
+ [ submit>> call ]
+ tri
+ ] [ drop <400> ] if
+ ] with-exit-continuation ;
: handle-rest ( path action -- assoc )
rest>> dup [ [ "/" join ] dip associate ] [ 2drop f ] if ;
: init-action ( path action -- )
- blank-values
- init-validation
+ begin-form
handle-rest
request get request-params assoc-union params set ;
@@ -110,8 +116,7 @@ M: action modify-form
validation-failed? [ validation-failed ] when ;
: validate-params ( validators -- )
- params get swap validate-values from-object
- check-validation ;
+ params get swap validate-values check-validation ;
: validate-integer-id ( -- )
{ { "id" [ v-number ] } } validate-params ;
diff --git a/extra/furnace/auth/login/login.factor b/extra/furnace/auth/login/login.factor
index a1d2bf47c3..80005c452a 100755
--- a/extra/furnace/auth/login/login.factor
+++ b/extra/furnace/auth/login/login.factor
@@ -13,6 +13,7 @@ destructors
checksums
checksums.sha2
validators
+html.forms
html.components
html.elements
urls
@@ -34,13 +35,16 @@ QUALIFIED: smtp
IN: furnace.auth.login
: word>string ( word -- string )
- [ word-vocabulary ] [ drop ":" ] [ word-name ] tri 3append ;
+ [ word-vocabulary ] [ word-name ] bi ":" swap 3append ;
: words>strings ( seq -- seq' )
[ word>string ] map ;
+ERROR: no-such-word name vocab ;
+
: string>word ( string -- word )
- ":" split1 swap lookup ;
+ ":" split1 swap 2dup lookup dup
+ [ 2nip ] [ drop no-such-word ] if ;
: strings>words ( seq -- seq' )
[ string>word ] map ;
diff --git a/extra/furnace/flash/flash.factor b/extra/furnace/flash/flash.factor
index 43e0d293a5..e06cdac090 100644
--- a/extra/furnace/flash/flash.factor
+++ b/extra/furnace/flash/flash.factor
@@ -25,7 +25,9 @@ TUPLE: flash-scopes < server-state-manager ;
SYMBOL: flash-scope
-: fget ( key -- value ) flash-scope get at ;
+: fget ( key -- value )
+ flash-scope get dup
+ [ namespace>> at ] [ 2drop f ] if ;
: get-flash-scope ( id -- flash-scope )
dup [ flash-scope get-state ] when
diff --git a/extra/furnace/furnace.factor b/extra/furnace/furnace.factor
index a51841d4ad..e9d1b29da8 100644
--- a/extra/furnace/furnace.factor
+++ b/extra/furnace/furnace.factor
@@ -10,6 +10,7 @@ xml.entities
xml.writer
html.components
html.elements
+html.forms
html.templates
html.templates.chloe
html.templates.chloe.syntax
@@ -154,11 +155,11 @@ CHLOE: a
input/>
] [ 2drop ] if ;
-: form-nesting-key "__n" ;
+: nested-forms-key "__n" ;
: form-magic ( tag -- )
[ modify-form ] each-responder
- nested-values get " " join f like form-nesting-key hidden-form-field
+ nested-forms get " " join f like nested-forms-key hidden-form-field
"for" optional-attr [ "," split [ hidden render ] each ] when* ;
: form-start-tag ( tag -- )
diff --git a/extra/html/components/components-tests.factor b/extra/html/components/components-tests.factor
index 8ec3a58611..5779371078 100644
--- a/extra/html/components/components-tests.factor
+++ b/extra/html/components/components-tests.factor
@@ -1,9 +1,9 @@
IN: html.components.tests
USING: tools.test kernel io.streams.string
io.streams.null accessors inspector html.streams
-html.elements html.components namespaces ;
+html.elements html.components html.forms namespaces ;
-[ ] [ blank-values ] unit-test
+[ ] [ begin-form ] unit-test
[ ] [ 3 "hi" set-value ] unit-test
@@ -63,7 +63,7 @@ TUPLE: color red green blue ;
] with-null-writer
] unit-test
-[ ] [ blank-values ] unit-test
+[ ] [ begin-form ] unit-test
[ ] [ "new york" "city1" set-value ] unit-test
@@ -101,7 +101,7 @@ TUPLE: color red green blue ;
] with-null-writer
] unit-test
-[ ] [ blank-values ] unit-test
+[ ] [ begin-form ] unit-test
[ ] [ t "delivery" set-value ] unit-test
@@ -167,12 +167,19 @@ M: link-test link-href drop "http://www.apple.com/foo&bar" ;
=
] unit-test
-[ ] [ blank-values ] unit-test
+[ ] [ begin-form ] unit-test
[ ] [
"factor" [
"concatenative" "model" set-value
- ] nest-values
+ ] nest-form
] unit-test
-[ H{ { "factor" H{ { "model" "concatenative" } } } } ] [ values get ] unit-test
+[
+ H{
+ {
+ "factor"
+ T{ form f V{ } H{ { "model" "concatenative" } } }
+ }
+ }
+] [ values ] unit-test
diff --git a/extra/html/components/components.factor b/extra/html/components/components.factor
index 7355cd153d..b6b7f22b1d 100644
--- a/extra/html/components/components.factor
+++ b/extra/html/components/components.factor
@@ -1,85 +1,26 @@
! Copyright (C) 2008 Slava Pestov
! See http://factorcode.org/license.txt for BSD license.
USING: accessors kernel namespaces io math.parser assocs classes
-classes.tuple words arrays sequences sequences.lib splitting
-mirrors hashtables combinators continuations math strings
-fry locals calendar calendar.format xml.entities validators
-html.elements html.streams xmode.code2html farkup inspector
-lcs.diff2html urls present ;
+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
+html.elements html.streams html.forms ;
IN: html.components
-SYMBOL: values
-
-: check-value-name ( name -- name )
- dup string? [ "Value name not a string" throw ] unless ;
-
-: value ( name -- value ) check-value-name values get at ;
-
-: set-value ( value name -- ) check-value-name values get set-at ;
-
-: blank-values ( -- ) H{ } clone values set ;
-
-: prepare-value ( name object -- value name object )
- [ [ value ] keep ] dip ; inline
-
-: from-object ( object -- )
- dup assoc? [ ] unless
- values get swap update ;
-
-: deposit-values ( destination names -- )
- [ dup value ] H{ } map>assoc update ;
-
-: deposit-slots ( destination names -- )
- [ ] dip deposit-values ;
-
-: with-each-value ( name quot -- )
- [ value ] dip '[
- [
- values [ clone ] change
- 1+ "index" set-value
- "value" set-value
- @
- ] with-scope
- ] each-index ; inline
-
-: with-each-object ( name quot -- )
- [ value ] dip '[
- [
- blank-values
- 1+ "index" set-value
- from-object
- @
- ] with-scope
- ] each-index ; inline
-
-SYMBOL: nested-values
-
-: with-values ( name quot -- )
- '[
- ,
- [ nested-values [ swap prefix ] change ]
- [ value blank-values from-object ]
- bi
- @
- ] with-scope ; inline
-
-: nest-values ( name quot -- )
- swap [
- [
- H{ } clone [ values set call ] keep
- ] with-scope
- ] dip set-value ; inline
-
GENERIC: render* ( value name render -- )
: render ( name renderer -- )
- over named-validation-messages get at [
- [ value>> ] [ message>> ] bi
- [ -rot render* ] dip
- render-error
- ] [
- prepare-value render*
- ] if* ;
+ prepare-value
+ [
+ dup validation-error?
+ [ [ message>> ] [ value>> ] bi ]
+ [ f swap ]
+ if
+ ] 2dip
+ render*
+ [ render-error ] when* ;
> "140" = ]
+ bi and
+ ] with-validation
+] unit-test
+
+TUPLE: person name age ;
+
+person {
+ { "name" [ ] }
+ { "age" [ v-number 13 v-min-value 100 v-max-value ] }
+} define-validators
+
+[ t t ] [
+ [
+ { { "age" "" } }
+ { { "age" [ v-required ] } }
+ validate-values
+ validation-failed?
+ "age" value
+ [ validation-error? ]
+ [ message>> "required" = ]
+ bi and
+ ] with-validation
+] unit-test
+
+[ H{ { "a" 123 } } f ] [
+ [
+ H{
+ { "a" "123" }
+ { "b" "c" }
+ { "c" "d" }
+ }
+ H{
+ { "a" [ v-integer ] }
+ } validate-values
+ values
+ validation-failed?
+ ] with-validation
+] unit-test
+
+[ t "foo" ] [
+ [
+ "foo" validation-error
+ validation-failed?
+ form get errors>> first
+ ] with-validation
+] unit-test
diff --git a/extra/html/forms/forms.factor b/extra/html/forms/forms.factor
new file mode 100644
index 0000000000..0da3fcb0b3
--- /dev/null
+++ b/extra/html/forms/forms.factor
@@ -0,0 +1,106 @@
+! Copyright (C) 2008 Slava Pestov
+! See http://factorcode.org/license.txt for BSD license.
+USING: kernel accessors strings namespaces assocs hashtables
+mirrors math fry sequences sequences.lib words continuations ;
+IN: html.forms
+
+TUPLE: form errors values validation-failed ;
+
+: