bond 0.1.4 → 0.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- 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/test/mission_test.rb
CHANGED
@@ -1,65 +1,51 @@
|
|
1
1
|
require File.join(File.dirname(__FILE__), 'test_helper')
|
2
2
|
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
before(:each) {|e| Bond.agent.reset }
|
8
|
-
test "completes" do
|
3
|
+
describe "Mission" do
|
4
|
+
describe "mission" do
|
5
|
+
before { Bond.agent.reset }
|
6
|
+
it "completes" do
|
9
7
|
complete(:on=>/bling/) {|e| %w{ab cd fg hi}}
|
10
8
|
complete(:method=>'cool') {|e| [] }
|
11
|
-
|
12
|
-
end
|
13
|
-
|
14
|
-
test "with method completes" do
|
15
|
-
complete(:on=>/bling/) {|e| [] }
|
16
|
-
complete(:method=>'cool') {|e| %w{ab cd ef gd} }
|
17
|
-
tabtab('cool c').should == %w{cd}
|
18
|
-
end
|
19
|
-
|
20
|
-
test "with method and quoted argument completes" do
|
21
|
-
complete(:on=>/bling/) {|e| [] }
|
22
|
-
complete(:method=>'cool') {|e| %w{ab cd ef ad} }
|
23
|
-
tabtab('cool "a').should == %w{ab ad}
|
9
|
+
tab('some bling f').should == %w{fg}
|
24
10
|
end
|
25
11
|
|
26
|
-
|
27
|
-
complete(:
|
28
|
-
|
29
|
-
tabtab('cool c').should == %w{cd}
|
12
|
+
it "with regexp condition completes" do
|
13
|
+
complete(:on=>/\s*'([^']+)$/, :search=>false) {|e| %w{coco for puffs}.grep(/#{e.matched[1]}/) }
|
14
|
+
tab("require 'ff").should == ['puffs']
|
30
15
|
end
|
31
16
|
|
32
|
-
|
33
|
-
complete(:
|
34
|
-
|
35
|
-
tabtab("ls c").should == %w{cd}
|
17
|
+
it "with non-string completions completes" do
|
18
|
+
complete(:on=>/.*/) { [:one,:two,:three] }
|
19
|
+
tab('ok ').should == %w{one two three}
|
36
20
|
end
|
37
21
|
|
38
|
-
|
39
|
-
complete(:on
|
40
|
-
|
22
|
+
it "with non-array completions completes" do
|
23
|
+
complete(:on=>/blah/) { 'blah' }
|
24
|
+
tab('blah ').should == ['blah']
|
41
25
|
end
|
42
26
|
|
43
|
-
|
44
|
-
|
45
|
-
|
27
|
+
it "with symbol action completes" do
|
28
|
+
Rc.module_eval %[def blah(input); %w{one two three}; end]
|
29
|
+
complete(:on=>/blah/, :action=>:blah)
|
30
|
+
tab('blah ').should == %w{one two three}
|
46
31
|
end
|
47
32
|
|
48
|
-
|
49
|
-
|
50
|
-
complete(:
|
51
|
-
|
33
|
+
it "with string action completes" do
|
34
|
+
Rc.module_eval %[def blah(input); %w{one two three}; end]
|
35
|
+
complete(:on=>/blah/, :action=>'blah')
|
36
|
+
tab('blah ').should == %w{one two three}
|
52
37
|
end
|
53
38
|
|
54
|
-
|
55
|
-
complete(:on=>/
|
56
|
-
|
39
|
+
it "always passes Input to action block" do
|
40
|
+
complete(:on=>/man/) {|e| e.should.be.is_a(Input); [] }
|
41
|
+
tab('man ')
|
57
42
|
end
|
58
43
|
end
|
59
44
|
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
45
|
+
it "sets binding to toplevel binding when not in irb" do
|
46
|
+
Mission.eval_binding = nil
|
47
|
+
mock_irb
|
48
|
+
::IRB.CurrentContext.expects(:workspace).raises
|
49
|
+
Mission.eval_binding.should == ::TOPLEVEL_BINDING
|
64
50
|
end
|
65
51
|
end
|
data/test/object_mission_test.rb
CHANGED
@@ -1,63 +1,59 @@
|
|
1
1
|
require File.join(File.dirname(__FILE__), 'test_helper')
|
2
2
|
|
3
|
-
|
4
|
-
before
|
5
|
-
|
6
|
-
|
7
|
-
test "with default action completes" do
|
3
|
+
describe "ObjectMission" do
|
4
|
+
before { Bond.agent.reset }
|
5
|
+
describe "object mission" do
|
6
|
+
it "with default action completes" do
|
8
7
|
complete(:object=>"String")
|
9
8
|
complete(:on=>/man/) { %w{upper upster upful}}
|
10
|
-
|
9
|
+
tab("'man'.up").sort.should == [".upcase", ".upcase!", ".upto"]
|
11
10
|
end
|
12
11
|
|
13
|
-
|
14
|
-
complete(:object
|
12
|
+
it "with regex condition completes" do
|
13
|
+
complete(:object=>'Str.*') {|e| e.object.class.superclass.instance_methods(true) }
|
15
14
|
complete(:on=>/man/) { %w{upper upster upful}}
|
16
|
-
|
15
|
+
tab("'man'.unta").should == [".untaint"]
|
17
16
|
end
|
18
17
|
|
19
|
-
|
18
|
+
it "with explicit action completes" do
|
20
19
|
complete(:object=>"String") {|e| e.object.class.superclass.instance_methods(true) }
|
21
20
|
complete(:on=>/man/) { %w{upper upster upful}}
|
22
|
-
|
21
|
+
tab("'man'.unta").should == [".untaint"]
|
23
22
|
end
|
24
23
|
|
25
|
-
|
24
|
+
it "completes without including word break characters" do
|
26
25
|
complete(:object=>"Hash")
|
27
|
-
matches =
|
28
|
-
|
26
|
+
matches = tab("{}.f")
|
27
|
+
matches.size.should.be > 0
|
29
28
|
matches.all? {|e| !e.include?('{')}.should == true
|
30
29
|
end
|
31
30
|
|
32
|
-
|
31
|
+
it "completes with additional text after completion point" do
|
33
32
|
complete(:object=>"Object")
|
34
|
-
|
35
|
-
assert tabtab("false.f").size > 0
|
36
|
-
assert tabtab("(1..10).f").size > 0
|
33
|
+
tab(':man.f blah', ':man.f').include?(':man.freeze').should == true
|
37
34
|
end
|
38
35
|
|
39
|
-
|
40
|
-
complete(:object=>
|
41
|
-
|
42
|
-
assert tabtab("{:a =>1}.f").size > 0
|
36
|
+
it "doesn't evaluate anything before the completion object" do
|
37
|
+
complete(:object=>'Object')
|
38
|
+
tab('raise :man.i').size.should > 0
|
43
39
|
end
|
44
40
|
|
45
|
-
|
41
|
+
it "ignores invalid ruby" do
|
46
42
|
complete(:object=>"String")
|
47
|
-
|
43
|
+
tab("blah.upt").should == []
|
44
|
+
end
|
45
|
+
|
46
|
+
it "ignores object that doesn't have a valid class" do
|
47
|
+
complete :on=>/(.*)./, :object=>'Object'
|
48
|
+
capture_stdout {
|
49
|
+
tab("obj = Object.new; def obj.class; end; obj.").should == []
|
50
|
+
}.should == ''
|
48
51
|
end
|
49
52
|
|
50
53
|
# needed to ensure Bond works in irbrc
|
51
|
-
|
54
|
+
it "doesn't evaluate irb binding on definition" do
|
52
55
|
Object.expects(:const_defined?).never
|
53
56
|
complete(:object=>"String")
|
54
57
|
end
|
55
|
-
|
56
|
-
test "sets binding to toplevel binding when not in irb" do
|
57
|
-
Object.expects(:const_defined?).with(:IRB).returns(false)
|
58
|
-
mission = Bond::Mission.create(:object=>'Symbol')
|
59
|
-
mission.class.expects(:eval).with(anything, ::TOPLEVEL_BINDING)
|
60
|
-
mission.matches?(':ok.')
|
61
|
-
end
|
62
58
|
end
|
63
59
|
end
|
@@ -0,0 +1,66 @@
|
|
1
|
+
require File.join(File.dirname(__FILE__), 'test_helper')
|
2
|
+
|
3
|
+
describe "operator method mission" do
|
4
|
+
before_all { MethodMission.reset }
|
5
|
+
before { Bond.agent.reset; Bond.complete(:all_operator_methods=>true) }
|
6
|
+
|
7
|
+
describe "operator" do
|
8
|
+
before { complete(:method=>"Hash#[]") { %w{ab cd ae} } }
|
9
|
+
|
10
|
+
it "completes" do
|
11
|
+
tab('{}[a').should == ["}[ab", "}[ae"]
|
12
|
+
end
|
13
|
+
|
14
|
+
it "completes quoted argument" do
|
15
|
+
tab('{:a=>1}["a').should == %w{ab ae}
|
16
|
+
end
|
17
|
+
|
18
|
+
it "completes symbolic argument" do
|
19
|
+
tab('{}[:a').should == ["}[:ab", "}[:ae"]
|
20
|
+
end
|
21
|
+
|
22
|
+
it "completes with no space between method and argument" do
|
23
|
+
tab('{}[a').should == ["}[ab", "}[ae"]
|
24
|
+
end
|
25
|
+
|
26
|
+
it "completes with space between method and argument" do
|
27
|
+
tab('{}[ a').should == ["ab", "ae"]
|
28
|
+
end
|
29
|
+
|
30
|
+
it "completes with operator characters in object" do
|
31
|
+
tab('{:a=> 1}[').should == ["1}[ab", "1}[cd", "1}[ae"]
|
32
|
+
end
|
33
|
+
|
34
|
+
it "completes all arguments with only space as argument" do
|
35
|
+
tab('{}[ ').should == ["ab", "cd", "ae"]
|
36
|
+
end
|
37
|
+
|
38
|
+
it "completes with a chain of objects" do
|
39
|
+
tab('Hash.new[a').should == %w{Hash.new[ab Hash.new[ae}
|
40
|
+
end
|
41
|
+
|
42
|
+
it "completes in middle of line" do
|
43
|
+
tab('nil; {}[a').should == ["}[ab", "}[ae"]
|
44
|
+
end
|
45
|
+
|
46
|
+
it "doesn't complete for multiple arguments" do
|
47
|
+
tab('{}[a,').should == []
|
48
|
+
end
|
49
|
+
end
|
50
|
+
|
51
|
+
it "operator with space between object and method completes" do
|
52
|
+
complete(:method=>"Array#*") { %w{ab cd ae} }
|
53
|
+
tab('[1,2] * a').should == %w{ab ae}
|
54
|
+
tab('[1,2] *a').should == %w{*ab *ae}
|
55
|
+
end
|
56
|
+
|
57
|
+
it "class operator completes" do
|
58
|
+
complete(:method=>"Hash.*") { %w{ab cd ae} }
|
59
|
+
tab('Hash * a').should == %w{ab ae}
|
60
|
+
end
|
61
|
+
|
62
|
+
it "with :search completes" do
|
63
|
+
complete(:method=>"Array#*", :search=>:anywhere) { %w{abc bcd cde} }
|
64
|
+
tab('[1, 2] * b').should == ['abc', 'bcd']
|
65
|
+
end
|
66
|
+
end
|
data/test/search_test.rb
CHANGED
@@ -1,55 +1,132 @@
|
|
1
1
|
require File.join(File.dirname(__FILE__), 'test_helper')
|
2
2
|
|
3
|
-
|
4
|
-
before
|
5
|
-
before(:each) {|e| Bond.agent.reset }
|
3
|
+
describe "Search" do
|
4
|
+
before { Bond.agent.reset }
|
6
5
|
|
7
|
-
|
8
|
-
|
6
|
+
describe "mission with search" do
|
7
|
+
it "false completes" do
|
9
8
|
complete(:on=>/cool '(.*)/, :search=>false) {|e| %w{coco for puffs}.grep(/#{e.matched[1]}/) }
|
10
|
-
|
9
|
+
tab("cool 'ff").should == ['puffs']
|
11
10
|
end
|
12
11
|
|
13
|
-
|
14
|
-
|
15
|
-
|
12
|
+
it "defined in Rc completes" do
|
13
|
+
Rc.module_eval %q{def coco_search(input, list); list.grep(/#{input}/); end }
|
14
|
+
complete(:on=>/blah/, :search=>:coco) {|e| %w{coco for puffs} }
|
15
|
+
tab("blah ff").should == ['puffs']
|
16
16
|
end
|
17
17
|
|
18
|
-
|
19
|
-
complete(:
|
20
|
-
|
18
|
+
it ":anywhere completes" do
|
19
|
+
complete(:on=>/blah/, :search=>:anywhere) {|e| %w{coco for puffs} }
|
20
|
+
tab("blah ff").should == ['puffs']
|
21
21
|
end
|
22
22
|
|
23
|
-
|
24
|
-
complete(:
|
25
|
-
|
23
|
+
it ":ignore_case completes" do
|
24
|
+
complete(:on=>/blah/, :search=>:ignore_case) {|e| %w{Coco For PufFs} }
|
25
|
+
tab("blah pu").should == ['PufFs']
|
26
26
|
end
|
27
27
|
|
28
|
-
|
28
|
+
it ":underscore completes" do
|
29
29
|
complete(:on=>/blah/, :search=>:underscore) {|e| %w{and_one big_two can_three} }
|
30
|
-
|
31
|
-
|
30
|
+
tab("blah and").should == ['and_one']
|
31
|
+
tab("blah b_t").should == ['big_two']
|
32
32
|
end
|
33
33
|
end
|
34
34
|
|
35
|
-
|
35
|
+
it "underscore search doesn't pick up strings starting with __" do
|
36
36
|
completions = ["include?", "instance_variable_defined?", "__id__", "include_and_exclude?"]
|
37
|
-
complete(:
|
38
|
-
|
37
|
+
complete(:on=>/blah/, :search=>:underscore) { completions }
|
38
|
+
tab("blah i").should == ["include?", "instance_variable_defined?", "include_and_exclude?"]
|
39
39
|
end
|
40
40
|
|
41
|
-
|
41
|
+
it "underscore search can match first unique strings of each underscored word" do
|
42
42
|
completions = %w{so_long so_larger so_louder}
|
43
|
-
complete(:
|
44
|
-
|
45
|
-
|
43
|
+
complete(:on=>/blah/, :search=>:underscore) { completions }
|
44
|
+
tab("blah s_lo").should == %w{so_long so_louder}
|
45
|
+
tab("blah s_lou").should == %w{so_louder}
|
46
46
|
end
|
47
47
|
|
48
|
-
|
48
|
+
it "underscore search acts normal if ending in underscore" do
|
49
|
+
complete(:on=>/blah/, :search=>:underscore) {|e| %w{and_one big_two can_three ander_one} }
|
50
|
+
tab("blah and_").should == %w{and_one}
|
51
|
+
end
|
52
|
+
|
53
|
+
it "search handles completions with regex characters" do
|
49
54
|
completions = ['[doh]', '.*a', '?ok']
|
50
55
|
complete(:on=>/blah/) { completions }
|
51
|
-
|
52
|
-
|
53
|
-
|
56
|
+
tab('blah .').should == ['.*a']
|
57
|
+
tab('blah [').should == ['[doh]']
|
58
|
+
tab('blah ?').should == ['?ok']
|
59
|
+
end
|
60
|
+
|
61
|
+
it "default search uses default search" do
|
62
|
+
Search.default_search.should == :underscore
|
63
|
+
Rc.expects(:underscore_search).with('a', %w{ab cd})
|
64
|
+
Rc.send(:default_search, 'a', %w{ab cd})
|
65
|
+
end
|
66
|
+
|
67
|
+
describe "modules search" do
|
68
|
+
before {
|
69
|
+
complete(:on=>/blah/, :search=>:modules) { %w{A1 M1::Z M1::Y::X M2::X} }
|
70
|
+
}
|
71
|
+
it "completes all modules" do
|
72
|
+
tab('blah ').should == ["A1", "M1::", "M2::"]
|
73
|
+
end
|
74
|
+
|
75
|
+
it "completes single first level module" do
|
76
|
+
tab('blah A').should == %w{A1}
|
77
|
+
end
|
78
|
+
|
79
|
+
it "completes single first level module parent" do
|
80
|
+
tab('blah M2').should == %w{M2::}
|
81
|
+
end
|
82
|
+
|
83
|
+
it "completes all second level modules" do
|
84
|
+
tab('blah M1::').should == %w{M1::Z M1::Y::}
|
85
|
+
end
|
86
|
+
|
87
|
+
it "completes second level module parent" do
|
88
|
+
tab('blah M1::Y').should == %w{M1::Y::}
|
89
|
+
end
|
90
|
+
|
91
|
+
it "completes third level module" do
|
92
|
+
tab('blah M1::Y::').should == %w{M1::Y::X}
|
93
|
+
end
|
94
|
+
end
|
95
|
+
|
96
|
+
describe "files search" do
|
97
|
+
before {
|
98
|
+
complete(:on=>/rm/, :search=>:files) { %w{a1 d1/f2 d1/d2/f1 d2/f1 d2/f1/ /f1} }
|
99
|
+
}
|
100
|
+
it "completes all paths" do
|
101
|
+
tab('rm ').should == %w{a1 d1/ d2/ /}
|
102
|
+
end
|
103
|
+
|
104
|
+
it "completes single first level file" do
|
105
|
+
tab('rm a').should == %w{a1}
|
106
|
+
end
|
107
|
+
|
108
|
+
it "completes single first level directory" do
|
109
|
+
tab('rm d2').should == %w{d2/}
|
110
|
+
end
|
111
|
+
|
112
|
+
it "completes all second level paths" do
|
113
|
+
tab('rm d1/').should == %w{d1/f2 d1/d2/}
|
114
|
+
end
|
115
|
+
|
116
|
+
it "completes single second level directory" do
|
117
|
+
tab('rm d1/d2').should == %w{d1/d2/}
|
118
|
+
end
|
119
|
+
|
120
|
+
it "completes single third level file" do
|
121
|
+
tab('rm d1/d2/').should == %w{d1/d2/f1}
|
122
|
+
end
|
123
|
+
|
124
|
+
it "completes file and directory with same name" do
|
125
|
+
tab('rm d2/f').should == %w{d2/f1 d2/f1/}
|
126
|
+
end
|
127
|
+
|
128
|
+
it "completes file with full path" do
|
129
|
+
tab('rm /f').should == %w{/f1}
|
130
|
+
end
|
54
131
|
end
|
55
132
|
end
|
data/test/test_helper.rb
CHANGED
@@ -1,14 +1,12 @@
|
|
1
|
-
require '
|
2
|
-
require '
|
3
|
-
require 'context' #gem install jeremymcanally-context -s http://gems.github.com
|
4
|
-
require 'matchy' #gem install jeremymcanally-matchy -s http://gems.github.com
|
1
|
+
require 'bacon'
|
2
|
+
require File.dirname(__FILE__)+'/bacon_extensions'
|
5
3
|
require 'mocha'
|
6
|
-
|
4
|
+
require 'mocha-on-bacon'
|
7
5
|
require 'bond'
|
8
6
|
|
9
|
-
|
10
|
-
|
11
|
-
|
7
|
+
module TestHelpers
|
8
|
+
extend self
|
9
|
+
def mock_irb
|
12
10
|
unless Object.const_defined?(:IRB)
|
13
11
|
eval %[
|
14
12
|
module ::IRB
|
@@ -18,7 +16,7 @@ class Test::Unit::TestCase
|
|
18
16
|
]
|
19
17
|
::IRB.CurrentContext = stub(:workspace=>stub(:binding=>binding))
|
20
18
|
end
|
21
|
-
|
19
|
+
end
|
22
20
|
|
23
21
|
def capture_stderr(&block)
|
24
22
|
original_stderr = $stderr
|
@@ -42,8 +40,8 @@ class Test::Unit::TestCase
|
|
42
40
|
fake.string
|
43
41
|
end
|
44
42
|
|
45
|
-
def
|
46
|
-
Bond.agent.stubs(:line_buffer).returns(full_line)
|
43
|
+
def tab(full_line, last_word=full_line)
|
44
|
+
Bond.agent.weapon.stubs(:line_buffer).returns(full_line)
|
47
45
|
Bond.agent.call(last_word)
|
48
46
|
end
|
49
47
|
|
@@ -52,6 +50,15 @@ class Test::Unit::TestCase
|
|
52
50
|
end
|
53
51
|
|
54
52
|
def valid_readline_plugin
|
55
|
-
Module.new{ def setup; end; def line_buffer; end }
|
53
|
+
Module.new{ def setup(arg); end; def line_buffer; end }
|
56
54
|
end
|
57
|
-
end
|
55
|
+
end
|
56
|
+
|
57
|
+
class Bacon::Context
|
58
|
+
include TestHelpers
|
59
|
+
include BaconExtensions
|
60
|
+
end
|
61
|
+
|
62
|
+
# Default settings
|
63
|
+
Bond::M.debrief(:readline_plugin=>TestHelpers.valid_readline_plugin, :debug=>true)
|
64
|
+
include Bond
|