Mission: Easy custom autocompletion for arguments, methods and beyond. Accomplished for irb and any other readline-like console environments.
Pull request Compare This branch is 310 commits behind cldwalker:master.
Fetching latest commit…
Cannot retrieve the latest commit at this time.
Failed to load latest commit information.



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 the gem with:

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


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)


Thanks to Csaba Hank for providing the C extension which Bond uses to read Readline's full buffer. Thanks also goes out to Takao Kouji for recently commiting this Readline enhancement to ruby.



  • Allow usage of prefined Bond::Actions in action procs.