Commits

Michael Granger  committed adce12f

Documentation fixes, bugfixes

  • Participants
  • Parent commits 8bb3f0e

Comments (0)

Files changed (22)

 }
 
 begin
+	require 'loggability'
+	Loggability.level = :debug
+	Loggability.format_with( :color )
+
 	require 'linguistics'
 	Linguistics.use( :en )
+	# Linguistics.use( :en, monkeypatch: true )
 rescue Exception => err
 	$stderr.puts "Linguistics failed to load: %p: %s" % [ err.class, err.message ]
 	$stderr.puts( err.backtrace )
 the cost of three or four more characters per method invocation. For
 example:
 
-	Linguistics::use( :en )
+	Linguistics.use( :en )
 	"goose".en.plural
 	# => "geese"
 
+If you prefer monkeypatching (around 70) linguistics methods directly onto core
+classes, you can do that by adding a 'monkeypatch' option to ::use:
+
+    Linguistics.use( :en, monkeypatch: true )
+	"goose".plural
+	# => "geese"
+
+=== Controlling Which Classes Get Extended
+
+If you should wish to extend classes other than the ones in
+<tt>Linguistics::DEFAULT_EXT_CLASSES</tt>, you have a few options.
+
+You can modify the DEFAULT_EXT_CLASSES array directly (before you call
+::use, of course):
+
+    Linguistics::DEFAULT_EXT_CLASSES << MyClass
+
+You can also pass an Array of classes to .use:
+
+    Linguistics.use( :en, classes: [MyClass] )
+
+Or you can add language methods to classes via mixin:
+
+    class MyClass
+	    include Linguistics::EN
+	end
+
+All Linguistics methods use Ruby's casting mechanism, so at a minimum,
+your classes should provide an implementation of #to_s that returns
+words or phrases.
+
+
+
 
 === Adding Language Modules
 

File lib/linguistics.rb

 	end
 
 
-	### Add linguistics functions for the specified languages to Ruby's core
-	### classes. The interface to all linguistic functions for a given language
-	### is through a method which is the same the language's international 2- or
-	### 3-letter code (ISO 639). You can also specify a Hash of configuration
-	### options which control which classes are extended:
-	###
-	### [<b>:classes</b>]
-	###   Specify the classes which are to be extended. If this is not specified,
-	###   the Class objects in Linguistics::DEFAULT_EXT_CLASSES (an Array) are
-	###   extended.
-	### [<b>:proxy</b>]
-	###
-	def self::use( *languages )
-		config = {}
-		config = languages.pop if languages.last.is_a?( Hash )
+	### Register a module as providing linguistic functions for the specified +language+ (a two- 
+	### or three-letter ISO639-2 language codes as a Symbol)
+	def self::register_language( language, mod )
+		language_entry = LANGUAGE_CODES[ language.to_sym ] or
+			raise "Unknown ISO639-2 language code '#{language}'"
+		Linguistics.log.info "Registering %s for language %p" % [ mod, language_entry ]
 
-		classes = Array(config[:classes]) if config[:classes] 
-		classes ||= DEFAULT_EXT_CLASSES
+		language_entry[:codes].each do |lang|
+			self.languages[ lang.to_sym ] = mod
+		end
 
-		Linguistics.log.debug "Extending %d classes with %d language modules." %
-			[ classes.length, languages.length ]
-
-		# Mix the language module for each requested language into each
-		# specified class
-		classes.each do |klass|
-			Linguistics.log.debug "  extending %p" % [ klass ]
-			languages.each do |lang|
-				mod = load_language( lang ) or
-					raise LoadError, "failed to load a language extension for %p" % [ lang ]
-				Linguistics.log.debug "    using %s language module: %p" % [ lang, mod ]
-
-				inflector = make_inflector_mixin( lang, mod )
-				Linguistics.log.debug "    made an inflector mixin: %p" % [ inflector ]
-				klass.send( :include, inflector )
+		# Load in plugins for the language
+		Gem.find_files( "linguistics/#{language}/**.rb" ).each do |extension|
+			Linguistics.log.debug "  trying to load #{language_entry[:eng_name]} extension %p" % [ extension ]
+			begin
+				require extension
+			rescue LoadError => err
+				Linguistics.log.debug "    failed (%s): %s %s" %
+					[ err.class.name, err.message, err.backtrace.first ]
+			else
+				Linguistics.log.debug "    success."
 			end
 		end
 
-		return classes
 	end
 
 
 	end
 
 
+	### Add linguistics functions for the specified languages to Ruby's core
+	### classes. The interface to all linguistic functions for a given language
+	### is through a method which is the same the language's international 2- or
+	### 3-letter code (ISO 639). You can also specify a Hash of configuration
+	### options which control which classes are extended:
+	###
+	### [<b>:classes</b>]
+	###   Specify the classes which are to be extended. If this is not specified,
+	###   the Class objects in Linguistics::DEFAULT_EXT_CLASSES (an Array) are
+	###   extended.
+	### [<b>:monkeypatch</b>]
+	###   Monkeypatch directly (albeit responsibly, via a mixin) the specified
+	###   +classes+ instead of adding a single language-code method.
+	def self::use( *languages )
+		config = languages.pop if languages.last.is_a?( Hash )
+		config ||= {}
+
+		classes = Array(config[:classes]) if config[:classes] 
+		classes ||= DEFAULT_EXT_CLASSES
+
+		Linguistics.log.debug "Extending %d classes with %d language modules." %
+			[ classes.length, languages.length ]
+
+		# Mix the language module for each requested language into each
+		# specified class
+		classes.each do |klass|
+			Linguistics.log.debug "  extending %p" % [ klass ]
+			languages.each do |lang|
+				mod = load_language( lang ) or
+					raise LoadError, "failed to load a language extension for %p" % [ lang ]
+				Linguistics.log.debug "    using %s language module: %p" % [ lang, mod ]
+
+				if config[:monkeypatch]
+					klass.send( :include, mod )
+				else
+					inflector = make_inflector_mixin( lang, mod )
+					Linguistics.log.debug "    made an inflector mixin: %p" % [ inflector ]
+					klass.send( :include, inflector )
+				end
+			end
+		end
+
+		return classes
+	end
+
+
 	### Create a mixin module/class pair that act as the per-object interface to
 	### the given language +mod+'s inflector.
 	def self::make_inflector_mixin( lang, mod )
 	end
 
 
-	### Register a module as providing linguistic functions for the specified +language+ (a two- 
-	### or three-letter ISO639-2 language codes as a Symbol)
-	def self::register_language( language, mod )
-		language_entry = LANGUAGE_CODES[ language.to_sym ] or
-			raise "Unknown ISO639-2 language code '#{language}'"
-		Linguistics.log.info "Registering %s for language %p" % [ mod, language_entry ]
-
-		language_entry[:codes].each do |lang|
-			self.languages[ lang.to_sym ] = mod
-		end
-	end
-
 end # module Linguistics
 

File lib/linguistics/en.rb

 #!/usr/bin/ruby
 
+require 'rubygems' # For Gem.find_files
 require 'pathname'
 
 require 'linguistics' unless defined?( Linguistics )
 
