/
abbrev_command.rb
77 lines (67 loc) · 1.37 KB
/
abbrev_command.rb
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
module DEBUGGER__
class AbbrevCommand
class TrieNode
def initialize
@children = {}
@types = {} # set
end
def append c, type
trie = (@children[c] ||= TrieNode.new)
trie.add_type type
end
def [](c)
@children[c]
end
def add_type type
@types[type] = true
self
end
def types
@types.keys
end
def type
if @types.size == 1
@types.keys.first
else
nil
end
end
def candidates
@children.map{|c, n|
ss = n.candidates
ss.empty? ? c :
ss.map{|s|
c+s
}
}.flatten
end
end
# config: { type: [commands...], ... }
def initialize config
@trie = TrieNode.new
build config
end
private def build config
config.each do |type, commands|
commands.each do |command|
trie = @trie
command.each_char do |c|
trie = trie.append(c, type)
end
end
end
end
def search str, if_none = nil
trie = @trie
str.each_char do |c|
if trie = trie[c]
return trie.type if trie.type
else
return if_none
end
end
yield trie.candidates.map{|s| str + s} if block_given?
if_none
end
end
end