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/lib/bond.rb
CHANGED
@@ -1,121 +1,90 @@
|
|
1
|
-
|
2
|
-
|
1
|
+
require 'bond/m'
|
2
|
+
require 'bond/version'
|
3
3
|
require 'bond/readline'
|
4
4
|
require 'bond/rawline'
|
5
5
|
require 'bond/agent'
|
6
6
|
require 'bond/search'
|
7
|
-
require 'bond/
|
7
|
+
require 'bond/input'
|
8
|
+
require 'bond/rc'
|
8
9
|
require 'bond/mission'
|
9
10
|
require 'bond/missions/default_mission'
|
10
11
|
require 'bond/missions/method_mission'
|
11
12
|
require 'bond/missions/object_mission'
|
13
|
+
require 'bond/missions/anywhere_mission'
|
14
|
+
require 'bond/missions/operator_method_mission'
|
12
15
|
|
13
|
-
# Bond allows easy handling and creation of completion missions/rules with Bond.complete. When Bond is asked to autocomplete, Bond looks
|
14
|
-
# up the completion missions in the order they were defined and picks the first one that matches what the user has typed.
|
15
|
-
# Bond::Agent handles finding and executing the correct completion mission.
|
16
|
-
# Some pointers on using/understanding Bond:
|
17
|
-
# * Bond can work outside of irb and readline when debriefed with Bond.debrief. This should be called before any Bond.complete calls.
|
18
|
-
# * Bond doesn't take over completion until an explicit Bond.complete is called.
|
19
|
-
# * Order of completion missions matters. The order they're defined in is the order Bond searches
|
20
|
-
# when looking for a matching completion. This means that more specific completions like method and object completions should come
|
21
|
-
# before more general ones. You can tweak completion placement by passing :place to Bond.complete.
|
22
|
-
# * If no completion missions match, then Bond falls back on a default mission. If using irb and irb/completion
|
23
|
-
# this falls back on irb's completion. Otherwise an empty completion list is returned.
|
24
16
|
module Bond
|
25
17
|
extend self
|
26
18
|
|
27
|
-
# Defines a completion
|
28
|
-
#
|
29
|
-
#
|
30
|
-
#
|
31
|
-
#
|
19
|
+
# Defines a completion rule (Mission). A valid Mission consists of a condition and an action. A
|
20
|
+
# condition is specified with one of the following options: :on, :object, :anywhere or :method(s). Each
|
21
|
+
# of these options creates a different Mission class. An action is either this method's block or :action.
|
22
|
+
# An action takes what the user has typed (Input) and returns an array of possible completions. Bond
|
23
|
+
# searches these completions and returns matching completions. This searching behavior can be configured
|
24
|
+
# or turned off per mission with :search. If turned off, the action must also handle searching.
|
32
25
|
# ====Options:
|
33
|
-
# [
|
34
|
-
#
|
35
|
-
# [
|
36
|
-
#
|
37
|
-
#
|
38
|
-
#
|
39
|
-
#
|
40
|
-
#
|
41
|
-
# [
|
42
|
-
#
|
43
|
-
#
|
44
|
-
#
|
45
|
-
#
|
46
|
-
#
|
47
|
-
#
|
48
|
-
# of :last are kept last in the order they are defined.
|
49
|
-
#
|
26
|
+
# [*:on*] Regular expression which matches the full line of input to create a Mission object.
|
27
|
+
# [*:method*, *:methods*, *:class*] See MethodMission.
|
28
|
+
# [*:anywhere*, *:prefix*] See AnywhereMission.
|
29
|
+
# [*:object*] See ObjectMission.
|
30
|
+
# [*:search*] A symbol or false which determines how completions are searched. Defaults to
|
31
|
+
# Search.default_search. If false, search is turned off and assumed to be done in the action.
|
32
|
+
# Possible symbols are :anywhere, :ignore_case, :underscore, :normal, :files and :modules.
|
33
|
+
# See Search for more info.
|
34
|
+
# [*:action*] Rc method name that takes an Input and returns possible completions. See MethodMission for
|
35
|
+
# specific behavior with :method(s).
|
36
|
+
# [*:place*] A number or :last which indicates where a mission is inserted amongst existing missions.
|
37
|
+
# If the symbol :last, places the mission at the end regardless of missions defined after
|
38
|
+
# it. Multiple declarations of :last are kept last in the order they are defined.
|
39
|
+
# [*:name*] A symbol or string that serves a unique id for a mission. This unique id can be passed by
|
40
|
+
# Bond.recomplete to identify and replace the mission.
|
50
41
|
# ==== Examples:
|
51
42
|
# Bond.complete(:method=>'shoot') {|input| %w{to kill} }
|
52
43
|
# Bond.complete(:on=>/^((([a-z][^:.\(]*)+):)+/, :search=>false) {|input| Object.constants.grep(/#{input.matched[1]}/) }
|
53
44
|
# Bond.complete(:object=>ActiveRecord::Base, :search=>:underscore, :place=>:last)
|
54
|
-
# Bond.complete(:object=>ActiveRecord::Base) {|input| input.object.class.instance_methods(false) }
|
55
45
|
# Bond.complete(:method=>'you', :search=>proc {|input, list| list.grep(/#{input}/i)} ) {|input| %w{Only Live Twice} }
|
56
|
-
|
57
|
-
|
58
|
-
$stderr.puts result
|
59
|
-
false
|
60
|
-
else
|
61
|
-
true
|
62
|
-
end
|
63
|
-
end
|
46
|
+
# Bond.complete(:method=>'system', :action=>:shell_commands)
|
47
|
+
def complete(options={}, &block); M.complete(options, &block); end
|
64
48
|
|
65
|
-
# Redefines an existing completion mission
|
66
|
-
#
|
67
|
-
def recomplete(options={}, &block)
|
68
|
-
if (result = agent.recomplete(options, &block)).is_a?(String)
|
69
|
-
$stderr.puts result
|
70
|
-
false
|
71
|
-
else
|
72
|
-
true
|
73
|
-
end
|
74
|
-
end
|
75
|
-
|
76
|
-
# Resets Bond so that next time Bond.complete is called, a new set of completion missions are created. This does not
|
77
|
-
# change current completion behavior.
|
78
|
-
def reset
|
79
|
-
@agent = nil
|
80
|
-
end
|
81
|
-
|
82
|
-
# Debriefs Bond to set global defaults. Call before defining completions.
|
83
|
-
# ==== Options:
|
84
|
-
# [:readline_plugin] Specifies a Bond plugin to interface with a Readline-like library. Available plugins are Bond::Readline and Bond::Rawline.
|
85
|
-
# Defaults to Bond::Readline. Note that a plugin doesn't imply use with irb. Irb is joined to the hip with Readline.
|
86
|
-
# [:default_mission] A proc to be used as the default completion proc when no completions match or one fails. When in irb with completion
|
87
|
-
# enabled, uses irb completion. Otherwise defaults to a proc with an empty completion list.
|
88
|
-
# [:default_search] A symbol or proc to be used as the default search in completions. See Bond.complete's :search option for valid symbols.
|
89
|
-
# [:eval_binding] Specifies a binding to be used with Bond::Missions::ObjectMission. When in irb, defaults to irb's main binding. Otherwise
|
90
|
-
# defaults to TOPLEVEL_BINDING.
|
91
|
-
# [:debug] Boolean to print unexpected errors when autocompletion fails. Default is false.
|
92
|
-
#
|
49
|
+
# Redefines an existing completion mission to have a different action. The condition can only be varied if :name is
|
50
|
+
# used to identify and replace a mission. Takes same options as Bond.complete.
|
93
51
|
# ==== Example:
|
94
|
-
# Bond.
|
95
|
-
def
|
96
|
-
config.merge! options
|
97
|
-
plugin_methods = %w{setup line_buffer}
|
98
|
-
unless config[:readline_plugin].is_a?(Module) &&
|
99
|
-
plugin_methods.all? {|e| config[:readline_plugin].instance_methods.map {|f| f.to_s}.include?(e)}
|
100
|
-
$stderr.puts "Invalid readline plugin set. Try again."
|
101
|
-
end
|
102
|
-
end
|
52
|
+
# Bond.recomplete(:on=>/man/, :name=>:count) { %w{4 5 6}}
|
53
|
+
def recomplete(options={}, &block); M.recomplete(options, &block); end
|
103
54
|
|
104
|
-
# Reports what completion mission
|
105
|
-
# your completion missions.
|
55
|
+
# Reports what completion mission matches for a given input. Helpful for debugging missions.
|
106
56
|
# ==== Example:
|
107
57
|
# >> Bond.spy "shoot oct"
|
108
58
|
# Matches completion mission for method matching "shoot".
|
109
59
|
# Possible completions: ["octopussy"]
|
110
|
-
def spy(
|
111
|
-
|
112
|
-
|
60
|
+
def spy(*args); M.spy(*args); end
|
61
|
+
|
62
|
+
# Global config with the following keys:
|
63
|
+
# [*:readline_plugin*] Specifies a Bond plugin to interface with a Readline-like library. Available
|
64
|
+
# plugins are Readline and Rawline. Defaults to Readline.
|
65
|
+
# [*:default_mission*] A proc or name of an Rc method to use as the default completion when no
|
66
|
+
# missions match.
|
67
|
+
# [*:default_search*] Name of a *_search method in Rc to use as the default search in completions.
|
68
|
+
# Default is :underscore. See Bond.complete's :search option for valid values.
|
69
|
+
# [*:eval_binding*] Specifies a binding to use when evaluating objects in ObjectMission and MethodMission.
|
70
|
+
# When in irb, defaults to irb's current binding. Otherwise defaults to TOPLEVEL_BINDING.
|
71
|
+
# [*:debug*] Boolean to show the stacktrace when autocompletion fails and raise exceptions in Rc.eval.
|
72
|
+
# Default is false.
|
73
|
+
def config; M.config; end
|
74
|
+
|
75
|
+
# Starts Bond with a default set of completions that replace and improve irb's completion. Loads completion
|
76
|
+
# files in the following order: lib/bond/completion.rb, optional ~/.bondrc, lib/bond/completions/*.rb,
|
77
|
+
# optional ~/.bond/completions/*.rb and optional block. See Rc for the DSL to use in completion files and
|
78
|
+
# in the block. See Bond.config for valid options.
|
79
|
+
# ==== Example:
|
80
|
+
# Bond.start(:default_search=>:ignore_case) do
|
81
|
+
# complete(:method=>"Object#respond_to?") {|e| e.object.methods }
|
82
|
+
# end
|
83
|
+
def start(options={}, &block); M.start(options, &block); end
|
113
84
|
|
114
|
-
|
115
|
-
|
116
|
-
end
|
85
|
+
# An Agent who saves all Bond.complete missions and executes the correct one when a completion is called.
|
86
|
+
def agent; M.agent; end
|
117
87
|
|
118
|
-
|
119
|
-
|
120
|
-
end
|
88
|
+
# Lists all methods that have argument completion.
|
89
|
+
def list_methods; MethodMission.all_methods; end
|
121
90
|
end
|
data/lib/bond/agent.rb
CHANGED
@@ -1,19 +1,29 @@
|
|
1
1
|
module Bond
|
2
|
-
#
|
2
|
+
# Every time a completion is attempted, the Agent searches its missions for the first one that matches the user input.
|
3
|
+
# Using either the found mission or Agent.default_mission, the Agent executes the mission's action.
|
3
4
|
class Agent
|
4
5
|
# The array of missions that will be searched when a completion occurs.
|
5
6
|
attr_reader :missions
|
7
|
+
# An agent's best friend a.k.a. the readline plugin.
|
8
|
+
attr_reader :weapon
|
6
9
|
|
7
10
|
def initialize(options={}) #:nodoc:
|
8
|
-
|
9
|
-
extend(options[:readline_plugin])
|
11
|
+
setup_readline_plugin(options[:readline_plugin])
|
10
12
|
@default_mission_action = options[:default_mission] if options[:default_mission]
|
11
|
-
|
12
|
-
|
13
|
-
setup
|
13
|
+
Mission.eval_binding = options[:eval_binding] if options[:eval_binding]
|
14
|
+
Search.default_search = options[:default_search] || :normal
|
14
15
|
@missions = []
|
15
16
|
end
|
16
17
|
|
18
|
+
def setup_readline_plugin(plugin) #:nodoc:
|
19
|
+
raise ArgumentError unless plugin.is_a?(Module)
|
20
|
+
@weapon = plugin.extend(plugin)
|
21
|
+
@weapon.setup(self)
|
22
|
+
rescue
|
23
|
+
$stderr.puts "Bond Error: Failed #{plugin.to_s[/[^:]+$/]} setup with '#{$!.message}'"
|
24
|
+
end
|
25
|
+
|
26
|
+
# Creates a mission.
|
17
27
|
def complete(options={}, &block)
|
18
28
|
if (mission = create_mission(options, &block)).is_a?(Mission)
|
19
29
|
mission.place.is_a?(Integer) ? @missions.insert(mission.place - 1, mission).compact! : @missions << mission
|
@@ -23,19 +33,17 @@ module Bond
|
|
23
33
|
end
|
24
34
|
|
25
35
|
def create_mission(options, &block) #:nodoc:
|
26
|
-
options[:action]
|
27
|
-
Mission.create(options.merge(:eval_binding=>@eval_binding))
|
36
|
+
Mission.create options.merge!(:action=>options[:action] || block)
|
28
37
|
rescue InvalidMissionError
|
29
|
-
"Invalid
|
30
|
-
rescue InvalidMissionActionError
|
31
|
-
"Invalid mission action given. Make sure action responds to :call or refers to a predefined action that does."
|
38
|
+
"Invalid #{$!.message} for completion with options: #{options.inspect}"
|
32
39
|
rescue
|
33
|
-
"
|
40
|
+
"Unexpected error while creating completion with options #{options.inspect}:\n#{$!}"
|
34
41
|
end
|
35
42
|
|
43
|
+
# Creates a mission and replaces the mission it matches if possible.
|
36
44
|
def recomplete(options={}, &block)
|
37
45
|
if (mission = create_mission(options, &block)).is_a?(Mission)
|
38
|
-
if (existing_mission = @missions.find {|e| e.
|
46
|
+
if (existing_mission = @missions.find {|e| e.name == mission.name })
|
39
47
|
@missions[@missions.index(existing_mission)] = mission
|
40
48
|
sort_last_missions
|
41
49
|
else
|
@@ -55,31 +63,29 @@ module Bond
|
|
55
63
|
|
56
64
|
# This is where the action starts when a completion is initiated.
|
57
65
|
def call(input)
|
58
|
-
mission_input = line_buffer
|
66
|
+
mission_input = @weapon.line_buffer
|
59
67
|
mission_input = $1 if mission_input !~ /#{Regexp.escape(input)}$/ && mission_input =~ /^(.*#{Regexp.escape(input)})/
|
60
|
-
(mission = find_mission(mission_input)) ? mission.execute : default_mission.execute(input)
|
61
|
-
rescue
|
62
|
-
|
68
|
+
(mission = find_mission(mission_input)) ? mission.execute : default_mission.execute(Input.new(input))
|
69
|
+
rescue FailedMissionError
|
70
|
+
completion_error($!.message[0], "Completion Info: #{$!.message[1]}")
|
63
71
|
rescue
|
64
|
-
|
65
|
-
|
66
|
-
p $!.backtrace.slice(0,5)
|
67
|
-
end
|
68
|
-
default_mission.execute(input)
|
72
|
+
completion_error "Failed internally with '#{$!.message}'.",
|
73
|
+
"Please report this issue with debug on: Bond.config[:debug] = true."
|
69
74
|
end
|
70
75
|
|
76
|
+
def completion_error(desc, message) #:nodoc:
|
77
|
+
arr = ["Bond Error: #{desc}", message]
|
78
|
+
arr << "Stack Trace: #{$!.backtrace.inspect}" if Bond.config[:debug]
|
79
|
+
arr
|
80
|
+
end
|
81
|
+
|
82
|
+
# Given a hypothetical user input, reports back what mission it would have found and executed.
|
71
83
|
def spy(input)
|
72
84
|
if (mission = find_mission(input))
|
73
|
-
|
74
|
-
|
75
|
-
elsif mission.is_a?(Missions::MethodMission)
|
76
|
-
puts "Matches completion mission for method matching #{mission.method_condition.inspect}."
|
77
|
-
else
|
78
|
-
puts "Matches completion mission with condition #{mission.condition.inspect}."
|
79
|
-
end
|
80
|
-
puts "Possible completions: #{mission.execute.inspect}"
|
85
|
+
puts mission.match_message, "Possible completions: #{mission.execute.inspect}",
|
86
|
+
"Matches for #{mission.condition.inspect} are #{mission.matched.to_a.inspect}"
|
81
87
|
else
|
82
|
-
puts "Doesn't match a completion
|
88
|
+
puts "Doesn't match a completion."
|
83
89
|
end
|
84
90
|
end
|
85
91
|
|
@@ -87,9 +93,9 @@ module Bond
|
|
87
93
|
@missions.find {|mission| mission.matches?(input) }
|
88
94
|
end
|
89
95
|
|
90
|
-
# Default mission used by agent.
|
96
|
+
# Default mission used by agent. An instance of DefaultMission.
|
91
97
|
def default_mission
|
92
|
-
@default_mission ||=
|
98
|
+
@default_mission ||= DefaultMission.new(:action=>@default_mission_action)
|
93
99
|
end
|
94
100
|
end
|
95
101
|
end
|
data/lib/bond/completion.rb
CHANGED
@@ -1,28 +1,16 @@
|
|
1
|
-
#
|
2
|
-
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
#
|
10
|
-
|
11
|
-
# Completes absolute constants
|
12
|
-
Bond.complete(:on=>/::([A-Z][^:\.\(]*)$/, :search=>false) {|e|
|
13
|
-
Object.constants.grep(/^#{Regexp.escape(e.matched[1])}/).collect{|f| "::" + f}
|
1
|
+
# any object's methods
|
2
|
+
complete :object=>"Object"
|
3
|
+
# method arguments
|
4
|
+
complete :all_methods=>true
|
5
|
+
complete :all_operator_methods=>true
|
6
|
+
# classes and constants
|
7
|
+
complete(:name=>:constants, :anywhere=>'(((::)?[A-Z][^:.\(]*)+)::?([^:.]*)') {|e|
|
8
|
+
receiver = e.matched[2]
|
9
|
+
candidates = eval("#{receiver}.constants | #{receiver}.methods") || []
|
10
|
+
normal_search(e.matched[5], candidates).map {|e| receiver + "::" + e}
|
14
11
|
}
|
15
|
-
#
|
16
|
-
|
17
|
-
|
18
|
-
}
|
19
|
-
|
20
|
-
Bond.complete(:on=>/(\$[^\s.]*)$/, :search=>false) {|e|
|
21
|
-
global_variables.grep(/^#{Regexp.escape(e.matched[1])}/)
|
22
|
-
}
|
23
|
-
# Completes files
|
24
|
-
Bond.complete(:on=>/[\s(]["']([^'"]*)$/, :search=>false, :action=>:quoted_files, :place=>:last)
|
25
|
-
# Completes any object's methods
|
26
|
-
Bond.complete(:object=>"Object", :place=>:last)
|
27
|
-
# Completes method completion anywhere in the line
|
28
|
-
Bond.complete(:on=>/([^.\s]+)\.([^.\s]*)$/, :object=>"Object", :place=>:last)
|
12
|
+
# absolute constants
|
13
|
+
complete(:prefix=>'::', :anywhere=>'[A-Z][^:\.\(]*') {|e| Object.constants }
|
14
|
+
complete(:anywhere=>':[^:\s.]*') {|e| Symbol.all_symbols.map {|f| ":#{f}" } rescue [] }
|
15
|
+
complete(:anywhere=>'\$[^\s.]*') {|e| global_variables }
|
16
|
+
complete(:name=>:quoted_files, :on=>/[\s(]["']([^'"]*)$/, :search=>false, :place=>:last) {|e| files(e.matched[1]) }
|
@@ -0,0 +1,12 @@
|
|
1
|
+
attribute_imethods = %w{attribute_for_inspect column_for_attribute decrement} +
|
2
|
+
%w{increment update_attribute toggle update_attributes []}
|
3
|
+
complete(:methods=>attribute_imethods, :class=>"ActiveRecord::Base#") {|e| e.object.attribute_names }
|
4
|
+
|
5
|
+
attribute_cmethods = %w{attr_accessible attr_protected attr_readonly create create! decrement_counter} +
|
6
|
+
%w{destroy_all exists? increment_counter new serialize update update_all update_counters where}
|
7
|
+
complete(:methods=>attribute_cmethods, :class=>'ActiveRecord::Base.') {|e| e.object.column_names }
|
8
|
+
|
9
|
+
complete(:method=>"ActiveRecord::Base.establish_connection") { %w{adapter host username password database} }
|
10
|
+
complete(:methods=>%w{find all first last}, :class=>'ActiveRecord::Base.') {
|
11
|
+
%w{conditions order group having limit offset joins include select from readonly lock}
|
12
|
+
}
|
@@ -0,0 +1 @@
|
|
1
|
+
complete(:methods=>%w{delete index rindex include?}, :class=>"Array#") {|e| e.object }
|
@@ -0,0 +1,13 @@
|
|
1
|
+
complete(:methods=>%w{Kernel#raise Kernel#fail}) { objects_of(Class).select {|e| e < StandardError } }
|
2
|
+
complete(:method=>%w{Kernel#system Kernel#exec}) {|e|
|
3
|
+
ENV['PATH'].split(File::PATH_SEPARATOR).uniq.map {|e| Dir.entries(e) }.flatten.uniq - ['.', '..']
|
4
|
+
}
|
5
|
+
complete(:method=>"Kernel#require", :search=>:files) {
|
6
|
+
paths = $:.map {|e| Dir["#{e}/**/*.{rb,bundle,dll,so}"].map {|f| f.sub(e+'/', '') } }.flatten
|
7
|
+
if Object.const_defined?(:Gem)
|
8
|
+
paths += Gem.path.map {|e| Dir["#{e}/gems/*/lib/*.{rb,bundle,dll,so}"].
|
9
|
+
map {|f| f.sub(/^.*\//,'') } }.flatten
|
10
|
+
end
|
11
|
+
paths.uniq
|
12
|
+
}
|
13
|
+
complete(:methods=>%w{Kernel#trace_var Kernel#untrace_var}) { global_variables.map {|e| ":#{e}"} }
|
@@ -0,0 +1,7 @@
|
|
1
|
+
complete(:methods=>%w{const_get const_set const_defined? remove_const}, :class=>"Module#") {|e| e.object.constants }
|
2
|
+
complete(:methods=>%w{class_variable_defined? class_variable_get class_variable_set remove_class_variable},
|
3
|
+
:class=>"Module#") {|e| e.object.class_variables }
|
4
|
+
complete(:methods=>%w{instance_method method_defined? module_function public private protected remove_method undef_method},
|
5
|
+
:class=>"Module#") {|e| e.object.instance_methods }
|
6
|
+
complete(:methods=>%w{< <= <=> > >= include? include}, :class=>"Module#", :search=>:modules) { objects_of(Module) }
|
7
|
+
complete(:method=>'Module#alias_method') {|e| e.argument > 1 ? e.object.instance_methods : [] }
|
@@ -0,0 +1,21 @@
|
|
1
|
+
instance_meths = %w{instance_variable_get instance_variable_set remove_instance_variable instance_variable_defined?}
|
2
|
+
complete(:methods=>instance_meths, :class=>"Object#") {|e| e.object.instance_variables }
|
3
|
+
complete(:method=>"Object#instance_of?", :search=>:modules) { objects_of(Class) }
|
4
|
+
complete(:methods=>%w{is_a? kind_a? extend}, :class=>"Object#", :search=>:modules) { objects_of(Module) }
|
5
|
+
complete(:methods=>%w{Object#method Object#respond_to?}) {|e| e.object.methods }
|
6
|
+
complete(:method=>"Object#[]") {|e| e.object.keys rescue [] }
|
7
|
+
complete(:method=>"Object#send") {|e|
|
8
|
+
if e.argument > 1
|
9
|
+
if (meth = eval(e.arguments[0])) && meth.to_s != 'send' &&
|
10
|
+
(action = MethodMission.find(e.object, meth.to_s))
|
11
|
+
e.argument -= 1
|
12
|
+
e.arguments.shift
|
13
|
+
action[0].call(e)
|
14
|
+
end
|
15
|
+
else
|
16
|
+
send_methods(e.object)
|
17
|
+
end
|
18
|
+
}
|
19
|
+
def send_methods(obj)
|
20
|
+
(obj.methods + obj.private_methods(false)).map {|e| e.to_s } - Mission::OPERATORS
|
21
|
+
end
|
@@ -0,0 +1 @@
|
|
1
|
+
complete(:method=>"Struct#[]") {|e| e.object.members }
|
data/lib/bond/input.rb
ADDED
@@ -0,0 +1,28 @@
|
|
1
|
+
module Bond
|
2
|
+
# A string representing the last word the user has typed. This string is passed to a mission
|
3
|
+
# action to generate possible completions. This string contains a number of attributes from the
|
4
|
+
# matching mission, useful in generating completions.
|
5
|
+
class Input < String
|
6
|
+
# Actual object a user has just typed. Used by MethodMission and ObjectMission.
|
7
|
+
attr_accessor :object
|
8
|
+
# MatchData object from the matching mission (Mission#matched).
|
9
|
+
attr_reader :matched
|
10
|
+
# Current argument number and array of argument strings. Used by MethodMission.
|
11
|
+
attr_accessor :argument, :arguments
|
12
|
+
# The full line the user has typed.
|
13
|
+
attr_reader :line
|
14
|
+
def initialize(str, options={}) #:nodoc:
|
15
|
+
super(str || '')
|
16
|
+
@matched = options[:matched]
|
17
|
+
@line = options[:line]
|
18
|
+
@object = options[:object] if options[:object]
|
19
|
+
@argument = options[:argument] if options[:argument]
|
20
|
+
@arguments = options[:arguments] if options[:arguments]
|
21
|
+
end
|
22
|
+
|
23
|
+
def inspect #:nodoc:
|
24
|
+
"#<Bond::Input #{self.to_s.inspect} @matched=#{@matched.to_a.inspect} @line=#{@line.inspect} "+
|
25
|
+
"@argument=#{@argument.inspect} @arguments=#{@arguments.inspect} @object=#{@object.inspect}>"
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|