+
 # This module is a container for various English-language linguistic
 # functions for the Linguistics library. It can be either loaded
 # directly, or by passing some variant of +:en+ or +:eng+ to the
 # Linguistics.use method.
-# 
+#
 # == Pluralization
-# 
-#  require 'linguistics'
-#  Linguistics::use( :en ) # extends Array, String, and Numeric
-#  
+#
 #  "box".en.plural
 #  # => "boxes"
-#  
+#
 #  "mouse".en.plural
 #  # => "mice"
-#  
+#
 #  "ruby".en.plural
 #  # => "rubies"
-# 
-# 
+#
+#
 # == Indefinite Articles
-# 
+#
 #  "book".en.a
 #  # => "a book"
-#  
+#
 #  "article".en.a
 #  # => "an article"
-# 
-# 
+#
+#
 # == Present Participles
-# 
+#
 #  "runs".en.present_participle
 #  # => "running"
-#  
+#
 #  "eats".en.present_participle
 #  # => "eating"
-#  
+#
 #  "spies".en.present_participle
 #  # => "spying"
-# 
-# 
+#
+#
 # == Ordinal Numbers
-# 
+#
 #  5.en.ordinal
 #  # => "5th"
-#  
+#
 #  2004.en.ordinal
 #  # => "2004th"
-# 
-# 
+#
+#
 # == Numbers to Words
-# 
+#
 #  5.en.numwords
 #  # => "five"
-#  
+#
 #  2004.en.numwords
 #  # => "two thousand and four"
-#  
+#
 #  2385762345876.en.numwords
-#  # => "two trillion, three hundred and eighty-five billion,
-#  seven hundred and sixty-two million, three hundred and
-#  forty-five thousand, eight hundred and seventy-six"
-# 
-# 
+#  # => "two trillion, three hundred and eighty-five billion, seven hundred and
+#  #     sixty-two million, three hundred and forty-five thousand, eight hundred
+#  #     and seventy-six"
+#
+#
 # == Quantification
-# 
+#
 #  "cow".en.quantify( 5 )
 #  # => "several cows"
-#  
+#
 #  "cow".en.quantify( 1005 )
 #  # => "thousands of cows"
-#  
+#
 #  "cow".en.quantify( 20_432_123_000_000 )
 #  # => "tens of trillions of cows"
-# 
-# 
+#
+#
 # == Conjunctions
-# 
-#    animals = %w{dog cow ox chicken goose goat cow dog rooster llama 
-#    pig goat dog cat cat dog cow goat goose goose ox alpaca}
-#    puts "The farm has: " + animals.en.conjunction
-#    
-#    # => The farm has: four dogs, three cows, three geese, three goats,
-#    two oxen, two cats, a chicken, a rooster, a llama, a pig, 
-#    and an alpaca
-# 
+#
+#  animals = %w{dog cow ox chicken goose goat cow dog rooster llama pig goat
+#               dog cat cat dog cow goat goose goose ox alpaca}
+#  "The farm has: " + animals.en.conjunction
+#  # => "The farm has: four dogs, three cows, three geese, three goats, two
+#  #     oxen, two cats, a chicken, a rooster, a llama, a pig, and an alpaca"
+#
 # Note that 'goose' and 'ox' are both correctly pluralized, and the correct
 # indefinite article 'an' has been used for 'alpaca'.
-# 
+#
 # You can also use the generalization function of the #quantify method to give
 # general descriptions of object lists instead of literal counts:
-# 
-#    allobjs = []
-#    ObjectSpace::each_object {|obj| allobjs << obj.class.name}
-#    
-#    puts "The current Ruby objectspace contains: " +
-#      allobjs.en.conjunction( :generalize => true )
-# 
-# which will print something like:
-# 
-#    The current Ruby objectspace contains: thousands of Strings,
-#    thousands of Arrays, hundreds of Hashes, hundreds of
-#    Classes, many Regexps, a number of Ranges, a number of
-#    Modules, several Floats, several Procs, several MatchDatas,
-#    several Objects, several IOS, several Files, a Binding, a
-#    NoMemoryError, a SystemStackError, a fatal, a ThreadGroup,
-#    and a Thread
-# 
-# 
+#
+#  allobjs = []
+#  ObjectSpace::each_object {|obj| allobjs << obj.class.name }
+#  puts "The current Ruby objectspace contains: " +
+#       allobjs.en.conjunction( :generalize => true )
+#
+# Outputs:
+#
+#  The current Ruby objectspace contains: hundreds of thousands of Strings,
+#  thousands of RubyVM::InstructionSequences, thousands of Arrays, thousands
+#  of Hashes, hundreds of Procs, hundreds of Regexps, [...], a
+#  SystemStackError, a Random, an ARGF.class, a Data, a fatal, an
+#  OptionParser::List, a YAML::EngineManager, a URI::Parser, a Rational, and
+#  a Gem::Platform
+#
+#
 # == Infinitives
-# 
-#    "leaving".en.infinitive
-#    # => "leave"
-#    
-#    "left".en.infinitive
-#    # => "leave"
-#    
-#    "leaving".en.infinitive.suffix
-#    # => "ing"
-# 
-# 
+#
+#   "leaving".en.infinitive
+#   # => "leave"
+#
+#   "left".en.infinitive
+#   # => "leave"
+#
+#   "leaving".en.infinitive.suffix
+#   # => "ing"
+#
+#
 # == Conjugation
-# 
+#
 # Conjugate a verb given an infinitive:
-# 
+#
 #   "run".en.past_tense
 #   # => "ran"
-#   
+#
 #   "run".en.past_participle
 #   # => "run"
-# 
+#
 #   "run".en.present_tense
 #   # => "run"
-# 
+#
 #   "run".en.present_participle
 #   # => "running"
-# 
+#
 # Conjugate an infinitive with an explicit tense and grammatical person:
-# 
+#
 #   "be".en.conjugate( :present, :third_person_singular )
 #   # => "is"
-#   
+#
 #   "be".en.conjugate( :present, :first_person_singular )
 #   # => "am"
-#   
+#
 #   "be".en.conjugate( :past, :first_person_singular )
 #   # => "was"
 #
-# The functionality is a port of the verb conjugation portion of Morph 
+# The functionality is a port of the verb conjugation portion of Morph
 # Adorner (http://morphadorner.northwestern.edu/).
-# 
-# It includes a good number of irregular verbs, but it's not going to be 
+#
+# It includes a good number of irregular verbs, but it's not going to be
 # 100% correct everytime.
-# 
-# 
+#
+#
 # == WordNet® Integration
-# 
-# If you have the 'wordnet' gem installed, you can look up WordNet synsets using 
+#
+# If you have the 'wordnet' gem installed, you can look up WordNet synsets using
 # the Linguistics interface:
-# 
-#    # Test to be sure the WordNet module loaded okay.
+#
+# Test to be sure the WordNet module loaded okay.
+#
 #    Linguistics::EN.has_wordnet?
 #    # => true
