latinverb 0.2.0 → 0.9.2

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.
Files changed (51) hide show
  1. data/.gitignore +0 -1
  2. data/Gemfile +1 -2
  3. data/README.markdown +54 -240
  4. data/etc/irreg_skel.json +104 -0
  5. data/{latinirb.gemspec → latinverb.gemspec} +4 -4
  6. data/lib/latinverb/chart.rb +94 -0
  7. data/lib/latinverb/version.rb +10 -0
  8. data/lib/latinverb.rb +710 -0
  9. data/lib/linguistics/latin/verb/classification_types.rb +59 -0
  10. data/lib/linguistics/latin/verb/constants.rb +201 -0
  11. data/lib/linguistics/latin/verb/deponent_tense_methods.rb +98 -0
  12. data/lib/linguistics/latin/verb/infinitives.rb +212 -0
  13. data/lib/linguistics/latin/verb/irregulars.rb +4393 -0
  14. data/lib/linguistics/latin/verb/latinverb/auxiliary_classes.rb +208 -0
  15. data/lib/linguistics/latin/verb/latinverb/classmethods.rb +215 -0
  16. data/lib/linguistics/latin/verb/latinverb/data.rb +90 -0
  17. data/lib/linguistics/latin/verb/latinverb/display.rb +23 -0
  18. data/lib/linguistics/latin/verb/latinverb/metaprogramming.rb +79 -0
  19. data/lib/linguistics/latin/verb/latinverb/validation.rb +66 -0
  20. data/lib/linguistics/latin/verb/participles.rb +202 -0
  21. data/lib/linguistics/latin/verb/phonographia.rb +109 -0
  22. data/lib/linguistics/latin/verb/supine.rb +42 -0
  23. data/lib/linguistics/latin/verb/tense_methods.rb +950 -0
  24. data/test/testAmbiguousLookups.rb +30 -0
  25. data/test/testClusterResolution.rb +20 -0
  26. data/test/testDataStructures.rb +29 -0
  27. data/test/testDefectSemiImp.rb +111 -0
  28. data/test/testDeponentFirstConjugation.rb +64 -0
  29. data/test/testDeponentFourthConjugation.rb +64 -0
  30. data/test/testDeponentSecondConjugation.rb +64 -0
  31. data/test/testDeponentThirdConjugation.rb +64 -0
  32. data/test/testDeponentThirdIOConjugation.rb +64 -0
  33. data/test/testDeserializeInfinitives.rb +38 -0
  34. data/test/testFirstConjugation.rb +388 -0
  35. data/test/testFourthConjugation.rb +190 -0
  36. data/test/testFreakishVerbs.rb +93 -0
  37. data/test/testImperativeBlock.rb +27 -0
  38. data/test/testIrregularSum.rb +22 -0
  39. data/test/testIrregulars.rb +652 -0
  40. data/test/testLatinVerb.rb +195 -0
  41. data/test/testMacronRules.rb +19 -0
  42. data/test/testSecondConjugation.rb +189 -0
  43. data/test/testThirdConjugation.rb +190 -0
  44. data/test/testThirdIOConjugation.rb +190 -0
  45. metadata +70 -18
  46. data/bin/latinirb.rb +0 -7
  47. data/latinverb.rb +0 -544
  48. data/lib/LatinIRB.rb +0 -172
  49. data/lib/latinirb/paradigmatic_verbs.rb +0 -17
  50. data/lib/latinirb/version.rb +0 -10
  51. 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