factor/basis/ui/tools/interactor/interactor.factor

190 lines
5.2 KiB
Factor
Raw Normal View History

2008-01-05 15:09:55 -05:00
! Copyright (C) 2006, 2008 Slava Pestov.
2007-09-20 18:09:08 -04:00
! See http://factorcode.org/license.txt for BSD license.
USING: arrays assocs combinators continuations documents
2008-05-06 23:20:27 -04:00
hashtables io io.styles kernel math math.order math.vectors
2008-07-04 18:58:37 -04:00
models models.delay namespaces parser lexer prettyprint
quotations sequences strings threads listener classes.tuple
ui.commands ui.gadgets ui.gadgets.editors ui.gadgets.status-bar
2008-07-04 18:58:37 -04:00
ui.gadgets.presentations ui.gadgets.worlds ui.gestures
definitions calendar concurrency.flags concurrency.mailboxes
ui.tools.workspace accessors sets destructors ;
2007-09-20 18:09:08 -04:00
IN: ui.tools.interactor
2008-04-27 04:16:12 -04:00
! If waiting is t, we're waiting for user input, and invoking
! evaluate-input resumes the thread.
TUPLE: interactor < source-editor
output history flag mailbox thread waiting help ;
2008-04-27 04:16:12 -04:00
: register-self ( interactor -- )
2008-05-07 03:32:58 -04:00
<mailbox> >>mailbox
self >>thread
drop ;
2007-09-20 18:09:08 -04:00
: interactor-continuation ( interactor -- continuation )
2008-04-27 04:16:12 -04:00
thread>> continuation>> value>> ;
: interactor-busy? ( interactor -- ? )
2008-04-27 04:16:12 -04:00
#! We're busy if there's no thread to resume.
[ waiting>> ]
[ thread>> dup [ thread-registered? ] when ]
bi and not ;
2008-01-04 21:10:49 -05:00
: interactor-use ( interactor -- seq )
dup interactor-busy? [ drop f ] [
use swap
2008-04-27 04:16:12 -04:00
interactor-continuation name>>
assoc-stack
] if ;
2008-01-04 21:10:49 -05:00
2008-04-27 04:16:12 -04:00
: <help-model> ( interactor -- model )
editor-caret 1/3 seconds <delay> ;
2007-09-20 18:09:08 -04:00
: <interactor> ( output -- gadget )
interactor new-editor
2008-04-27 04:16:12 -04:00
V{ } clone >>history
<flag> >>flag
dup <help-model> >>help
swap >>output ;
2007-09-20 18:09:08 -04:00
M: interactor graft*
[ call-next-method ] [ dup help>> add-connection ] bi ;
2008-04-27 04:16:12 -04:00
M: interactor ungraft*
[ dup help>> remove-connection ] [ call-next-method ] bi ;
2007-09-20 18:09:08 -04:00
2007-12-30 21:15:59 -05:00
: word-at-loc ( loc interactor -- word )
over [
[ gadget-model T{ one-word-elt } elt-string ] keep
interactor-use assoc-stack
] [
2drop f
] if ;
M: interactor model-changed
2008-04-27 04:16:12 -04:00
2dup help>> eq? [
swap model-value over word-at-loc swap show-summary
] [
call-next-method
] if ;
2007-09-20 18:09:08 -04:00
: write-input ( string input -- )
<input> presented associate
[ H{ { font-style bold } } format ] with-nesting ;
: interactor-input. ( string interactor -- )
2008-04-27 04:16:12 -04:00
output>> [
2007-09-20 18:09:08 -04:00
dup string? [ dup write-input nl ] [ short. ] if
] with-output-stream* ;
2007-09-20 18:09:08 -04:00
: add-interactor-history ( str interactor -- )
2008-05-25 20:44:37 -04:00
over empty? [ 2drop ] [ interactor-history adjoin ] if ;
2007-09-20 18:09:08 -04:00
: interactor-continue ( obj interactor -- )
2008-05-07 02:56:55 -04:00
mailbox>> mailbox-put ;
2007-09-20 18:09:08 -04:00
2008-01-04 21:10:49 -05:00
: clear-input ( interactor -- ) gadget-model clear-doc ;
2007-12-30 21:15:59 -05:00
: interactor-finish ( interactor -- )
#! The spawn is a kludge to make it infer. Stupid.
2007-09-20 18:09:08 -04:00
[ editor-string ] keep
[ interactor-input. ] 2keep
[ add-interactor-history ] keep
[ clear-input ] curry "Clearing input" spawn drop ;
2007-09-20 18:09:08 -04:00
: interactor-eof ( interactor -- )
2007-12-30 21:15:59 -05:00
dup interactor-busy? [
f over interactor-continue
] unless drop ;
2007-09-20 18:09:08 -04:00
: evaluate-input ( interactor -- )
2007-12-30 21:15:59 -05:00
dup interactor-busy? [
2008-02-18 06:07:40 -05:00
dup control-value over interactor-continue
2007-12-30 21:15:59 -05:00
] unless drop ;
2007-09-20 18:09:08 -04:00
2007-12-30 21:15:59 -05:00
: interactor-yield ( interactor -- obj )
2008-04-27 04:16:12 -04:00
dup thread>> self eq? [
2008-05-07 02:56:55 -04:00
{
[ t >>waiting drop ]
[ flag>> raise-flag ]
[ mailbox>> mailbox-get ]
[ f >>waiting drop ]
} cleave
2008-04-27 04:16:12 -04:00
] [ drop f ] if ;
2007-09-20 18:09:08 -04:00
: interactor-read ( interactor -- lines )
[ interactor-yield ] [ interactor-finish ] bi ;
2007-09-20 18:09:08 -04:00
M: interactor stream-readln
interactor-read dup [ first ] when ;
2007-09-20 18:09:08 -04:00
: interactor-call ( quot interactor -- )
2007-12-30 21:15:59 -05:00
dup interactor-busy? [
2dup interactor-input.
2dup interactor-continue
] unless 2drop ;
2007-09-20 18:09:08 -04:00
M: interactor stream-read
swap dup zero? [
2drop ""
] [
>r interactor-read dup [ "\n" join ] when r> short head
2007-09-20 18:09:08 -04:00
] if ;
M: interactor stream-read-partial
stream-read ;
M: interactor stream-read1
dup interactor-read {
{ [ dup not ] [ 2drop f ] }
{ [ dup empty? ] [ drop stream-read1 ] }
{ [ dup first empty? ] [ 2drop CHAR: \n ] }
[ nip first first ]
} cond ;
M: interactor dispose drop ;
2007-09-20 18:09:08 -04:00
: go-to-error ( interactor error -- )
2008-04-04 01:33:06 -04:00
[ line>> 1- ] [ column>> ] bi 2array
2007-12-30 21:15:59 -05:00
over set-caret
2007-09-20 18:09:08 -04:00
mark>caret ;
: handle-parse-error ( interactor error -- )
2008-06-25 04:25:08 -04:00
dup lexer-error? [ 2dup go-to-error error>> ] when
2007-09-20 18:09:08 -04:00
swap find-workspace debugger-popup ;
2007-12-30 21:15:59 -05:00
: try-parse ( lines interactor -- quot/error/f )
2007-09-20 18:09:08 -04:00
[
2008-01-04 21:10:49 -05:00
drop parse-lines-interactive
2007-12-30 21:15:59 -05:00
] [
2nip
2008-06-25 04:25:08 -04:00
dup lexer-error? [
2008-04-10 22:49:08 -04:00
dup error>> unexpected-eof? [ drop f ] when
] when
2007-12-30 21:15:59 -05:00
] recover ;
: handle-interactive ( lines interactor -- quot/f ? )
2007-09-20 18:09:08 -04:00
tuck try-parse {
2007-12-30 21:15:59 -05:00
{ [ dup quotation? ] [ nip t ] }
{ [ dup not ] [ drop "\n" swap user-input f f ] }
2008-04-11 13:54:33 -04:00
[ handle-parse-error f f ]
2007-09-20 18:09:08 -04:00
} cond ;
2007-12-29 22:29:59 -05:00
M: interactor stream-read-quot
2008-01-04 21:10:49 -05:00
[ interactor-yield ] keep {
{ [ over not ] [ drop ] }
{ [ over callable? ] [ drop ] }
2008-04-11 13:54:33 -04:00
[
2008-01-04 21:10:49 -05:00
[ handle-interactive ] keep swap
[ interactor-finish ] [ nip stream-read-quot ] if
2008-04-11 13:54:33 -04:00
]
2008-01-04 21:10:49 -05:00
} cond ;
2007-09-20 18:09:08 -04:00
M: interactor pref-dim*
[ line-height 4 * 0 swap 2array ] [ call-next-method ] bi
2008-04-27 04:16:12 -04:00
vmax ;
2007-09-20 18:09:08 -04:00
interactor "interactor" f {
{ T{ key-down f f "RET" } evaluate-input }
{ T{ key-down f { C+ } "k" } clear-input }
} define-command-map