-#    
-#    # Fetch the default synset for the word "balance"
+#
+# Fetch the default synset for the word "balance"
+#
 #    "balance".en.synset
-#    # => #<WordNet::Synset:0x40376844 balance (noun): "a state of equilibrium"
-#    #   (derivations: 3, antonyms: 1, hypernyms: 1, hyponyms: 3)>
-#    
-#    # Fetch the synset for the first verb sense of "balance"
-#    "balance".en.synset( :verb )
-#    # => #<WordNet::Synset:0x4033f448 balance, equilibrate, equilibrize, equilibrise
-#    #    (verb): "bring into balance or equilibrium; "She has to balance work and her
-#    #    domestic duties"; "balance the two weights"" (derivations: 7, antonyms: 1,
-#    #    verbGroups: 2, hypernyms: 1, hyponyms: 5)>
-#    
-#    # Fetch the second noun sense
-#    "balance".en.synset( 2, :noun )
-#    # => #<WordNet::Synset:0x404ebb24 balance (noun): "a scale for weighing; depends
-#    #    on pull of gravity" (hypernyms: 1, hyponyms: 5)>
-#    
-#    # Fetch the second noun sense's hypernyms (more-general words, like a superclass)
-#    "balance".en.synset( 2, :noun ).hypernyms
-#    # => [#<WordNet::Synset:0x404e5620 scale, weighing machine (noun): "a measuring
-#    #     instrument for weighing; shows amount of mass" (derivations: 2, hypernyms: 1,
-#    #     hyponyms: 2)>]
-#    
-#    # A simpler way of doing the same thing:
-#    "balance".en.hypernyms( 2, :noun )
-#    # => [#<WordNet::Synset:0x404e5620 scale, weighing machine (noun): "a measuring
-#    #     instrument for weighing; shows amount of mass" (derivations: 2, hypernyms: 1,
-#    #     hyponyms: 2)>]
-#    
-#    # Fetch the first hypernym's hypernyms
-#    "balance".en.synset( 2, :noun ).hypernyms.first.hypernyms
-#    # => [#<WordNet::Synset:0x404c60b8 measuring instrument, measuring system,
-#    #     measuring device (noun): "instrument that shows the extent or amount or quantity
-#    #     or degree of something" (hypernyms: 1, hyponyms: 83)>]
-#    
-#    # Find the synset to which both the second noun sense of "balance" and the
-#    # default sense of "shovel" belong.
-#    ("balance".en.synset( 2, :noun ) | "shovel".en.synset)
-#    # => #<WordNet::Synset:0x40473da4 instrumentality, instrumentation (noun): "an
-#    #    artifact (or system of artifacts) that is instrumental in accomplishing some
-#    #    end" (derivations: 1, hypernyms: 1, hyponyms: 13)>
-#    
-#    # Fetch just the words for the other kinds of "instruments"
-#    "instrument".en.hyponyms.collect {|synset| synset.words}.flatten
-#    # => ["analyzer", "analyser", "cautery", "cauterant", "drafting instrument",
-#    #     "extractor", "instrument of execution", "instrument of punishment", "measuring
-#    #     instrument", "measuring system", "measuring device", "medical instrument",
-#    #     "navigational instrument", "optical instrument", "plotter", "scientific
-#    #     instrument", "sonograph", "surveying instrument", "surveyor's instrument",
-#    #     "tracer", "weapon", "arm", "weapon system", "whip"]
-# 
+#    # => #<WordNet::Synset:0x7f9fb11012f8 {102777100} 'balance' (noun):
+#    #    [noun.artifact] a scale for weighing; depends on pull of gravity>
+#
+# Fetch the synset for the first verb sense of "balance"
+#
+#   "balance".en.synset( :verb )
+#   # => #<WordNet::Synset:0x7f9fb10f3fb8 {201602318} 'balance, poise' (verb):
+#   #    [verb.contact] hold or carry in equilibrium>
+#
+# Fetch the second noun sense
+#
+#   "balance".en.synset( 2, :noun )
+#   # => #<WordNet::Synset:0x7f9fb10ebbd8 {102777402} 'balance, balance wheel'
+#   #     (noun): [noun.artifact] a wheel that regulates the rate of movement in a
+#   #     machine; especially a wheel oscillating against the hairspring of a
+#   #     timepiece to regulate its beat>
+#
+# Fetch the second noun sense's hypernyms (more-general words, like a
+# superclass)
+#
+#   "balance".en.synset( 2, :noun ).hypernyms
+#   # => [#<WordNet::Synset:0x7f9fb10dd100 {104574999} 'wheel' (noun):
+#   #    [noun.artifact] a simple machine consisting of a circular frame with
+#   #    spokes (or a solid disc) that can rotate on a shaft or axle (as in
+#   #    vehicles or other machines)>]
+#
+# A simpler way of doing the same thing:
+#
+#   "balance".en.hypernyms( 2, :noun )
+#   # => [#<WordNet::Synset:0x7f9fb10d24d0 {104574999} 'wheel' (noun):
+#   #    [noun.artifact] a simple machine consisting of a circular frame with
+#   #    spokes (or a solid disc) that can rotate on a shaft or axle (as in
+#   #    vehicles or other machines)>]
+#
+# Fetch the first hypernym's hypernyms
+#
+#   "balance".en.synset( 2, :noun ).hypernyms.first.hypernyms
+#   # => [#<WordNet::Synset:0x7f9fb10c5190 {103700963} 'machine, simple machine'
+#   #    (noun): [noun.artifact] a device for overcoming resistance at one point by
+#   #    applying force at some other point>]
+#
+# Find the synset to which both the second noun sense of "balance" and the
+# default sense of "shovel" belong.
+#
+#   ("balance".en.synset( 2, :noun ) | "shovel".en.synset)
+#   # => #<WordNet::Synset:0x7f9fb1091e58 {103183080} 'device' (noun):
+#   #    [noun.artifact] an instrumentality invented for a particular purpose>
+#
+# Fetch words for the specific kinds of (device-ish) "instruments"
+#
+#   "instrument".en.hyponyms( "device" ).collect( &:words ).flatten.join(', ')
+#   # => "analyser, analyzer, cauterant, cautery, drafting instrument, engine,
+#   #    extractor, instrument of execution, instrument of punishment, measuring
+#   #    device, measuring instrument, measuring system, medical instrument,
+#   #    navigational instrument, optical instrument, plotter, scientific
+#   #    instrument, sonograph, surveying instrument, surveyor's instrument,
+#   #    tracer, arm, weapon, weapon system, whip"
+#
+# ...or musical instruments
+#
+#   "instrument".en.hyponyms( "musical" ).collect( &:words ).flatten.join(', ')
+#   # => "barrel organ, grind organ, hand organ, hurdy-gurdy, hurdy gurdy,
+#   #    street organ, bass, calliope, steam organ, electronic instrument,
+#   #    electronic musical instrument, jew's harp, jews' harp, mouth bow, keyboard
+#   #    instrument, music box, musical box, percussion instrument, percussive
+#   #    instrument, stringed instrument, wind, wind instrument"
+#
 # There are many more WordNet methods supported--too many to list here. See the
