bond 0.1.4 → 0.2.0
Sign up to get free protection for your applications and to get access to all the features.
- data/CHANGELOG.rdoc +12 -0
- data/LICENSE.txt +1 -1
- data/README.rdoc +195 -173
- data/Rakefile +9 -45
- data/lib/bond.rb +62 -93
- data/lib/bond/agent.rb +39 -33
- data/lib/bond/completion.rb +15 -27
- data/lib/bond/completions/activerecord.rb +12 -0
- data/lib/bond/completions/array.rb +1 -0
- data/lib/bond/completions/bond.rb +2 -0
- data/lib/bond/completions/hash.rb +3 -0
- data/lib/bond/completions/kernel.rb +13 -0
- data/lib/bond/completions/module.rb +7 -0
- data/lib/bond/completions/object.rb +21 -0
- data/lib/bond/completions/struct.rb +1 -0
- data/lib/bond/input.rb +28 -0
- data/lib/bond/m.rb +95 -0
- data/lib/bond/mission.rb +109 -69
- data/lib/bond/missions/anywhere_mission.rb +18 -0
- data/lib/bond/missions/default_mission.rb +16 -6
- data/lib/bond/missions/method_mission.rb +194 -13
- data/lib/bond/missions/object_mission.rb +29 -32
- data/lib/bond/missions/operator_method_mission.rb +26 -0
- data/lib/bond/rawline.rb +3 -3
- data/lib/bond/rc.rb +48 -0
- data/lib/bond/readline.rb +9 -6
- data/lib/bond/search.rb +51 -12
- data/lib/bond/version.rb +3 -0
- data/test/agent_test.rb +168 -65
- data/test/anywhere_mission_test.rb +34 -0
- data/test/bacon_extensions.rb +26 -0
- data/test/bond_test.rb +38 -23
- data/test/completion_test.rb +123 -21
- data/test/completions_test.rb +96 -0
- data/test/method_mission_test.rb +246 -0
- data/test/mission_test.rb +30 -44
- data/test/object_mission_test.rb +28 -32
- data/test/operator_method_mission_test.rb +66 -0
- data/test/search_test.rb +106 -29
- data/test/test_helper.rb +20 -13
- metadata +37 -8
- data/VERSION.yml +0 -4
- data/lib/bond/actions.rb +0 -69
data/CHANGELOG.rdoc
CHANGED
@@ -1,3 +1,15 @@
|
|
1
|
+
== 0.2.0
|
2
|
+
* Added comprehensive argument completion per module, method and argument.
|
3
|
+
* Added 60+ default method argument completions.
|
4
|
+
* Added configuration system and DSL.
|
5
|
+
* Added user-friendly completion error handling.
|
6
|
+
* Improved Bond.spy.
|
7
|
+
* Fixed several 1.9 bugs.
|
8
|
+
* Replaced require 'bond/completion' with Bond.start.
|
9
|
+
* Changed underscore_search to use '_' instead of '-'.
|
10
|
+
* Removed Bond.debrief and Bond.reset.
|
11
|
+
* Switched to bacon for tests.
|
12
|
+
|
1
13
|
== 0.1.4
|
2
14
|
* Added Bond.recomplete to make redefinition of completion missions easy.
|
3
15
|
* Added flag to readline extension building so that installing bond doesn't fail for
|
data/LICENSE.txt
CHANGED
data/README.rdoc
CHANGED
@@ -1,186 +1,205 @@
|
|
1
|
+
Note: To read a linked version of this README, {click here}[http://tagaholic.me/bond/doc/]
|
2
|
+
|
1
3
|
== Description
|
2
4
|
|
3
|
-
Bond is on a mission to
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
5
|
+
Bond is on a mission to improve irb's autocompletion. Aside from doing everything irb's can do and fixing its quirks,
|
6
|
+
Bond can autocomplete argument(s) to methods, uniquely completing per module, per method and per argument. Bond brings
|
7
|
+
irb's completion closer to bash/zsh as it provides a configuration system and a DSL for creating custom completions
|
8
|
+
and completion rules. With this configuration system, users can customize their irb autocompletions and share
|
9
|
+
it with others. Bond is able to offer more than irb's completion since it uses a Readline C extension to get the full
|
10
|
+
line of input when completing as opposed to irb's last-word approach.
|
9
11
|
|
10
12
|
== Install
|
11
13
|
|
12
14
|
Install the gem with:
|
13
15
|
|
14
|
-
sudo gem install
|
16
|
+
sudo gem install bond
|
15
17
|
|
16
|
-
==
|
18
|
+
== Setup
|
17
19
|
|
18
|
-
To start
|
19
|
-
in your irbrc :
|
20
|
+
To start off, replace irb's completion (require 'irb/completion') with Bond's enhanced version in your irbrc :
|
20
21
|
|
21
22
|
require 'bond'
|
22
|
-
|
23
|
-
|
24
|
-
This
|
25
|
-
and argument completion of
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
-
|
82
|
-
|
83
|
-
|
84
|
-
|
85
|
-
|
86
|
-
|
87
|
-
|
88
|
-
|
89
|
-
|
90
|
-
|
91
|
-
|
92
|
-
|
93
|
-
|
94
|
-
|
95
|
-
|
96
|
-
|
97
|
-
|
98
|
-
|
99
|
-
|
100
|
-
|
101
|
-
|
102
|
-
|
103
|
-
|
104
|
-
|
105
|
-
|
106
|
-
|
107
|
-
|
108
|
-
|
109
|
-
|
110
|
-
|
111
|
-
|
112
|
-
|
113
|
-
|
114
|
-
|
115
|
-
|
116
|
-
|
117
|
-
|
118
|
-
|
119
|
-
|
120
|
-
|
121
|
-
|
122
|
-
|
123
|
-
|
124
|
-
|
125
|
-
|
126
|
-
|
127
|
-
|
128
|
-
|
129
|
-
|
130
|
-
|
131
|
-
|
132
|
-
|
133
|
-
|
134
|
-
|
135
|
-
|
136
|
-
|
137
|
-
|
138
|
-
|
139
|
-
|
140
|
-
|
141
|
-
|
142
|
-
|
143
|
-
|
144
|
-
|
145
|
-
|
146
|
-
|
147
|
-
|
148
|
-
|
149
|
-
|
150
|
-
|
151
|
-
|
152
|
-
|
153
|
-
|
154
|
-
|
155
|
-
|
156
|
-
|
157
|
-
|
158
|
-
|
159
|
-
|
160
|
-
|
161
|
-
|
162
|
-
|
163
|
-
|
164
|
-
|
165
|
-
|
166
|
-
|
167
|
-
|
168
|
-
|
169
|
-
|
170
|
-
|
171
|
-
|
172
|
-
|
173
|
-
|
174
|
-
|
175
|
-
|
176
|
-
|
177
|
-
|
178
|
-
|
179
|
-
|
180
|
-
|
181
|
-
|
182
|
-
|
183
|
-
|
23
|
+
Bond.start
|
24
|
+
|
25
|
+
This gives you more consistent method completion on any object, customizable completions
|
26
|
+
and argument completion of some 80+ methods including Hash#[], Kernel#system, Kernel#require and some Rails methods.
|
27
|
+
|
28
|
+
== Method Argument Completion
|
29
|
+
|
30
|
+
By default, Bond autocompletes arguments for a number of core methods:
|
31
|
+
|
32
|
+
$ irb
|
33
|
+
# require completes gems and anything in $LOAD_PATH
|
34
|
+
>> require 'rb[TAB]
|
35
|
+
rbconfig.rb rbconfig/
|
36
|
+
>> require 'rbconfig
|
37
|
+
>> require 'rbconfig.rb'
|
38
|
+
|
39
|
+
# hash methods can complete their keys
|
40
|
+
>> CONFIG::CONFIG[TAB]
|
41
|
+
>> CONFIG::CONFIG['m[TAB]
|
42
|
+
>> CONFIG::CONFIG['mandir'
|
43
|
+
>> CONFIG::CONFIG['mandir']
|
44
|
+
|
45
|
+
>> ENV['CO[TAB]
|
46
|
+
COLUMNS COMMAND_MODE
|
47
|
+
>> ENV['COL[TAB]
|
48
|
+
>> ENV['COLUMNS'
|
49
|
+
>> ENV['COLUMNS']
|
50
|
+
|
51
|
+
# array methods can complete their elements
|
52
|
+
>> %w{ab bc cd de}.delete '[TAB]
|
53
|
+
ab bc cd de
|
54
|
+
>> %w{ab bc cd de}.delete 'a[TAB]
|
55
|
+
>> %w{ab bc cd de}.delete 'ab'
|
56
|
+
|
57
|
+
# system can complete shell commands
|
58
|
+
>> system 'ec[TAB]
|
59
|
+
>> system 'echo
|
60
|
+
>> system 'echo'
|
61
|
+
|
62
|
+
Bond also comes with some basic Rails completions, mostly for attributes/columns of models:
|
63
|
+
|
64
|
+
$ script/console
|
65
|
+
>> Url.column_names
|
66
|
+
=> ["id", "name", "description", "created_at", "updated_at"]
|
67
|
+
>> Url.create :n[TAB]
|
68
|
+
>> Url.create :name
|
69
|
+
...
|
70
|
+
>> Url.first.update_attribute :d[TAB]
|
71
|
+
>> Url.first.update_attribute :description
|
72
|
+
...
|
73
|
+
|
74
|
+
To see more methods whose arguments can be completed:
|
75
|
+
>> puts Bond.list_methods
|
76
|
+
ActiveRecord::Base#[]
|
77
|
+
ActiveRecord::Base#attribute_for_inspect
|
78
|
+
...
|
79
|
+
|
80
|
+
== Multiple Arguments
|
81
|
+
Every time a comma appears after a method, Bond starts a new completion. This allows a method to
|
82
|
+
complete multiple arguments. *Each* argument can be have a unique set of completions since a completion action
|
83
|
+
is aware of what argument it is currently completing. Take for example the completion for Object#send:
|
84
|
+
|
85
|
+
>> Bond.send :me[TAB]
|
86
|
+
>> Bond.send :method
|
87
|
+
>> Bond.send :method, [TAB]
|
88
|
+
agent complete config recomplete spy start
|
89
|
+
>> Bond.send :method, :a[TAB]
|
90
|
+
>> Bond.send :method, :agent
|
91
|
+
=> #<Method: Module#agent>
|
92
|
+
|
93
|
+
Notice the arguments were completed differently: the first completing for Bond.send and the second for Bond.method. The second
|
94
|
+
argument was only able to complete because there's a completion for Module#method. Using Object#send it's possible to
|
95
|
+
use completions defined for private methods i.e. Module#remove_const:
|
96
|
+
>> Bond.send :remove_const, :A[TAB]
|
97
|
+
:Agent :AnywhereMission
|
98
|
+
>> Bond.send :remove_const, :Ag[TAB]
|
99
|
+
>> Bond.send :remove_const, :Agent
|
100
|
+
|
101
|
+
Since Bond uses a comma to delimit completions, methods whose last argument is a hash can have their hash keys
|
102
|
+
autocompleted. Revisiting the above Rails example:
|
103
|
+
>> Url.create :n[TAB]
|
104
|
+
>> Url.create :name
|
105
|
+
>> Url.create :name=>'example.com', :d[TAB]
|
106
|
+
>> Url.create :name=>'example.com', :description
|
107
|
+
...
|
108
|
+
>> Url.first.update_attributes :d[TAB]
|
109
|
+
>> Url.first.update_attributes :description
|
110
|
+
>> Url.first.update_attributes :description=>'zzz', :u[TAB]
|
111
|
+
>> Url.first.update_attributes :description=>'zzz', :updated_at
|
112
|
+
...
|
113
|
+
|
114
|
+
== Creating Completions
|
115
|
+
Bond's completion resembles bash/zsh's. When Bond.start is called, Bond looks up completion files in multiple places:
|
116
|
+
~/.bondrc and ~/.bond/completions/*.rb. Here's how bash and bond completion definitions compare in their config files:
|
117
|
+
# Bash
|
118
|
+
complete -W "one two three" example
|
119
|
+
complete -F _example example
|
120
|
+
|
121
|
+
# Bond
|
122
|
+
complete(:method=>'example') { %w{one two three} }
|
123
|
+
complete(:method=>'example', :action=>'_example')
|
124
|
+
|
125
|
+
To read up on the wealth of completion types one can make, see the docs for Bond.complete.
|
126
|
+
|
127
|
+
=== Creating Argument Completions for Methods
|
128
|
+
While the above method completion was a static list, most completions will dynamically generate completions based on the method's
|
129
|
+
receiver (object). Let's look at such an example with Hash#[] :
|
130
|
+
complete(:method=>"Hash#[]") {|e| e.object.keys }
|
131
|
+
|
132
|
+
As you can see, the currently typed object is available as the :object attribute of the block's argument, a Bond::Input object.
|
133
|
+
This object can offer other useful attributes describing what the user has typed. For example, the :argument attribute holds the
|
134
|
+
current argument number being completed. Here's a completion that uses this attribute to complete differently for the first argument
|
135
|
+
and remaining arguments:
|
136
|
+
complete(:method=>'example') {|e| e.argument > 1 ? %w{verbose force noop} : %w{one two three} }
|
137
|
+
|
138
|
+
=== Creating Other Completions
|
139
|
+
First you should know Bond works: A user creates completion missions with Bond.start and its config files (which are just
|
140
|
+
Bond.complete calls). When a user autocompletes, Bond.agent looks up missions in the *order* they were defined and completes
|
141
|
+
with the first one that matches. The exception to this ordering are :method completions.
|
142
|
+
|
143
|
+
To create a completion, Bond.complete needs a regexp to match the user input and an action to generate completions when
|
144
|
+
it matches. If the completion isn't working, use Bond.spy to see which completion is executing. If a completion needs to be placed
|
145
|
+
before existing completions, use the :place option.
|
146
|
+
|
147
|
+
== Irb's Incorrect Completions
|
148
|
+
|
149
|
+
There are a number of incorrect completions irb gives for object methods. Bond fixes all of the ones described below.
|
150
|
+
|
151
|
+
Irb completes anything surrounded with '{}' the same:
|
152
|
+
|
153
|
+
>> proc {}.c[TAB]
|
154
|
+
}.call }.class }.clear }.clone }.collect
|
155
|
+
>> %w{ab bc}.c[TAB]
|
156
|
+
}.call }.class }.clear }.clone }.collect
|
157
|
+
>> %r{ab bc}.c[TAB]
|
158
|
+
}.call }.class }.clear }.clone }.collect
|
159
|
+
>> {}.c[TAB]
|
160
|
+
}.call }.class }.clear }.clone }.collect
|
161
|
+
>> {}.call
|
162
|
+
NoMethodError: undefined method `call' for {}:Hash
|
163
|
+
from (irb):1
|
164
|
+
|
165
|
+
There are a number of cases where irb gives a default completion because it doesn't know what else to do.
|
166
|
+
# The default completion
|
167
|
+
>> self.[TAB]
|
168
|
+
Display all 496 possibilities? (y or n)
|
169
|
+
|
170
|
+
# And all of these cases are apparently the same:
|
171
|
+
>> nil.[TAB]
|
172
|
+
Display all 496 possibilities? (y or n)
|
173
|
+
>> false.[TAB]
|
174
|
+
Display all 496 possibilities? (y or n)
|
175
|
+
>> true.[TAB]
|
176
|
+
Display all 496 possibilities? (y or n)
|
177
|
+
# Regular expressions with spaces
|
178
|
+
>> /man oh man/.[TAB]
|
179
|
+
Display all 496 possibilities? (y or n)
|
180
|
+
# Grouped expressions
|
181
|
+
>> (3 + 4).[TAB]
|
182
|
+
Display all 496 possibilities? (y or n)
|
183
|
+
|
184
|
+
# Nested hashes and arrays
|
185
|
+
>> {:a=>{:a=>1}}.[TAB]
|
186
|
+
Display all 496 possibilities? (y or n)
|
187
|
+
>> [[1,2], [3,4]].[TAB]
|
188
|
+
Display all 496 possibilities? (y or n)
|
189
|
+
|
190
|
+
# Any object produced from a method call
|
191
|
+
>> 'awesome'.to_sym.[TAB]
|
192
|
+
Display all 496 possibilities? (y or n)
|
193
|
+
>> :dude.to_s.[TAB]
|
194
|
+
Display all 496 possibilities? (y or n)
|
195
|
+
|
196
|
+
Ranges don't get much love
|
197
|
+
>> (2..4).[TAB]
|
198
|
+
# Nothing happens
|
199
|
+
|
200
|
+
== Limitations
|
201
|
+
If on a Mac and using Editline as a Readline replacement (Readline::VERSION =~ /editline/i), Bond will probably not work consistently. I strongly recommend switching to the official Readline. If using rvm, {this post}[http://niwos.com/2010/03/19/rvm-on-osx-snow-leopard-readline-errors/]
|
202
|
+
has good instructions for reinstalling ruby with the official Readline.
|
184
203
|
|
185
204
|
== Credits
|
186
205
|
Thanks to Csaba Hank for {providing the C extension}[http://www.creo.hu/~csaba/ruby/irb-enhancements/doc/files/README.html]
|
@@ -194,4 +213,7 @@ this Readline enhancement to ruby.
|
|
194
213
|
* http://tagaholic.me/2009/07/23/mini-irb-and-mini-script-console.html
|
195
214
|
|
196
215
|
== Todo
|
197
|
-
*
|
216
|
+
* Load completions that come with a gem easily.
|
217
|
+
* Make completion actions more synonymous with argument types.
|
218
|
+
* Cache expensive completion actions.
|
219
|
+
* Ensure completions work when there is additional, unrelated text to the right of a completion.
|
data/Rakefile
CHANGED
@@ -1,6 +1,4 @@
|
|
1
1
|
require 'rake'
|
2
|
-
require 'rake/testtask'
|
3
|
-
require 'rake/rdoctask'
|
4
2
|
begin
|
5
3
|
require 'rcov/rcovtask'
|
6
4
|
|
@@ -11,15 +9,17 @@ begin
|
|
11
9
|
t.verbose = true
|
12
10
|
end
|
13
11
|
rescue LoadError
|
14
|
-
puts "Rcov not available. Install it for rcov-related tasks with: sudo gem install rcov"
|
15
12
|
end
|
16
13
|
|
17
14
|
begin
|
18
15
|
require 'jeweler'
|
16
|
+
require File.dirname(__FILE__) + "/lib/bond/version"
|
17
|
+
|
19
18
|
Jeweler::Tasks.new do |s|
|
20
19
|
s.name = "bond"
|
20
|
+
s.version = Bond::VERSION
|
21
21
|
s.summary = "Mission: Easy custom autocompletion for arguments, methods and beyond. Accomplished for irb and any other readline-like console environments."
|
22
|
-
s.description = "Bond is on a mission to
|
22
|
+
s.description = "Bond is on a mission to improve irb’s autocompletion. Aside from doing everything irb’s can do and fixing its quirks, Bond can autocomplete argument(s) to methods, uniquely completing per module, per method and per argument. Bond brings irb’s completion closer to bash/zsh as it provides a configuration system and a DSL for creating custom completions and completion rules. With this configuration system, users can customize their irb autocompletions and share it with others. Bond is able to offer more than irb’s completion since it uses a Readline C extension to get the full line of input when completing as opposed to irb’s last-word approach."
|
23
23
|
s.email = "gabriel.horner@gmail.com"
|
24
24
|
s.homepage = "http://tagaholic.me/bond/"
|
25
25
|
s.authors = ["Gabriel Horner"]
|
@@ -27,51 +27,15 @@ begin
|
|
27
27
|
s.has_rdoc = true
|
28
28
|
s.extra_rdoc_files = ["README.rdoc", "LICENSE.txt"]
|
29
29
|
s.extensions = ["ext/readline_line_buffer/extconf.rb"]
|
30
|
-
s.files = FileList["CHANGELOG.rdoc", "Rakefile", "README.rdoc", "
|
30
|
+
s.files = FileList["CHANGELOG.rdoc", "Rakefile", "README.rdoc", "LICENSE.txt", "{bin,lib,test,ext}/**/*"]
|
31
31
|
end
|
32
32
|
|
33
33
|
rescue LoadError
|
34
|
-
puts "Jeweler not available. Install it for jeweler-related tasks with: sudo gem install technicalpickles-jeweler -s http://gems.github.com"
|
35
|
-
end
|
36
|
-
|
37
|
-
Rake::TestTask.new do |t|
|
38
|
-
t.libs << 'lib'
|
39
|
-
t.pattern = 'test/**/*_test.rb'
|
40
|
-
t.verbose = false
|
41
34
|
end
|
42
35
|
|
43
|
-
|
44
|
-
rdoc.rdoc_dir = 'rdoc'
|
45
|
-
rdoc.title = 'test'
|
46
|
-
rdoc.options << '--line-numbers' << '--inline-source'
|
47
|
-
rdoc.rdoc_files.include('README*')
|
48
|
-
rdoc.rdoc_files.include('lib/**/*.rb')
|
49
|
-
end
|
36
|
+
task :default => :test
|
50
37
|
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
# More about this here: http://tagaholic.me/2009/04/08/building-dry-gems-with-thor-and-jeweler.html .
|
55
|
-
desc "Update gemspec from existing one by regenerating path globs specified in *.gemspec.yml or defaults to liberal path globs."
|
56
|
-
task :gemspec_update do
|
57
|
-
if (gemspec_file = Dir['*.gemspec'][0])
|
58
|
-
original_gemspec = eval(File.read(gemspec_file))
|
59
|
-
if File.exists?("#{gemspec_file}.yml")
|
60
|
-
require 'yaml'
|
61
|
-
YAML::load_file("#{gemspec_file}.yml").each do |attribute, globs|
|
62
|
-
original_gemspec.send("#{attribute}=", FileList[globs])
|
63
|
-
end
|
64
|
-
else
|
65
|
-
# liberal defaults
|
66
|
-
original_gemspec.files = FileList["**/*"]
|
67
|
-
test_directories = original_gemspec.test_files.grep(/\//).map {|e| e[/^[^\/]+/]}.compact.uniq
|
68
|
-
original_gemspec.test_files = FileList["{#{test_directories.join(',')}}/**/*"] unless test_directories.empty?
|
69
|
-
end
|
70
|
-
File.open(gemspec_file, 'w') {|f| f.write(original_gemspec.to_ruby) }
|
71
|
-
puts "Updated gemspec."
|
72
|
-
else
|
73
|
-
puts "No existing gemspec file found."
|
74
|
-
end
|
38
|
+
desc 'Run specs with unit test style output'
|
39
|
+
task :test do |t|
|
40
|
+
sh 'bacon -q -Ilib test/*_test.rb'
|
75
41
|
end
|
76
|
-
|
77
|
-
task :default => :test
|