latinverb 0.2.0 → 0.9.2

Sign up to get free protection for your applications and to get access to all the features.
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