-# documentation for the complete list.
-# 
-# 
+# WordNet::Synset API documentation for the complete list.
+#
+#
 # == LinkParser Integration
-# 
+#
 # If you have the 'linkparser' gem installed, you can create linkages
 # from English sentences that let you query for parts of speech:
-# 
-#    # Test to see whether or not the link parser is loaded.
-#    Linguistics::EN.has_link_parser?
-#    # => true
-#    
-#    # Diagram the first linkage for a test sentence
-#    puts "he is a big dog".sentence.linkages.first.to_s
-#    #     +---O*---+ 
-#    #     | +--Ds--+ 
-#    #  +Ss+ |  +-A-+ 
-#    #  |  | |  |   | 
-#    # he is a big dog
-#    
-#    # Find the verb in the sentence
-#    "he is a big dog".en.sentence.verb.to_s      
-#    # => "is"
-#    
-#    # Combined infinitive + LinkParser: Find the infinitive form of the verb of the
-#    # given sentence.
-#    "he is a big dog".en.sentence.verb.infinitive
-#    # => "be"
-#    
-#    # Find the direct object of the sentence
-#    "he is a big dog".en.sentence.object.to_s
-#    # => "dog"
-#    
-#    # Look at the raw LinkParser::Word for the direct object of the sentence.
-#    "he is a big dog".en.sentence.object     
-#    # => #<LinkParser::Word:0x403da0a0 @definition=[[{@A-}, Ds-, {@M+}, J-], [{@A-},
-#    #    Ds-, {@M+}, Os-], [{@A-}, Ds-, {@M+}, Ss+, {@CO-}, {C-}], [{@A-}, Ds-, {@M+},
-#    #    Ss+, R-], [{@A-}, Ds-, {@M+}, SIs-], [{@A-}, Ds-, {R+}, {Bs+}, J-], [{@A-}, Ds-,
-#    #    {R+}, {Bs+}, Os-], [{@A-}, Ds-, {R+}, {Bs+}, Ss+, {@CO-}, {C-}], [{@A-}, Ds-,
-#    #    {R+}, {Bs+}, Ss+, R-], [{@A-}, Ds-, {R+}, {Bs+}, SIs-]], @right=[], @suffix="",
-#    #    @left=[#<LinkParser::Connection:0x403da028 @rword=#<LinkParser::Word:0x403da0a0
-#    #    ...>, @lword=#<LinkParser::Word:0x403da0b4 @definition=[[Ss-, O+, {@MV+}], [Ss-,
-#    #    B-, {@MV+}], [Ss-, P+], [Ss-, AF-], [RS-, Bs-, O+, {@MV+}], [RS-, Bs-, B-,
-#    #    {@MV+}], [RS-, Bs-, P+], [RS-, Bs-, AF-], [{Q-}, SIs+, O+, {@MV+}], [{Q-}, SIs+,
-#    #    B-, {@MV+}], [{Q-}, SIs+, P+], [{Q-}, SIs+, AF-]],
-#    #    @right=[#<LinkParser::Connection:0x403da028 ...>], @suffix="", @left=[],
-#    #    @name="is", @position=1>, @subName="*", @name="O", @length=3>], @name="dog",
-#    #    @position=4>
-#    
-#    # Combine WordNet + LinkParser to find the definition of the direct object of
-#    # the sentence
-#    "he is a big dog".en.sentence.object.gloss
-#    # => "a member of the genus Canis (probably descended from the common wolf) that
-#    #    has been domesticated by man since prehistoric times; occurs in many breeds;
-#    #    \"the dog barked all night\""
-# 
-# 
+#
+# Test to see whether or not the link parser is loaded.
+#
+#   Linguistics::EN.has_linkparser?
+#   # => true
+#
+# Diagram the first linkage for a test sentence
+#
+#   puts "he is a big dog".en.sentence.linkages.first.diagram
+#
+# Outputs:
+#
+#        +-----Ost----+
+#        |  +----Ds---+
+#    +-Ss+  |   +--A--+
+#    |   |  |   |     |
+#   he is.v a big.a dog.n
+#
+# Find the verb in the sentence
+#
+#   "he is a big dog".en.sentence.verb.to_s
+#   # => "is"
+#
+# Combined infinitive + LinkParser: Find the infinitive form of the verb of the
+# given sentence.
+#
+#   "he is a big dog".en.sentence.verb.en.infinitive
+#   # => "be"
+#
+# Find the direct object of the sentence
+#
+#   "he is a big dog".en.sentence.object.to_s
+#   # => "dog"
+#
+# Combine WordNet + LinkParser to find the definition of the direct object of
+# the sentence
+#
+#   "he is a big dog".en.sentence.object.en.definition
+#   # => "a member of the genus Canis (probably descended from the common wolf)
+#   #    that has been domesticated by man since prehistoric times; occurs in many
+#   #    breeds"
+#
+#
 module Linguistics::EN
+	extend Loggability
 
-	# Add 'english' to the list of default languages
-	Linguistics.register_language( :en, self )
+	# Loggability API -- log to the Linguistics logger
+	log_to :linguistics
 
 	# The list of loaded modules
 	MODULES = []
 	def self::register_extension( mod )
 		MODULES.push( mod )
 		Linguistics.log.debug "Registered English extension %p" % [ mod ]
+
 		include( mod )
+		mod.extend( Loggability )
+		mod.log_to( :linguistics )
+
 		if mod.const_defined?( :SingletonMethods )
 			smod = mod.const_get(:SingletonMethods)
 			Linguistics.log.debug "  and its singleton methods %p" % [ smod ]
 			extend( smod )
+
 			ivars = mod.instance_variables
 			Linguistics.log.debug "  and instance variables %p" % [ ivars ]
 			ivars.each do |ivar|
 	end
 
 
-	### Add an lprintf formatter that will use the specified +callback+ method.
-	### @param [#to_s] name         the name of the formatter, i.e., the 
-	###                             placeholder that will be used in the
-	###                             format string.
-	### @param [#to_proc] callback  the method to call on the english-language
-	###                             inflector for the lprintf argument
-	### @example Using a Symbol
+	### Add an lprintf formatter named +name+ that will use the specified +callback+ method.
+	### The name of the formatter is the placeholder that will be used in the
+	### format string, and the +callback+ is the method to call on the english-language
+	### inflector for the lprintf argument, and can either be an object that responds to
+	### #call, or the name of a method to call as a Symbol.
+	###
+	### Using a Symbol:
+	###
 	###    def plural( count=2 )
-	###      # return the plural of the inflected object
+	###        # return the plural of the inflected object
 	###    end
 	###    Linguistics::EN.register_lprintf_formatter :PL, :plural
 	###
-	### @example Using a Method
+	### Using a method:
+	###
 	###    Linguistics::EN.register_lprintf_formatter :PL, method( :plural )
 	###
-	### @example Using a block
+	### Using a block:
+	###
 	###    Linguistics::EN.register_lprintf_formatter :PL do |obj|
-	###      obj.en.plural
+	###        obj.en.plural
 	###    end
 	###
 	def self::register_lprintf_formatter( name, callback=nil )
 	end
 
 
