]> gitweb.factorcode.org Git - factor.git/commitdiff
Merge branch 'master' of git://factorcode.org/git/factor
authorDoug Coleman <doug.coleman@gmail.com>
Sat, 3 May 2008 13:49:43 +0000 (08:49 -0500)
committerDoug Coleman <doug.coleman@gmail.com>
Sat, 3 May 2008 13:49:43 +0000 (08:49 -0500)
44 files changed:
Factor.app/Contents/Info.plist
core/bootstrap/image/image.factor
core/classes/algebra/algebra-docs.factor
core/classes/algebra/algebra-tests.factor
core/classes/algebra/algebra.factor
core/classes/classes.factor
core/math/order/order-docs.factor
core/optimizer/def-use/def-use-tests.factor
extra/bank/bank.factor
extra/html/html.factor
extra/http/http-tests.factor
extra/http/http.factor
extra/http/server/actions/actions.factor
extra/http/server/auth/admin/admin.xml
extra/http/server/auth/admin/edit-user.xml
extra/http/server/auth/admin/new-user.xml
extra/http/server/auth/login/edit-profile.xml
extra/http/server/auth/login/login.factor
extra/http/server/auth/login/login.xml
extra/http/server/auth/login/recover-3.xml
extra/http/server/auth/login/register.xml
extra/http/server/components/code/code.factor
extra/http/server/components/components.factor
extra/http/server/templating/chloe/chloe.factor
extra/monads/authors.txt [new file with mode: 0644]
extra/monads/monads-tests.factor [new file with mode: 0644]
extra/monads/monads.factor [new file with mode: 0644]
extra/monads/summary.txt [new file with mode: 0644]
extra/monads/tags.txt [new file with mode: 0644]
extra/shuffle/shuffle.factor
extra/tools/deploy/shaker/shaker.factor
extra/webapps/factor-website/page.css
extra/webapps/pastebin/annotation.xml
extra/webapps/pastebin/new-annotation.xml
extra/webapps/pastebin/paste-summary.xml
extra/webapps/pastebin/paste.xml
extra/webapps/pastebin/pastebin.factor
extra/webapps/pastebin/pastebin.xml
extra/webapps/planet/edit-blog.xml
extra/webapps/planet/planet.xml
extra/webapps/todo/edit-todo.xml
extra/webapps/todo/todo.xml
extra/webapps/todo/view-todo.xml
misc/Factor.tmbundle/Syntaxes/HTML (Factor).tmLanguage

index ca0e6d5f8adc3e5804d714ae090dcab1d601c57e..a8943d0d32f507a804ad341bef02ea8aaefef533 100644 (file)
@@ -32,7 +32,7 @@
        <key>CFBundlePackageType</key>
        <string>APPL</string>
        <key>NSHumanReadableCopyright</key>
-       <string>Copyright © 2003-2007, Slava Pestov and friends</string>
+       <string>Copyright © 2003-2008, Slava Pestov and friends</string>
        <key>NSServices</key>
        <array>
                <dict>
index cb73dc387efbbbafef6f199b39792b2498c8ea35..cb83dd948876f51025c2bdd971521781727b008b 100755 (executable)
@@ -404,7 +404,7 @@ M: quotation '
     [
         {
             dictionary source-files builtins
-            update-map class<=-cache class<=>-cache
+            update-map class<=-cache
             class-not-cache classes-intersect-cache class-and-cache
             class-or-cache
         } [ dup get swap bootstrap-word set ] each
index 3903da1ebcef94d5e5b938165319e36d1e4f9232..810bdbe10fc23ae0c4eb26e0b5880182403e188f 100755 (executable)
@@ -23,30 +23,19 @@ ARTICLE: "class-linearization" "Class linearization"
     "If a generic word defines a method on a mixin class A and another class B, and B is the only instance of A, there is an ambiguity because A and B are equal as sets; any object that is an instance of one is an instance of both."\r
     { "If a generic word defines methods on two union classes which are incomparable but not disjoint, for example " { $link sequence } " and " { $link number } ", there is an ambiguity because the generic word may be called on an object that is an instance of both unions." }\r
 }\r
-"These difficulties are resolved by imposing a linear order on classes, computed as follows for two classes A and B:"\r
+"The first ambiguity is resolved with a tie-breaker that compares metaclasses. The intrinsic meta-class order, from most-specific to least-specific:"\r
 { $list\r
-    "If A and B are the same class (not just equal as sets), then comparison stops."\r
-    "If A is a proper subset of B, or B is a proper subset of A, then comparison stops."\r
-    { "Next, the metaclasses of A and B are compared, with intrinsic meta-class order, from most-specific to least-specific:"\r
-        { $list\r
-            "Built-in classes and tuple classes"\r
-            "Predicate classes"\r
-            "Union classes"\r
-            "Mixin classes"\r
-        }\r
-    "If this yields an unambiguous answer, comparison stops."\r
-    }\r
-    "If the metaclasses of A and B occupy the same position in the order, then the vocabularies of A and B are compared lexicographically. If this yields an unambiguous answer, comparison stops."\r
-    "If A and B belong to the same vocabulary, their names are compared lexicographically. This must yield an unambiguous result, since if the names equal they must be the same class and this case was already handled in the first step."\r
-}\r
-"Some examples:"\r
-{ $list\r
-    { { $link integer } " precedes " { $link number } " because it is a strict subset" }\r
-    { { $link number } " precedes " { $link sequence } " because the " { $vocab-link "math" } " vocabulary precedes the " { $vocab-link "sequences" } " vocabulary" }\r
-    { { $link crc32 } " precedes " { $link checksum } ", even if it were the only instance, because " { $link crc32 } " is a singleton class which is more specific than a mixin class" }\r
+    "Built-in classes and tuple classes"\r
+    "Predicate classes"\r
+    "Union classes"\r
+    "Mixin classes"\r
 }\r
+"This means that in the above example, the generic word with methods on a mixin and its sole instance will always call the method for the sole instance, since it is more specific than a mixin class."\r
+$nl\r
+"The second problem is resolved with another tie-breaker. When performing the topological sort of classes, if there are multiple candidates at any given step of the sort, lexicographical order on the class name is used."\r
+$nl\r
 "Operations:"\r
-{ $subsection class<=> }\r
+{ $subsection class< }\r
 { $subsection sort-classes }\r
 "Metaclass order:"\r
 { $subsection rank-class } ;\r
@@ -72,8 +61,6 @@ HELP: sort-classes
 { $values { "seq" "a sequence of class" } { "newseq" "a new seqence of classes" } }\r
 { $description "Outputs a linear sort of a sequence of classes. Larger classes come before their subclasses." } ;\r
 \r
-{ sort-classes class<=> } related-words\r
-\r
 HELP: class-or\r
 { $values { "first" class } { "second" class } { "class" class } }\r
 { $description "Outputs the smallest anonymous class containing both " { $snippet "class1" } " and " { $snippet "class2" } "." } ;\r
