1 ! Copyright (C) 2009 Slava Pestov.
2 ! See http://factorcode.org/license.txt for BSD license.
3 USING: accessors arrays assocs calendar colors documents
4 documents.elements fry kernel words sets splitting math math.vectors
5 models.delay models.filter combinators.short-circuit parser present
6 sequences tools.completion generic generic.standard.engines.tuple
7 fonts ui.commands ui.gadgets ui.gadgets.editors ui.gadgets.glass
8 ui.gadgets.scrollers ui.gadgets.tables ui.gadgets.theme
9 ui.gadgets.worlds ui.gadgets.wrappers ui.gestures ui.render
10 ui.tools.listener.history ;
11 IN: ui.tools.listener.completion
13 : complete-IN:/USE:? ( tokens -- ? )
14 2 short tail* { "IN:" "USE:" } intersects? ;
16 : chop-; ( seq -- seq' )
17 { ";" } split1-last [ ] [ ] ?if ;
19 : complete-USING:? ( tokens -- ? )
20 chop-; { "USING:" } intersects? ;
22 : up-to-caret ( caret document -- string )
23 [ { 0 0 } ] 2dip doc-range ;
25 : vocab-completion? ( interactor -- ? )
26 [ editor-caret ] [ model>> ] bi up-to-caret " \r\n" split
27 { [ complete-IN:/USE:? ] [ complete-USING:? ] } 1|| ;
29 ! We don't directly depend on the listener tool but we use a couple
31 SLOT: completion-popup
35 TUPLE: completion-popup < wrapper table interactor element ;
37 : find-completion-popup ( gadget -- popup )
38 [ completion-popup? ] find-parent ;
40 SINGLETON: completion-renderer
41 M: completion-renderer row-columns drop present 1array ;
42 M: completion-renderer row-value drop ;
44 : <completion-model> ( editor quot -- model )
45 [ one-word-elt <element-model> 1/3 seconds <delay> ] dip
46 '[ @ keys 1000 short head ] <filter> ;
48 M: completion-popup hide-glass-hook
49 interactor>> f >>completion-popup request-focus ;
51 : hide-completion-popup ( popup -- )
52 find-world hide-glass ;
54 : completion-loc/doc ( popup -- loc doc )
55 interactor>> [ editor-caret ] [ model>> ] bi ;
57 GENERIC: completion-string ( object -- string )
59 M: object completion-string present ;
61 : method-completion-string ( word -- string )
62 "method-generic" word-prop present ;
64 M: method-body completion-string method-completion-string ;
66 M: engine-word completion-string method-completion-string ;
68 GENERIC# accept-completion-hook 1 ( item popup -- )
70 : insert-completion ( item popup -- )
71 [ completion-string ] [ completion-loc/doc ] bi*
72 one-word-elt set-elt-string ;
74 : accept-completion ( item table -- )
77 [ accept-completion-hook ]
78 [ nip hide-completion-popup ]
81 : <completion-table> ( interactor quot -- table )
82 <completion-model> <table>
84 t >>selection-required?
85 completion-renderer >>renderer
86 dup '[ _ accept-completion ] >>action ;
88 : <completion-scroller> ( object -- object )
91 { 300 120 } >>max-dim ;
93 : <completion-popup> ( interactor quot -- popup )
94 [ completion-popup new-gadget ] 2dip
95 [ drop >>interactor ] [ <completion-table> >>table ] 2bi
96 dup table>> <completion-scroller> add-gadget
97 white <solid> >>interior ;
100 { T{ key-down f f "ESC" } [ hide-completion-popup ] }
101 { T{ key-down f f "TAB" } [ table>> row-action ] }
102 { T{ key-down f f " " } [ table>> row-action ] }
105 CONSTANT: completion-popup-offset { -4 0 }
107 : (completion-popup-loc) ( interactor element -- loc )
108 [ drop screen-loc ] [
109 [ [ [ editor-caret ] [ model>> ] bi ] dip prev-elt ] [ drop ] 2bi
111 ] 2bi v+ completion-popup-offset v+ ;
113 : completion-popup-loc-1 ( interactor element -- loc )
114 [ (completion-popup-loc) ] [ drop caret-dim ] 2bi v+ ;
116 : completion-popup-loc-2 ( interactor element popup -- loc )
117 [ (completion-popup-loc) ] dip pref-dim { 0 1 } v* v- ;
119 : completion-popup-fits? ( interactor element popup -- ? )
120 [ [ completion-popup-loc-1 ] dip pref-dim v+ ]
121 [ 2drop find-world dim>> ]
122 3bi [ second ] bi@ <= ;
124 : completion-popup-loc ( interactor element popup -- loc )
125 3dup completion-popup-fits?
126 [ drop completion-popup-loc-1 ]
127 [ completion-popup-loc-2 ]
130 : show-completion-popup ( interactor quot element -- )
131 [ nip ] [ drop <completion-popup> ] 3bi
132 [ nip >>completion-popup drop ]
133 [ [ 2drop find-world ] [ 2nip ] [ completion-popup-loc ] 3tri ] 3bi
136 : code-completion-popup ( interactor -- )
137 dup vocab-completion?
138 [ vocabs-matching ] [ words-matching ] ? '[ [ { } ] _ if-empty ]
139 one-word-elt show-completion-popup ;
141 : history-matching ( interactor -- alist )
143 [ dup string>> { { CHAR: \n CHAR: \s } } substitute ] { } map>assoc
146 : history-completion-popup ( interactor -- )
147 dup '[ drop _ history-matching ] one-line-elt show-completion-popup ;
149 : recall-previous ( interactor -- )
150 history>> history-recall-previous ;
152 : recall-next ( interactor -- )
153 history>> history-recall-next ;
155 : selected-word ( editor -- word )
156 dup completion-popup>> [
157 [ table>> selected-row drop ] [ hide-completion-popup ] bi
159 selected-token dup search [ ] [ no-word ] ?if