Merge branch 'master' of git://factorcode.org/git/factor
commit
fdf9e7dc98
Factor.app/Contents
core
bootstrap/image
math/order
optimizer/def-use
extra
bank
html
http
server
actions
components
templating/chloe
shuffle
tools/deploy/shaker
webapps
misc/Factor.tmbundle/Syntaxes
|
@ -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>
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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."
|
||||
{ "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." }
|
||||
}
|
||||
"These difficulties are resolved by imposing a linear order on classes, computed as follows for two classes A and B:"
|
||||
"The first ambiguity is resolved with a tie-breaker that compares metaclasses. The intrinsic meta-class order, from most-specific to least-specific:"
|
||||
{ $list
|
||||
"If A and B are the same class (not just equal as sets), then comparison stops."
|
||||
"If A is a proper subset of B, or B is a proper subset of A, then comparison stops."
|
||||
{ "Next, the metaclasses of A and B are compared, with intrinsic meta-class order, from most-specific to least-specific:"
|
||||
{ $list
|
||||
"Built-in classes and tuple classes"
|
||||
"Predicate classes"
|
||||
"Union classes"
|
||||
"Mixin classes"
|
||||
}
|
||||
"If this yields an unambiguous answer, comparison stops."
|
||||
}
|
||||
"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."
|
||||
"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."
|
||||
}
|
||||
"Some examples:"
|
||||
{ $list
|
||||
{ { $link integer } " precedes " { $link number } " because it is a strict subset" }
|
||||
{ { $link number } " precedes " { $link sequence } " because the " { $vocab-link "math" } " vocabulary precedes the " { $vocab-link "sequences" } " vocabulary" }
|
||||
{ { $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" }
|
||||
"Built-in classes and tuple classes"
|
||||
"Predicate classes"
|
||||
"Union classes"
|
||||
"Mixin classes"
|
||||
}
|
||||
"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."
|
||||
$nl
|
||||
"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."
|
||||
$nl
|
||||
"Operations:"
|
||||
{ $subsection class<=> }
|
||||
{ $subsection class< }
|
||||
{ $subsection sort-classes }
|
||||
"Metaclass order:"
|
||||
{ $subsection rank-class } ;
|
||||
|
@ -72,8 +61,6 @@ HELP: sort-classes
|
|||
{ $values { "seq" "a sequence of class" } { "newseq" "a new seqence of classes" } }
|
||||
{ $description "Outputs a linear sort of a sequence of classes. Larger classes come before their subclasses." } ;
|
||||
|
||||
{ sort-classes class<=> } related-words
|
||||
|
||||
HELP: class-or
|
||||
{ $values { "first" class } { "second" class } { "class" class } }
|
||||
{ $description "Outputs the smallest anonymous class containing both " { $snippet "class1" } " and " { $snippet "class2" } "." } ;
|
||||
|
@ -89,7 +76,3 @@ HELP: classes-intersect?
|
|||
HELP: min-class
|
||||
{ $values { "class" class } { "seq" "a sequence of class words" } { "class/f" "a class word or " { $link f } } }
|
||||
{ $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 } "." } ;
|
||||
|
||||
HELP: class<=>
|
||||
{ $values { "first" class } { "second" class } { "n" symbol } }
|
||||
{ $description "Compares two classes with the class linearization order." } ;
|
||||
|
|
|
@ -248,7 +248,16 @@ UNION: yyy xxx ;
|
|||
[ { yyy xxx } ] [ { xxx yyy } sort-classes ] unit-test
|
||||
[ { yyy xxx } ] [ { yyy xxx } sort-classes ] unit-test
|
||||
|
||||
[ { number integer ratio } ] [ { ratio number integer } sort-classes ] unit-test
|
||||
[ { number ratio integer } ] [ { ratio number integer } sort-classes ] unit-test
|
||||
[ { sequence number ratio } ] [ { ratio number sequence } sort-classes ] unit-test
|
||||
|
||||
[ +lt+ ] [ \ real sequence class<=> ] unit-test
|
||||
TUPLE: xa ;
|
||||
TUPLE: xb ;
|
||||
TUPLE: xc < xa ;
|
||||
TUPLE: xd < xb ;
|
||||
TUPLE: xe ;
|
||||
TUPLE: xf < xb ;
|
||||
TUPLE: xg < xb ;
|
||||
TUPLE: xh < xb ;
|
||||
|
||||
[ t ] [ { xa xb xc xd xe xf xg xh } sort-classes dup sort-classes = ] unit-test
|
||||
|
|
|
@ -187,31 +187,15 @@ C: <anonymous-complement> anonymous-complement
|
|||
[ [ rank-class ] bi@ < ]
|
||||
} cond ;
|
||||
|
||||
: class-tie-breaker ( first second -- n )
|
||||
2dup [ rank-class ] compare {
|
||||
{ +lt+ [ 2drop +lt+ ] }
|
||||
{ +gt+ [ 2drop +gt+ ] }
|
||||
{ +eq+ [ <=> ] }
|
||||
} case ;
|
||||
|
||||
: (class<=>) ( first second -- n )
|
||||
{
|
||||
{ [ 2dup class<= ] [
|
||||
2dup swap class<=
|
||||
[ class-tie-breaker ] [ 2drop +lt+ ] if
|
||||
] }
|
||||
{ [ 2dup swap class<= ] [
|
||||
2dup class<=
|
||||
[ class-tie-breaker ] [ 2drop +gt+ ] if
|
||||
] }
|
||||
[ class-tie-breaker ]
|
||||
} cond ;
|
||||
|
||||
: class<=> ( first second -- n )
|
||||
class<=>-cache get [ (class<=>) ] 2cache ;
|
||||
: largest-class ( seq -- n elt )
|
||||
dup [ [ class< ] with contains? not ] curry find-last
|
||||
[ "Topological sort failed" throw ] unless* ;
|
||||
|
||||
: sort-classes ( seq -- newseq )
|
||||
[ class<=> invert-comparison ] sort ;
|
||||
[ [ word-name ] compare ] sort >vector
|
||||
[ dup empty? not ]
|
||||
[ dup largest-class >r over delete-nth r> ]
|
||||
[ ] unfold nip ;
|
||||
|
||||
: min-class ( class seq -- class/f )
|
||||
over [ classes-intersect? ] curry filter
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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+" } } ;
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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 ;
|
||||
|
||||
|
|
|
@ -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> ;
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -2,13 +2,20 @@
|
|||
! See http://factorcode.org/license.txt for BSD license.
|
||||
USING: accessors sequences kernel assocs combinators
|
||||
http.server http.server.validators http hashtables namespaces
|
||||
fry continuations locals ;
|
||||
fry continuations locals boxes xml.entities html.elements io ;
|
||||
IN: http.server.actions
|
||||
|
||||
SYMBOL: +path+
|
||||
|
||||
SYMBOL: params
|
||||
|
||||
SYMBOL: validation-message
|
||||
|
||||
: render-validation-message ( -- )
|
||||
validation-message get value>> [
|
||||
<span "error" =class span>
|
||||
escape-string write
|
||||
</span>
|
||||
] when* ;
|
||||
|
||||
TUPLE: action init display submit get-params post-params ;
|
||||
|
||||
: <action>
|
||||
|
@ -37,11 +44,16 @@ TUPLE: action init display submit get-params post-params ;
|
|||
: validation-failed ( -- * )
|
||||
action get display>> call exit-with ;
|
||||
|
||||
: validation-failed-with ( string -- * )
|
||||
validation-message get >box
|
||||
validation-failed ;
|
||||
|
||||
M: action call-responder* ( path action -- response )
|
||||
'[
|
||||
, [ CHAR: / = ] right-trim empty? [
|
||||
, action set
|
||||
request get
|
||||
<box> validation-message set
|
||||
[ request-params params set ]
|
||||
[
|
||||
method>> {
|
||||
|
|
|
@ -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>
|
||||
|
|
|
@ -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>
|
||||
|
||||
|
@ -49,17 +47,10 @@
|
|||
|
||||
<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>
|
||||
|
|
|
@ -42,14 +42,7 @@
|
|||
|
||||
<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>
|
||||
|
|
|
@ -62,14 +62,7 @@
|
|||
|
||||
<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>
|
||||
|
|
|
@ -30,8 +30,6 @@ http.server.validators ;
|
|||
IN: http.server.auth.login
|
||||
QUALIFIED: smtp
|
||||
|
||||
SYMBOL: login-failed?
|
||||
|
||||
TUPLE: login < dispatcher users checksum ;
|
||||
|
||||
: users ( -- provider )
|
||||
|
@ -82,6 +80,8 @@ M: user-saver dispose
|
|||
username>> set-uid
|
||||
"$login" end-flow ;
|
||||
|
||||
: login-failed "invalid username or password" validation-failed-with ;
|
||||
|
||||
:: <login-action> ( -- action )
|
||||
[let | form [ <login-form> ] |
|
||||
<action>
|
||||
|
@ -94,12 +94,8 @@ M: user-saver dispose
|
|||
|
||||
form validate-form
|
||||
|
||||
"password" value "username" value check-login [
|
||||
successful-login
|
||||
] [
|
||||
login-failed? on
|
||||
validation-failed
|
||||
] if*
|
||||
"password" value "username" value check-login
|
||||
[ successful-login ] [ login-failed ] if*
|
||||
] >>submit
|
||||
] ;
|
||||
|
||||
|
@ -121,14 +117,13 @@ M: user-saver dispose
|
|||
"email" <email> add-field
|
||||
"captcha" <captcha> add-field ;
|
||||
|
||||
SYMBOL: password-mismatch?
|
||||
SYMBOL: user-exists?
|
||||
: password-mismatch "passwords do not match" validation-failed-with ;
|
||||
|
||||
: user-exists "username taken" validation-failed-with ;
|
||||
|
||||
: same-password-twice ( -- )
|
||||
"new-password" value "verify-password" value = [
|
||||
password-mismatch? on
|
||||
validation-failed
|
||||
] unless ;
|
||||
"new-password" value "verify-password" value =
|
||||
[ password-mismatch ] unless ;
|
||||
|
||||
:: <register-action> ( -- action )
|
||||
[let | form [ <register-form> ] |
|
||||
|
@ -150,10 +145,7 @@ SYMBOL: user-exists?
|
|||
"email" value >>email
|
||||
H{ } clone >>profile
|
||||
|
||||
users new-user [
|
||||
user-exists? on
|
||||
validation-failed
|
||||
] unless*
|
||||
users new-user [ user-exists ] unless*
|
||||
|
||||
successful-login
|
||||
|
||||
|
@ -201,7 +193,7 @@ SYMBOL: user-exists?
|
|||
same-password-twice
|
||||
|
||||
"password" value uid check-login
|
||||
[ login-failed? on validation-failed ] unless
|
||||
[ login-failed ] unless
|
||||
|
||||
"new-password" value >>encoded-password
|
||||
] unless
|
||||
|
|
|
@ -23,10 +23,8 @@
|
|||
<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>
|
||||
|
|
|
@ -32,10 +32,7 @@
|
|||
|
||||
<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>
|
||||
|
|
|
@ -63,14 +63,7 @@
|
|||
<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>
|
||||
|
||||
|
|
|
@ -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>
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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 ] }
|
||||
|
|
|
@ -0,0 +1 @@
|
|||
Slava Pestov
|
|
@ -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
|
|
@ -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 ;
|
|
@ -0,0 +1 @@
|
|||
Haskell-style monads
|
|
@ -0,0 +1 @@
|
|||
extensions
|
|
@ -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 ;
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -10,14 +10,8 @@
|
|||
<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>
|
||||
|
|
|
@ -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>
|
||||
|
|
|
@ -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>
|
||||
|
|
|
@ -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>
|
||||
|
@ -14,10 +12,7 @@
|
|||
|
||||
<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>
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -11,15 +11,13 @@
|
|||
| <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>
|
||||
|
||||
|
|
|
@ -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>
|
||||
|
|
|
@ -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>
|
||||
|
||||
|
|
|
@ -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>
|
||||
|
@ -16,11 +14,12 @@
|
|||
<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>
|
||||
|
|
|
@ -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>
|
||||
|
|
|
@ -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>
|
||||
|
|
|
@ -29,7 +29,7 @@
|
|||
<key>begin</key>
|
||||
<string><%\s</string>
|
||||
<key>end</key>
|
||||
<string>\s%></string>
|
||||
<string>(?<=\s)%></string>
|
||||
<key>name</key>
|
||||
<string>source.factor.embedded.html</string>
|
||||
<key>patterns</key>
|
||||
|
|
Loading…
Reference in New Issue