-	### Set classical mode for the current thread inside the block, then 
+	### Set classical mode for the current thread inside the block, then
 	### unset it when it returns.
 	def self::in_classical_mode
 		old_setting = Thread.current[ THREAD_CLASSICAL_KEY ]
 	### %CONJUNCT::
 	###   Conjunction.
 	def lprintf( *args )
-		return self.obj.to_s.gsub( /%([A-Z_]+)/ ) do |match|
+		return self.to_s.gsub( /%([A-Z_]+)/ ) do |match|
 			op = $1.to_s.upcase.to_sym
 			if (( callback = Linguistics::EN.lprintf_formatters[op] ))
 				arg = args.shift
 		end
 	end
 
+
+	# Add 'english' to the list of default languages
+	Linguistics.register_language( :en, self )
+
+
 end # module Linguistics::EN
 
-
-# Load in the secondary modules and add them to Linguistics::EN.
-$LOAD_PATH.each do |prefix|
-	pat = Pathname( prefix ) + 'linguistics/en/**/*.rb'
-	Dir.glob( pat.to_s ).each do |extension|
-
-		next if extension =~ /_spec.rb/
-
-		Linguistics.log.debug "  trying to load English extension %p" % [ extension ]
-		begin
-			require extension
-		rescue LoadError => err
-			Linguistics.log.debug "    failed (%s): %s %s" %
-				[ err.class.name, err.message, err.backtrace.first ]
-		else
-			Linguistics.log.debug "    success."
-		end
-	end
-end
-
-
-
-

File lib/linguistics/en/articles.rb

 	### Returns the given word with a prepended indefinite article, unless
 	### +count+ is non-nil and not singular.
 	def indef_article( count=nil )
-		word = self.obj.to_s
+		word = self.to_s
 
 		self.log.debug "Fetching the indefinite article for %p (count = %p)" % [ word, count ]
 		return "#{count} #{word}" if
 	### "an") prepended. 
 	def a( count=nil )
 		count ||= 1
-		phrase = self.obj.to_s
+		phrase = self.to_s
 
 		md = /\A(\s*)(.+?)(\s*)\Z/.match( phrase )
 		pre, word, post = md.to_a[1,3]
 
 	### Translate zero-quantified +phrase+ to "no +phrase.plural+"
 	def no( count=nil )
-		phrase = self.obj.to_s
+		phrase = self.to_s
 		md = /\A(\s*)(.+?)(\s*)\Z/.match( phrase )
 		pre, word, post = md.to_a[1,3]
 		count ||= 0

File lib/linguistics/en/conjugation.rb

 
 
 	# Hash of irregular verb infinitives, read from the DATA section of the file
-	IRREGULAR_VERBS = {}
+	IRREGULAR_VERBS = {} # :nodoc:
 
 	# Array of doubling verbs, read from the DATA section of the file
-	DOUBLING_VERBS = []
+	DOUBLING_VERBS = [] # :nodoc:
 
 
+	### Return the past tense of the word
+	def past_tense( person=nil )
+		return self.conjugate( :past, person )
+	end
+
+
+	### Return the past participle of the word
+	def past_participle( person=nil )
+		return self.conjugate( :past_participle, person )
+	end
+
+
+	### Return the present tense of the word
+	def present_tense( person=nil )
+		return self.conjugate( :present, person )
+	end
+
+
+	### Return the present participle of the word
+	def present_participle( person=nil )
+		return self.conjugate( :present_participle, person )
+	end
+
+
+
+	### Conjugate the receiving string as an infinitive with the specified +tense+ 
+	### and +person+.
+	def conjugate( tense, person=nil )
+		self.log.debug "Conjugating %p in %s tense, %s person" %
+			[ self.to_s, tense, person || "any" ]
+		person ||= :*
+		verb = self.to_s.downcase
+
+		if result = get_irregular( verb, person, tense )
+			self.log.debug "  verb %p is irregular: %p" % [ verb, result ]
+			return result
+		end
+
+		self.log.debug "  regular verb: conjugating by tense"
+		return case tense
+			when :present
+				conjugate_present( verb, person )
+			when :present_participle
+				conjugate_present_participle( verb )
+			when :past
+				conjugate_past( verb )
+			when :past_participle
+				conjugate_past_participle( verb )
+			else
+				verb
+			end
+	end
+
+
+	#######
+	private
+	#######
+
+	### Conjugate the specified +verb+ in the present tense in the given +person+. The
+	### only +person+ that is 
+	def conjugate_present( verb, person=:third_person_singular )
+		return verb unless person == :third_person_singular
+
+		case verb
+		when /(ch|s|sh|x|z)$/
+			return verb + 'es'
+		when /(ay|ey|oy|uy)$/
+			return verb + 's'
+		when /[^aeiou]y$/
+			return verb[ 0..-2 ] + 'ies'
+		else
+			return verb + 's'
+		end
+	end
+
+
+	### Convugate the given +verb+ as a present participle.
+	def conjugate_present_participle( verb )
+		case verb
+		when /[^aeiou]e$/
+			return verb[ 0..-2 ]
+		when /ie$/
+			return verb[ 0..-3 ] + 'y'
+		when /[aou]e$/
+			return verb[ 0..-2 ]
+		else
+			if DOUBLING_VERBS.include?( verb )
+				return verb + verb[ -1 ] + 'ing'
+			else
+				return verb + 'ing'
+			end
+		end
+	end
+
+
+	### Conjugate the specified verb in the past tense; also used to conjugate the
+	### past participle.
+	def conjugate_past( verb )
+		case verb
+		when /e$/
+			return verb + 'd'
+		when /[^aeiou]y$/
+			return verb[ 0..-1 ] + 'ied'
+		else
+			if DOUBLING_VERBS.include?( verb )
+				verb = verb[ -2..-1 ] + 'ed'
+			else
+				return verb + 'ed'
+			end
+		end
+	end
+	alias_method :conjugate_past_participle, :conjugate_past
+
+
+	#### If the given +verb+ is irregular in the given +person_ and 
+	def get_irregular( verb, person, tense )
+		self.log.debug "  looking for irregular verb: %p, %p person, %p tense" %
+			[ verb, person, tense ]
+
+		irregular = IRREGULAR_VERBS[ verb ] or return nil
+		self.log.debug "    %p is irregular: %p, selecting %p person" %
+			[ verb, irregular, person ]
+		irrperson = irregular[ person ] || irregular[ :* ] or return nil
+		self.log.debug "    selected %p. Using %p tense: %p" %
+			[ irrperson, tense, irrperson[tense] ]
+		return irrperson[ tense ]
+	end
+
+
+	######
+	public
+	######
+
 	### Inclusion hook -- load the verb data when the module is first included.
-	def self::included( mod )
+	def self::included( mod ) # :nodoc:
 		if IRREGULAR_VERBS.empty?
 			self.log.debug "Loading conjunctions data."
 			data = File.read( __FILE__ ).split( /^__END__$/ ).last
 
 
 	### Parse irregular verbs from the given +data+, and return the resulting Hash.
