== Description

Bond is on a mission to make custom autocompletion easy in irb and other console/readline-like
environments. Bond supports custom argument completion of methods, method completion of objects and
anything else your wicked regex's can do. Bond comes armed with a Readline C extension to get the
full line of input as opposed to irb's last-word based completion. Bond makes custom searching of
possible completions easy which allows for nontraditional ways of autocompleting i.e. instant
aliasing of multi worded methods.

== Install

Install the gem with:

    sudo gem install cldwalker-bond --source http://gems.github.com

== Usage

To start of with, you may want to replace irb's completion (irb/completion) with Bond's enhanced version
in your irbrc :

  require 'bond'
  require 'bond/completion'

This should give you more consistent method completion on any objects, file completion of strings
and argument completion of Kernel#require, Kernel#system and the backtick (`).

=== Argument Completion for Methods

    bash> irb -rirb/completion -rubygems
    # This loads Bond but it doesn't take over completion yet.
    >> require 'bond'

    # For Bond to handle completions, we must explicitly define a completion mission.
    # Order matters since the order they're declared in is the order they're searched.
    >> Bond.complete(:method=>'method1') {|input|  %w{some args to autocomplete} }
    => true
    >> Bond.complete(:method=>'method2') {|input|  %w{more args to autocomplete} }
    => true

    # Works as above
    >> method1 [TAB]
    args   autocomplete   some   to
    >> method1 'a[TAB]
    args   autocomplete
    >> method1 'au[TAB]
    >> method1 'autocomplete'

    # Anything not matched by the above completion missions defaults to irb completion
    >> $std[TAB]
    $stderr  $stdin   $stdout
    
