Class: Bond::MethodMission

Inherits:
Mission
  • Object
show all
Defined in:
lib/bond/missions/method_mission.rb

Overview

A mission which completes arguments for any module/class method that isn’t an operator method. To create this mission or OperatorMethodMission, :method or :methods must be passed to Bond.complete. A completion for a given module/class effects any object that has it as an ancestor. If an object has two ancestors that have completions for the same method, the ancestor closer to the object is picked. For example, if Array#collect and Enumerable#collect have completions, argument completion on ‘[].collect ’ would use Array#collect.

Bond.complete Options:

:action

If a string, value is assumed to be a :method and that method’s action is copied. Otherwise defaults to normal :action behavior.

:search

If :action is a :method string, defaults to copying its search. Otherwise defaults to normal :search behavior.

:name, :place

These options aren’t supported by a MethodMission/OperatorMethodMission completion.

Examples:

Bond.complete(:methods => %w{delete index rindex}, :class => "Array#") {|e| e.object }
Bond.complete(:method => "Hash#index") {|e| e.object.values }

Argument Format

All method arguments can autocomplete as symbols or strings and the first argument can be prefixed with ‘(’:

 >> Bond.complete(:method => 'example') { %w{some example eh} }
 => true
 >> example '[TAB]
 eh    example    some
 >> example :[TAB]
 :eh   :example   :some

>> example("[TAB]
 eh    example    some

Multiple Arguments

Every time a comma appears after a method, Bond starts a new completion. This allows a method to complete multiple arguments as well as complete keys for a hash. Each argument can be have a unique set of completions since a completion action is aware of what argument it is currently completing:

>> Bond.complete(:method => 'FileUtils.chown') {|e|
     e.argument > 3 ? %w{noop verbose} : %w{root admin me} }
=> true
>> FileUtils.chown 'r[TAB]
>> FileUtils.chown 'root'
>> FileUtils.chown 'root', 'a[TAB]
>> FileUtils.chown 'root', 'admin'
>> FileUtils.chown 'root', 'admin', 'some_file', :v[TAB]
>> FileUtils.chown 'root', 'admin', 'some_file', :verbose
>> FileUtils.chown 'root', 'admin', 'some_file', :verbose => true

Developer Notes

Unlike other missions, creating these missions with Bond.complete doesn’t add more completion rules for an Agent to look through. Instead, all :method(s) completions are handled by one MethodMission object which looks them up with its own hashes. In the same way, all operator methods are handled by one OperatorMethodMission object.

Direct Known Subclasses

OperatorMethodMission

Constant Summary collapse

OBJECTS =
Mission::OBJECTS + %w{\S*?}
CONDITION =
%q{(OBJECTS)\.?(METHODS)(?:\s+|\()(['":])?(.*)$}

Constants inherited from Mission

Bond::Mission::OPERATORS

Class Attribute Summary collapse

Attributes inherited from Mission

#action, #matched, #on, #place

Class Method Summary collapse

Instance Method Summary collapse

Methods inherited from Mission

#call_action, #call_search, #condition, current_eval, #execute, #initialize, #matches?, #name

Constructor Details

This class inherits a constructor from Bond::Mission

Class Attribute Details

.actionsObject

Hash of instance method completions which maps methods to hashes of modules to arrays ([action, search])



55
56
57
# File 'lib/bond/missions/method_mission.rb', line 55

def actions
  @actions
end

.class_actionsObject

Same as :actions but for class methods



57
58
59
# File 'lib/bond/missions/method_mission.rb', line 57

def class_actions
  @class_actions
end

.last_classObject

Stores class from last search in MethodMission.find



61
62
63
# File 'lib/bond/missions/method_mission.rb', line 61

def last_class
  @last_class
end

.last_findObject

Stores last search result from MethodMission.find



59
60
61
# File 'lib/bond/missions/method_mission.rb', line 59

def last_find
  @last_find
end

Class Method Details

.action_methodsObject

Lists method names



96
97
98
# File 'lib/bond/missions/method_mission.rb', line 96

def action_methods
  (actions.keys + class_actions.keys).uniq
end

.all_methodsObject

Lists full method names, prefixed with class/module



101
102
103
104
# File 'lib/bond/missions/method_mission.rb', line 101

def all_methods
  (class_actions.map {|m,h| h.map {|k,v| "#{k}.#{m}" } } +
    actions.map {|m,h| h.map {|k,v| "#{k}##{m}" } }).flatten.sort
end

.any_const_get(name) ⇒ Object

Returns a constant like Module#const_get no matter what namespace it’s nested in. Returns nil if the constant is not found.



118
119
120
121
122
123
124
125
# File 'lib/bond/missions/method_mission.rb', line 118

def any_const_get(name)
  return name if name.is_a?(Module)
  klass = Object
  name.split('::').each {|e| klass = klass.const_get(e) }
  klass
rescue
   nil
end

.create(options) ⇒ Object

Creates a method action given the same options as Bond.complete



64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
# File 'lib/bond/missions/method_mission.rb', line 64

def create(options)
  if options[:action].is_a?(String)
    klass, klass_meth = split_method(options[:action])
    if (arr = (current_actions(options[:action])[klass_meth] || {})[klass])
      options[:action], options[:search] = [arr[0], options[:search] || arr[1]]
    else
      raise InvalidMissionError, "string :action"
    end
  end

  raise InvalidMissionError, "array :method" if options[:method].is_a?(Array)
  meths = options[:methods] || Array(options[:method])
  raise InvalidMissionError, "non-string :method(s)" unless meths.all? {|e| e.is_a?(String) }
  if options[:class].is_a?(String)
    options[:class] << '#' unless options[:class][/[#.]$/]
    meths.map! {|e| options[:class] + e }
  end

  meths.each {|meth|
    klass, klass_meth = split_method(meth)
    (current_actions(meth)[klass_meth] ||= {})[klass] = [options[:action], options[:search]].compact
  }
  nil
end

.find(obj, meth) ⇒ Object

Returns the first completion by looking up the object’s ancestors and finding the closest one that has a completion definition for the given method. Completion is returned as an array containing action proc and optional search to go with it.



109
110
111
112
113
114
# File 'lib/bond/missions/method_mission.rb', line 109

def find(obj, meth)
  last_find = find_with(obj, meth, :<=, @class_actions) if obj.is_a?(Module)
  last_find = find_with(obj, meth, :is_a?, @actions) unless last_find
  @last_class = last_find.is_a?(Array) ? last_find[0] : nil
  @last_find = last_find ? last_find[1] : last_find
end

.resetObject

Resets all instance and class method actions.



90
91
92
93
# File 'lib/bond/missions/method_mission.rb', line 90

def reset
  @actions = {}
  @class_actions = {}
end

Instance Method Details

#match_messageObject



152
153
154
# File 'lib/bond/missions/method_mission.rb', line 152

def match_message #@private
  "Matches completion for method '#{@meth}' in '#{MethodMission.last_class}'."
end