@@ -89,7 +76,3 @@ HELP: classes-intersect?
 HELP: min-class\r
 { $values { "class" class } { "seq" "a sequence of class words" } { "class/f" "a class word or " { $link f } } }\r
 { $description "If all classes in " { $snippet "seq" } " that intersect " { $snippet "class" } " are subtypes of " { $snippet "class" } ", outputs the last such element of " { $snippet "seq" } ". If any conditions fail to hold, outputs " { $link f } "." } ;\r
-\r
-HELP: class<=>\r
-{ $values { "first" class } { "second" class } { "n" symbol } }\r
-{ $description "Compares two classes with the class linearization order." } ;\r
index 7387b8ae3a6cd06ffc0b704b0ece9a791a0ae509..dfe4a0fbc9753c70f5e0b15b47e2f714462347c5 100755 (executable)
@@ -248,7 +248,16 @@ UNION: yyy xxx ;
 [ { yyy xxx } ] [ { xxx yyy } sort-classes ] unit-test\r
 [ { yyy xxx } ] [ { yyy xxx } sort-classes ] unit-test\r
 \r
-[ { number integer ratio } ] [ { ratio number integer } sort-classes ] unit-test\r
+[ { number ratio integer } ] [ { ratio number integer } sort-classes ] unit-test\r
 [ { sequence number ratio } ] [ { ratio number sequence } sort-classes ] unit-test\r
 \r
-[ +lt+ ] [ \ real sequence class<=> ] unit-test\r
+TUPLE: xa ;\r
+TUPLE: xb ;\r
+TUPLE: xc < xa ;\r
+TUPLE: xd < xb ;\r
+TUPLE: xe ;\r
+TUPLE: xf < xb ;\r
+TUPLE: xg < xb ;\r
+TUPLE: xh < xb ;\r
+\r
+[ t ] [ { xa xb xc xd xe xf xg xh } sort-classes dup sort-classes = ] unit-test\r
index 8c910a1f8c29ddb630f38b2a6a72373ba2bbeec2..4160f4e9d2f0ac232c14c640723fcf8bc952a1a2 100755 (executable)
@@ -187,31 +187,15 @@ C: <anonymous-complement> anonymous-complement
         [ [ rank-class ] bi@ < ]\r
     } cond ;\r
 \r
-: class-tie-breaker ( first second -- n )\r
-    2dup [ rank-class ] compare {\r
-        { +lt+ [ 2drop +lt+ ] }\r
-        { +gt+ [ 2drop +gt+ ] }\r
-        { +eq+ [ <=> ] }\r
-    } case ;\r
-\r
-: (class<=>) ( first second -- n )\r
-    {\r
-        { [ 2dup class<= ] [\r
-            2dup swap class<=\r
-            [ class-tie-breaker ] [ 2drop +lt+ ] if\r
-        ] }\r
-        { [ 2dup swap class<= ] [\r
-            2dup class<=\r
-            [ class-tie-breaker ] [ 2drop +gt+ ] if\r
-        ] }\r
-        [ class-tie-breaker ]\r
-    } cond ;\r
-\r
-: class<=> ( first second -- n )\r
-    class<=>-cache get [ (class<=>) ] 2cache ;\r
+: largest-class ( seq -- n elt )\r
+    dup [ [ class< ] with contains? not ] curry find-last\r
+    [ "Topological sort failed" throw ] unless* ;\r
 \r
 : sort-classes ( seq -- newseq )\r
-    [ class<=> invert-comparison ] sort ;\r
+    [ [ word-name ] compare ] sort >vector\r
+    [ dup empty? not ]\r
+    [ dup largest-class >r over delete-nth r> ]\r
+    [ ] unfold nip ;\r
 \r
 : min-class ( class seq -- class/f )\r
     over [ classes-intersect? ] curry filter\r
index 53840c002725387ee5e99bdf87e3e73d49e002a3..594b2005b8a332cea7d73d5650b6050ceebe204a 100755 (executable)
@@ -6,7 +6,6 @@ quotations combinators sorting effects graphs vocabs ;
 IN: classes
 
 SYMBOL: class<=-cache
-SYMBOL: class<=>-cache
 SYMBOL: class-not-cache
 SYMBOL: classes-intersect-cache
 SYMBOL: class-and-cache
@@ -14,7 +13,6 @@ SYMBOL: class-or-cache
 
 : init-caches ( -- )
     H{ } clone class<=-cache set
-    H{ } clone class<=>-cache set
     H{ } clone class-not-cache set
     H{ } clone classes-intersect-cache set
     H{ } clone class-and-cache set
@@ -22,7 +20,6 @@ SYMBOL: class-or-cache
 
 : reset-caches ( -- )
     class<=-cache get clear-assoc
-    class<=>-cache get clear-assoc
     class-not-cache get clear-assoc
     classes-intersect-cache get clear-assoc
     class-and-cache get clear-assoc
index 98ff1920fa2fa9c4b822583ff1d580a743a26ca7..23ea1058ad92b8c648f151cd6963c26a80fba58c 100644 (file)
@@ -25,8 +25,8 @@ HELP: +gt+
 { $description "Returned by " { $link <=> } " when the first object is strictly greater than the second object." } ;
 
 HELP: invert-comparison
-{ $values { "symbol" "a comparison symbol, +lt+, +eq+, or +gt+" }
-          { "new-symbol" "a comparison symbol, +lt+, +eq+, or +gt+" } }
+{ $values { "symbol" symbol }
+          { "new-symbol" symbol } }
 { $description "Invert the comparison symbol returned by " { $link <=> } ". The output for the symbol " { $snippet "+eq+" } " is itself." }
 { $examples
     { $example "USING: math.order prettyprint ;" "+lt+ invert-comparison ." "+gt+" } } ;
index ef829da9f2796fbd397a47e5ddccdd5706480464..f49ab7fcba8bc57c559a38e28153692c9acdce10 100755 (executable)
@@ -1,6 +1,6 @@
 IN: optimizer.def-use.tests
 USING: inference inference.dataflow optimizer optimizer.def-use