=== File Argument Completion for Methods

    # Pass :search=>false to turn off Bond searching since FILENAME_COMPLETION_PROC does it for us.
    >> Bond.complete(:method=>"File.read", :search=>false) {|input| 
        Readline::FILENAME_COMPLETION_PROC.call(input) || [] }
    => true

    # Test drive it
    >> File.read '[TAB]
    .git/   LICENSE.txt   README.rdoc   Rakefile      VERSION.yml   bond.gemspec  ext/    lib/     test/
    >> File.read 'l[TAB]
    >> File.read 'lib/
    >> File.read 'lib/bond.[TAB]
    >> File.read 'lib/bond.rb'

    # Since File.read doesn't understand ~, let's improve the above completion proc
    >> file_completion = proc {|input| (Readline::FILENAME_COMPLETION_PROC.call(input) ||
        []).map {|f| f =~ /^~/ ?  File.expand_path(f) : f } }
    => #< Proc:0x0100f1d0@(irb):20>
    >> Bond.reset; Bond.complete :method=>"File.read", :search=>false, &file_completion
    => true

    # Tilda test driving
    >> File.read "~/[TAB]
    >> File.read "/Users/bozo/
    >> File.read "/Users/bozo/.alias.[TAB]
    >> File.read "/Users/bozo/.alias.yml"
    
    # Let's add this to *all* our File methods:
    >> Bond.reset; Bond.complete :method=>/File\.(#{Regexp.union(*File.methods(false))})/,
        :search=>false, &file_completion
    => true

=== Method Autocompletion on Specified Objects
    # Let's explore Bond::Agent's functionality
     >> ba = Bond.agent; nil
     => nil
     # Irb let's you autocomplete everything that an object responds to for better or worse.
     >> ba.[TAB]
     ba.__id__                      ba.eql?                        ba.instance_eval               ba.method                      ba.send                        ba.to_yaml
     ba.__send__                    ba.equal?                      ba.instance_of?                ba.methods                     ba.setup                       ba.to_yaml_properties
     ba.call                        ba.extend                      ba.instance_variable_defined?  ba.missions                    ba.singleton_methods           ba.to_yaml_style
     ba.class                       ba.find_mission                ba.instance_variable_get       ba.nil?                        ba.taguri                      ba.type
     ba.clone                       ba.freeze                      ba.instance_variable_set       ba.object_id                   ba.taguri=                     ba.untaint
     ba.complete                    ba.frozen?                     ba.instance_variables          ba.private_methods             ba.taint                       
     ba.default_mission             ba.hash                        ba.is_a?                       ba.protected_methods           ba.tainted?                    
     ba.display                     ba.id                          ba.kind_of?                    ba.public_methods              ba.to_a                        
     ba.dup                         ba.inspect                     ba.line_buffer                 ba.respond_to?                 ba.to_s                        


     # Since it's hard to see Bond::Agent's functionality amidst all the Object and Kernel methods, 
     # let's autocomplete just it's instance methods.
     >> Bond.complete(:object=>Bond::Agent) {|input| input.object.class.instance_methods(false) }
     => true

     # A less cluttered display of Bond::Agent's functionality.
     >> ba.[TAB]
     ba.call             ba.complete         ba.default_mission  ba.find_mission     ba.missions

     # Let's have all Bond::* objects do this.
     >> Bond.reset; Bond.complete(:object=>/^Bond::/) {|input| input.object.class.instance_methods(false) }
     => true

    # Let's revert method autocompletion back to irb's defaults for Bond::* objects.
    >> Bond.reset; Bond.complete :object=>/^Bond::/
    
=== Underscore Search

    # Firing up a rails console
    bash> script/console
    >> require 'bond'
    => true

    # Set all ActiveRecord::Base descendants to use the predefined underscore search
    >> Bond.complete :object=>ActiveRecord::Base, :search=>:underscore
    => true

    # With this search we can still autocomplete the traditional way.
    # Url is a model object
    >> Url.first.tag_[TAB]
    Url.first.tag_add_and_remove   Url.first.tag_and_save         Url.first.tag_ids=             Url.first.tag_list=            
    Url.first.tag_add_and_save     Url.first.tag_ids              Url.first.tag_list             Url.first.tag_remove_and_save
    >> Url.tag_ad[TAB]
    >> Url.tag_add_and_
    >> Url.tag_add_and_[TAB]
    Url.first.tag_add_and_remove  Url.first.tag_add_and_save 
    >> Url.tag_add_and_s[TAB]
    >> Url.tag_add_and_save

    # But this search goes the extra mile with textmate-like searching.
    # Type just the first letter of each underscored word separated by '-'
    >> Url.first.t-a-a-s[TAB]
    >> Url.first.tag_add_and_save

    # With this search, most multi-worded methods are just a few keystrokes away.
    # If multiple methods match the underscore alias, it still autocompletes the beginning of the method:
    >> Url.first.p[TAB]
    Url.first.partial_updates                  Url.first.pretty_inspect                   Url.first.pretty_print_instance_variables  Url.first.public_methods
    Url.first.partial_updates?                 Url.first.pretty_print                     Url.first.primary_key_prefix_type          
    Url.first.pluralize_table_names            Url.first.pretty_print_cycle               Url.first.private_methods                  
    Url.first.present?                         Url.first.pretty_print_inspect             Url.first.protected_methods
    >> Url.first.p-p[TAB]
    >> Url.first.pretty_print
    >> Url.first.pretty_print_c[TAB]
    >> Url.first.pretty_print_cycle


=== Custom AutoCompletion

    bash> irb -rirb/completion -rubygems -rbond
    # Let's reuse the file completion from above
    >> file_completion = proc {|input| (Readline::FILENAME_COMPLETION_PROC.call(input) ||
        []).map {|f| f =~ /^~/ ?  File.expand_path(f) : f } }
    => #< Proc:0x0100f1d0@(irb):1>

    # But this time let's trigger it whenever the last word in the line is quoted
    # fyi this is default behavior if you use irb without requiring irb/completion
    >> Bond.complete(:on=>/\S+\s*["']([^'".]*)$/, :search=>false) {|input| file_completion.call(input.matched[1]) }
    => true

    # Now it doesn't matter what methods come before. If the last word is quoted we get file completion:
    >> Dir.entries '[TAB]
    .git/   LICENSE.txt   README.rdoc   Rakefile      VERSION.yml   bond.gemspec  ext/    lib/     test/
    >> Dir.entries 'l[TAB]
    >> Dir.entries 'lib/
    >> `ls 't[TAB]
    >> `ls 'test/
    >> `ls 'test/'`

    # String method completion still works
    >> '007'.[TAB]
    Display all 137 possibilities? (y or n)

== Credits
Thanks to Csaba Hank for {providing the C extension}[http://www.creo.hu/~csaba/ruby/irb-enhancements/doc/files/README.html]
which Bond uses to read Readline's full buffer. Thanks also goes out to Takao Kouji for {recently
commiting}[http://svn.ruby-lang.org/cgi-bin/viewvc.cgi/trunk/ext/readline/readline.c?view=diff&r1=24018&r2=24019]
this Readline enhancement to ruby.

== Links
* http://tagaholic.me/2009/07/16/bond-from-irb-with-completion-love.html

== Todo
* Allow usage of prefined Bond::Actions in action procs.