lingo 1.8.5 → 1.8.6
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/ChangeLog +25 -0
- data/README +7 -5
- data/Rakefile +58 -55
- data/{lingo-call.cfg → config/lingo-call.cfg} +1 -1
- data/{lingo.cfg → config/lingo.cfg} +10 -2
- data/{lir.cfg → config/lir.cfg} +10 -2
- data/{de → dict/de}/lingo-abk.txt +0 -0
- data/{de → dict/de}/lingo-dic.txt +0 -0
- data/{de → dict/de}/lingo-mul.txt +0 -0
- data/{de → dict/de}/lingo-syn.txt +0 -0
- data/{de → dict/de}/test_dic.txt +0 -0
- data/{de → dict/de}/test_gen.txt +0 -0
- data/{de → dict/de}/test_mu2.txt +0 -0
- data/{de → dict/de}/test_mul.txt +0 -0
- data/{de → dict/de}/test_sgw.txt +0 -0
- data/{de → dict/de}/test_syn.txt +0 -0
- data/{de → dict/de}/user-dic.txt +0 -0
- data/{en → dict/en}/lingo-dic.txt +0 -0
- data/{en → dict/en}/lingo-irr.txt +0 -0
- data/{en → dict/en}/lingo-mul.txt +0 -0
- data/{en → dict/en}/lingo-syn.txt +0 -0
- data/{en → dict/en}/lingo-wdn.txt +0 -0
- data/{en → dict/en}/user-dic.txt +0 -0
- data/{ru → dict/ru}/lingo-dic.txt +0 -0
- data/{ru → dict/ru}/lingo-mul.txt +0 -0
- data/{ru → dict/ru}/lingo-syn.txt +0 -0
- data/{ru → dict/ru}/user-dic.txt +0 -0
- data/{de.lang → lang/de.lang} +1 -1
- data/{en.lang → lang/en.lang} +0 -0
- data/{ru.lang → lang/ru.lang} +0 -0
- data/lib/lingo.rb +14 -15
- data/lib/lingo/app.rb +4 -2
- data/lib/lingo/attendee.rb +23 -43
- data/lib/lingo/attendee/abbreviator.rb +5 -5
- data/lib/lingo/attendee/debugger.rb +39 -12
- data/lib/lingo/attendee/decomposer.rb +3 -4
- data/lib/lingo/attendee/dehyphenizer.rb +4 -4
- data/lib/lingo/attendee/formatter.rb +1 -3
- data/lib/lingo/attendee/multi_worder.rb +3 -4
- data/lib/lingo/attendee/noneword_filter.rb +8 -12
- data/lib/lingo/attendee/object_filter.rb +6 -3
- data/lib/lingo/attendee/sequencer.rb +5 -5
- data/lib/lingo/attendee/stemmer.rb +3 -2
- data/lib/lingo/attendee/synonymer.rb +3 -4
- data/lib/lingo/attendee/text_reader.rb +39 -38
- data/lib/lingo/attendee/text_writer.rb +10 -10
- data/lib/lingo/attendee/tokenizer.rb +63 -33
- data/lib/lingo/attendee/variator.rb +3 -7
- data/lib/lingo/attendee/vector_filter.rb +132 -65
- data/lib/lingo/attendee/word_searcher.rb +5 -3
- data/lib/lingo/buffered_attendee.rb +1 -3
- data/lib/lingo/call.rb +4 -3
- data/lib/lingo/cli.rb +5 -1
- data/lib/lingo/config.rb +11 -5
- data/lib/lingo/ctl.rb +3 -3
- data/lib/lingo/database.rb +3 -1
- data/lib/lingo/database/crypter.rb +1 -3
- data/lib/lingo/database/source.rb +3 -1
- data/lib/lingo/database/source/key_value.rb +3 -1
- data/lib/lingo/database/source/multi_key.rb +3 -1
- data/lib/lingo/database/source/multi_value.rb +3 -1
- data/lib/lingo/database/source/single_word.rb +3 -1
- data/lib/lingo/database/source/word_class.rb +3 -1
- data/lib/lingo/debug.rb +5 -5
- data/lib/lingo/{agenda_item.rb → deferred_attendee.rb} +21 -12
- data/lib/lingo/error.rb +1 -1
- data/lib/lingo/language.rb +1 -9
- data/lib/lingo/language/dictionary.rb +2 -17
- data/lib/lingo/language/grammar.rb +10 -10
- data/lib/lingo/language/lexical.rb +2 -0
- data/lib/lingo/language/lexical_hash.rb +2 -0
- data/lib/lingo/language/token.rb +17 -3
- data/lib/lingo/language/word.rb +13 -5
- data/lib/lingo/language/word_form.rb +5 -3
- data/lib/lingo/progress.rb +2 -2
- data/lib/lingo/srv.rb +1 -1
- data/lib/lingo/srv/lingosrv.cfg +1 -1
- data/lib/lingo/version.rb +1 -1
- data/lib/lingo/web.rb +1 -1
- data/lib/lingo/web/lingoweb.cfg +1 -1
- data/test/attendee/ts_abbreviator.rb +4 -2
- data/test/attendee/ts_multi_worder.rb +81 -88
- data/test/attendee/ts_noneword_filter.rb +2 -2
- data/test/attendee/ts_object_filter.rb +2 -2
- data/test/attendee/ts_sequencer.rb +40 -20
- data/test/attendee/ts_stemmer.rb +52 -26
- data/test/attendee/ts_text_reader.rb +75 -56
- data/test/attendee/ts_text_writer.rb +6 -4
- data/test/attendee/ts_tokenizer.rb +304 -193
- data/test/attendee/ts_vector_filter.rb +242 -9
- data/test/ref/artikel.non +3 -0
- data/test/ref/artikel.vec +1 -4
- data/test/ref/artikel.vef +940 -0
- data/test/ref/artikel.ven +0 -3
- data/test/ref/artikel.ver +0 -3
- data/test/ref/artikel.vet +2580 -0
- data/test/ref/lir.non +34 -31
- data/test/ref/lir.seq +14 -15
- data/test/ref/lir.vec +37 -37
- data/test/ref/lir.vef +329 -0
- data/test/ref/lir.ven +329 -0
- data/test/ref/lir.ver +329 -0
- data/test/ref/lir.vet +329 -0
- data/test/test_helper.rb +29 -16
- data/test/ts_language.rb +6 -47
- metadata +74 -87
- data/lingo.rb +0 -29
- data/spec/spec_helper.rb +0 -5
@@ -28,6 +28,7 @@ class Lingo
|
|
28
28
|
|
29
29
|
class Attendee
|
30
30
|
|
31
|
+
#--
|
31
32
|
# Der Variator ermöglicht bei nicht erkannten Wörtern den listenbasierten
|
32
33
|
# Austausch einzelner Wortteile einchließlich erneuter Wörterbuchsuche zur
|
33
34
|
# Verbesserung der Worterkennungsquote.
|
@@ -69,11 +70,10 @@ class Lingo
|
|
69
70
|
# out> :./PUNC:
|
70
71
|
# out> *EOL('test.txt')
|
71
72
|
# out> *EOF('test.txt')
|
73
|
+
#++
|
72
74
|
|
73
75
|
class Variator < self
|
74
76
|
|
75
|
-
protected
|
76
|
-
|
77
77
|
def init
|
78
78
|
@marker = get_key('marker', '*')
|
79
79
|
@max = get_key('max-var', max = 10000).to_i
|
@@ -89,8 +89,7 @@ class Lingo
|
|
89
89
|
set_gra
|
90
90
|
end
|
91
91
|
|
92
|
-
def control(
|
93
|
-
# can control
|
92
|
+
def control(*)
|
94
93
|
end
|
95
94
|
|
96
95
|
def process(obj)
|
@@ -118,9 +117,6 @@ class Lingo
|
|
118
117
|
|
119
118
|
private
|
120
119
|
|
121
|
-
# Variiere die Bestandteile eines Arrays gemäß den Austauschvorgaben.
|
122
|
-
#
|
123
|
-
# variate( 'Tiieh', 'ieh', 'sch' ) => ['Tiieh', 'Tisch']
|
124
120
|
def variate(variations, from, to)
|
125
121
|
add, change, re = [], [from, to], Regexp.new(from)
|
126
122
|
|
@@ -24,10 +24,13 @@
|
|
24
24
|
###############################################################################
|
25
25
|
#++
|
26
26
|
|
27
|
+
require 'csv'
|
28
|
+
|
27
29
|
class Lingo
|
28
30
|
|
29
31
|
class Attendee
|
30
32
|
|
33
|
+
#--
|
31
34
|
# Die Hauptaufgabe des VectorFilter ist die Erstellung eines Dokumenten-Index-Vektor.
|
32
35
|
# Dabei werden die durch die anderen Attendees ermittelten Grundformen eines Wortes
|
33
36
|
# gespeichert und bei einem Datei- oder Record-Wechsel weitergeleitet. Der VectorFilter
|
@@ -76,101 +79,165 @@ class Lingo
|
|
76
79
|
# out> *FILE('test.txt')
|
77
80
|
# out> "0.28571 indexierung"
|
78
81
|
# out> *EOF('test.txt')
|
82
|
+
#++
|
79
83
|
|
80
84
|
class VectorFilter < self
|
81
85
|
|
82
|
-
|
86
|
+
DEFAULT_SRC_SEPARATOR = '|'
|
87
|
+
DEFAULT_POS_SEPARATOR = '@'
|
88
|
+
|
89
|
+
DEFAULT_DICT_SEPARATOR = Database::Source::WordClass::DEFAULT_SEPARATOR
|
90
|
+
|
91
|
+
DEFAULT_GENDER_SEPARATOR = Database::Source::WordClass::GENDER_SEPARATOR
|
83
92
|
|
84
|
-
|
93
|
+
TERMINALS = [:FILE, :RECORD, :EOF]
|
85
94
|
|
86
95
|
def init
|
87
|
-
|
88
|
-
|
89
|
-
|
90
|
-
|
91
|
-
@lex = get_re('lexicals', '[sy]')
|
92
|
-
@skip = get_array('skip', DEFAULT_SKIP, :upcase)
|
96
|
+
@lex = get_re('lexicals', '[sy]')
|
97
|
+
@skip = get_array('skip', DEFAULT_SKIP, :upcase)
|
98
|
+
|
99
|
+
@src = @pos = @sort_fmt = @sort_rel = @docnum = nil
|
93
100
|
|
94
|
-
|
95
|
-
@norm = get_key('norm', false) if @dict
|
96
|
-
@dict = Database::Source::WordClass::DEFAULT_SEPARATOR if @dict == true
|
101
|
+
@tokens, @vectors, @word_count = [], Hash.nest(1) { [] }, Hash.new(0)
|
97
102
|
|
103
|
+
if @dict = get_key('dict', false)
|
104
|
+
@norm = get_key('norm', false)
|
105
|
+
@dict = DEFAULT_DICT_SEPARATOR if @dict == true
|
106
|
+
else
|
98
107
|
@src = get_key('src', false)
|
99
|
-
@src =
|
108
|
+
@src = DEFAULT_SRC_SEPARATOR if @src == true
|
100
109
|
|
101
|
-
|
102
|
-
|
103
|
-
|
110
|
+
@pos = get_key('pos', false)
|
111
|
+
@pos = DEFAULT_POS_SEPARATOR if @pos == true
|
112
|
+
|
113
|
+
@tokens = get_array('tokens', '', :upcase)
|
114
|
+
@tokens.concat(Tokenizer.rules) if @tokens.delete('ALL')
|
104
115
|
end
|
105
116
|
|
106
|
-
|
117
|
+
if sort = get_key('sort', ENV['LINGO_NO_SORT'] ? false : 'normal')
|
118
|
+
@sort_fmt, sort_method = sort.downcase.split('_', 2)
|
119
|
+
|
120
|
+
@sort_rel = rel = sort_method == 'rel'
|
121
|
+
|
122
|
+
unless @sort_fmt == 'normal'
|
123
|
+
if @tfidf = get_key('tfidf', false)
|
124
|
+
DeferredAttendee.enhance(self)
|
125
|
+
@docnum, rel = 0, true
|
126
|
+
end
|
127
|
+
|
128
|
+
_sort_fmt = @sort_fmt == 'sto' ? '%2$s {%1$X}' : '%X %s'
|
129
|
+
@sort_fmt = _sort_fmt.sub('X', rel ? '.5f' : 'd')
|
130
|
+
end
|
131
|
+
end
|
107
132
|
end
|
108
133
|
|
109
|
-
def control(cmd,
|
134
|
+
def control(cmd, *)
|
110
135
|
case cmd
|
111
|
-
when
|
112
|
-
|
113
|
-
when STR_CMD_FILE, STR_CMD_RECORD, STR_CMD_EOF
|
114
|
-
send_vectors unless @vectors.empty?
|
136
|
+
when :EOL then :skip_command
|
137
|
+
when *TERMINALS then send_vectors unless @docnum
|
115
138
|
end
|
116
139
|
end
|
117
140
|
|
141
|
+
def control_deferred(cmd, *)
|
142
|
+
@docnum += 1 if TERMINALS.include?(cmd)
|
143
|
+
end
|
144
|
+
|
118
145
|
def process(obj)
|
119
|
-
if
|
120
|
-
|
121
|
-
|
122
|
-
|
123
|
-
|
124
|
-
|
125
|
-
|
126
|
-
|
127
|
-
|
128
|
-
|
129
|
-
|
130
|
-
|
131
|
-
|
132
|
-
|
133
|
-
|
134
|
-
unless vec.empty?
|
135
|
-
wrd = @norm ? obj.lexicals.first.form : obj.form
|
136
|
-
vec = Unicode.downcase("#{wrd}#{@dict}#{vec.join(' ')}")
|
137
|
-
@sort_format ? @vectors << vec : forward(vec)
|
138
|
-
end
|
139
|
-
else
|
140
|
-
obj.get_class(@lex).each { |lex|
|
141
|
-
vec = Unicode.downcase(lex.form)
|
142
|
-
vec << @src << lex.src if @src && lex.src
|
143
|
-
@sort_format ? @vectors << vec : forward(vec)
|
144
|
-
}
|
145
|
-
end
|
146
|
+
if obj.is_a?(Token)
|
147
|
+
return unless @tokens.include?(obj.attr)
|
148
|
+
elsif obj.is_a?(Word)
|
149
|
+
return if @skip.include?(obj.attr)
|
150
|
+
else
|
151
|
+
return
|
152
|
+
end
|
153
|
+
|
154
|
+
@word_count[@docnum] += 1
|
155
|
+
|
156
|
+
@dict ? forward_dict(obj) : begin
|
157
|
+
pos = obj.position_and_offset if @pos
|
158
|
+
|
159
|
+
obj.is_a?(Token) ? forward_vector(obj, pos) :
|
160
|
+
obj.get_class(@lex).each { |lex| forward_vector(lex, pos, lex.src) }
|
146
161
|
end
|
147
162
|
end
|
148
163
|
|
149
164
|
private
|
150
165
|
|
151
|
-
def
|
152
|
-
|
153
|
-
|
154
|
-
|
155
|
-
|
156
|
-
|
166
|
+
def vectors(docnum = nil)
|
167
|
+
@vectors[docnum || @docnum]
|
168
|
+
end
|
169
|
+
|
170
|
+
def word_count(docnum = nil)
|
171
|
+
@word_count[docnum || @docnum]
|
172
|
+
end
|
157
173
|
|
158
|
-
|
159
|
-
|
174
|
+
def forward_dict(obj, sep = DEFAULT_GENDER_SEPARATOR)
|
175
|
+
vectors = obj.get_class(@lex).map { |lex|
|
176
|
+
"#{lex.form} ##{lex.attr}".tap { |str|
|
177
|
+
str << sep << lex.gender if lex.gender
|
178
|
+
}
|
179
|
+
}
|
160
180
|
|
161
|
-
|
162
|
-
|
163
|
-
|
164
|
-
|
181
|
+
unless vectors.empty?
|
182
|
+
vec = @norm ? obj.lexicals.first.form : obj.form
|
183
|
+
forward_vector("#{vec}#{@dict}#{vectors.join(' ')}")
|
184
|
+
end
|
185
|
+
end
|
186
|
+
|
187
|
+
def forward_vector(vec, pos = nil, src = nil)
|
188
|
+
vec = vec.form if vec.is_a?(WordForm)
|
189
|
+
|
190
|
+
vec = Unicode.downcase(vec)
|
191
|
+
vec << @src << src if @src && src
|
192
|
+
|
193
|
+
@sort_fmt ? vectors[vec] << pos : forward(vec_pos(vec, [pos]))
|
194
|
+
end
|
195
|
+
|
196
|
+
def send_vectors
|
197
|
+
if @docnum
|
198
|
+
df, abs = Hash.new(0), @sort_rel ? nil : 1
|
199
|
+
|
200
|
+
@vectors.each_value { |w| w.each_key { |v| df[v] += 1 } }
|
165
201
|
|
166
|
-
if @
|
167
|
-
|
168
|
-
else
|
169
|
-
fmt.insert(1, '2$') << ' %1$s'
|
202
|
+
if @tfidf.is_a?(String)
|
203
|
+
CSV.open(@tfidf, 'wb') { |c| df.sort.each { |v| c << v } }
|
170
204
|
end
|
171
205
|
|
172
|
-
|
206
|
+
yield lambda { |docnum|
|
207
|
+
wc = abs || word_count(docnum)
|
208
|
+
flush_vectors(wc, docnum) { |c, v, vp| [c / df[v], vp] }
|
209
|
+
}
|
210
|
+
elsif @sort_fmt == 'normal'
|
211
|
+
flush(map_vectors { |_, _, vp| vp }.sort!)
|
212
|
+
else
|
213
|
+
flush_vectors(@sort_rel ? word_count : 1) { |c, _, vp| [c, vp] }
|
173
214
|
end
|
215
|
+
|
216
|
+
@word_count.clear
|
217
|
+
@vectors.clear
|
218
|
+
end
|
219
|
+
|
220
|
+
alias_method :flush_deferred, :send_vectors
|
221
|
+
|
222
|
+
def map_vectors(wc = 1, docnum = nil)
|
223
|
+
v = vectors(docnum)
|
224
|
+
v.map { |vec, pos| yield pos.size / wc.to_f, vec, vec_pos(vec, pos) }
|
225
|
+
ensure
|
226
|
+
v.clear if v
|
227
|
+
end
|
228
|
+
|
229
|
+
def flush_vectors(*args, &block)
|
230
|
+
map_vectors(*args, &block)
|
231
|
+
.sort_by { |w, v| [-w, v] }
|
232
|
+
.each { |vec| forward(@sort_fmt % vec) }
|
233
|
+
end
|
234
|
+
|
235
|
+
def vec_pos(vec, pos)
|
236
|
+
pos.clear unless @pos
|
237
|
+
|
238
|
+
pos.compact!
|
239
|
+
pos.uniq!
|
240
|
+
pos.empty? ? vec : "#{vec}#{@pos}#{pos.join(',')}"
|
174
241
|
end
|
175
242
|
|
176
243
|
end
|
@@ -28,6 +28,7 @@ class Lingo
|
|
28
28
|
|
29
29
|
class Attendee
|
30
30
|
|
31
|
+
#--
|
31
32
|
# Der WordSearcher ist das Herzstück von Lingo. Er macht die Hauptarbeit und versucht
|
32
33
|
# alle Token die nach einem sinnvollen Wort aussehen, in den ihm angegebenen
|
33
34
|
# Wörterbüchern zu finden und aufzulösen. Dabei werden die im Wörterbuch gefundenen
|
@@ -64,6 +65,7 @@ class Lingo
|
|
64
65
|
# out> :./PUNC:
|
65
66
|
# out> *EOL('test.txt')
|
66
67
|
# out> *EOF('test.txt')
|
68
|
+
#++
|
67
69
|
|
68
70
|
class WordSearcher < self
|
69
71
|
|
@@ -71,12 +73,12 @@ class Lingo
|
|
71
73
|
set_dic
|
72
74
|
end
|
73
75
|
|
74
|
-
def control(
|
75
|
-
# can control
|
76
|
+
def control(*)
|
76
77
|
end
|
77
78
|
|
78
79
|
def process(obj)
|
79
|
-
forward(obj.is_a?(Token) && obj.word? ?
|
80
|
+
forward(obj.is_a?(Token) && obj.word? ?
|
81
|
+
@dic.find_word(obj.form, obj) : obj)
|
80
82
|
end
|
81
83
|
|
82
84
|
end
|
@@ -33,8 +33,6 @@ class Lingo
|
|
33
33
|
super
|
34
34
|
end
|
35
35
|
|
36
|
-
protected
|
37
|
-
|
38
36
|
def process(obj)
|
39
37
|
@buffer << obj
|
40
38
|
process_buffer if process_buffer?
|
@@ -70,7 +68,7 @@ class Lingo
|
|
70
68
|
end
|
71
69
|
|
72
70
|
def control_multi(cmd)
|
73
|
-
if [
|
71
|
+
if [:RECORD, :EOF].include?(cmd)
|
74
72
|
@eof_handling = true
|
75
73
|
|
76
74
|
while valid_tokens_in_buffer > 1
|
data/lib/lingo/call.rb
CHANGED
@@ -6,7 +6,7 @@
|
|
6
6
|
# Lingo -- A full-featured automatic indexing system #
|
7
7
|
# #
|
8
8
|
# Copyright (C) 2005-2007 John Vorhauer #
|
9
|
-
# Copyright (C) 2007-
|
9
|
+
# Copyright (C) 2007-2014 John Vorhauer, Jens Wille #
|
10
10
|
# #
|
11
11
|
# Lingo is free software; you can redistribute it and/or modify it under the #
|
12
12
|
# terms of the GNU Affero General Public License as published by the Free #
|
@@ -48,8 +48,9 @@ class Lingo
|
|
48
48
|
end
|
49
49
|
end
|
50
50
|
|
51
|
-
def talk(
|
52
|
-
config.stdin.reopen(
|
51
|
+
def talk(input, raw = false)
|
52
|
+
config.stdin.reopen(
|
53
|
+
input.respond_to?(:read) ? input.read : input)
|
53
54
|
|
54
55
|
start
|
55
56
|
|
data/lib/lingo/cli.rb
CHANGED
@@ -6,7 +6,7 @@
|
|
6
6
|
# Lingo -- A full-featured automatic indexing system #
|
7
7
|
# #
|
8
8
|
# Copyright (C) 2005-2007 John Vorhauer #
|
9
|
-
# Copyright (C) 2007-
|
9
|
+
# Copyright (C) 2007-2014 John Vorhauer, Jens Wille #
|
10
10
|
# #
|
11
11
|
# Lingo is free software; you can redistribute it and/or modify it under the #
|
12
12
|
# terms of the GNU Affero General Public License as published by the Free #
|
@@ -50,6 +50,10 @@ class Lingo
|
|
50
50
|
|
51
51
|
private
|
52
52
|
|
53
|
+
def config_present?(config)
|
54
|
+
Lingo.find(:config, config) {}
|
55
|
+
end
|
56
|
+
|
53
57
|
def load_config(*)
|
54
58
|
@config = {}
|
55
59
|
end
|
data/lib/lingo/config.rb
CHANGED
@@ -6,7 +6,7 @@
|
|
6
6
|
# Lingo -- A full-featured automatic indexing system #
|
7
7
|
# #
|
8
8
|
# Copyright (C) 2005-2007 John Vorhauer #
|
9
|
-
# Copyright (C) 2007-
|
9
|
+
# Copyright (C) 2007-2015 John Vorhauer, Jens Wille #
|
10
10
|
# #
|
11
11
|
# Lingo is free software; you can redistribute it and/or modify it under the #
|
12
12
|
# terms of the GNU Affero General Public License as published by the Free #
|
@@ -32,7 +32,7 @@ class Lingo
|
|
32
32
|
class Config
|
33
33
|
|
34
34
|
def initialize(*args)
|
35
|
-
@deprecated = Hash.
|
35
|
+
@deprecated = Hash.seen
|
36
36
|
|
37
37
|
@cli, @opts = CLI.new, {}
|
38
38
|
|
@@ -42,7 +42,9 @@ class Lingo
|
|
42
42
|
load_config('language', :lang)
|
43
43
|
load_config('config')
|
44
44
|
|
45
|
-
|
45
|
+
if Array(self['meeting/attendees']).flat_map(&:keys).include?('textreader')
|
46
|
+
deprecate(:textreader, :text_reader)
|
47
|
+
end
|
46
48
|
|
47
49
|
if r = get('meeting/attendees', 'text_reader') ||
|
48
50
|
get('meeting/attendees', 'textreader') # DEPRECATE textreader
|
@@ -56,6 +58,8 @@ class Lingo
|
|
56
58
|
end
|
57
59
|
end
|
58
60
|
|
61
|
+
attr_reader :language_file, :config_file
|
62
|
+
|
59
63
|
def to_h
|
60
64
|
@opts
|
61
65
|
end
|
@@ -106,10 +110,10 @@ class Lingo
|
|
106
110
|
@cli.send(:quit, *args)
|
107
111
|
end
|
108
112
|
|
109
|
-
def deprecate(old, new, obj = self)
|
113
|
+
def deprecate(old, new, obj = self, what = :option)
|
110
114
|
unless @deprecated[[source = obj.class.name.sub(/\ALingo::/, ''), old]]
|
111
115
|
warn(
|
112
|
-
"DEPRECATION WARNING: #{source}
|
116
|
+
"DEPRECATION WARNING: #{source} #{what} `#{old}' is deprecated " <<
|
113
117
|
"and will be removed in Lingo 1.9. Please use `#{new}' instead."
|
114
118
|
)
|
115
119
|
end
|
@@ -127,6 +131,8 @@ class Lingo
|
|
127
131
|
|
128
132
|
def load_config(key, type = key.to_sym)
|
129
133
|
file = Lingo.find(type, @opts[key]) { quit }
|
134
|
+
instance_variable_set("@#{type}_file", file)
|
135
|
+
|
130
136
|
File.open(file, encoding: ENC) { |f| @opts.update(SafeYAML.load(f)) }
|
131
137
|
rescue Psych::SyntaxError => err
|
132
138
|
err.message << " (in #{file})"
|
data/lib/lingo/ctl.rb
CHANGED
@@ -38,8 +38,8 @@ class Lingo
|
|
38
38
|
PROG, VERSION, OPTWIDTH = $0, '0.0.2', 18
|
39
39
|
PROGNAME, OPTIONS = File.basename(PROG), {}
|
40
40
|
|
41
|
-
COMMANDS, ALIASES = {}, Hash.
|
42
|
-
|
41
|
+
COMMANDS, ALIASES = {}, Hash.nest { |k|
|
42
|
+
COMMANDS.key?(k) ? k : 'usage'
|
43
43
|
}
|
44
44
|
|
45
45
|
USAGE = <<-EOT
|
@@ -187,7 +187,7 @@ Usage: #{PROG} <command> [arguments] [options]
|
|
187
187
|
|
188
188
|
msg = opts ? [opts, 'Commands:'] : []
|
189
189
|
|
190
|
-
aliases = Hash.
|
190
|
+
aliases = Hash.nest { [] }
|
191
191
|
ALIASES.each { |k, v| aliases[v] << k }
|
192
192
|
|
193
193
|
COMMANDS.each { |c, (d, *e)|
|