-namespaces assocs kernel sequences math tools.test words ;
+namespaces assocs kernel sequences math tools.test words sets ;
 
 [ 3 { 1 1 1 } ] [
     [ 1 2 3 ] dataflow compute-def-use drop
index 35d1337afc937a6f2522228f424c7b175012af63..abe3250ecfc86e1a5ba366683aaf082ce18b3284 100644 (file)
@@ -26,8 +26,6 @@ C: <transaction> transaction
 : daily-rate>> ( account date -- rate )
     [ interest-rate>> ] dip daily-rate ;
 
-: before? ( date date -- ? ) <=> 0 < ;
-
 : transactions-on-date ( account date -- transactions )
     [ before? ] curry filter ;
 
index f0ae42476064358a0522455ceb819b8ae94063d1..7a0fa17c9a35f076f2731977a58dba8fe63e0a6d 100755 (executable)
@@ -225,13 +225,13 @@ M: html-stream stream-nl ( stream -- )
 
 : vertical-layout ( list -- )
     #! Given a list of HTML components, arrange them vertically.
-    <table> 
+    <table>
     [ <tr> <td> call </td> </tr> ] each
     </table> ;
 
 : horizontal-layout ( list -- )
     #! Given a list of HTML components, arrange them horizontally.
-    <table> 
+    <table>
      <tr "top" =valign tr> [ <td> call </td> ] each </tr>
     </table> ;
 
@@ -246,8 +246,8 @@ M: html-stream stream-nl ( stream -- )
 : simple-page ( title quot -- )
     #! Call the quotation, with all output going to the
     #! body of an html page with the given title.
-    <html>  
-        <head> <title> swap write </title> </head> 
+    <html>
+        <head> <title> swap write </title> </head>
         <body> call </body>
     </html> ;
 
@@ -255,10 +255,13 @@ M: html-stream stream-nl ( stream -- )
     #! Call the quotation, with all output going to the
     #! body of an html page with the given title. stylesheet-quot
     #! is called to generate the required stylesheet.
-    <html>  
-        <head>  
-             <title> rot write </title> 
-             swap call 
-        </head> 
+    <html>
+        <head>
+             <title> rot write </title>
+             swap call
+        </head>
         <body> call </body>
     </html> ;
+
+: render-error ( message -- )
+    <span "error" =class span> escape-string write </span> ;
index 831becd264760e00a8a4eb2dfb2a03a5342097fa..76c48d38f12c569b67031a24b2cab3f67632d805 100755 (executable)
@@ -30,6 +30,7 @@ IN: http.tests
 
 [ H{ { "a" { "b" "c" } } } ] [ "a=b&a=c" query>assoc ] unit-test
 
+[ "a=3" ] [ { { "a" 3 } } assoc>query ] unit-test
 : lf>crlf "\n" split "\r\n" join ;
 
 STRING: read-request-test-1
index 315250692bff6315ee6c40205978fb3f6551f27e..98c1d8e74ced4e9fd0719c9e64c0e22b13eb9594 100755 (executable)
@@ -143,7 +143,7 @@ IN: http
 : assoc>query ( hash -- str )
     [
         {
-            { [ dup number? ] [ number>string ] }
+            { [ dup number? ] [ number>string 1array ] }
             { [ dup string? ] [ 1array ] }
             { [ dup sequence? ] [ ] }
         } cond
index 6e1aac96272ceb0d4780a782b4ef7d1325c99fe2..2d73cb46a786ed0b58b812b65b193385fde561a1 100755 (executable)
@@ -2,13 +2,20 @@
 ! See http://factorcode.org/license.txt for BSD license.\r
 USING: accessors sequences kernel assocs combinators\r
 http.server http.server.validators http hashtables namespaces\r
-fry continuations locals ;\r
+fry continuations locals boxes xml.entities html.elements io ;\r
 IN: http.server.actions\r
 \r
-SYMBOL: +path+\r
-\r
 SYMBOL: params\r
 \r
+SYMBOL: validation-message\r
+\r
+: render-validation-message ( -- )\r
+    validation-message get value>> [\r
+        <span "error" =class span>\r
+            escape-string write\r
+        </span>\r
+    ] when* ;\r
+\r
 TUPLE: action init display submit get-params post-params ;\r
 \r
 : <action>\r
@@ -37,11 +44,16 @@ TUPLE: action init display submit get-params post-params ;
 : validation-failed ( -- * )\r
     action get display>> call exit-with ;\r
 \r
+: validation-failed-with ( string -- * )\r
+    validation-message get >box\r
+    validation-failed ;\r
+\r
 M: action call-responder* ( path action -- response )\r
     '[\r
         , [ CHAR: / = ] right-trim empty? [\r
             , action set\r
             request get\r
+            <box> validation-message set\r
             [ request-params params set ]\r
             [\r
                 method>> {\r
index 1864c3c4bf69edf49620054616ba966f08631ac7..05817565ed6e6c3c63f409471ecdce68eb1c02c9 100644 (file)
@@ -2,8 +2,6 @@
 
 <t:chloe xmlns:t="http://factorcode.org/chloe/1.0">
 
-       <t:style t:include="resource:extra/http/server/auth/admin/admin.css" />
-
        <div class="navbar">
                  <t:a t:href="$user-admin">List Users</t:a>
                | <t:a t:href="$user-admin/new">Add User</t:a>
@@ -12,9 +10,7 @@
                        | <t:a t:href="$login/edit-profile" t:flow="begin">Edit Profile</t:a>
                </t:if>
 
-               <t:form t:action="$login/logout" t:flow="begin" class="inline">
-                       | <button type="submit" class="link-button link">Logout</button>
-               </t:form>
+               | <t:button t:action="$login/logout" t:flow="begin" class="link-button link">Logout</t:button>
        </div>
 
        <h1><t:write-title /></h1>
index b8c235532b691d92a9cbe29f0a63102a95276baf..9c0fe702bbcd6cd66ec408eb74ffa970bcfcd645 100644 (file)
@@ -4,9 +4,7 @@
 
        <t:title>Edit User</t:title>
 
-       <t:form t:action="$user-admin/edit">
-
-       <t:edit t:component="username" />
+       <t:form t:action="$user-admin/edit" t:for="username">
 
        <table>
        
        
        <p>
                <button type="submit" class="link-button link">Update</button>
-
-               <t:if t:var="http.server.auth.login:password-mismatch?">
-                       <t:error>passwords do not match</t:error>
-               </t:if>
+               <t:validation-message />
        </p>
 
        </t:form>
 
-       <t:form t:action="$user-admin/delete">
-               <t:edit t:component="username" />
-
-               <button type="submit" class="link-button link">Delete</button>
-       </t:form>
+       <t:button t:action="$user-admin/delete" t:for="username" class="link-button link">Delete</t:button>
 </t:chloe>
index 072e0c95bdbb7f5a55625c7a628002983a50b32c..2d67639985699de19df902a26be8557b7ef45c64 100644 (file)
        
        <p>
                <button type="submit" class="link-button link">Create</button>
-
-               <t:if t:var="http.server.auth.login:user-exists?">
-                               <t:error>username taken</t:error>
-               </t:if>
-
-               <t:if t:var="http.server.auth.login:password-mismatch?">
-                       <t:error>passwords do not match</t:error>
-               </t:if>
+               <t:validation-message />
        </p>
 
        </t:form>
index 107dbba2b891cd4651d98295614848e8a4ee32b7..1eaf65fa07e09d52519edf9b3457525f717db1c7 100644 (file)
 
        <p>
                <input type="submit" value="Update" />
-
-               <t:if t:var="http.server.auth.login:login-failed?">
-                       <t:error>invalid password</t:error>
-               </t:if>
-               
-               <t:if t:var="http.server.auth.login:password-mismatch?">
-                       <t:error>passwords do not match</t:error>
-               </t:if>
+               <t:validation-message />
        </p>
 
        </t:form>
index 28486f33624b1cd915ff02d1e0b412771fb0a44d..9f1fe6fe77b842d0e1311872989bd11a07988888 100755 (executable)
@@ -30,8 +30,6 @@ http.server.validators ;
 IN: http.server.auth.login\r
 QUALIFIED: smtp\r
 \r
-SYMBOL: login-failed?\r
-\r
 TUPLE: login < dispatcher users checksum ;\r
 \r
 : users ( -- provider )\r
@@ -82,6 +80,8 @@ M: user-saver dispose
     username>> set-uid\r
     "$login" end-flow ;\r
 \r
+: login-failed "invalid username or password" validation-failed-with ;\r
+\r
 :: <login-action> ( -- action )\r
     [let | form [ <login-form> ] |\r
         <action>\r
@@ -94,12 +94,8 @@ M: user-saver dispose
 \r
                 form validate-form\r
 \r
-                "password" value "username" value check-login [\r
-                    successful-login\r
-                ] [\r
-                    login-failed? on\r
-                    validation-failed\r
-                ] if*\r
+                "password" value "username" value check-login\r
+                [ successful-login ] [ login-failed ] if*\r
             ] >>submit\r
     ] ;\r
 \r
@@ -121,14 +117,13 @@ M: user-saver dispose
         "email" <email> add-field\r
         "captcha" <captcha> add-field ;\r
 \r
-SYMBOL: password-mismatch?\r
-SYMBOL: user-exists?\r
+: password-mismatch "passwords do not match" validation-failed-with ;\r
+\r
+: user-exists "username taken" validation-failed-with ;\r
 \r
 : same-password-twice ( -- )\r
-    "new-password" value "verify-password" value = [ \r
-        password-mismatch? on\r
-        validation-failed\r
-    ] unless ;\r
+    "new-password" value "verify-password" value =\r
+    [ password-mismatch ] unless ;\r
 \r
 :: <register-action> ( -- action )\r
     [let | form [ <register-form> ] |\r
@@ -150,10 +145,7 @@ SYMBOL: user-exists?
                     "email" value >>email\r
                     H{ } clone >>profile\r
 \r
-                users new-user [\r
-                    user-exists? on\r
-                    validation-failed\r
-                ] unless*\r
+                users new-user [ user-exists ] unless*\r
 \r
                 successful-login\r
 \r
@@ -201,7 +193,7 @@ SYMBOL: user-exists?
                     same-password-twice\r
 \r
                     "password" value uid check-login\r
-                    [ login-failed? on validation-failed ] unless\r
+                    [ login-failed ] unless\r
 \r
                     "new-password" value >>encoded-password\r
                 ] unless\r
index 0524d0889fdc04ca1debf4d99ce607f5ae34bc79..d0a73a4d8b07046b19660899ffbb36f41f70a93a 100644 (file)
                <p>
 
                        <input type="submit" value="Log in" />
+                       <t:validation-message />
 
-                       <t:if t:var="http.server.auth.login:login-failed?">
-                               <t:error>invalid username or password</t:error>
-                       </t:if>
                </p>
 
        </t:form>
index 61ef0aef869229ec7f9cd0bb3a1b80144a051b29..6c60b257a890bdd5fd80a677c8c8d9487435bb9c 100644 (file)
 
                <p>
                        <input type="submit" value="Set password" />
-
-                       <t:if t:var="http.server.auth.login:password-mismatch?">
-                               <t:error>passwords do not match</t:error>
-                       </t:if>
+                       <t:validation-message />
                </p>
 
        </t:form>
index 19917002b5d621e72b1dd5706f165881ddd69cb1..9b45a7f0876d70a7bc66286886adb903c2c71213 100644 (file)
                <p>
 
                        <input type="submit" value="Register" />
-
-                       <t:if t:var="http.server.auth.login:user-exists?">
-                               <t:error>username taken</t:error>
-                       </t:if>
-
-                       <t:if t:var="http.server.auth.login:password-mismatch?">
-                               <t:error>passwords do not match</t:error>
-                       </t:if>
+                       <t:validation-message />
 
                </p>
 
index 8bf07700e81d690467d1f0d28221decc8401b1bf..19fc8c5ca87475f62135abd176773d980ce3efce 100644 (file)
@@ -1,7 +1,7 @@
 ! Copyright (C) 2008 Slava Pestov
 ! See http://factorcode.org/license.txt for BSD license.
 USING: splitting kernel io sequences xmode.code2html accessors
-http.server.components xml.entities ;
+http.server.components html xml.entities ;
 IN: http.server.components.code
 
 TUPLE: code-renderer < text-renderer mode ;
@@ -11,7 +11,9 @@ TUPLE: code-renderer < text-renderer mode ;
         swap >>mode ;
 
 M: code-renderer render-view*
-    [ string-lines ] [ mode>> value ] bi* htmlize-lines ;
+    [
+        [ string-lines ] [ mode>> value ] bi* htmlize-lines
+    ] with-html-stream ;
 
 : <code> ( id mode -- component )
     swap <text>
index c0bac1fb99bd626ec4597b4c00b64b4ada428fbd..7f2a5a9ce182928699e78cfae99324b91394b1d5 100755 (executable)
@@ -3,7 +3,7 @@
 USING: accessors namespaces kernel io math.parser assocs classes
 words classes.tuple arrays sequences splitting mirrors
 hashtables fry locals combinators continuations math
-calendar.format html.elements xml.entities
+calendar.format html html.elements xml.entities
 http.server.validators ;
 IN: http.server.components
 
@@ -24,9 +24,6 @@ M: field render-view*
 M: field render-edit*
     <input type>> =type =name =value input/> ;
 
-: render-error ( message -- )
-    <span "error" =class span> escape-string write </span> ;
-
 TUPLE: hidden < field ;
 
 : hidden ( -- renderer ) T{ hidden f "hidden" } ; inline
index a8a456cdb2472d2ec38d501a9876447a97942f96..c3d93f59099a202ea9f188fb48e39ef95fe87d4d 100644 (file)
@@ -1,10 +1,14 @@
+! Copyright (C) 2008 Slava Pestov.
+! See http://factorcode.org/license.txt for BSD license.
 USING: accessors kernel sequences combinators kernel namespaces
 classes.tuple assocs splitting words arrays memoize
-io io.files io.encodings.utf8 html.elements unicode.case
-tuple-syntax xml xml.data xml.writer xml.utilities
+io io.files io.encodings.utf8 io.streams.string
+unicode.case tuple-syntax html html.elements
+multiline xml xml.data xml.writer xml.utilities
 http.server
 http.server.auth
 http.server.flows
+http.server.actions
 http.server.components
 http.server.sessions
 http.server.templating
@@ -21,7 +25,10 @@ DEFER: process-template
 
 : chloe-ns "http://factorcode.org/chloe/1.0" ; inline
 
-: filter-chloe-attrs ( assoc -- assoc' )
+: chloe-attrs-only ( assoc -- assoc' )
+    [ drop name-url chloe-ns = ] assoc-filter ;
+
+: non-chloe-attrs-only ( assoc -- assoc' )
     [ drop name-url chloe-ns = not ] assoc-filter ;
 
 : chloe-tag? ( tag -- ? )
@@ -45,6 +52,12 @@ MEMO: chloe-name ( string -- name )
 : optional-attr ( tag name -- value )
     chloe-name swap at ;
 
+: children>string ( tag -- string )
+    [ [ process-template ] each ] with-string-writer ;
+
+: title-tag ( tag -- )
+    children>string set-title ;
+
 : write-title-tag ( tag -- )
     drop
     "head" tags get member? "title" tags get member? not and
@@ -131,16 +144,20 @@ MEMO: chloe-name ( string -- name )
 
 : form-start-tag ( tag -- )
     [
-        <form
-        "POST" =method
-        {
-            [ flow-attr ]
-            [ session-attr ]
-            [ "action" required-attr resolve-base-path =action ]
-            [ tag-attrs filter-chloe-attrs print-attrs ]
-        } cleave
-        form>
-        hidden-form-field
+        [
+            <form
+            "POST" =method
+            {
+                [ flow-attr ]
+                [ session-attr ]
+                [ "action" required-attr resolve-base-path =action ]
+                [ tag-attrs non-chloe-attrs-only print-attrs ]
+            } cleave
+            form>
+        ] [
+            hidden-form-field
+            "for" optional-attr [ component render-edit ] when*
+        ] bi
     ] with-scope ;
 
 : form-tag ( tag -- )
@@ -149,6 +166,26 @@ MEMO: chloe-name ( string -- name )
     [ drop </form> ]
     tri ;
 
+DEFER: process-chloe-tag
+
+STRING: button-tag-markup
+<t:form class="inline" xmlns:t="http://factorcode.org/chloe/1.0">
+    <button type="submit"></button>
+</t:form>
+;
+
+: add-tag-attrs ( attrs tag -- )
+    tag-attrs swap update ;
+
+: button-tag ( tag -- )
+    button-tag-markup string>xml delegate
+    {
+        [ >r tag-attrs chloe-attrs-only r> add-tag-attrs ]
+        [ >r tag-attrs non-chloe-attrs-only r> "button" tag-named add-tag-attrs ]
+        [ >r children>string 1array r> "button" tag-named set-tag-children ]
+        [ nip ]
+    } 2cleave process-chloe-tag ;
+
 : attr>word ( value -- word/f )
     dup ":" split1 swap lookup
     [ ] [ "No such word: " swap append throw ] ?if ;
@@ -159,23 +196,25 @@ MEMO: chloe-name ( string -- name )
     ] unless ;
 
 : if-satisfied? ( tag -- ? )
+    t swap
     {
-        [ "code" optional-attr [ attr>word execute ] [ t ] if* ]
-        [  "var" optional-attr [ attr>var      get ] [ t ] if* ]
-        [ "svar" optional-attr [ attr>var     sget ] [ t ] if* ]
-        [ "uvar" optional-attr [ attr>var     uget ] [ t ] if* ]
-    } cleave 4array [ ] all? ;
+        [ "code"  optional-attr [ attr>word execute and ] when* ]
+        [  "var"  optional-attr [ attr>var      get and ] when* ]
+        [ "svar"  optional-attr [ attr>var     sget and ] when* ]
+        [ "uvar"  optional-attr [ attr>var     uget and ] when* ]
+        [ "value" optional-attr [ value             and ] when* ]
+    } cleave ;
 
 : if-tag ( tag -- )
     dup if-satisfied? [ process-tag-children ] [ drop ] if ;
 
-: error-tag ( tag -- )
+: error-message-tag ( tag -- )
     children>string render-error ;
 
 : process-chloe-tag ( tag -- )
     dup name-tag {
         { "chloe" [ [ process-template ] each ] }
-        { "title" [ children>string set-title ] }
+        { "title" [ title-tag ] }
         { "write-title" [ write-title-tag ] }
         { "style" [ style-tag ] }
         { "write-style" [ write-style-tag ] }
@@ -186,7 +225,9 @@ MEMO: chloe-name ( string -- name )
         { "summary" [ summary-tag ] }
         { "a" [ a-tag ] }
         { "form" [ form-tag ] }
-        { "error" [ error-tag ] }
+        { "button" [ button-tag ] }
+        { "error-message" [ error-message-tag ] }
+        { "validation-message" [ drop render-validation-message ] }
         { "if" [ if-tag ] }
         { "comment" [ drop ] }
         { "call-next-template" [ drop call-next-template ] }
diff --git a/extra/monads/authors.txt b/extra/monads/authors.txt
new file mode 100644 (file)
index 0000000..1901f27
--- /dev/null
@@ -0,0 +1 @@
+Slava Pestov
diff --git a/extra/monads/monads-tests.factor b/extra/monads/monads-tests.factor
new file mode 100644 (file)
index 0000000..52cdc47
--- /dev/null
@@ -0,0 +1,128 @@
+USING: tools.test monads math kernel sequences lazy-lists promises ;
+IN: monads.tests
+
+[ 5 ] [ 1 identity-monad return [ 4 + ] fmap run-identity ] unit-test
+[ "OH HAI" identity-monad fail ] must-fail
+
+[ 666 ] [
+    111 just [ 6 * ] fmap [ ] [ "OOPS" throw ] if-maybe
+] unit-test
+
+[ nothing ] [
+    111 just [ maybe-monad fail ] bind
+] unit-test
+
+[ 100 ] [
+    5 either-monad return [ 10 * ] [ 20 * ] if-either
+] unit-test
+
+[ T{ left f "OOPS" } ] [
+    5 either-monad return >>= [ drop "OOPS" either-monad fail ] swap call
+] unit-test
+
+[ { 10 20 30 } ] [
+    { 1 2 3 } [ 10 * ] fmap
+] unit-test
+
+[ { } ] [
+    { 1 2 3 } [ drop "OOPS" array-monad fail ] bind
+] unit-test
+
+[ 5 ] [
+    5 state-monad return "initial state" run-st
+] unit-test
+
+[ 8 ] [
+    5 state-monad return [ 3 + state-monad return ] bind
+    "initial state" run-st
+] unit-test
+
+[ 8 ] [
+    5 state-monad return >>=
+    [ 3 + state-monad return ] swap call
+    "initial state" run-st
+] unit-test
+
+[ 11 ] [
+    f state-monad return >>=
+    [ drop get-st ] swap call
+    11 run-st
+] unit-test
+
+[ 15 ] [
+    f state-monad return
+    [ drop get-st ] bind
+    [ 4 + put-st ] bind
+    [ drop get-st ] bind
+    11 run-st
+] unit-test
+
+[ 15 ] [
+    {
+        [ f return-st ]
+        [ drop get-st ]
+        [ 4 + put-st ]
+        [ drop get-st ]
+    } do
+    11 run-st
+] unit-test
+
+[ nothing ] [
+    {
+        [ "hi" just ]
+        [ " bye" append just ]
+        [ drop nothing ]
+        [ reverse just ]
+    } do
+] unit-test
+
+LAZY: nats-from ( n -- list )
+    dup 1+ nats-from cons ;
+
+: nats 0 nats-from ;
+
+[ 3 ] [
+    {
+        [ nats ]
+        [ dup 3 = [ list-monad return ] [ list-monad fail ] if ]
+    } do car
+] unit-test
+
+[ 9/11 ] [
+    {
+        [ ask ]
+    } do 9/11 run-reader
+] unit-test
+
+[ 8 ] [
+    {
+        [ ask ]
+        [ 3 + reader-monad return ]
+    } do
+    5 run-reader
+] unit-test
+
+[ 6 ] [
+    f reader-monad return [ drop ask ] bind [ 1 + ] local 5 run-reader
+] unit-test
+
+[ f { 1 2 3 } ] [
+    5 writer-monad return
+    [ drop { 1 2 3 } tell ] bind
+    run-writer
+] unit-test
+
+[ T{ identity f 7 } ]
+[
+    4 identity-monad return
+    [ 3 + ] identity-monad return
+    identity-monad apply
+] unit-test
+
+[ nothing ] [
+    5 just nothing maybe-monad apply
+] unit-test
+
+[ T{ just f 15 } ] [
+    5 just [ 10 + ] just maybe-monad apply
+] unit-test
diff --git a/extra/monads/monads.factor b/extra/monads/monads.factor
new file mode 100644 (file)
index 0000000..0f4138c
--- /dev/null
@@ -0,0 +1,192 @@
+! Copyright (C) 2008 Slava Pestov
+! See http://factorcode.org/license.txt for BSD license.
+USING: arrays kernel sequences sequences.deep splitting
+accessors fry locals combinators namespaces lazy-lists
+shuffle ;
+IN: monads
+
+! Functors
+GENERIC# fmap 1 ( functor quot -- functor' ) inline
+
+! Monads
+
+! Mixin type for monad singleton classes, used for return/fail only
+MIXIN: monad
+
+GENERIC: monad-of ( mvalue -- singleton )
+GENERIC: return ( string singleton -- mvalue )
+GENERIC: fail ( value singleton -- mvalue )
+GENERIC: >>= ( mvalue -- quot )
+
+M: monad return monad-of return ;
+M: monad fail   monad-of fail   ;
+
+: bind ( mvalue quot -- mvalue' ) swap >>= call ;
+: >>   ( mvalue k -- mvalue' ) '[ drop , ] bind ;
+
+:: lift-m2 ( m1 m2 f monad -- m3 )
+    m1 [| x1 | m2 [| x2 | x1 x2 f monad return ] bind ] bind ;
+
+:: apply ( mvalue mquot monad -- result )
+    mvalue [| value |
+        mquot [| quot |
+            value quot call monad return
+        ] bind
+    ] bind ;
+
+M: monad fmap over '[ @ , return ] bind ;
+
+! 'do' notation
+: do ( quots -- result ) unclip dip [ bind ] each ;
+
+! Identity
+SINGLETON: identity-monad
+INSTANCE:  identity-monad monad
+
+TUPLE: identity value ;
+INSTANCE: identity monad
+
+M: identity monad-of drop identity-monad ;
+
+M: identity-monad return drop identity boa ;
+M: identity-monad fail   "Fail" throw ;
+
+M: identity >>= value>> '[ , _ call ] ;
+
+: run-identity ( identity -- value ) value>> ;
+
+! Maybe
+SINGLETON: maybe-monad
+INSTANCE:  maybe-monad monad
+
+SINGLETON: nothing
+
+TUPLE: just value ;
+: just \ just boa ;
+
+UNION: maybe just nothing ;
+INSTANCE: maybe monad
+
+M: maybe monad-of drop maybe-monad ;
+
+M: maybe-monad return drop just ;
+M: maybe-monad fail   2drop nothing ;
+
+M: nothing >>= '[ drop , ] ;
+M: just    >>= value>> '[ , _ call ] ;
+
+: if-maybe ( maybe just-quot nothing-quot -- )
+    pick nothing? [ 2nip call ] [ drop [ value>> ] dip call ] if ; inline
+
+! Either
+SINGLETON: either-monad
+INSTANCE:  either-monad monad
+
+TUPLE: left value ;
+: left \ left boa ;
+
+TUPLE: right value ;
+: right \ right boa ;
+
+UNION: either left right ;
+INSTANCE: either monad
+
+M: either monad-of drop either-monad ;
+
+M: either-monad return  drop right ;
+M: either-monad fail    drop left ;
+
+M: left  >>= '[ drop , ] ;
+M: right >>= value>> '[ , _ call ] ;
+
+: if-either ( value left-quot right-quot -- )
+    [ [ value>> ] [ left? ] bi ] 2dip if ; inline
+
+! Arrays
+SINGLETON: array-monad
+INSTANCE:  array-monad monad
+INSTANCE:  array monad
+
+M: array-monad return  drop 1array ;
+M: array-monad fail   2drop { } ;
+
+M: array monad-of drop array-monad ;
+
+M: array >>= '[ , _ map concat ] ;
+
+! List
+SINGLETON: list-monad
+INSTANCE:  list-monad monad
+INSTANCE:  list monad
+
+M: list-monad return drop 1list ;
+M: list-monad fail   2drop nil ;
+
+M: list monad-of drop list-monad ;
+
+M: list >>= '[ , _ lmap lconcat ] ;
+
+! State
+SINGLETON: state-monad
+INSTANCE:  state-monad monad
+
+TUPLE: state quot ;
+: state \ state boa ;
+
+INSTANCE: state monad
+
+M: state monad-of drop state-monad ;
+
+M: state-monad return drop '[ , 2array ] state ;
+M: state-monad fail   "Fail" throw ;
+
+: mcall quot>> call ;
+
+M: state >>= '[ , _ '[ , mcall first2 @ mcall ] state ] ;
+
+: get-st ( -- state ) [ dup 2array ] state ;
+: put-st ( value -- state ) '[ drop , f 2array ] state ;
+
+: run-st ( state initial -- ) swap mcall second ;
+
+: return-st state-monad return ;
+
+! Reader
+SINGLETON: reader-monad
+INSTANCE:  reader-monad monad
+
+TUPLE: reader quot ;
+: reader \ reader boa ;
+INSTANCE: reader monad
+
+M: reader monad-of drop reader-monad ;
+
+M: reader-monad return drop '[ drop , ] reader ;
+M: reader-monad fail   "Fail" throw ;
+
+M: reader >>= '[ , _ '[ dup , mcall @ mcall ] reader ] ;
+
+: run-reader ( reader env -- ) swap mcall ;
+
+: ask ( -- reader ) [ ] reader ;
+: local ( reader quot -- reader' ) swap '[ @ , mcall ] reader ;
+
+! Writer
+SINGLETON: writer-monad
+INSTANCE:  writer-monad monad
+
+TUPLE: writer value log ;
+: writer \ writer boa ;
+
+M: writer monad-of drop writer-monad ;
+
+M: writer-monad return drop { } writer ;
+M: writer-monad fail   "Fail" throw ;
+
+: run-writer ( writer -- value log ) [ value>> ] [ log>> ] bi ;
+
+M: writer >>= '[ , run-writer _ '[ @ run-writer ] dip append writer ] ;
+
+: pass ( writer -- writer' ) run-writer [ first2 ] dip swap call writer ;
+: listen ( writer -- writer' ) run-writer [ 2array ] keep writer ;
+: tell ( seq -- writer ) f swap writer ;
diff --git a/extra/monads/summary.txt b/extra/monads/summary.txt
new file mode 100644 (file)
index 0000000..359722c
--- /dev/null
@@ -0,0 +1 @@
+Haskell-style monads
diff --git a/extra/monads/tags.txt b/extra/monads/tags.txt
new file mode 100644 (file)
index 0000000..f427429
--- /dev/null
@@ -0,0 +1 @@
+extensions
index 33587bb7fafa40f2a4833f2ddf0e9dbc2af6d852..89522d1f76b685fefe88f0c8f1baee3458a4ff80 100644 (file)
@@ -5,6 +5,8 @@ USING: kernel sequences namespaces math inference.transforms
 
 IN: shuffle
 
+: 2dip -rot 2slip ; inline
+
 MACRO: npick ( n -- ) 1- dup saver [ dup ] rot [ r> swap ] n*quot 3append ;
 
 MACRO: ndup ( n -- ) dup [ npick ] curry n*quot ;
index 1ad9957cc97bd27457c680c88c63aded0e649622..d507357590f0d0b20a00f26b9a6ea59472162e98 100755 (executable)
@@ -145,7 +145,6 @@ IN: tools.deploy.shaker
                 classes:class-not-cache
                 classes:class-or-cache
                 classes:class<=-cache
-                classes:class<=>-cache
                 classes:classes-intersect-cache
                 classes:update-map
                 command-line:main-vocab-hook
index 9846e7b20ce4e583386e853f37e109e621cd34f0..55721d7bef3c696f19d03b0c209e05d9b24aa77d 100644 (file)
@@ -43,6 +43,13 @@ a:hover, .link:hover {
        border: 1px dashed #ccc;
        background-color: #f5f5f5;
        padding: 5px;
-       font-size: 150%;
-       color: #000000;
+       color: #000;
+}
+
+.description p:first-child {
+       margin-top: 0px;
+}
+
+.description p:last-child {
+       margin-bottom: 0px;
 }
index e5a95d8908c4fbdebc7a993106f28abd79c7580b..d5b4ea8d3a0059c7f924dcdaaa8dfbb59cfb4874 100644 (file)
                <tr><th class="field-label">Date:    </th><td><t:view t:component="date"    /></td></tr>
        </table>
 
-       <div class="description">
-               <t:view t:component="contents" />
-       </div>
+       <pre class="description"><t:view t:component="contents" /></pre>
 
-       <t:form t:action="$pastebin/delete-annotation" class="inline">
-               <t:edit t:component="id" />
-               <t:edit t:component="aid" />
-               <button class="link-button link">Delete Annotation</button>
-       </t:form>
+       <t:button t:action="$pastebin/delete-annotation" t:for="aid" class="link-button link">Delete Annotation</t:button>
 
 </t:chloe>
index ad7152d20995736603151c0fe93b5f79b92cb87b..5d18860977fdcf84393da908964ca536129b1af7 100644 (file)
@@ -4,8 +4,7 @@
 
        <t:title>New Annotation</t:title>
 
-       <t:form t:action="$pastebin/annotate">
-               <t:edit t:component="id" />
+       <t:form t:action="$pastebin/annotate" t:for="id">
 
                <table>
                        <tr><th class="field-label">Summary: </th><td><t:edit t:component="summary" /></td></tr>
index eca46e254d714007eb64e26b28cab04398b05fcd..c751b110c09570f788662b5a78705812d5351b5d 100644 (file)
@@ -3,7 +3,7 @@
 <t:chloe xmlns:t="http://factorcode.org/chloe/1.0">
 
        <tr>
-               <td><t:a t:href="view-paste" query="id"><t:view t:component="summary" /></t:a></td>
+               <td><t:a t:href="$pastebin/view-paste" t:query="id"><t:view t:component="summary" /></t:a></td>
                <td><t:view t:component="author" /></td>
                <td><t:view t:component="date" /></td>
        </tr>
index 9db60bfcc321f22e21f771651cf3f3acd632173e..9141ee4ef1b8d3ba338792bf92fd75d565919a09 100644 (file)
@@ -2,9 +2,7 @@
 
 <t:chloe xmlns:t="http://factorcode.org/chloe/1.0">
 
-       <t:title>Pastebin</t:title>
-
-       <h2>Paste: <t:view t:component="summary" /></h2>
+       <t:title>Paste: <t:view t:component="summary" /></t:title>
 
        <table>
                <tr><th class="field-label">Author:  </th><td><t:view t:component="author"  /></td></tr>
 
        <pre class="description"><t:view t:component="contents" /></pre>
 
-       <t:form t:action="$pastebin/delete-paste" class="inline">
-               <t:edit t:component="id" />
-               <button class="link-button link">Delete Paste</button>
-       </t:form>
+       <t:button t:action="$pastebin/delete-paste" t:for="id" class="link-button link">Delete Paste</t:button>
        |
        <t:a t:href="$pastebin/annotate" t:query="id">Annotate</t:a>
 
index 144900d6ec8f392a25c1c6c25525f0962ad7e4b8..a18eb8147cedf6f086bd03eea47d373a8648457a 100644 (file)
@@ -207,12 +207,11 @@ annotation "ANNOTATION"
 
 :: <delete-annotation-action> ( ctor next -- action )
     <action>
-        { { "id" [ v-number ] } { "aid" [ v-number ] } } >>post-params
+        { { "aid" [ v-number ] } } >>post-params
 
         [
-            "id" get "aid" get ctor call delete-tuples
-
-            "id" get next <id-redirect>
+            f "aid" get ctor call select-tuple
+            [ delete-tuples ] [ id>> next <id-redirect> ] bi
         ] >>submit ;
 
 :: <new-paste-action> ( form ctor next -- action )
@@ -247,7 +246,7 @@ can-delete-pastes? define-capability
         <feed-action> "feed.xml" add-responder
         <paste-form> [ <paste> ] <view-paste-action> "view-paste" add-responder
         [ <paste> ] "$pastebin/list" <delete-paste-action> { can-delete-pastes? } <protected> "delete-paste" add-responder
-        [ <annotation> ] "$pastebin/view-paste" { can-delete-pastes? } <delete-annotation-action> <protected> "delete-annotation" add-responder
+        [ <annotation> ] "$pastebin/view-paste" <delete-annotation-action> { can-delete-pastes? } <protected> "delete-annotation" add-responder
         <paste-form> [ <paste> ]    <view-paste-action>     "$pastebin/view-paste"   add-responder
         <new-paste-form> [ <paste> now >>date ] "$pastebin/view-paste" <new-paste-action>     "new-paste"    add-responder
         <new-annotation-form> [ <annotation> now >>date ] "$pastebin/view-paste" <annotate-action> "annotate" add-responder
index 461a7be384b56058bcd532cfd36f1f811df1e554..7ca4c95f8e518b257fe85e5da8f3cb10d2c03b66 100644 (file)
                | <t:a t:href="$pastebin/new-paste">New Paste</t:a>
                | <t:a t:href="$pastebin/feed.xml">Atom Feed</t:a>
 
-               <t:if t:var="http.server.auth:logged-in-user">
+               <t:if t:code="http.server.sessions:uid">
 
                        <t:if t:code="http.server.auth.login:allow-edit-profile?">
                                | <t:a t:href="$login/edit-profile" t:flow="begin">Edit Profile</t:a>
                        </t:if>
 
-                       <t:form t:action="$login/logout" t:flow="begin" class="inline">
-                               | <button type="submit" class="link-button link">Logout</button>
-                       </t:form>
+                       | <t:button t:action="$login/logout" t:flow="begin" class="link-button link">Logout</t:button>
 
                </t:if>
 
index b2eab2b0b48d1565f3a6f01ba21395e712760252..ebfccc47de901e7584073f97c2ab309c04b012f9 100644 (file)
@@ -4,9 +4,7 @@
 
        <t:title>Edit Blog</t:title>
 
-       <t:form t:action="$planet-factor/admin/edit-blog">
-
-               <t:edit t:component="id" />
+       <t:form t:action="$planet-factor/admin/edit-blog" t:for="id">
 
                <table>
 
@@ -31,8 +29,5 @@
 
        </t:form>
 
-       <t:form t:action="$planet-factor/admin/delete-blog" class="inline">
-               <t:edit t:component="id" />
-               <button type="submit" class="link-button link">Delete</button>
-       </t:form>
+       <t:button t:action="$planet-factor/admin/delete-blog" t:for="id" class="link-button link">Delete</t:button>
 </t:chloe>
index 7f2b034366bb3ca9e51b8e70564dadb7b1bb09c4..29609e12ba6873829d1c980fe7c07399f2495bee 100644 (file)
@@ -9,14 +9,12 @@
                | <t:a t:href="$planet-factor/feed.xml">Atom Feed</t:a>
                | <t:a t:href="$planet-factor/admin">Admin</t:a>
 
-               <t:if t:var="http.server.auth:logged-in-user">
+               <t:if t:code="http.server.sessions:uid">
                        <t:if t:code="http.server.auth.login:allow-edit-profile?">
                                | <t:a t:href="$login/edit-profile" t:flow="begin">Edit Profile</t:a>
                        </t:if>
        
-                       <t:form t:action="$login/logout" t:flow="begin" class="inline">
-                               | <button type="submit" class="link-button link">Logout</button>
-                       </t:form>
+                       | <t:button t:action="$login/logout" t:flow="begin" class="link-button link">Logout</t:button>
                </t:if>
        </div>
 
index 9b7e9e667a0afe10100c000bff3d92607334e318..e1d4c40e236bb0a372f0c3aa98b8b4b601f4d7c1 100644 (file)
@@ -4,9 +4,7 @@
 
        <t:title>Edit Item</t:title>
 
-       <t:form t:action="$todo-list/edit">
-               <t:edit t:component="id" />
-
+       <t:form t:action="$todo-list/edit" t:for="id">
                <table>
                        <tr><th class="field-label">Summary: </th><td><t:edit t:component="summary" /></td></tr>
                        <tr><th class="field-label">Priority: </th><td><t:edit t:component="priority" /></td></tr>
                <input type="SUBMIT" value="Done" />
        </t:form>
 
-       <t:a t:href="$todo-list/view" t:query="id">View</t:a>
-       |
-       <t:form t:action="$todo-list/delete" t:class="inline">
-               <t:edit t:component="id" />
-               <button type="submit" class="link-button link">Delete</button>
-       </t:form>
+       <t:if t:value="id">
+       
+               <t:a t:href="$todo-list/view" t:query="id">View</t:a>
+               |
+               <t:button t:action="$todo-list/delete" t:for="id" class="link-button link">Delete</t:button>
+               
+       </t:if>
 
 </t:chloe>
index 3e6d3cfd44e5aaa5d9d2b8b0465f2825a4566141..651e29d867279af213a8d410d8c65cdc26cfb823 100644 (file)
@@ -12,9 +12,7 @@
                        | <t:a t:href="$login/edit-profile" t:flow="begin">Edit Profile</t:a>
                </t:if>
 
-               <t:form t:action="$login/logout" t:flow="begin" class="inline">
-                       | <button type="submit" class="link-button link">Logout</button>
-               </t:form>
+               <t:button t:action="$login/logout" t:flow="begin" class="link-button link">Logout</t:button>
        </div>
 
        <h1><t:write-title /></h1>
index 1bd73f48e1f0e271d6bfe663f0344af62d7def40..8c90ba9056bc7473164494ac81060d5649e76e60 100644 (file)
@@ -15,9 +15,6 @@
 
        <t:a t:href="$todo-list/edit" t:query="id">Edit</t:a>
        |
-       <t:form t:action="$todo-list/delete" class="inline">
-               <t:edit t:component="id" />
-               <button class="link-button link">Delete</button>
-       </t:form>
+       <t:button t:action="$todo-list/delete" t:for="id" class="link-button link">Delete</t:button>
 
 </t:chloe>
index 03394b933c04cb7da3b6aae31336b5b808e69179..1bf9a17aa6c26a7e0f83b9b0f33bb4a9a30a3dfa 100644 (file)
@@ -29,7 +29,7 @@
                        <key>begin</key>
                        <string>&lt;%\s</string>
                        <key>end</key>
-                       <string>\s%&gt;</string>
+                       <string>(?&lt;=\s)%&gt;</string>
                        <key>name</key>
                        <string>source.factor.embedded.html</string>
                        <key>patterns</key>