latinverb 0.2.0 → 0.9.2
Sign up to get free protection for your applications and to get access to all the features.
- data/.gitignore +0 -1
- data/Gemfile +1 -2
- data/README.markdown +54 -240
- data/etc/irreg_skel.json +104 -0
- data/{latinirb.gemspec → latinverb.gemspec} +4 -4
- data/lib/latinverb/chart.rb +94 -0
- data/lib/latinverb/version.rb +10 -0
- data/lib/latinverb.rb +710 -0
- data/lib/linguistics/latin/verb/classification_types.rb +59 -0
- data/lib/linguistics/latin/verb/constants.rb +201 -0
- data/lib/linguistics/latin/verb/deponent_tense_methods.rb +98 -0
- data/lib/linguistics/latin/verb/infinitives.rb +212 -0
- data/lib/linguistics/latin/verb/irregulars.rb +4393 -0
- data/lib/linguistics/latin/verb/latinverb/auxiliary_classes.rb +208 -0
- data/lib/linguistics/latin/verb/latinverb/classmethods.rb +215 -0
- data/lib/linguistics/latin/verb/latinverb/data.rb +90 -0
- data/lib/linguistics/latin/verb/latinverb/display.rb +23 -0
- data/lib/linguistics/latin/verb/latinverb/metaprogramming.rb +79 -0
- data/lib/linguistics/latin/verb/latinverb/validation.rb +66 -0
- data/lib/linguistics/latin/verb/participles.rb +202 -0
- data/lib/linguistics/latin/verb/phonographia.rb +109 -0
- data/lib/linguistics/latin/verb/supine.rb +42 -0
- data/lib/linguistics/latin/verb/tense_methods.rb +950 -0
- data/test/testAmbiguousLookups.rb +30 -0
- data/test/testClusterResolution.rb +20 -0
- data/test/testDataStructures.rb +29 -0
- data/test/testDefectSemiImp.rb +111 -0
- data/test/testDeponentFirstConjugation.rb +64 -0
- data/test/testDeponentFourthConjugation.rb +64 -0
- data/test/testDeponentSecondConjugation.rb +64 -0
- data/test/testDeponentThirdConjugation.rb +64 -0
- data/test/testDeponentThirdIOConjugation.rb +64 -0
- data/test/testDeserializeInfinitives.rb +38 -0
- data/test/testFirstConjugation.rb +388 -0
- data/test/testFourthConjugation.rb +190 -0
- data/test/testFreakishVerbs.rb +93 -0
- data/test/testImperativeBlock.rb +27 -0
- data/test/testIrregularSum.rb +22 -0
- data/test/testIrregulars.rb +652 -0
- data/test/testLatinVerb.rb +195 -0
- data/test/testMacronRules.rb +19 -0
- data/test/testSecondConjugation.rb +189 -0
- data/test/testThirdConjugation.rb +190 -0
- data/test/testThirdIOConjugation.rb +190 -0
- metadata +70 -18
- data/bin/latinirb.rb +0 -7
- data/latinverb.rb +0 -544
- data/lib/LatinIRB.rb +0 -172
- data/lib/latinirb/paradigmatic_verbs.rb +0 -17
- data/lib/latinirb/version.rb +0 -10
- data/lib/latirb.rb +0 -20
data/latinverb.rb
DELETED
@@ -1,544 +0,0 @@
|
|
1
|
-
# encoding: utf-8
|
2
|
-
|
3
|
-
module Latin
|
4
|
-
|
5
|
-
=begin rdoc
|
6
|
-
|
7
|
-
== Description
|
8
|
-
|
9
|
-
LatinVerb is a class for turning a given 4-part string of:
|
10
|
-
|
11
|
-
* active voice, present, first person singular: amō, or amo
|
12
|
-
* present, active infinitive: amāre, or amare
|
13
|
-
* present, perfect, first person singular: amāvī, or amavi
|
14
|
-
* perfect passive participle: amatum, or amatus
|
15
|
-
|
16
|
-
Into a fully-exploded, fully conjugated Latin verb ( like you would see in
|
17
|
-
chart forms on Wikipedia et in locis alteriis.
|
18
|
-
|
19
|
-
These are traditionally given in Wheelock as:
|
20
|
-
<tt>amō, amāre, amāvī, amatum</tt>
|
21
|
-
|
22
|
-
Philosophically, in this class, we keep attributes and methods which are
|
23
|
-
used to define the meta-structure of the verb. The specific verb calls
|
24
|
-
("Give me the present active participles" or "Give me the present tense
|
25
|
-
active indicative class") are handled metaprogrammatically and held
|
26
|
-
in Latin::LatinConjugation.
|
27
|
-
|
28
|
-
=end
|
29
|
-
|
30
|
-
|
31
|
-
class LatinVerb < Latin::LatinWord
|
32
|
-
include Latin::Conjugation
|
33
|
-
include Latin::Display
|
34
|
-
=begin
|
35
|
-
|
36
|
-
Scalar, created during initialization
|
37
|
-
These are iVar's pointing to the “four principal parts” of a Latin
|
38
|
-
verb.
|
39
|
-
|
40
|
-
=end
|
41
|
-
|
42
|
-
attr_reader :first_pers_singular, :pres_act_inf,
|
43
|
-
:first_pers_perf, :pass_perf_part, :conjugation
|
44
|
-
|
45
|
-
=begin
|
46
|
-
|
47
|
-
Conjugation state, set by metapgrogrammatically handling the method
|
48
|
-
call. Latin verbs have voice, mood, tense, number, and person. The
|
49
|
-
:voice, :mood, etc. iVars will trap this. The default mode
|
50
|
-
use case is to return all number / person “nodes” in a given
|
51
|
-
tense. As such, the number and person are not stored here as iVars.
|
52
|
-
|
53
|
-
=end
|
54
|
-
|
55
|
-
attr_reader :voice, :mood, :tense, :number, :person
|
56
|
-
|
57
|
-
=begin
|
58
|
-
|
59
|
-
Here are iVars that are used in calculation of nodes.
|
60
|
-
|
61
|
-
Stem is a place to store the verb stem e.g. amare=>ama, dicere => dic
|
62
|
-
Vector is the original method that's passed. As mentioned above, we
|
63
|
-
take a metaprogrammatic approach to handling method calls to the
|
64
|
-
object. @vector records the method call that is trapped by
|
65
|
-
method_missing?(id,*opts)
|
66
|
-
|
67
|
-
Participal stem is used as the base for forming participles.
|
68
|
-
|
69
|
-
Response is stored. It is a hash
|
70
|
-
with only one pair: the name of the collection accessed, and the block
|
71
|
-
of nodes ( or a single node, if it has been defined in such an
|
72
|
-
explicit fashion )
|
73
|
-
|
74
|
-
Collections is is where the displayable payload is stored.
|
75
|
-
|
76
|
-
=end
|
77
|
-
|
78
|
-
attr_reader :stem, :participial_stem, :vector, :response,
|
79
|
-
:collections
|
80
|
-
|
81
|
-
=begin
|
82
|
-
|
83
|
-
Array
|
84
|
-
|
85
|
-
Four_pp is an aray of the four principal parts ( headers on listings)
|
86
|
-
|
87
|
-
=end
|
88
|
-
|
89
|
-
attr_reader :four_pp
|
90
|
-
|
91
|
-
=begin
|
92
|
-
|
93
|
-
##############################################################################
|
94
|
-
METHOD DECLARATION
|
95
|
-
##############################################################################
|
96
|
-
|
97
|
-
=end
|
98
|
-
|
99
|
-
=begin rdoc
|
100
|
-
|
101
|
-
<b>Arguments</b>: Array containing 4 principal parts
|
102
|
-
|
103
|
-
<b>Attribs Used</b>: N/A
|
104
|
-
|
105
|
-
<b>Attribs Set</b>: @four_pp, @first_pers_singular, @pres_act_inf,
|
106
|
-
@first_pers_perf, @pass_perf_part, @four_pp,
|
107
|
-
@voice_mood_matrix, @stem ( via #calculate_stem)
|
108
|
-
|
109
|
-
*Returns*: Instance of LatinVerb
|
110
|
-
|
111
|
-
*Purpose*: A LatinVerb is created by passing an array of the four principal
|
112
|
-
parts that define a Latin Verb. Typically these are: They are defined in an array:
|
113
|
-
<tt>amō amāre amāvī amatum</tt>.
|
114
|
-
|
115
|
-
=end
|
116
|
-
|
117
|
-
def initialize(*params)
|
118
|
-
|
119
|
-
# Creates an array of LatinWords for each of the passed-in parameters
|
120
|
-
# Each principal part is given its own iVar
|
121
|
-
|
122
|
-
@four_pp = params[0].map { |a_principal_part| Latin::LatinWord.new(a_principal_part) }
|
123
|
-
|
124
|
-
if @four_pp.length != 4
|
125
|
-
deponent_handler if @four_pp[2] =~ /sum$/
|
126
|
-
end
|
127
|
-
|
128
|
-
irregular_handler(@four_pp[1])
|
129
|
-
|
130
|
-
|
131
|
-
@first_pers_singular, @pres_act_inf,
|
132
|
-
@first_pers_perf, @pass_perf_part = @four_pp
|
133
|
-
|
134
|
-
# Create a top-level matrix that defines active_indicative /
|
135
|
-
# passive_indicative, etc.
|
136
|
-
#
|
137
|
-
# ____________
|
138
|
-
# | | X | Y |
|
139
|
-
# | 1 | a | b |
|
140
|
-
# | 2 | c | d |
|
141
|
-
# -------------
|
142
|
-
#
|
143
|
-
# In this case we have “voice by mood”
|
144
|
-
|
145
|
-
@voice_mood_matrix = TenseBlock.new( {
|
146
|
-
:boundaries => 'voice by mood',
|
147
|
-
:voice => %w(Active Passive),
|
148
|
-
:mood => %w(Indicative Subjunctive),
|
149
|
-
:tense => nil,
|
150
|
-
:default_p => lambda {
|
151
|
-
|x,y| "#{x.downcase}_voice_#{y.downcase}_mood"
|
152
|
-
}
|
153
|
-
}
|
154
|
-
)
|
155
|
-
|
156
|
-
# Given the 4 PP's, we can now derive the stem
|
157
|
-
@stem = Latin::LatinWord.new(calculate_stem)
|
158
|
-
|
159
|
-
# Set my conjugation
|
160
|
-
@conjugation = evaluate_conjugation
|
161
|
-
|
162
|
-
# Calculate participal stem
|
163
|
-
@participial_stem = Latin::LatinWord.new(calculate_participial_stem)
|
164
|
-
|
165
|
-
# Where to store things to-be displayed
|
166
|
-
@collections = []
|
167
|
-
|
168
|
-
|
169
|
-
end
|
170
|
-
|
171
|
-
=begin rdoc
|
172
|
-
|
173
|
-
*Arguments*: Unrecognized method call, optional arguments
|
174
|
-
|
175
|
-
<b>Attribs Used</b>: N/A
|
176
|
-
|
177
|
-
<b>Attribs Set</b>: @vector
|
178
|
-
|
179
|
-
*Returns*: Instance of LatinVerb
|
180
|
-
|
181
|
-
*Purpose*: The method calls to a verb object can vary in over 100 ways, as such, coding that many methods seemed painful. Accordingly, we trap the unknown method call, parse it, and set iVars.
|
182
|
-
|
183
|
-
Having identified the iVars, we are able to call a hash structure
|
184
|
-
containing lambdas to do the appropriate processing based on the “vector”
|
185
|
-
of voice, mood, tense, person, etc.
|
186
|
-
|
187
|
-
=end
|
188
|
-
def method_missing(id, *args)
|
189
|
-
# We expect that method calls will be made to the object in the form:
|
190
|
-
# V.active_voice_indicative_mood_present_tense. Instead of having to
|
191
|
-
# create all these methods, we will look for unknown methods containing
|
192
|
-
# the pattern _voice_
|
193
|
-
|
194
|
-
if id.to_s =~ /_voice_/
|
195
|
-
|
196
|
-
@vector = id.to_s
|
197
|
-
|
198
|
-
# This assignation needs to be done each call to the metaprog.
|
199
|
-
# method because of the event that a verb was called for
|
200
|
-
# a tense vector, and then a node vector. The first instance's
|
201
|
-
# filling in of @number, @person will cause the second call to do
|
202
|
-
# the wrong thing
|
203
|
-
|
204
|
-
@number = @person = nil
|
205
|
-
evaluate_method(id)
|
206
|
-
|
207
|
-
# In the case that the instance has been used before to get
|
208
|
-
# a specific vector, then we want to clear it out
|
209
|
-
@collections=[] if not @person.nil? and not @collections.nil?
|
210
|
-
|
211
|
-
generated_method = [@voice,@mood,@tense].join('_').to_sym
|
212
|
-
|
213
|
-
raise("Method #{generated_method.to_} is not responded to!") unless
|
214
|
-
self.respond_to?(generated_method)
|
215
|
-
|
216
|
-
raise ("FLAMING DETH: pass to handler method returned nothing!") if
|
217
|
-
self.send(generated_method.to_sym).nil?
|
218
|
-
|
219
|
-
|
220
|
-
@collections <<
|
221
|
-
conjoin_nodes_with_labels(
|
222
|
-
self.send(generated_method),
|
223
|
-
TenseBlock.new( {
|
224
|
-
:boundaries => 'numbers by persons',
|
225
|
-
:numbers => %w(Singular Plural),
|
226
|
-
:persons => %w(First Second Third),
|
227
|
-
:tense => 'present',
|
228
|
-
}
|
229
|
-
)
|
230
|
-
)
|
231
|
-
else
|
232
|
-
super(id)
|
233
|
-
end
|
234
|
-
end
|
235
|
-
|
236
|
-
def to_s
|
237
|
-
display!("\n")
|
238
|
-
end
|
239
|
-
|
240
|
-
def definition_string
|
241
|
-
return @four_pp.join(', ').to_s
|
242
|
-
end
|
243
|
-
=begin
|
244
|
-
|
245
|
-
##############################################################################
|
246
|
-
# PRIVATE METHODS BELOW
|
247
|
-
##############################################################################
|
248
|
-
|
249
|
-
=end
|
250
|
-
private
|
251
|
-
|
252
|
-
=begin rdoc
|
253
|
-
|
254
|
-
*Arguments*: None
|
255
|
-
|
256
|
-
*Attribs Used*: @pres_act_inf
|
257
|
-
|
258
|
-
*Attribs Set*: None
|
259
|
-
|
260
|
-
*Returns*: The “stem” of a Latin Verb
|
261
|
-
|
262
|
-
*Purpose*: Based on the present active infinitive, identify the “stem” and set the @stem iVar.
|
263
|
-
The method also returns the stem value.
|
264
|
-
|
265
|
-
=end
|
266
|
-
|
267
|
-
def calculate_stem
|
268
|
-
# For efficiency, if the iVar @stem is defined, don't go through this structure
|
269
|
-
|
270
|
-
pres_act_inf = @pres_act_inf.to_s
|
271
|
-
|
272
|
-
if pres_act_inf =~ /āre$/
|
273
|
-
return pres_act_inf.gsub(/(.*)āre$/,'\\1ā')
|
274
|
-
end
|
275
|
-
if pres_act_inf =~ /ēre$/
|
276
|
-
return pres_act_inf.gsub(/(.*)ēre$/,'\\1ē')
|
277
|
-
end
|
278
|
-
if pres_act_inf =~ /ere$/
|
279
|
-
if @first_pers_singular =~ /io$/
|
280
|
-
return pres_act_inf.gsub(/(.*)ere$/,'\\1')
|
281
|
-
else
|
282
|
-
return pres_act_inf.gsub(/(.*)ere$/,'\\1')
|
283
|
-
end
|
284
|
-
end
|
285
|
-
if pres_act_inf =~ /īre$/
|
286
|
-
return pres_act_inf.gsub(/(.*)īre$/,'\\1')
|
287
|
-
end
|
288
|
-
end
|
289
|
-
|
290
|
-
=begin rdoc
|
291
|
-
|
292
|
-
|
293
|
-
*Arguments*: None
|
294
|
-
|
295
|
-
*Attribs Used*: @pres_act_inf
|
296
|
-
|
297
|
-
*Attribs Set*: @conjugation
|
298
|
-
|
299
|
-
*Returns*: The “stem” of a Latin Verb
|
300
|
-
|
301
|
-
*Purpose*: Based on the present, active infinitive, decide on the conjugation. This method requires that the endings be macron-ized in order to differentiate between _ere_ ( 2nd conjugation ) and _ere_ ( 4th conjugation). It returns the value as a String: <tt>1</tt>, <tt>2</tt>, <tt>3</tt>, <tt>4</tt>, or <tt>3IO</tt> (e.g. <i>duco/ducere</i>)
|
302
|
-
|
303
|
-
=end
|
304
|
-
|
305
|
-
def evaluate_conjugation
|
306
|
-
ending = @pres_act_inf.get_last_three_characters
|
307
|
-
returnValue = nil
|
308
|
-
|
309
|
-
if ending =~ /āre$/
|
310
|
-
returnValue = "1"
|
311
|
-
end
|
312
|
-
|
313
|
-
if ending =~ /ēre$/
|
314
|
-
returnValue = "2"
|
315
|
-
end
|
316
|
-
|
317
|
-
if ending =~ /ere$/
|
318
|
-
if @first_pers_singular.get_last_three_characters =~ /iō$/
|
319
|
-
returnValue = "3IO"
|
320
|
-
else
|
321
|
-
returnValue = "3"
|
322
|
-
end
|
323
|
-
end
|
324
|
-
|
325
|
-
if ending =~ /īre$/
|
326
|
-
returnValue = "4"
|
327
|
-
end
|
328
|
-
|
329
|
-
return returnValue
|
330
|
-
end
|
331
|
-
|
332
|
-
=begin rdoc
|
333
|
-
|
334
|
-
Calculate the participial stem, used in forming participles.
|
335
|
-
|
336
|
-
=end
|
337
|
-
|
338
|
-
def calculate_participial_stem
|
339
|
-
raise("@pres_act_inf was nil!") if
|
340
|
-
@pres_act_inf.nil? or @first_pers_singular.nil?
|
341
|
-
|
342
|
-
if @pres_act_inf.to_s =~ /(.*ā)re$/
|
343
|
-
return $1
|
344
|
-
end
|
345
|
-
|
346
|
-
if @pres_act_inf.to_s =~ /(.*ē)re$/
|
347
|
-
return $1
|
348
|
-
end
|
349
|
-
|
350
|
-
if @pres_act_inf.to_s =~ /(.*)ere$/
|
351
|
-
match=$1
|
352
|
-
if @first_pers_singular =~ /iō/
|
353
|
-
return match + "iē"
|
354
|
-
else
|
355
|
-
return match + "e"
|
356
|
-
end
|
357
|
-
end
|
358
|
-
|
359
|
-
if @pres_act_inf.to_s =~ /(.*)īre$/
|
360
|
-
return $1 + "iē"
|
361
|
-
end
|
362
|
-
end
|
363
|
-
|
364
|
-
|
365
|
-
=begin
|
366
|
-
|
367
|
-
This is used to print out a full vector's nodes. The value
|
368
|
-
of @vector is used as a title. The nodes that were produced
|
369
|
-
by means of the lambda are then printed out.
|
370
|
-
|
371
|
-
=end
|
372
|
-
|
373
|
-
def conjoin_nodes_with_labels(nodes,labels)
|
374
|
-
raise "conjoin_nodes failed to receieve a node or label set" if
|
375
|
-
nodes.nil? or labels.nil?
|
376
|
-
paired_node_array=[]
|
377
|
-
|
378
|
-
0.upto(labels.length-1) do |i|
|
379
|
-
paired_node_array.push(Latin::LatinNode.new(labels.matrix[i],
|
380
|
-
nodes[i], {:displayable => 'valuesonly'}) )
|
381
|
-
end
|
382
|
-
|
383
|
-
tense_label = @vector.capitalize!.split(/_/).join(' ')
|
384
|
-
|
385
|
-
full_tense = Latin::LatinTense.new(tense_label, paired_node_array)
|
386
|
-
|
387
|
-
if @person.nil? and @number.nil? # For handling ...present_tense
|
388
|
-
return full_tense
|
389
|
-
elsif @number.nil? and not @person.nil? # number not defined; person yes
|
390
|
-
|
391
|
-
# Find the methods that match the parameter that we were given
|
392
|
-
matching_methods =
|
393
|
-
full_tense.verb_methods.map {|x| x if x =~ /#{@person}/}.compact!
|
394
|
-
|
395
|
-
# Call those methods and store the result to an array
|
396
|
-
ambiguous_results =
|
397
|
-
matching_methods.map{|aMethod| full_tense.send(aMethod.to_sym)}
|
398
|
-
|
399
|
-
# Return it
|
400
|
-
return ambiguous_results.join(", ")
|
401
|
-
elsif not @number.nil? and @person.nil?
|
402
|
-
# This guy is really just the inverse of the above.
|
403
|
-
|
404
|
-
# Find the methods that match the parameter that we were given
|
405
|
-
matching_methods =
|
406
|
-
full_tense.verb_methods.map {|x| x if x =~ /#{@number}/}.compact!
|
407
|
-
|
408
|
-
# Call those methods and store the result to an array
|
409
|
-
ambiguous_results =
|
410
|
-
matching_methods.map{|aMethod| full_tense.send(aMethod.to_sym)}
|
411
|
-
|
412
|
-
# Return it
|
413
|
-
return ambiguous_results.join(", ")
|
414
|
-
|
415
|
-
elsif not @number.nil? and not @person.nil? # fully specified node
|
416
|
-
locate_string = [@number,'number',@person,'person',].join('_')
|
417
|
-
return full_tense.send(locate_string.to_sym)
|
418
|
-
end
|
419
|
-
|
420
|
-
end
|
421
|
-
|
422
|
-
# This method is used internally to evaluate a method call that looks like
|
423
|
-
# a request for a conjugation. The first descriptor pair is chopped off
|
424
|
-
# from the given 'name' and the rest is held. The given is sent through
|
425
|
-
# is recognized? where, if valid, an iVar is set.
|
426
|
-
#
|
427
|
-
# e.g. active_voice performs @voice=active
|
428
|
-
#
|
429
|
-
# Failure to successfully classify raises an exception
|
430
|
-
#
|
431
|
-
# If there is anything left in 'rest', then the function is recursively
|
432
|
-
# called with 'rest'.
|
433
|
-
#
|
434
|
-
|
435
|
-
def evaluate_method(name)
|
436
|
-
command = name.to_s.match(/(\w+?_){2}/).to_s
|
437
|
-
rest = name.to_s[command.to_s.length..name.to_s.length]
|
438
|
-
|
439
|
-
# If you're at the last term, command does not get loaded
|
440
|
-
# but rest stays the same.
|
441
|
-
if command !~ /\w/ and name == rest
|
442
|
-
command = rest
|
443
|
-
rest = nil
|
444
|
-
end
|
445
|
-
|
446
|
-
# We've reached the end
|
447
|
-
return if command !~ /\w/ and rest !~ /\w/
|
448
|
-
|
449
|
-
# Recurse
|
450
|
-
evaluate_method(rest) if is_recognized?(command)
|
451
|
-
|
452
|
-
end
|
453
|
-
|
454
|
-
# Given a string of the form "active_voice" ( or a "value/term" pair )
|
455
|
-
# test its validity by Object.send(term.to_sym, value).
|
456
|
-
|
457
|
-
def is_recognized?(datum)
|
458
|
-
value, term = datum.split(/_/)
|
459
|
-
term = "calculate_" + term
|
460
|
-
send(term.to_sym, value)
|
461
|
-
|
462
|
-
# Return true, because the 'send' call did not throw an exception
|
463
|
-
return true
|
464
|
-
end
|
465
|
-
|
466
|
-
# Used to set the voice iVar OR raise an exception
|
467
|
-
def calculate_voice(param)
|
468
|
-
if param =~ /^(active|passive)$/i
|
469
|
-
@voice = param
|
470
|
-
return
|
471
|
-
end
|
472
|
-
raise "Unknown voice: #{param.to_s}, called."
|
473
|
-
end
|
474
|
-
|
475
|
-
# Used to set the voice iVar OR raise an exception
|
476
|
-
def calculate_mood(param)
|
477
|
-
param.gsub!(/\W/, '')
|
478
|
-
if param =~ /(indicative|subjunctive)/i
|
479
|
-
@mood = param.downcase
|
480
|
-
return
|
481
|
-
end
|
482
|
-
raise "Unknown mood: #{param.to_s}, called"
|
483
|
-
end
|
484
|
-
|
485
|
-
# Used to set the voice iVar OR raise an exception
|
486
|
-
def calculate_tense(param)
|
487
|
-
param.downcase!
|
488
|
-
if @mood == "indicative"
|
489
|
-
# All the legitimate moods in the indicative
|
490
|
-
if param == "present" or
|
491
|
-
param == "imperfect" or
|
492
|
-
param == "future" or
|
493
|
-
param == "perfect" or
|
494
|
-
param == "pluperfect" or
|
495
|
-
param == "pastperfect" or
|
496
|
-
param == "futureperfect"
|
497
|
-
@tense = param
|
498
|
-
end
|
499
|
-
elsif @mood == "subjunctive"
|
500
|
-
# All the legitimate moods in the subjunctive
|
501
|
-
if param == "present" or
|
502
|
-
param == "imperfect" or
|
503
|
-
param == "perfect" or
|
504
|
-
param == "pluperfect" or
|
505
|
-
param == "pastperfect"
|
506
|
-
@tense = param
|
507
|
-
end
|
508
|
-
else
|
509
|
-
raise "Tense [#{param}] was found to be invalid."
|
510
|
-
end
|
511
|
-
end
|
512
|
-
|
513
|
-
def calculate_person(param)
|
514
|
-
@person = param.downcase
|
515
|
-
end
|
516
|
-
|
517
|
-
def calculate_number(param)
|
518
|
-
@number = param.downcase
|
519
|
-
end
|
520
|
-
|
521
|
-
def deponent_handler
|
522
|
-
raise "Sorry, we do not handle (semi-) deponent verbs at this time. It's on the TODO list, thought!"
|
523
|
-
end
|
524
|
-
|
525
|
-
def irregular_handler(test_infinitive)
|
526
|
-
if %w(esse nōlle).find{|irregular| test_infinitive.to_s == irregular}
|
527
|
-
raise "Sorry, we do not handle irregular verbs at this time. It's on the TODO list, thought!"
|
528
|
-
end
|
529
|
-
end
|
530
|
-
end # ends the class
|
531
|
-
|
532
|
-
=begin rdoc
|
533
|
-
|
534
|
-
== Dependencies
|
535
|
-
|
536
|
-
None
|
537
|
-
|
538
|
-
== Author
|
539
|
-
|
540
|
-
Steven G. Harms, http://www.stevengharms.com
|
541
|
-
|
542
|
-
=end
|
543
|
-
end
|
544
|
-
|
data/lib/LatinIRB.rb
DELETED
@@ -1,172 +0,0 @@
|
|
1
|
-
#!/usr/bin/env ruby
|
2
|
-
|
3
|
-
require 'irb'
|
4
|
-
require 'irb/completion'
|
5
|
-
require 'latinverb'
|
6
|
-
require 'latinirb/paradigmatic_verbs'
|
7
|
-
require 'macronconversions'
|
8
|
-
require 'pp'
|
9
|
-
|
10
|
-
# Monkey-patch to change the gets behavior. In the gem, the FileInputMethod
|
11
|
-
# class's 'gets' method always prints out what was read. This should be
|
12
|
-
# suppressed by the IRB class's Context class's ECHO state, but this is not
|
13
|
-
# used, possibly a bug depending on what the semantics of that @echo variable
|
14
|
-
# are meant to mean.
|
15
|
-
|
16
|
-
module IRB
|
17
|
-
class FileInputMethod < InputMethod
|
18
|
-
def gets
|
19
|
-
@io.gets
|
20
|
-
end
|
21
|
-
end
|
22
|
-
end
|
23
|
-
|
24
|
-
module Linguistics
|
25
|
-
module Latin
|
26
|
-
module Util
|
27
|
-
class LatinIRB
|
28
|
-
def self.begin
|
29
|
-
#---
|
30
|
-
#
|
31
|
-
# This method is taken from irb.rb's IRB.start method. I trimmed
|
32
|
-
# out some of the conditional possibilities that I did not want to
|
33
|
-
# handle here (because they're not necessary).
|
34
|
-
#
|
35
|
-
# Run the basic setup script and pull the configuration object
|
36
|
-
# (IRB::Context) back into the present scope. Then we set that
|
37
|
-
# object's options and proceed.
|
38
|
-
#
|
39
|
-
#+++
|
40
|
-
|
41
|
-
IRB.setup(nil)
|
42
|
-
@CONF = IRB.conf
|
43
|
-
|
44
|
-
# This will be the script IRB sources on execution. You can
|
45
|
-
# pre-define variables (@aFirst, etc.) and convenience methods here.
|
46
|
-
|
47
|
-
@CONF[:SCRIPT]="lib/latirb.rb"
|
48
|
-
|
49
|
-
# No, do not tell me what you read in
|
50
|
-
@CONF[:ECHO]=false
|
51
|
-
|
52
|
-
# Nor tell me how it evaluated
|
53
|
-
@CONF[:VERBOSE]=false
|
54
|
-
|
55
|
-
# We need this module
|
56
|
-
@CONF[:LOAD_MODULES]=["latinverb"]
|
57
|
-
|
58
|
-
# Create an irb object that is programmed to (silently, per above)
|
59
|
-
# source a configuration file that ends with a call to 'irb' itself
|
60
|
-
# after defining several instance variables
|
61
|
-
|
62
|
-
irb = IRB::Irb.new(nil, @CONF[:SCRIPT])
|
63
|
-
|
64
|
-
# Create a LatinIRB prompt
|
65
|
-
@CONF[:PROMPT][:LATINIRB] = {
|
66
|
-
:PROMPT_I => "LatinIRB > ",
|
67
|
-
:PROMPT_S => "LatinIRB%l> ",
|
68
|
-
:PROMPT_C => "LatinIRB > ",
|
69
|
-
:PROMPT_N => "LatinIRB ?> ",
|
70
|
-
:RETURN => " => %s \n",
|
71
|
-
:AUTO_INDENT => true
|
72
|
-
}
|
73
|
-
@CONF[:PROMPT_MODE]=:LATINIRB
|
74
|
-
|
75
|
-
# Unless this is set, eval_input will fail. Make sure this is
|
76
|
-
# set.
|
77
|
-
@CONF[:MAIN_CONTEXT] = irb.context
|
78
|
-
|
79
|
-
# This corrects the tab-completion behavior as provided by
|
80
|
-
# irb/completion.rb. In the even that what's tabbed-after matches
|
81
|
-
# the RegExp, it should invoke this process. If the receiver is a
|
82
|
-
# LatinVerb, the full complement of vectors should be provided as
|
83
|
-
# complet-able. IF NOT, then the pairing is passed to the standard
|
84
|
-
# CompletionProc.
|
85
|
-
|
86
|
-
Readline.completion_proc = calculate_completion_proc
|
87
|
-
|
88
|
-
# We have finished the configuration at this point, so now we need
|
89
|
-
# to kick up the REPL after providing preliminary instruction.
|
90
|
-
puts "Beginning a LatinVerb session."
|
91
|
-
|
92
|
-
puts "The following verbs have been made available to this session via latirb.rb:"
|
93
|
-
|
94
|
-
instance_variables.grep(/[a-z]/).each{|x| puts " * #{x}"}
|
95
|
-
|
96
|
-
puts "Tab-completion of the conjugation \"vectors\" is supported."
|
97
|
-
|
98
|
-
trap("SIGINT") do
|
99
|
-
irb.signal_handle
|
100
|
-
end
|
101
|
-
|
102
|
-
begin
|
103
|
-
catch(:IRB_EXIT) do
|
104
|
-
# Start the REPL
|
105
|
-
irb.eval_input
|
106
|
-
end
|
107
|
-
end
|
108
|
-
|
109
|
-
puts "Vale! Come back to LatinIRB soon."
|
110
|
-
end
|
111
|
-
|
112
|
-
##
|
113
|
-
#
|
114
|
-
# Used to override IRB::InputCompletor::select_message for handling
|
115
|
-
# tab-completion of instance variables. Code is largely taken from
|
116
|
-
# that method with the addition of the /^@/ condition. In
|
117
|
-
# IRB::Completor, when an array of matches has been identified, they
|
118
|
-
# are sent as the "candidates" while the "receiver" bears the match
|
119
|
-
# based on the regex of "message."
|
120
|
-
#
|
121
|
-
##
|
122
|
-
|
123
|
-
def self.select_message(receiver, message, candidates)
|
124
|
-
candidates.grep(/^#{message}/).collect do |e|
|
125
|
-
case e
|
126
|
-
when /^[a-zA-Z_]/
|
127
|
-
receiver + "." + e
|
128
|
-
when /^[0-9]/
|
129
|
-
when /^@/
|
130
|
-
e
|
131
|
-
when *Operators
|
132
|
-
#receiver + " " + e
|
133
|
-
end
|
134
|
-
end
|
135
|
-
end
|
136
|
-
|
137
|
-
##
|
138
|
-
#
|
139
|
-
# As part of the TAB completion, Readline must be provided a
|
140
|
-
# completion proc that will be used to generate the matching results
|
141
|
-
# that will be appended to the line at whose end the TAB key was
|
142
|
-
# struck. This method provides that proc.
|
143
|
-
#
|
144
|
-
##
|
145
|
-
|
146
|
-
def self.calculate_completion_proc
|
147
|
-
proc do |input|
|
148
|
-
bind = IRB.conf[:MAIN_CONTEXT].workspace.binding
|
149
|
-
|
150
|
-
input =~ /^([^."].*)\.([^.]*)$/
|
151
|
-
begin
|
152
|
-
receiver = $1
|
153
|
-
message = Regexp.quote($2)
|
154
|
-
rObj = instance_variable_get(receiver.to_sym)
|
155
|
-
rescue Exception
|
156
|
-
end
|
157
|
-
|
158
|
-
if rObj.class == Linguistics::Latin::Verb::LatinVerb
|
159
|
-
IRB::InputCompletor::select_message(receiver, message, rObj.instance_methods.grep(/^#{message}/))
|
160
|
-
elsif input =~ /^@/
|
161
|
-
# This handles instance variables. input is @someInstanceVariable's @aSomeIn<TAB>
|
162
|
-
self.select_message(input, input, eval("instance_variables", bind).grep(/^@a/))
|
163
|
-
else
|
164
|
-
IRB::InputCompletor::CompletionProc.call input
|
165
|
-
end
|
166
|
-
end
|
167
|
-
end
|
168
|
-
|
169
|
-
end
|
170
|
-
end
|
171
|
-
end
|
172
|
-
end
|