commit
523ca2033b
|
@ -0,0 +1,2 @@
|
||||||
|
Slava Pestov
|
||||||
|
Doug Coleman
|
|
@ -28,7 +28,7 @@ TUPLE: test-tuple m n ;
|
||||||
[
|
[
|
||||||
H{
|
H{
|
||||||
{ "bar" "hello" }
|
{ "bar" "hello" }
|
||||||
} \ foo query>quot
|
} \ foo query>seq
|
||||||
] with-scope
|
] with-scope
|
||||||
] unit-test
|
] unit-test
|
||||||
|
|
||||||
|
|
|
@ -1,55 +1,39 @@
|
||||||
! Copyright (C) 2006 Slava Pestov
|
! Copyright (C) 2006 Slava Pestov, Doug Coleman
|
||||||
! See http://factorcode.org/license.txt for BSD license.
|
! See http://factorcode.org/license.txt for BSD license.
|
||||||
USING: kernel vectors io assocs quotations splitting strings
|
USING: arrays assocs debugger furnace.sessions furnace.validator
|
||||||
words sequences namespaces arrays hashtables debugger
|
hashtables html.elements http http.server.responders
|
||||||
continuations tuples classes io.files
|
http.server.templating
|
||||||
http http.server.templating http.basic-authentication
|
io.files kernel namespaces quotations sequences splitting words
|
||||||
webapps.callback html html.elements
|
strings vectors webapps.callback ;
|
||||||
http.server.responders furnace.validator vocabs ;
|
USING: continuations io prettyprint ;
|
||||||
IN: furnace
|
IN: furnace
|
||||||
|
|
||||||
SYMBOL: default-action
|
|
||||||
|
|
||||||
SYMBOL: template-path
|
|
||||||
|
|
||||||
: define-authenticated-action ( word params realm -- )
|
|
||||||
pick swap "action-realm" set-word-prop
|
|
||||||
over t "action" set-word-prop
|
|
||||||
"action-params" set-word-prop ;
|
|
||||||
|
|
||||||
: define-action ( word params -- )
|
|
||||||
f define-authenticated-action ;
|
|
||||||
|
|
||||||
: code>quotation ( word/quot -- quot )
|
: code>quotation ( word/quot -- quot )
|
||||||
dup word? [ 1quotation ] when ;
|
dup word? [ 1quotation ] when ;
|
||||||
|
|
||||||
: define-form ( formword actionword params -- )
|
SYMBOL: default-action
|
||||||
|
SYMBOL: template-path
|
||||||
|
|
||||||
|
: render-template ( template -- )
|
||||||
|
template-path get swap path+
|
||||||
|
".furnace" append resource-path
|
||||||
|
run-template-file ;
|
||||||
|
|
||||||
|
: define-action ( word hash -- )
|
||||||
|
over t "action" set-word-prop
|
||||||
|
"action-params" set-word-prop ;
|
||||||
|
|
||||||
|
: define-form ( word1 word2 hash -- )
|
||||||
dupd define-action
|
dupd define-action
|
||||||
swap code>quotation "form-quotation" set-word-prop ;
|
swap code>quotation "form-failed" set-word-prop ;
|
||||||
|
|
||||||
: define-redirect ( word quot -- )
|
: default-values ( word hash -- )
|
||||||
"action-redirect" set-word-prop ;
|
"default-values" set-word-prop ;
|
||||||
|
|
||||||
: responder-vocab ( name -- vocab )
|
SYMBOL: request-params
|
||||||
"webapps." swap append ;
|
SYMBOL: current-action
|
||||||
|
SYMBOL: validators-errored
|
||||||
: lookup-action ( name webapp -- word )
|
SYMBOL: validation-errors
|
||||||
responder-vocab lookup dup [
|
|
||||||
dup "action" word-prop [ drop f ] unless
|
|
||||||
] when ;
|
|
||||||
|
|
||||||
: truncate-url ( url -- action-name )
|
|
||||||
CHAR: / over index [ head ] when* ;
|
|
||||||
|
|
||||||
: current-action ( url -- word/f )
|
|
||||||
dup empty? [ drop default-action get ] when
|
|
||||||
truncate-url "responder" get lookup-action ;
|
|
||||||
|
|
||||||
PREDICATE: word action "action" word-prop ;
|
|
||||||
|
|
||||||
: quot>query ( seq action -- hash )
|
|
||||||
>r >array r> "action-params" word-prop
|
|
||||||
[ first swap 2array ] 2map >hashtable ;
|
|
||||||
|
|
||||||
: action-link ( query action -- url )
|
: action-link ( query action -- url )
|
||||||
[
|
[
|
||||||
|
@ -59,6 +43,34 @@ PREDICATE: word action "action" word-prop ;
|
||||||
word-name %
|
word-name %
|
||||||
] "" make swap build-url ;
|
] "" make swap build-url ;
|
||||||
|
|
||||||
|
: action-param ( hash paramsepc -- obj error/f )
|
||||||
|
unclip rot at swap >quotation apply-validators ;
|
||||||
|
|
||||||
|
: query>seq ( hash word -- seq )
|
||||||
|
"action-params" word-prop [
|
||||||
|
dup first -rot
|
||||||
|
action-param [
|
||||||
|
t validators-errored >session
|
||||||
|
rot validation-errors session> set-at
|
||||||
|
] [
|
||||||
|
nip
|
||||||
|
] if*
|
||||||
|
] curry* map ;
|
||||||
|
|
||||||
|
: lookup-session ( hash -- session )
|
||||||
|
"furnace-session-id" over at* [
|
||||||
|
sessions get-global at
|
||||||
|
[ nip ] [ "furnace-session-id" over delete-at lookup-session ] if*
|
||||||
|
] [
|
||||||
|
drop new-session rot "furnace-session-id" swap set-at
|
||||||
|
] if ;
|
||||||
|
|
||||||
|
: quot>query ( seq action -- hash )
|
||||||
|
>r >array r> "action-params" word-prop
|
||||||
|
[ first swap 2array ] 2map >hashtable ;
|
||||||
|
|
||||||
|
PREDICATE: word action "action" word-prop ;
|
||||||
|
|
||||||
: action-call? ( quot -- ? )
|
: action-call? ( quot -- ? )
|
||||||
>vector dup pop action? >r [ word? not ] all? r> and ;
|
>vector dup pop action? >r [ word? not ] all? r> and ;
|
||||||
|
|
||||||
|
@ -71,62 +83,94 @@ PREDICATE: word action "action" word-prop ;
|
||||||
t register-html-callback
|
t register-html-callback
|
||||||
] if ;
|
] if ;
|
||||||
|
|
||||||
: render-link ( quot name -- )
|
: replace-variables ( quot -- quot )
|
||||||
<a swap quot-link =href a> write </a> ;
|
[ dup string? [ request-params session> at ] when ] map ;
|
||||||
|
|
||||||
: action-param ( params paramspec -- obj error/f )
|
: furnace-session-id ( -- hash )
|
||||||
unclip rot at swap >quotation apply-validators ;
|
"furnace-session-id" request-params session> at
|
||||||
|
"furnace-session-id" associate ;
|
||||||
|
|
||||||
: query>quot ( params action -- seq )
|
: redirect-to-action ( -- )
|
||||||
"action-params" word-prop [ action-param drop ] curry* map ;
|
current-action session>
|
||||||
|
"form-failed" word-prop replace-variables
|
||||||
|
quot-link furnace-session-id build-url permanent-redirect ;
|
||||||
|
|
||||||
SYMBOL: request-params
|
: if-form-page ( if then -- )
|
||||||
|
current-action session> "form-failed" word-prop -rot if ;
|
||||||
|
|
||||||
: perform-redirect ( action -- )
|
: do-action
|
||||||
"action-redirect" word-prop
|
current-action session> [ query>seq ] keep add >quotation call ;
|
||||||
[ dup string? [ request-params get at ] when ] map
|
|
||||||
[ quot-link permanent-redirect ] when* ;
|
|
||||||
|
|
||||||
: (call-action) ( params action -- )
|
: process-form ( -- )
|
||||||
over request-params set
|
H{ } clone validation-errors >session
|
||||||
[ query>quot ] keep [ add >quotation call ] keep
|
request-params session> current-action session> query>seq
|
||||||
perform-redirect ;
|
validators-errored session> [
|
||||||
|
drop redirect-to-action
|
||||||
|
] [
|
||||||
|
current-action session> add >quotation call
|
||||||
|
] if ;
|
||||||
|
|
||||||
: call-action ( params action -- )
|
: page-submitted ( -- )
|
||||||
dup "action-realm" word-prop [
|
[ process-form ] [ request-params session> do-action ] if-form-page ;
|
||||||
[ (call-action) ] with-basic-authentication
|
|
||||||
] [ (call-action) ] if* ;
|
|
||||||
|
|
||||||
: service-request ( params url -- )
|
: action-first-time ( -- )
|
||||||
current-action [
|
request-params session> current-action session>
|
||||||
|
[ "default-values" word-prop swap union request-params >session ] keep
|
||||||
|
request-params session> do-action ;
|
||||||
|
|
||||||
|
: page-not-submitted ( -- )
|
||||||
|
[ redirect-to-action ] [ action-first-time ] if-form-page ;
|
||||||
|
|
||||||
|
: setup-call-action ( hash word -- )
|
||||||
|
over lookup-session session set
|
||||||
|
current-action >session
|
||||||
|
request-params session> swap union
|
||||||
|
request-params >session
|
||||||
|
f validators-errored >session ;
|
||||||
|
|
||||||
|
: call-action ( hash word -- )
|
||||||
|
setup-call-action
|
||||||
|
"furnace-form-submitted" request-params session> at
|
||||||
|
[ page-submitted ] [ page-not-submitted ] if ;
|
||||||
|
|
||||||
|
: responder-vocab ( str -- newstr )
|
||||||
|
"webapps." swap append ;
|
||||||
|
|
||||||
|
: lookup-action ( str webapp -- word )
|
||||||
|
responder-vocab lookup dup [
|
||||||
|
dup "action" word-prop [ drop f ] unless
|
||||||
|
] when ;
|
||||||
|
|
||||||
|
: truncate-url ( str -- newstr )
|
||||||
|
CHAR: / over index [ head ] when* ;
|
||||||
|
|
||||||
|
: parse-action ( str -- word/f )
|
||||||
|
dup empty? [ drop default-action get ] when
|
||||||
|
truncate-url "responder" get lookup-action ;
|
||||||
|
|
||||||
|
: service-request ( hash str -- )
|
||||||
|
parse-action [
|
||||||
[ call-action ] [ <pre> print-error </pre> ] recover
|
[ call-action ] [ <pre> print-error </pre> ] recover
|
||||||
] [
|
] [
|
||||||
"404 no such action: " "argument" get append httpd-error
|
"404 no such action: " "argument" get append httpd-error
|
||||||
] if* ;
|
] if* ;
|
||||||
|
|
||||||
: service-get ( url -- ) "query" get swap service-request ;
|
: service-get
|
||||||
|
"query" get swap service-request ;
|
||||||
|
|
||||||
: service-post ( url -- ) "response" get swap service-request ;
|
: service-post
|
||||||
|
"response" get swap service-request ;
|
||||||
|
|
||||||
: send-resource ( name -- )
|
: web-app ( name defaul path -- )
|
||||||
template-path get swap path+ resource-path <file-reader>
|
|
||||||
stdio get stream-copy ;
|
|
||||||
|
|
||||||
: render-template ( template -- )
|
|
||||||
template-path get swap path+
|
|
||||||
".furnace" append resource-path
|
|
||||||
run-template-file ;
|
|
||||||
|
|
||||||
: web-app ( name default path -- )
|
|
||||||
[
|
[
|
||||||
template-path set
|
template-path set
|
||||||
default-action set
|
default-action set
|
||||||
"responder" set
|
"responder" set
|
||||||
[ service-get ] "get" set
|
[ service-get ] "get" set
|
||||||
[ service-post ] "post" set
|
[ service-post ] "post" set
|
||||||
! [ service-head ] "head" set
|
|
||||||
] make-responder ;
|
] make-responder ;
|
||||||
|
|
||||||
|
USING: classes html tuples vocabs ;
|
||||||
: explode-tuple ( tuple -- )
|
: explode-tuple ( tuple -- )
|
||||||
dup tuple-slots swap class "slot-names" word-prop
|
dup tuple-slots swap class "slot-names" word-prop
|
||||||
[ set ] 2each ;
|
[ set ] 2each ;
|
||||||
|
@ -145,3 +189,24 @@ SYMBOL: model
|
||||||
<a f >vocab-link browser-link-href =href a>
|
<a f >vocab-link browser-link-href =href a>
|
||||||
"Browse source" write
|
"Browse source" write
|
||||||
</a> ;
|
</a> ;
|
||||||
|
|
||||||
|
: send-resource ( name -- )
|
||||||
|
template-path get swap path+ resource-path <file-reader>
|
||||||
|
stdio get stream-copy ;
|
||||||
|
|
||||||
|
: render-link ( quot name -- )
|
||||||
|
<a swap quot-link =href a> write </a> ;
|
||||||
|
|
||||||
|
: session-var ( str -- newstr )
|
||||||
|
request-params session> at ;
|
||||||
|
|
||||||
|
: render ( str -- )
|
||||||
|
request-params session> at [ write ] when* ;
|
||||||
|
|
||||||
|
: render-error ( str error-str -- )
|
||||||
|
swap validation-errors session> at validation-error? [
|
||||||
|
write
|
||||||
|
] [
|
||||||
|
drop
|
||||||
|
] if ;
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,31 @@
|
||||||
|
USING: assocs calendar init kernel math.parser namespaces random ;
|
||||||
|
IN: furnace.sessions
|
||||||
|
|
||||||
|
SYMBOL: sessions
|
||||||
|
|
||||||
|
[ H{ } clone sessions set-global ] "furnace.sessions" add-init-hook
|
||||||
|
|
||||||
|
: new-session-id ( -- str )
|
||||||
|
1 big-random number>string ;
|
||||||
|
|
||||||
|
TUPLE: session created last-seen user-agent namespace ;
|
||||||
|
|
||||||
|
: <session> ( -- obj )
|
||||||
|
now dup H{ } clone
|
||||||
|
[ set-session-created set-session-last-seen set-session-namespace ]
|
||||||
|
\ session construct ;
|
||||||
|
|
||||||
|
: new-session ( -- obj id )
|
||||||
|
<session> new-session-id [ sessions get-global set-at ] 2keep ;
|
||||||
|
|
||||||
|
: get-session ( id -- obj/f )
|
||||||
|
sessions get-global at* [ "no session found 1" throw ] unless ;
|
||||||
|
|
||||||
|
: destroy-session ( id -- )
|
||||||
|
sessions get-global delete-at ;
|
||||||
|
|
||||||
|
: session> ( str -- obj )
|
||||||
|
session get session-namespace at ;
|
||||||
|
|
||||||
|
: >session ( value key -- )
|
||||||
|
session get session-namespace set-at ;
|
|
@ -60,11 +60,18 @@ IN: http
|
||||||
: url-decode ( str -- str )
|
: url-decode ( str -- str )
|
||||||
[ 0 swap url-decode-iter ] "" make ;
|
[ 0 swap url-decode-iter ] "" make ;
|
||||||
|
|
||||||
: build-url ( path query-params -- str )
|
: hash>query ( hash -- str )
|
||||||
[
|
|
||||||
swap % dup assoc-empty? [
|
|
||||||
"?" % dup
|
|
||||||
[ [ url-encode ] 2apply "=" swap 3append ] { } assoc>map
|
[ [ url-encode ] 2apply "=" swap 3append ] { } assoc>map
|
||||||
"&" join %
|
"&" join ;
|
||||||
] unless drop
|
|
||||||
|
: build-url ( str query-params -- newstr )
|
||||||
|
[
|
||||||
|
over %
|
||||||
|
dup assoc-empty? [
|
||||||
|
2drop
|
||||||
|
] [
|
||||||
|
CHAR: ? rot member? "&" "?" ? %
|
||||||
|
hash>query %
|
||||||
|
] if
|
||||||
] "" make ;
|
] "" make ;
|
||||||
|
|
||||||
|
|
|
@ -34,14 +34,10 @@ focused? ;
|
||||||
: field-theme ( gadget -- )
|
: field-theme ( gadget -- )
|
||||||
gray <solid> swap set-gadget-boundary ;
|
gray <solid> swap set-gadget-boundary ;
|
||||||
|
|
||||||
: construct-editor ( class -- tuple )
|
: construct-editor ( object class -- tuple )
|
||||||
>r <editor> { set-gadget-delegate } r> construct
|
>r { set-gadget-delegate } r> construct
|
||||||
dup dup set-editor-self ; inline
|
dup dup set-editor-self ; inline
|
||||||
|
|
||||||
TUPLE: source-editor ;
|
|
||||||
|
|
||||||
: <source-editor> source-editor construct-editor ;
|
|
||||||
|
|
||||||
: activate-editor-model ( editor model -- )
|
: activate-editor-model ( editor model -- )
|
||||||
2dup add-connection
|
2dup add-connection
|
||||||
dup activate-model
|
dup activate-model
|
||||||
|
@ -340,9 +336,6 @@ M: editor gadget-text* editor-string % ;
|
||||||
: delete-to-end-of-line T{ one-line-elt } editor-backspace ;
|
: delete-to-end-of-line T{ one-line-elt } editor-backspace ;
|
||||||
|
|
||||||
editor "general" f {
|
editor "general" f {
|
||||||
{ T{ key-down f f "RET" } insert-newline }
|
|
||||||
{ T{ key-down f { S+ } "RET" } insert-newline }
|
|
||||||
{ T{ key-down f f "ENTER" } insert-newline }
|
|
||||||
{ T{ key-down f f "DELETE" } delete-next-character }
|
{ T{ key-down f f "DELETE" } delete-next-character }
|
||||||
{ T{ key-down f { S+ } "DELETE" } delete-next-character }
|
{ T{ key-down f { S+ } "DELETE" } delete-next-character }
|
||||||
{ T{ key-down f f "BACKSPACE" } delete-previous-character }
|
{ T{ key-down f f "BACKSPACE" } delete-previous-character }
|
||||||
|
@ -448,6 +441,23 @@ editor "selection" f {
|
||||||
{ T{ key-down f { S+ C+ } "END" } select-end-of-document }
|
{ T{ key-down f { S+ C+ } "END" } select-end-of-document }
|
||||||
} define-command-map
|
} define-command-map
|
||||||
|
|
||||||
|
! Multi-line editors
|
||||||
|
TUPLE: multiline-editor ;
|
||||||
|
|
||||||
|
: <multiline-editor> ( -- editor )
|
||||||
|
<editor> multiline-editor construct-editor ;
|
||||||
|
|
||||||
|
multiline-editor "general" f {
|
||||||
|
{ T{ key-down f f "RET" } insert-newline }
|
||||||
|
{ T{ key-down f { S+ } "RET" } insert-newline }
|
||||||
|
{ T{ key-down f f "ENTER" } insert-newline }
|
||||||
|
} define-command-map
|
||||||
|
|
||||||
|
TUPLE: source-editor ;
|
||||||
|
|
||||||
|
: <source-editor> ( -- editor )
|
||||||
|
<multiline-editor> source-editor construct-editor ;
|
||||||
|
|
||||||
! Fields are like editors except they edit an external model
|
! Fields are like editors except they edit an external model
|
||||||
TUPLE: field model editor ;
|
TUPLE: field model editor ;
|
||||||
|
|
||||||
|
|
|
@ -95,7 +95,7 @@ deploy-gadget "toolbar" f {
|
||||||
{ f com-help }
|
{ f com-help }
|
||||||
{ f com-revert }
|
{ f com-revert }
|
||||||
{ f com-save }
|
{ f com-save }
|
||||||
{ T{ key-down f f "RETURN" } com-deploy }
|
{ T{ key-down f f "RET" } com-deploy }
|
||||||
} define-command-map
|
} define-command-map
|
||||||
|
|
||||||
: buttons,
|
: buttons,
|
||||||
|
|
|
@ -33,9 +33,8 @@ help ;
|
||||||
|
|
||||||
: <interactor> ( output -- gadget )
|
: <interactor> ( output -- gadget )
|
||||||
<source-editor>
|
<source-editor>
|
||||||
{ set-interactor-output set-gadget-delegate }
|
interactor construct-editor
|
||||||
interactor construct
|
tuck set-interactor-output
|
||||||
dup dup set-editor-self
|
|
||||||
dup init-interactor-history
|
dup init-interactor-history
|
||||||
dup init-caret-help ;
|
dup init-caret-help ;
|
||||||
|
|
||||||
|
|
|
@ -33,7 +33,8 @@ M: live-search handle-gesture* ( gadget gesture delegate -- ? )
|
||||||
|
|
||||||
TUPLE: search-field ;
|
TUPLE: search-field ;
|
||||||
|
|
||||||
: <search-field> ( -- gadget ) search-field construct-editor ;
|
: <search-field> ( -- gadget )
|
||||||
|
<editor> search-field construct-editor ;
|
||||||
|
|
||||||
search-field H{
|
search-field H{
|
||||||
{ T{ key-down f f "UP" } [ find-search-list select-previous ] }
|
{ T{ key-down f f "UP" } [ find-search-list select-previous ] }
|
||||||
|
|
|
@ -6,18 +6,19 @@ USING: kernel furnace furnace.validator http.server.responders
|
||||||
arrays io.files ;
|
arrays io.files ;
|
||||||
IN: webapps.help
|
IN: webapps.help
|
||||||
|
|
||||||
|
! : string>topic ( string -- topic )
|
||||||
|
! " " split dup length 1 = [ first ] when ;
|
||||||
|
|
||||||
: show-help ( topic -- )
|
: show-help ( topic -- )
|
||||||
serving-html
|
serving-html
|
||||||
dup article-title [
|
dup article-title [
|
||||||
[ help ] with-html-stream
|
[ help ] with-html-stream
|
||||||
] simple-html-document ;
|
] simple-html-document ;
|
||||||
|
|
||||||
: string>topic ( string -- topic )
|
|
||||||
" " split dup length 1 = [ first ] when ;
|
|
||||||
|
|
||||||
\ show-help {
|
\ show-help {
|
||||||
{ "topic" "handbook" v-default string>topic }
|
{ "topic" }
|
||||||
} define-action
|
} define-action
|
||||||
|
\ show-help { { "topic" "handbook" } } default-values
|
||||||
|
|
||||||
M: link browser-link-href
|
M: link browser-link-href
|
||||||
link-name
|
link-name
|
||||||
|
@ -32,9 +33,10 @@ M: link browser-link-href
|
||||||
lookup show-help ;
|
lookup show-help ;
|
||||||
|
|
||||||
\ show-word {
|
\ show-word {
|
||||||
{ "word" "call" v-default }
|
{ "word" }
|
||||||
{ "vocab" "kernel" v-default }
|
{ "vocab" }
|
||||||
} define-action
|
} define-action
|
||||||
|
\ show-word { { "word" "call" } { "vocab" "kernel" } } default-values
|
||||||
|
|
||||||
M: f browser-link-href
|
M: f browser-link-href
|
||||||
drop \ f browser-link-href ;
|
drop \ f browser-link-href ;
|
||||||
|
@ -47,9 +49,11 @@ M: word browser-link-href
|
||||||
f >vocab-link show-help ;
|
f >vocab-link show-help ;
|
||||||
|
|
||||||
\ show-vocab {
|
\ show-vocab {
|
||||||
{ "vocab" "kernel" v-default }
|
{ "vocab" }
|
||||||
} define-action
|
} define-action
|
||||||
|
|
||||||
|
\ show-vocab { { "vocab" "kernel" } } default-values
|
||||||
|
|
||||||
M: vocab-spec browser-link-href
|
M: vocab-spec browser-link-href
|
||||||
vocab-name [ show-vocab ] curry quot-link ;
|
vocab-name [ show-vocab ] curry quot-link ;
|
||||||
|
|
||||||
|
|
|
@ -6,16 +6,16 @@
|
||||||
|
|
||||||
<table>
|
<table>
|
||||||
|
|
||||||
<input type="hidden" name="n" value="<% "n" get number>string write %>" />
|
|
||||||
|
|
||||||
<tr>
|
<tr>
|
||||||
<th align="right">Summary:</th>
|
<th align="right">Summary:</th>
|
||||||
<td><input type="TEXT" name="summary" value="" /></td>
|
<td><input type="TEXT" name="summary" value="<% "summary" render %>" /></td>
|
||||||
|
<td align="left" class="error"><% "summary" "*Required" render-error %></td>
|
||||||
</tr>
|
</tr>
|
||||||
|
|
||||||
<tr>
|
<tr>
|
||||||
<th align="right">Your name:</th>
|
<th align="right">Your name:</th>
|
||||||
<td><input type="TEXT" name="author" value="" /></td>
|
<td><input type="TEXT" name="author" value="<% "author" render %>" /></td>
|
||||||
|
<td class="error"><% "author" "*Required" render-error %></td>
|
||||||
</tr>
|
</tr>
|
||||||
|
|
||||||
<tr>
|
<tr>
|
||||||
|
@ -23,11 +23,25 @@
|
||||||
<td><% "modes" render-template %></td>
|
<td><% "modes" render-template %></td>
|
||||||
</tr>
|
</tr>
|
||||||
|
|
||||||
|
<!--
|
||||||
|
<tr>
|
||||||
|
<th align="right">Channel:</th>
|
||||||
|
<td><input type="TEXT" name="channel" value="#concatenative" /></td>
|
||||||
|
</tr>
|
||||||
|
-->
|
||||||
|
|
||||||
|
<tr>
|
||||||
|
<td></td>
|
||||||
|
<td colspan="2" class="error" align="left"><% "contents" "*Required" render-error %></td>
|
||||||
|
</tr>
|
||||||
|
|
||||||
<tr>
|
<tr>
|
||||||
<th align="right" valign="top">Content:</th>
|
<th align="right" valign="top">Content:</th>
|
||||||
<td><textarea rows="24" cols="60" name="contents"></textarea></td>
|
<td colspan="2"><textarea rows="24" cols="60" name="contents"><% "contents" render %></textarea></td>
|
||||||
</tr>
|
</tr>
|
||||||
</table>
|
</table>
|
||||||
|
|
||||||
|
<input type="hidden" name="n" value="<% "n" get number>string write %>" />
|
||||||
|
<input type="hidden" name="furnace-form-submitted" value="annotate-paste"/>
|
||||||
<input type="SUBMIT" value="Annotate" />
|
<input type="SUBMIT" value="Annotate" />
|
||||||
</form>
|
</form>
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
<% USING: xmode.catalog sequences kernel html.elements assocs io sorting ; %>
|
<% USING: furnace xmode.catalog sequences kernel html.elements assocs io sorting continuations ; %>
|
||||||
|
|
||||||
<select name="mode">
|
<select name="mode">
|
||||||
<% modes keys natural-sort [
|
<% modes keys natural-sort [
|
||||||
<option dup "factor" = [ "true" =selected ] when option> write </option>
|
<option dup "mode" session-var = [ "true" =selected ] when option> write </option>
|
||||||
] each %>
|
] each %>
|
||||||
</select>
|
</select>
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
<% USING: furnace namespaces ; %>
|
<% USING: continuations furnace namespaces ; %>
|
||||||
|
|
||||||
<%
|
<%
|
||||||
"New paste" "title" set
|
"New paste" "title" set
|
||||||
|
@ -11,12 +11,14 @@
|
||||||
|
|
||||||
<tr>
|
<tr>
|
||||||
<th align="right">Summary:</th>
|
<th align="right">Summary:</th>
|
||||||
<td><input type="TEXT" name="summary" value="" /></td>
|
<td><input type="TEXT" name="summary" value="<% "summary" render %>" /></td>
|
||||||
|
<td align="left" class="error"><% "summary" "*Required" render-error %></td>
|
||||||
</tr>
|
</tr>
|
||||||
|
|
||||||
<tr>
|
<tr>
|
||||||
<th align="right">Your name:</th>
|
<th align="right">Your name:</th>
|
||||||
<td><input type="TEXT" name="author" value="" /></td>
|
<td><input type="TEXT" name="author" value="<% "author" render %>" /></td>
|
||||||
|
<td class="error"><% "author" "*Required" render-error %></td>
|
||||||
</tr>
|
</tr>
|
||||||
|
|
||||||
<tr>
|
<tr>
|
||||||
|
@ -31,12 +33,18 @@
|
||||||
</tr>
|
</tr>
|
||||||
-->
|
-->
|
||||||
|
|
||||||
|
<tr>
|
||||||
|
<td></td>
|
||||||
|
<td colspan="2" class="error" align="left"><% "contents" "*Required" render-error %></td>
|
||||||
|
</tr>
|
||||||
|
|
||||||
<tr>
|
<tr>
|
||||||
<th align="right" valign="top">Content:</th>
|
<th align="right" valign="top">Content:</th>
|
||||||
<td><textarea rows="24" cols="60" name="contents"></textarea></td>
|
<td colspan="2"><textarea rows="24" cols="60" name="contents"><% "contents" render %></textarea></td>
|
||||||
</tr>
|
</tr>
|
||||||
</table>
|
</table>
|
||||||
|
|
||||||
|
<input type="hidden" name="furnace-form-submitted" value="new-paste"/>
|
||||||
<input type="SUBMIT" value="Submit paste" />
|
<input type="SUBMIT" value="Submit paste" />
|
||||||
</form>
|
</form>
|
||||||
|
|
||||||
|
|
|
@ -84,28 +84,37 @@ C: <annotation> annotation
|
||||||
store save-store
|
store save-store
|
||||||
] keep paste-link permanent-redirect ;
|
] keep paste-link permanent-redirect ;
|
||||||
|
|
||||||
|
\ new-paste
|
||||||
\ submit-paste {
|
\ submit-paste {
|
||||||
{ "summary" "- no summary -" v-default }
|
{ "summary" v-required }
|
||||||
{ "author" "- no author -" v-default }
|
{ "author" v-required }
|
||||||
{ "channel" "#concatenative" v-default }
|
{ "channel" }
|
||||||
{ "mode" "factor" v-default }
|
{ "mode" v-required }
|
||||||
{ "contents" v-required }
|
{ "contents" v-required }
|
||||||
} define-action
|
} define-form
|
||||||
|
|
||||||
|
\ new-paste {
|
||||||
|
{ "channel" "#concatenative" }
|
||||||
|
{ "mode" "factor" }
|
||||||
|
} default-values
|
||||||
|
|
||||||
: annotate-paste ( n summary author mode contents -- )
|
: annotate-paste ( n summary author mode contents -- )
|
||||||
<annotation> swap get-paste
|
<annotation> swap get-paste
|
||||||
paste-annotations push
|
[ paste-annotations push store save-store ] keep
|
||||||
store save-store ;
|
paste-link permanent-redirect ;
|
||||||
|
|
||||||
|
[ "n" show-paste ]
|
||||||
\ annotate-paste {
|
\ annotate-paste {
|
||||||
{ "n" v-required v-number }
|
{ "n" v-required v-number }
|
||||||
{ "summary" "- no summary -" v-default }
|
{ "summary" v-required }
|
||||||
{ "author" "- no author -" v-default }
|
{ "author" v-required }
|
||||||
{ "mode" "factor" v-default }
|
{ "mode" v-required }
|
||||||
{ "contents" v-required }
|
{ "contents" v-required }
|
||||||
} define-action
|
} define-form
|
||||||
|
|
||||||
\ annotate-paste [ "n" show-paste ] define-redirect
|
\ show-paste {
|
||||||
|
{ "mode" "factor" }
|
||||||
|
} default-values
|
||||||
|
|
||||||
: style.css ( -- )
|
: style.css ( -- )
|
||||||
"text/css" serving-content
|
"text/css" serving-content
|
||||||
|
|
|
@ -35,3 +35,7 @@ pre.code {
|
||||||
border: 1px solid #C1DAD7;
|
border: 1px solid #C1DAD7;
|
||||||
padding: 10px;
|
padding: 10px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.error {
|
||||||
|
color: red;
|
||||||
|
}
|
||||||
|
|
|
@ -270,7 +270,7 @@ refresh_image() {
|
||||||
}
|
}
|
||||||
|
|
||||||
install_libraries() {
|
install_libraries() {
|
||||||
sudo apt-get install libc6-dev libfreetype6-dev wget git-core git-doc libx11-dev glutg3-dev rlwrap
|
sudo apt-get install libc6-dev libfreetype6-dev libx11-dev xorg-dev glutg3-dev wget git-core git-doc rlwrap
|
||||||
}
|
}
|
||||||
|
|
||||||
case "$1" in
|
case "$1" in
|
||||||
|
|
Loading…
Reference in New Issue