1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
module Concurrent = Concurrent
module Modal = Modal
module Mode = Mode
module Key = Key
module Make (Modal:Modal.S) (Concurrent:Concurrent.S) =
struct
module Key = Modal.Key
module Mode = Modal.Mode
module MsgBox = Concurrent.MsgBox
module Thread = Concurrent.Thread
let (>>=)= Thread.bind
class edit state= object(self)
val i= MsgBox.create ()
val o: Key.t MsgBox.t= MsgBox.create ()
val mutable curr_mode: Mode.t= let _, mode= state#default_mode in mode
method keyin (key:Key.t)= MsgBox.put i key
method i= i
method o= o
method getMode= curr_mode
method setMode mode= curr_mode <- Mode.Modes.find mode state#modes
method timeout= match Mode.timeout self#getMode with
| Some timeout-> timeout
| None-> state#timeout
method bindings= Mode.bindings self#getMode
initializer
let rec get_key sources=
match sources with
| []-> MsgBox.get i >>= fun key-> Thread.return (key, sources)
| source::tl->
match Queue.take source with
| key-> Thread.return (key, sources)
| exception Queue.Empty-> get_key tl
in
let output_seq o seq=
let rec output_seq ()=
match Queue.take seq with
| key-> MsgBox.put o key >>= output_seq
| exception Queue.Empty-> Thread.return ()
in
output_seq ()
in
let perform action sources=
match action with
| Mode.Switch name-> self#setMode name;
sources
| Key key->
let seq= Queue.create() in
Queue.add key seq;
seq::sources
| KeySeq keyseq-> keyseq::sources
| Custom f-> f (); sources
in
let rec listen sources mem_key last node=
match node with
| Some node->
Thread.pick
[ (Thread.sleep self#timeout >>=
fun ()-> Thread.return None);
get_key sources >>= fun (key, sources)->
Thread.return (Some (key, sources))
]
>>= (function
| Some (key, sources)->
Queue.add key mem_key;
try_matching sources mem_key last node key
| None-> skip_matching sources mem_key last)
| None-> let node= self#bindings in
get_key sources >>= fun (key, sources)->
Queue.add key mem_key;
try_matching sources mem_key last node key
and try_matching sources mem_key last node key=
match Mode.KeyTrie.sub node [key] with
| Some node->
let last=
match Mode.KeyTrie.get node [] with
| Some action->
Some (Queue.copy mem_key, action)
| None-> last
in
if Mode.KeyTrie.is_leaf node then
skip_matching sources mem_key last
else
listen sources mem_key last (Some node)
| None->
skip_matching sources mem_key last
and skip_matching sources mem_key last=
match last with
| Some (seq, action)->
Utils.Queue.drop (Queue.length seq) mem_key;
let sources= perform action sources in
listen (mem_key::sources) (Queue.create ()) None None
| None->
output_seq o mem_key >>= fun ()->
listen sources (Queue.create()) None None
in
Thread.async (fun ()-> listen [] (Queue.create ()) None None)
end
class state modes= object(self)
val mutable timeout= 1.
val mutable default_mode= Modal.Mode.default_mode modes
method edit= new edit self
method modes= modes
method default_mode= default_mode
method timeout= timeout
end
end