-	### @param [String] data  the irregular verb data from the DATA section of this file.
-	### @return [Hash]
 	def self::load_irregular_verbs( data )
 		self.log.debug "  loading irregular verbs from %d bytes of data." % [ data.length ]
 		results = {}
 
 
 	### Load the doubling verbs from the given +data+ and return the resulting Array.
-	### @param [String] data  the doubling verbs, one on each line
-	### @return [Array]
 	def self::load_doubling_verbs( data )
 		self.log.debug "  loading doubling verbs."
 		results = []
 	Linguistics::EN.register_extension( self )
 
 
-	### Return the past tense of the word
-	def past_tense( person=nil )
-		return self.conjugate( :past, person )
-	end
-
-
-	### Return the past participle of the word
-	def past_participle( person=nil )
-		return self.conjugate( :past_participle, person )
-	end
-
-
-	### Return the present tense of the word
-	def present_tense( person=nil )
-		return self.conjugate( :present, person )
-	end
-
-
-	### Return the present participle of the word
-	def present_participle( person=nil )
-		return self.conjugate( :present_participle, person )
-	end
-
-
-
-	### Conjugate the receiving string as an infinitive with the specified +tense+ 
-	### and +person+.
-	def conjugate( tense, person=nil )
-		self.log.debug "Conjugating %p in %s tense, %s person" %
-			[ self.obj, tense, person || "any" ]
-		person ||= :*
-		verb = self.obj.to_s.downcase
-
-		if result = get_irregular( verb, person, tense )
-			self.log.debug "  verb %p is irregular: %p" % [ verb, result ]
-			return result
-		end
-
-		self.log.debug "  regular verb: conjugating by tense"
-		return case tense
-			when :present
-				conjugate_present( verb, person )
-			when :present_participle
-				conjugate_present_participle( verb )
-			when :past
-				conjugate_past( verb )
-			when :past_participle
-				conjugate_past_participle( verb )
-			else
-				verb
-			end
-	end
-
-
-	#######
-	private
-	#######
-
-	### Conjugate the specified +verb+ in the present tense in the given +person+. The
-	### only +person+ that is 
-	def conjugate_present( verb, person=:third_person_singular )
-		return verb unless person == :third_person_singular
-
-		case verb
-		when /(ch|s|sh|x|z)$/
-			return verb + 'es'
-		when /(ay|ey|oy|uy)$/
-			return verb + 's'
-		when /[^aeiou]y$/
-			return verb[ 0..-2 ] + 'ies'
-		else
-			return verb + 's'
-		end
-	end
-
-
-	### Convugate the given +verb+ as a present participle.
-	def conjugate_present_participle( verb )
-		case verb
-		when /[^aeiou]e$/
-			return verb[ 0..-2 ]
-		when /ie$/
-			return verb[ 0..-3 ] + 'y'
-		when /[aou]e$/
-			return verb[ 0..-2 ]
-		else
-			if DOUBLING_VERBS.include?( verb )
-				return verb + verb[ -1 ] + 'ing'
-			else
-				return verb + 'ing'
-			end
-		end
-	end
-
-
-	### Conjugate the specified verb in the past tense; also used to conjugate the
-	### past participle.
-	def conjugate_past( verb )
-		case verb
-		when /e$/
-			return verb + 'd'
-		when /[^aeiou]y$/
-			return verb[ 0..-1 ] + 'ied'
-		else
-			if DOUBLING_VERBS.include?( verb )
-				verb = verb[ -2..-1 ] + 'ed'
-			else
-				return verb + 'ed'
-			end
-		end
-	end
-	alias_method :conjugate_past_participle, :conjugate_past
-
-
-	#### If the given +verb+ is irregular in the given +person_ and 
-	def get_irregular( verb, person, tense )
-		self.log.debug "  looking for irregular verb: %p, %p person, %p tense" %
-			[ verb, person, tense ]
-
-		irregular = IRREGULAR_VERBS[ verb ] or return nil
-		self.log.debug "    %p is irregular: %p, selecting %p person" %
-			[ verb, irregular, person ]
-		irrperson = irregular[ person ] || irregular[ :* ] or return nil
-		self.log.debug "    selected %p. Using %p tense: %p" %
-			[ irrperson, tense, irrperson[tense] ]
-		return irrperson[ tense ]
-	end
-
 end # module Linguistics::EN::Conjugation
 
 __END__

File lib/linguistics/en/conjunctions.rb

 	###
 	def conjunction( args={} )
 		config = CONJUNCTION_DEFAULTS.merge( args )
-		phrases = []
 
 		# Transform items in the obj to phrases
-		if block_given?
-			phrases = self.obj.collect {|item| yield(item) }.compact
-		else
-			phrases = self.obj.collect {|item| item.to_s }
-		end
+		phrases = if block_given?
+				self.log.debug "  collecting with a block"
+				self.collect {|item| yield(item) }.compact
+			else
+				self.log.debug "  collecting without a block"
+				rval = self.collect( &:to_s )
+				self.log.debug "  collected: %p" % [ rval ]
+				rval
+			end
+
+		self.log.debug "  phrases is: %p" % [ phrases ]
 
 		# No need for a conjunction if there's only one thing
 		return phrases[0].en.a if phrases.length < 2

File lib/linguistics/en/infinitives.rb

 
 	### Return the infinitive form of the given word
 	def infinitive
-		word = self.obj.to_s
+		word = self.to_s
 		word1 = word2 = suffix = rule = newword = ''
 
 		if IRREGULAR_INFINITIVES.key?( word )

File lib/linguistics/en/linkparser.rb

 
 	### Return a LinkParser::Sentence for the stringified +obj+.
 	def sentence
-		return Linguistics::EN::LinkParser.lp_dict.parse( self.obj.to_s )
+		return Linguistics::EN::LinkParser.lp_dict.parse( self.to_s )
 	end
 
 end # class Linguistics::EN::LinkParser

File lib/linguistics/en/numbers.rb

 	###   If set to a true value, the number will be returned as an array of
 	###   word groups instead of a String.
 	def numwords( hashargs={} )
-		num = self.obj.to_s
+		num = self.to_s
 		Linguistics.log.debug "Turning %p into number words..." % [ num ]
 		config = NUMWORD_DEFAULTS.merge( hashargs )
 		raise "Bad chunking option: #{config[:group]}" unless
 	### Transform the given +number+ into an ordinal word. The +number+ object
 	### can be either an Integer or a String.
 	def ordinal
-		number = self.obj
-
-		case number
-		when Integer
-			Linguistics.log.debug "Making an ordinal out of an Integer (%p)" % [ number ]
-			return number.to_s + (NTH[ number % 100 ] || NTH[ number % 10 ])
+		if self.respond_to?( :to_int )
+			number = self.to_int
+			return "%d%s" % [ number, (NTH[ number % 100 ] || NTH[ number % 10 ]) ]
 
 		else
+			number = self.to_s
 			Linguistics.log.debug "Making an ordinal out of a non-Integer (%p)" % [ number ]
-			return number.to_s.sub( /(#{ORDINAL_SUFFIXES})\Z/ ) { ORDINALS[$1] }
+			return number.sub( /(#{ORDINAL_SUFFIXES})\Z/ ) { ORDINALS[$1] }
 		end
 	end
 	Linguistics::EN.register_lprintf_formatter :ORD, :ordinal
 	### Return a phrase describing the specified +number+ of objects in the
 	### inflected object in general terms. The following options can be used to 
 	### control the makeup of the returned quantity String:
-	### 
+	###
     ### [<b>:joinword</b>]
     ###   Sets the word (and any surrounding spaces) used as the word separating the
     ###   quantity from the noun in the resulting string. Defaults to <tt>' of
     ###   '</tt>.
 	def quantify( number=0, args={} )
-		phrase = self.obj.to_s
+		phrase = self.to_s
 		self.log.debug "Quantifying %d instances of %p" % [ number, phrase ]
 
 		num = number.to_i
 
 	### Split the given +number+ up into groups of +groupsize+ and return
 	### them as an Array of words. Use +zeroword+ for any occurences of '0'.
-	### @param [Integer] number     the number to wordify
-	### @param [Integer] groupsize  the size of the groups
-	### @param [String] zeroword    the word to use for the numeral '0'
-	### @return [Array<String>]  words
 	def number_to_custom_word_groups( number, groupsize, zeroword="zero" )
 		self.log.debug "Making custom word groups of %d digits out of %p" % [ groupsize, number ]
 
 
 	### Split the given +number+ up into groups of three and return
 	### the Array of words describing each group in the standard style.
-	### @param [Integer] number  the number to describe
-	### @param [String] andword  the word to use in the last clause of the
-	###                          number.
 	def number_to_standard_word_groups( number, andword="and" )
 		phrase = number.to_s
 		phrase.sub!( /\A\s*0+/, '' )

File lib/linguistics/en/participles.rb

 	### Attempt to return the inflected string in its present participle 
 	### form (e.g., talked -> talking).
 	def present_participle
-        plural = self.obj.to_s.en.plural_verb
+        plural = self.to_s.en.plural_verb
 
 		plural.sub!( /ie$/, 'y' ) or
 			plural.sub!( /ue$/, 'u' ) or

File lib/linguistics/en/pluralization.rb

 	### Return the plural of the given +phrase+ if +count+ indicates it should
 	### be plural.
 	def plural( count=2 )
-		phrase = if self.obj.is_a?( Numeric )
-				self.log.debug "Converting %p to number words." % [ self.obj ]
+		phrase = if self.respond_to?( :to_int )
 				self.numwords
 			else
-				self.obj.to_s
+				self.to_s
 			end
 
 		self.log.debug "Pluralizing %p" % [ phrase ]
+		pre = text = post = nil
 
 		# If the string has whitespace, only pluralize the middle bit, but
 		# preserve the whitespace to add back to the result.
-		md = /\A(\s*)(.+?)(\s*)\Z/.match( phrase.to_s )
-		pre, text, post = md.captures
-
-		return phrase if text.nil? or text.empty?
+		if md = /\A(\s*)(.+?)(\s*)\Z/.match( phrase.to_s )
+			pre, text, post = md.captures
+		else
+			return phrase
+		end
 
 		plural = postprocess( text,
 			pluralize_special_adjective(text, count) ||
 	### Return the plural of the given noun +phrase+ if +count+ indicates it
 	### should be plural.
 	def plural_noun( count=2 )
-		phrase = self.obj
-		md = /\A(\s*)(.+?)(\s*)\Z/.match( phrase.to_s )
+		phrase = self.to_s
+		md = /\A(\s*)(.+?)(\s*)\Z/.match( phrase )
 		pre, word, post = md.captures
 
 		return phrase if word.nil? or word.empty?
 	### Return the plural of the given verb +phrase+ if +count+ indicates it
 	### should be plural.
 	def plural_verb( count=2 )
-		phrase = self.obj
-		md = /\A(\s*)(.+?)(\s*)\Z/.match( phrase.to_s )
+		phrase = self.to_s
+		md = /\A(\s*)(.+?)(\s*)\Z/.match( phrase )
 		pre, word, post = md.captures
 
 		return phrase if word.nil? or word.empty?
 	### Return the plural of the given adjectival +phrase+ if +count+ indicates
 	### it should be plural.
 	def plural_adjective( count=2 )
-		phrase = self.obj
-		md = /\A(\s*)(.+?)(\s*)\Z/.match( phrase.to_s )
+		phrase = self.to_s
+		md = /\A(\s*)(.+?)(\s*)\Z/.match( phrase )
 		pre, word, post = md.captures
 
 		return phrase if word.nil? or word.empty?

File lib/linguistics/en/titlecase.rb

 	### Turns a camel-case +string+ ("camelCaseToEnglish") to plain English
 	### ("camel case to english"). Each word is decapitalized.
 	def un_camel_case
-		self.obj.to_s.
+		self.to_s.
 			gsub( /([A-Z])([A-Z])/ ) { "#$1 #$2" }.
 			gsub( /([a-z])([A-Z])/ ) { "#$1 #$2" }.downcase
 	end
 
 	### Turns an English language +string+ into a CamelCase word.
 	def to_camel_case
-		self.obj.to_s.gsub( /\s+([a-z])/i ) { $1.upcase }
+		self.to_s.gsub( /\s+([a-z])/i ) { $1.upcase }
 	end
 
 
-	### This method doesn't work quite right yet. It does okay for simple cases,
-	### but it misses more complex ones, e.g. 'as' used as a coordinating
-	### conjunction in "A Portrait of the Artist as a Young Man". Perhaps after
-	### there's a working (non-leaking) LinkParser for Ruby, this can be fixed
-	### up. Until then it'll just be undocumented.
-
 	### Returns the inflected object as a title-cased String.
+	###
+	### Some examples:
+	###
+	###   "a portrait of the artist as a young man".en.titlecase
+	###   # => "A Portrait of the Artist as a Young Man"
+	###
+	###   "a seven-sided romance".en.titlecase
+	###   # => "A Seven-Sided Romance"
+	###
+	###   "the curious incident of the dog in the night-time".en.titlecase
+	###   # => "The Curious Incident of the Dog in the Night-Time"
+	###
+	###   "the rats of n.i.m.h.".en.titlecase
+	###   # => "The Rats of N.I.M.H."
 	def titlecase
 
 		# Split on word-boundaries
-		words = self.obj.to_s.split( /\b/ )
+		words = self.to_s.split( /\b/ )
 
 		# Always capitalize the first and last words
 		words.first.capitalize!
 	### Returns the proper noun form of the inflected object by capitalizing most of the
 	### words.
 	###
-	### @example
-	###   English.proper_noun("bosnia and herzegovina") ->
-	###     "Bosnia and Herzegovina"
-	###   English.proper_noun("macedonia, the former yugoslav republic of") ->
-	###     "Macedonia, the Former Yugoslav Republic of"
-	###   English.proper_noun("virgin islands, u.s.") ->
-	###     "Virgin Islands, U.S."
+	### Some examples:
+	###
+	###   "bosnia and herzegovina".en.proper_noun
+	###   # => "Bosnia and Herzegovina"
+	###   "macedonia, the former yugoslav republic of".en.proper_noun
+	###   # => "Macedonia, the Former Yugoslav Republic of"
+	###   "virgin islands, u.s.".en.proper_noun
+	###   # => "Virgin Islands, U.S."
 	def proper_noun
-		return self.obj.to_s.split(/([ .]+)/).collect do |word|
+		return self.to_s.split(/([ .]+)/).collect do |word|
 			next word unless
 				/^[a-z]/.match( word ) &&
 				! (PROPER_NOUN_EXCEPTIONS.include?( word ))

File lib/linguistics/en/wordnet.rb

 	### word.
 	def self::def_synset_function( name )
 		define_method( name ) do |*criteria|
-			syn = self.en.synset( *criteria ) or return nil
+			syn = self.synset( *criteria ) or return nil
 			return syn.send( name )
 		end
 	end
 	### Look up the synset associated with the given word or collocation in the
 	### WordNet lexicon and return a WordNet::Synset object.
 	def synset( *args )
-		return Linguistics::EN::WordNet.lexicon[ self.obj.to_s, *args ]
+		return Linguistics::EN::WordNet.lexicon[ self.to_s, *args ]
 	end
 
 
 	### the WordNet lexicon and return an Array of WordNet::Synset objects. If
 	### +pos+ is +nil+, return synsets for all parts of speech.
 	def synsets( *args )
-		return Linguistics::EN.lexicon.lookup_synsets( self.obj.to_s, *args )
+		return Linguistics::EN.lexicon.lookup_synsets( self.to_s, *args )
 	end
 
 
 	# Returns definitions and/or example sentences as a String.
-	def_synset_function :gloss
-
-	# Returns definitions and/or example sentences as an Array.
-	def_synset_function :glosses
+	def_synset_function :definition
 
 	# Return nouns or verbs that have the same hypernym as the receiver.
 	def_synset_function :coordinates

File lib/linguistics/inflector.rb

 
 	### Create a new inflector for +obj+.
 	def initialize( language_code, obj )
+		raise TypeError, "can't inflect for another inflector!" if
+			obj.is_a?( Linguistics::Inflector )
 		@language_code = language_code
 		@obj = obj
 		super()
 	end
 
 
+	### Returns +true+ if either the inflector or the object it's wrapping respond to
+	### the specified +message+.
+	def respond_to_missing?( message, include_priv=false )
+		return self.obj.respond_to?( message, include_priv )
+	end
+
+
+	### Return the target object as a String.
+	def to_s
+		return self.obj.to_s
+	end
+
+
+	### Return the target object as an Integer
+	def to_i
+		return self.obj.to_i
+	end
+
+
 	### Output a programmer-readable representation of the object suitable for debugging.
 	def inspect
 		return "#<(%s-language inflector) for <%s:0x%0x> >" % [
 	end
 
 
-	### Output a human-readable representation of the object.
-	def to_s
-		return "%s-language inflector for %s" % [ self.language, @obj ]
+	#########
+	protected
+	#########
+
+	### Delegate missing methods to the target object.
+	def method_missing( sym, *args, &block )
+		return super unless self.obj.respond_to?( sym )
+		meth = self.obj.method( sym )
+		self.singleton_class.send( :define_method, sym, &meth )
+		return self.method( sym ).call( *args, &block )
 	end
 
 end # class Linguistics::Inflector

File lib/linguistics/iso639.rb

 # [<tt>:fre_name</tt>]
 #   The French-language name of the language.
 #
-# @example Entries for 'ja' and 'en'
+# Entries for 'ja' and 'en':
 #
-# irb > Linguistics::ISO639::LANGUAGE_CODES[:en]
-#  => {:eng_name=>"English", :fre_name=>"anglais", :codes=>["en", "eng"]} 
-# irb > Linguistics::ISO639::LANGUAGE_CODES[:eng]
-#  => {:eng_name=>"English", :fre_name=>"anglais", :codes=>["en", "eng"]} 
-# irb > Linguistics::ISO639::LANGUAGE_CODES[:ja]
-#  => {:eng_name=>"Japanese", :fre_name=>"japonais", :codes=>["ja", "jpn"]} 
+#   irb > Linguistics::ISO639::LANGUAGE_CODES[:en]
+#    => {:eng_name=>"English", :fre_name=>"anglais", :codes=>["en", "eng"]}
+#   irb > Linguistics::ISO639::LANGUAGE_CODES[:eng]
+#    => {:eng_name=>"English", :fre_name=>"anglais", :codes=>["en", "eng"]}
+#   irb > Linguistics::ISO639::LANGUAGE_CODES[:ja]
+#    => {:eng_name=>"Japanese", :fre_name=>"japonais", :codes=>["ja", "jpn"]}
 
 module Linguistics::ISO639
 

File spec/linguistics/en/articles_spec.rb

 
 require 'linguistics'
 require 'linguistics/en'
+require 'linguistics/en/articles'
 
 
 describe Linguistics::EN::Articles do

File spec/linguistics/en/conjunctions_spec.rb

 
 require 'linguistics'
 require 'linguistics/en'
+require 'linguistics/en/conjunctions'
 
 
 describe Linguistics::EN::Conjunctions do

File spec/linguistics/en/participles_spec.rb

 
 require 'linguistics'
 require 'linguistics/en'
+require 'linguistics/en/participles'
 
 
 describe Linguistics::EN::Participles do

File spec/linguistics/en/pluralization_spec.rb

 
 require 'linguistics'
 require 'linguistics/en'
+require 'linguistics/en/pluralization'
 
 
 describe Linguistics::EN::Pluralization do

File spec/linguistics/en/titlecase_spec.rb

 
 require 'linguistics'
 require 'linguistics/en'
+require 'linguistics/en/titlecase'
 
 
 describe Linguistics::EN::TitleCase do

File spec/linguistics/en/wordnet_spec.rb

 require 'spec/lib/helpers'
 
 require 'linguistics'
+require 'linguistics/en'
 require 'linguistics/en/wordnet'
 
 
 describe Linguistics::EN::WordNet do
 
 	before( :all ) do
-		setup_logging( :debug )
+		setup_logging()
 		Linguistics.use( :en )
 	end
 
 		before( :all ) do
 			# If the system *does* have wordnet support, pretend it doesn't.
 			if Linguistics::EN.has_wordnet?
+				@had_wordnet = true
 				error = LoadError.new( "no such file to load -- wordnet" )
 				Linguistics::EN::WordNet.instance_variable_set( :@has_wordnet, false )
 				Linguistics::EN::WordNet.instance_variable_set( :@error, error )
 			end
 		end
 
+		after( :all ) do
+			if @had_wordnet
+				Linguistics::EN::WordNet.instance_variable_set( :@has_wordnet, true )
+				Linguistics::EN::WordNet.instance_variable_set( :@error, nil )
+			end
+		end
+
 		it "raises an NotImplementedError when you try to use wordnet functionality" do
 			expect {
 				"persimmon".en.synset