bond 0.3.5 → 0.4.0

Sign up to get free protection for your applications and to get access to all the features.
data/.gemspec CHANGED
@@ -9,7 +9,7 @@ Gem::Specification.new do |s|
9
9
  s.email = "gabriel.horner@gmail.com"
10
10
  s.homepage = "http://tagaholic.me/bond/"
11
11
  s.summary = "Mission: Easy custom autocompletion for arguments, methods and beyond. Accomplished for irb and any other readline-like console environments."
12
- s.description = "Bond is on a mission to improve autocompletion in ruby, especially for ripl/irb. 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 can also load completions that ship with gems. 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."
12
+ s.description = "Bond is on a mission to improve autocompletion in ruby, especially for irb/ripl. 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 ruby autocompletion 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 autocompletions and share it with others. Bond can also load completions that ship with gems. Bond is able to offer more than irb's completion since it uses the full line of input when completing as opposed to irb's last-word approach."
13
13
  s.required_rubygems_version = ">= 1.3.6"
14
14
  s.rubyforge_project = 'tagaholic'
15
15
  s.has_rdoc = 'yard'
@@ -1,3 +1,9 @@
1
+ == 0.4.0
2
+ * Improve extconf.rb: support --without-readline, fail hard, detect windows
3
+ * Add rb-readline support for windows and non-readline users
4
+ * Rename :readline_plugin option to :readline
5
+ * Allow :readline option to take a symbol
6
+
1
7
  == 0.3.5
2
8
  * Move yard-related functionality to bond-yard gem
3
9
 
@@ -1,32 +1,42 @@
1
- Note: To read a linked version of this README, {click here}[http://tagaholic.me/bond/doc/]
2
-
3
1
  == Description
4
2
 
5
- Bond is on a mission to improve autocompletion in ruby, especially for ripl/irb. Aside from doing
3
+ Bond is on a mission to improve autocompletion in ruby, especially for irb/ripl. Aside from doing
6
4
  everything irb's can do and fixing its quirks, Bond can autocomplete argument(s) to methods,
7
- uniquely completing per module, per method and per argument. Bond brings irb's completion closer to
8
- bash/zsh as it provides a configuration system and a DSL for creating custom completions and
9
- completion rules. With this configuration system, users can customize their irb autocompletions and
5
+ uniquely completing per module, per method and per argument. Bond brings ruby autocompletion closer
6
+ to bash/zsh as it provides a configuration system and a DSL for creating custom completions and
7
+ completion rules. With this configuration system, users can customize their autocompletions and
10
8
  share it with others. Bond can also load completions that ship with gems. Bond is able to offer
11
- more than irb's completion since it uses a Readline C extension to get the full line of input when
12
- completing as opposed to irb's last-word approach.
9
+ more than irb's completion since it uses the full line of input when completing as opposed to irb's
10
+ last-word approach.
13
11
 
14
12
  == Install
15
13
 
16
- Install the gem with:
14
+ To use bond with {Readline}[http://cnswww.cns.cwru.edu/php/chet/readline/rltop.html] (version >=
15
+ 5.6 recommended) or JLine for JRuby users, install the gem with:
16
+
17
+ gem install bond
18
+
19
+ To use bond with {a pure ruby readline}[https://github.com/luislavena/rb-readline] i.e. Windows
20
+ users or users without Readline:
21
+
22
+ gem install bond rb-readline -- --without-readline
17
23
 
18
- sudo gem install bond
24
+ To use bond without readline support (and presumably use your own readline plugin):
25
+
26
+ gem install bond -- --without-readline
19
27
 
20
28
  == Setup
21
29
 
22
- To start off, replace irb's completion (require 'irb/completion') with Bond's enhanced version in your irbrc :
30
+ If you're using {ripl}[http://github.com/cldwalker/ripl] instead of irb, bond is already setup.
31
+
32
+ To start off, replace irb's completion (require 'irb/completion') with Bond's enhanced version in your irbrc:
23
33
 
24
34
  require 'bond'
25
35
  Bond.start
36
+ # For users using a pure ruby readline
37
+ Bond.start :readline => :ruby
26
38
 
27
- If you're using {ripl}[http://github.com/cldwalker/ripl], bond is used by default.
28
-
29
- This gives you more consistent method completion on any object, customizable completions
39
+ This setup gives you more consistent method completion on any object, customizable completions
30
40
  and argument completion of some 80+ methods including Hash#[], Kernel#system, Kernel#require and some Rails methods.
31
41
 
32
42
  == Method Argument Completion
@@ -7,16 +7,17 @@ def dummy_makefile
7
7
  }
8
8
  end
9
9
 
10
- if RUBY_VERSION < '1.9.2' && RUBY_PLATFORM !~ /java/
10
+ if RUBY_VERSION >= '1.9.2' || RUBY_PLATFORM[/java|mswin|mingw|bccwin|wince/i] ||
11
+ ARGV.include?('--without-readline')
12
+ dummy_makefile
13
+ else
11
14
  dir_config("readline")
12
15
  have_library('readline')
13
16
  if !have_header('readline/readline.h')
14
- puts "Bond was built without readline. To use it with readline: gem install bond" +
15
- " -- --with-readline-dir=/path/to/readline"
16
- dummy_makefile
17
+ abort "\n** Bond Install Error: Unable to find readline.h. Please try again. **\n"+
18
+ "To install with your readline: gem install bond -- --with-readline-dir=/path/to/readline\n"+
19
+ "To install without readline: gem install bond -- --without-readline"
17
20
  else
18
21
  create_makefile 'readline_line_buffer'
19
22
  end
20
- else
21
- dummy_makefile
22
23
  end
@@ -1,7 +1,9 @@
1
1
  require 'bond/m'
2
2
  require 'bond/version'
3
3
  require 'bond/readline'
4
- require 'bond/rawline'
4
+ require 'bond/readlines/rawline'
5
+ require 'bond/readlines/ruby'
6
+ require 'bond/readlines/jruby'
5
7
  require 'bond/agent'
6
8
  require 'bond/search'
7
9
  require 'bond/input'
@@ -24,11 +26,11 @@ module Bond
24
26
  # or turned off per mission with :search. If turned off, the action must also handle searching.
25
27
  #
26
28
  # ==== Examples:
27
- # Bond.complete(:method=>'shoot') {|input| %w{to kill} }
28
- # Bond.complete(:on=>/^((([a-z][^:.\(]*)+):)+/, :search=>false) {|input| Object.constants.grep(/#{input.matched[1]}/) }
29
- # Bond.complete(:object=>ActiveRecord::Base, :search=>:underscore, :place=>:last)
30
- # Bond.complete(:method=>'you', :search=>proc {|input, list| list.grep(/#{input}/i)} ) {|input| %w{Only Live Twice} }
31
- # Bond.complete(:method=>'system', :action=>:shell_commands)
29
+ # Bond.complete(:method => 'shoot') {|input| %w{to kill} }
30
+ # Bond.complete(:on => /^((([a-z][^:.\(]*)+):)+/, :search => false) {|input| Object.constants.grep(/#{input.matched[1]}/) }
31
+ # Bond.complete(:object => ActiveRecord::Base, :search => :underscore, :place => :last)
32
+ # Bond.complete(:method => 'you', :search => proc {|input, list| list.grep(/#{input}/i)} ) {|input| %w{Only Live Twice} }
33
+ # Bond.complete(:method => 'system', :action => :shell_commands)
32
34
  #
33
35
  # @param [Hash] options When using :method(s) or :object, some hash keys may have different behavior. See
34
36
  # Bond.complete sections of {MethodMission} and {ObjectMission} respectively.
@@ -61,7 +63,7 @@ module Bond
61
63
  # Redefines an existing completion mission to have a different action. The condition can only be varied if :name is
62
64
  # used to identify and replace a mission. Takes same options as {#complete}.
63
65
  # ==== Example:
64
- # Bond.recomplete(:on=>/man/, :name=>:count) { %w{4 5 6}}
66
+ # Bond.recomplete(:on => /man/, :name => :count) { %w{4 5 6}}
65
67
  def recomplete(options={}, &block); M.recomplete(options, &block); end
66
68
 
67
69
  # Reports what completion mission matches for a given input. Helpful for debugging missions.
@@ -80,17 +82,18 @@ module Bond
80
82
  # {Rc} for the DSL to use in completion files and in the block.
81
83
  #
82
84
  # ==== Examples:
83
- # Bond.start :gems=>%w{hirb}
84
- # Bond.start(:default_search=>:ignore_case) do
85
- # complete(:method=>"Object#respond_to?") {|e| e.object.methods }
85
+ # Bond.start :gems => %w{hirb}
86
+ # Bond.start(:default_search => :ignore_case) do
87
+ # complete(:method => "Object#respond_to?") {|e| e.object.methods }
86
88
  # end
87
89
  #
88
90
  # @param [Hash] options Sets global keys in {#config}, some which specify what completions to load.
89
91
  # @option options [Array<String>] :gems Gems which have their completions loaded from
90
92
  # @gem_source/lib/bond/completions/*.rb. If gem is a plugin gem i.e. ripl-plugin, completion will be loaded
91
93
  # from @gem_source/lib/ripl/completions/plugin.rb.
92
- # @option options [Module] :readline_plugin (Bond::Readline) Specifies a Bond plugin to interface with a Readline-like
93
- # library. Available plugins are Bond::Readline and Bond::Rawline.
94
+ # @option options [Module, Symbol] :readline (Bond::Readline) Specifies a Bond readline plugin.
95
+ # A symbol points to a capitalized Bond constant i.e. :ruby -> Bond::Ruby.
96
+ # Available plugins are Bond::Readline, Bond::Ruby, Bond::Jruby and Bond::Rawline.
94
97
  # @option options [Proc] :default_mission (DefaultMission) Sets default completion to use when no missions match.
95
98
  # See {Agent#default_mission}.
96
99
  # @option options [Symbol] :default_search (:underscore) Name of a *_search method in Rc to use as the default
@@ -1,6 +1,7 @@
1
1
  module Bond
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.
2
+ # Every time a completion is attempted, the Agent searches its missions for
3
+ # the first one that matches the user input. Using either the found mission
4
+ # or Agent.default_mission, the Agent executes the mission's action.
4
5
  class Agent
5
6
  # The array of missions that will be searched when a completion occurs.
6
7
  attr_reader :missions
@@ -8,7 +9,7 @@ module Bond
8
9
  attr_reader :weapon
9
10
 
10
11
  def initialize(options={}) #@private
11
- setup_readline_plugin(options[:readline_plugin])
12
+ setup_readline(options[:readline])
12
13
  @default_mission_action = options[:default_mission] if options[:default_mission]
13
14
  Mission.eval_binding = options[:eval_binding] if options[:eval_binding]
14
15
  Search.default_search = options[:default_search] || :normal
@@ -37,20 +38,21 @@ module Bond
37
38
  mission
38
39
  end
39
40
 
40
- # This is where the action starts when a completion is initiated. Optional line_buffer
41
- # overrides line buffer from readline plugin.
41
+ # This is where the action starts when a completion is initiated. Optional
42
+ # line_buffer overrides line buffer from readline plugin.
42
43
  def call(input, line_buffer=nil)
43
44
  mission_input = line_buffer || @weapon.line_buffer
44
45
  mission_input = $1 if mission_input !~ /#{Regexp.escape(input)}$/ && mission_input =~ /^(.*#{Regexp.escape(input)})/
45
46
  (mission = find_mission(mission_input)) ? mission.execute : default_mission.execute(Input.new(input))
46
- rescue FailedMissionError=>e
47
+ rescue FailedMissionError => e
47
48
  completion_error(e.message, "Completion Info: #{e.mission.match_message}")
48
49
  rescue
49
50
  completion_error "Failed internally with '#{$!.message}'.",
50
51
  "Please report this issue with debug on: Bond.config[:debug] = true."
51
52
  end
52
53
 
53
- # Given a hypothetical user input, reports back what mission it would have found and executed.
54
+ # Given a hypothetical user input, reports back what mission it would have
55
+ # found and executed.
54
56
  def spy(input)
55
57
  if (mission = find_mission(input))
56
58
  puts mission.match_message, "Possible completions: #{mission.execute.inspect}",
@@ -58,7 +60,7 @@ module Bond
58
60
  else
59
61
  puts "Doesn't match a completion."
60
62
  end
61
- rescue FailedMissionError=>e
63
+ rescue FailedMissionError => e
62
64
  puts e.mission.match_message, e.message,
63
65
  "Matches for #{e.mission.condition.inspect} are #{e.mission.matched.to_a.inspect}"
64
66
  end
@@ -69,7 +71,7 @@ module Bond
69
71
 
70
72
  # Default mission used by agent. An instance of DefaultMission.
71
73
  def default_mission
72
- @default_mission ||= DefaultMission.new(:action=>@default_mission_action)
74
+ @default_mission ||= DefaultMission.new(:action => @default_mission_action)
73
75
  end
74
76
 
75
77
  # Resets an agent's missions
@@ -78,16 +80,15 @@ module Bond
78
80
  end
79
81
 
80
82
  protected
81
- def setup_readline_plugin(plugin)
82
- raise ArgumentError unless plugin.is_a?(Module)
83
- @weapon = plugin.extend(plugin)
83
+ def setup_readline(plugin)
84
+ @weapon = plugin
84
85
  @weapon.setup(self)
85
86
  rescue
86
87
  $stderr.puts "Bond Error: Failed #{plugin.to_s[/[^:]+$/]} setup with '#{$!.message}'"
87
88
  end
88
89
 
89
90
  def create_mission(options, &block)
90
- Mission.create options.merge!(:action=>options[:action] || block)
91
+ Mission.create options.merge!(:action => options[:action] || block)
91
92
  rescue InvalidMissionError
92
93
  "Invalid #{$!.message} for completion with options: #{options.inspect}"
93
94
  rescue
@@ -104,4 +105,4 @@ module Bond
104
105
  arr
105
106
  end
106
107
  end
107
- end
108
+ end
@@ -2,5 +2,5 @@ complete(:methods=>%w{Bond.complete Bond.recomplete}) {
2
2
  ["on", "method", "methods", "class", "object", "anywhere", "prefix", "search", "action", "place", "name"]
3
3
  }
4
4
  complete(:methods=>['Bond.start', 'Bond.restart']) {
5
- %w{gems readline_plugin default_mission default_search eval_binding debug eval_debug bare}
5
+ %w{gems readline default_mission default_search eval_binding debug eval_debug bare}
6
6
  }
@@ -1,5 +1,6 @@
1
1
  module Bond
2
- # Takes international quagmires (a user's completion setup) and passes them on as missions to an Agent.
2
+ # Takes international quagmires (a user's completion setup) and passes them on
3
+ # as missions to an Agent.
3
4
  module M
4
5
  extend self
5
6
 
@@ -30,7 +31,7 @@ module Bond
30
31
 
31
32
  # See {Bond#config}
32
33
  def config
33
- @config ||= {:readline_plugin=>Bond::Readline, :debug=>false, :default_search=>:underscore}
34
+ @config ||= {:debug => false, :default_search => :underscore}
34
35
  end
35
36
 
36
37
  # Resets M's missions and config
@@ -47,10 +48,13 @@ module Bond
47
48
  # Validates and sets values in M.config.
48
49
  def debrief(options={})
49
50
  config.merge! options
50
- plugin_methods = %w{setup line_buffer}
51
- unless config[:readline_plugin].is_a?(Module) &&
52
- plugin_methods.all? {|e| config[:readline_plugin].instance_methods.map {|f| f.to_s}.include?(e)}
53
- $stderr.puts "Bond Error: Invalid readline plugin given."
51
+ config[:readline] ||= default_readline
52
+ if !config[:readline].is_a?(Module) &&
53
+ Bond.const_defined?(config[:readline].to_s.capitalize)
54
+ config[:readline] = Bond.const_get(config[:readline].to_s.capitalize)
55
+ end
56
+ unless %w{setup line_buffer}.all? {|e| config[:readline].respond_to?(e) }
57
+ $stderr.puts "Bond Error: Invalid readline plugin '#{config[:readline]}'."
54
58
  end
55
59
  end
56
60
 
@@ -74,7 +78,8 @@ module Bond
74
78
  !!@started
75
79
  end
76
80
 
77
- # Finds the full path to a gem's file relative it's load path directory. Returns nil if not found.
81
+ # Finds the full path to a gem's file relative it's load path directory.
82
+ # Returns nil if not found.
78
83
  def find_gem_file(rubygem, file)
79
84
  begin gem(rubygem); rescue Exception; end
80
85
  (dir = $:.find {|e| File.exists?(File.join(e, file)) }) && File.join(dir, file)
@@ -110,6 +115,11 @@ module Bond
110
115
  end
111
116
 
112
117
  protected
118
+ def default_readline
119
+ RUBY_PLATFORM[/mswin|mingw|bccwin|wince/i] ? Ruby :
120
+ RUBY_PLATFORM[/java/i] ? Jruby : Bond::Readline
121
+ end
122
+
113
123
  def load_gem_completion(rubygem)
114
124
  (dir = find_gem_file(rubygem, File.join(rubygem, '..', 'bond'))) ? load_dir(dir) :
115
125
  rubygem[/\/|-/] ? load_plugin_file(rubygem) :
@@ -145,7 +145,7 @@ module Bond
145
145
  end
146
146
 
147
147
  def create_input(input, options={})
148
- @input = Input.new(input, options.merge(:line=>@line, :matched=>@matched))
148
+ @input = Input.new(input, options.merge(:line => @line, :matched => @matched))
149
149
  end
150
150
  end
151
151
  end
@@ -1,6 +1,7 @@
1
- # A mission which completes anywhere i.e. even after non word break characters such as '[' or '}'.
2
- # With options :prefix and :anywhere, this mission matches on the following regexp condition
3
- # /:prefix?(:anywhere)$/ and passes the first capture group to the mission action.
1
+ # A mission which completes anywhere i.e. even after non word break characters
2
+ # such as '[' or '}'. With options :prefix and :anywhere, this mission matches
3
+ # on the following regexp condition /:prefix?(:anywhere)$/ and passes the first
4
+ # capture group to the mission action.
4
5
  class Bond::AnywhereMission < Bond::Mission
5
6
  def initialize(options={}) #@private
6
7
  options[:on] = Regexp.new("#{options[:prefix]}(#{options[:anywhere]})$")
@@ -13,13 +13,13 @@ module Bond
13
13
  # Otherwise defaults to normal :search behavior.
14
14
  # [:name, :place] These options aren't supported by a MethodMission/OperatorMethodMission completion.
15
15
  # ==== Examples:
16
- # Bond.complete(:methods=>%w{delete index rindex}, :class=>"Array#") {|e| e.object }
17
- # Bond.complete(:method=>"Hash#index") {|e| e.object.values }
16
+ # Bond.complete(:methods => %w{delete index rindex}, :class => "Array#") {|e| e.object }
17
+ # Bond.complete(:method => "Hash#index") {|e| e.object.values }
18
18
  #
19
19
  # ==== Argument Format
20
20
  # All method arguments can autocomplete as symbols or strings and the first argument can be prefixed
21
21
  # with '(':
22
- # >> Bond.complete(:method=>'example') { %w{some example eh} }
22
+ # >> Bond.complete(:method => 'example') { %w{some example eh} }
23
23
  # => true
24
24
  # >> example '[TAB]
25
25
  # eh example some
@@ -33,7 +33,7 @@ module Bond
33
33
  # Every time a comma appears after a method, Bond starts a new completion. This allows a method to
34
34
  # complete multiple arguments as well as complete keys for a hash. *Each* argument can be have a unique
35
35
  # set of completions since a completion action is aware of what argument it is currently completing:
36
- # >> Bond.complete(:method=>'FileUtils.chown') {|e|
36
+ # >> Bond.complete(:method => 'FileUtils.chown') {|e|
37
37
  # e.argument > 3 ? %w{noop verbose} : %w{root admin me} }
38
38
  # => true
39
39
  # >> FileUtils.chown 'r[TAB]
@@ -42,7 +42,7 @@ module Bond
42
42
  # >> FileUtils.chown 'root', 'admin'
43
43
  # >> FileUtils.chown 'root', 'admin', 'some_file', :v[TAB]
44
44
  # >> FileUtils.chown 'root', 'admin', 'some_file', :verbose
45
- # >> FileUtils.chown 'root', 'admin', 'some_file', :verbose=>true
45
+ # >> FileUtils.chown 'root', 'admin', 'some_file', :verbose => true
46
46
  #
47
47
  # ==== Developer Notes
48
48
  # Unlike other missions, creating these missions with Bond.complete doesn't add more completion rules
@@ -183,8 +183,8 @@ module Bond
183
183
  def after_match(input)
184
184
  set_action_and_search
185
185
  @completion_prefix, typed = @matched[3], @matched[-1]
186
- input_options = {:object=>@evaled_object, :argument=>1+typed.count(','),
187
- :arguments=>(@completion_prefix.to_s+typed).split(/\s*,\s*/) }
186
+ input_options = {:object => @evaled_object, :argument => 1+typed.count(','),
187
+ :arguments => (@completion_prefix.to_s+typed).split(/\s*,\s*/) }
188
188
  if typed.to_s.include?(',') && (match = typed.match(/(.*?\s*)([^,]*)$/))
189
189
  typed = match[2]
190
190
  typed.sub!(/^(['":])/,'')
@@ -194,4 +194,4 @@ module Bond
194
194
  end
195
195
 
196
196
  end
197
- end
197
+ end
@@ -1,14 +1,14 @@
1
- # A mission which completes an object's methods. For this mission to match,
2
- # the condition must match and the current object must have an ancestor that matches :object.
3
- # Note: To access to the current object being completed on within an action, use the input's
4
- # object attribute.
1
+ # A mission which completes an object's methods. For this mission to match, the
2
+ # condition must match and the current object must have an ancestor that matches
3
+ # :object. Note: To access to the current object being completed on within an
4
+ # action, use the input's object attribute.
5
5
  #
6
6
  # ==== Bond.complete Options:
7
- # [:action] If an action is not specified, the default action is to complete an object's
8
- # non-operator methods.
7
+ # [:action] If an action is not specified, the default action is to complete an
8
+ # object's non-operator methods.
9
9
  #
10
10
  # ===== Example:
11
- # Bond.complete(:object=>'ActiveRecord::Base') {|input| input.object.class.instance_methods(false) }
11
+ # Bond.complete(:object => 'ActiveRecord::Base') {|input| input.object.class.instance_methods(false) }
12
12
  class Bond::ObjectMission < Bond::Mission
13
13
  OBJECTS = %w<\S+> + Bond::Mission::OBJECTS
14
14
  CONDITION = '(OBJECTS)\.(\w*(?:\?|!)?)$'
@@ -35,10 +35,10 @@ class Bond::ObjectMission < Bond::Mission
35
35
  def after_match(input)
36
36
  @completion_prefix = @matched[1] + "."
37
37
  @action ||= lambda {|e| default_action(e.object) }
38
- create_input @matched[2], :object=>@evaled_object
38
+ create_input @matched[2], :object => @evaled_object
39
39
  end
40
40
 
41
41
  def default_action(obj)
42
42
  obj.methods.map {|e| e.to_s} - OPERATORS
43
43
  end
44
- end
44
+ end
@@ -1,7 +1,9 @@
1
1
  module Bond
2
- # A mission which completes arguments for any module/class method that is an operator i.e. '>' or '*'.
3
- # Takes same Bond.complete options as MethodMission. The only operator method this mission doesn't
4
- # complete is '[]='. The operator '[]' should cover the first argument completion of '[]=' anyways.
2
+ # A mission which completes arguments for any module/class method that is an
3
+ # operator i.e. '>' or '*'. Takes same Bond.complete options as
4
+ # MethodMission. The only operator method this mission doesn't complete is
5
+ # '[]='. The operator '[]' should cover the first argument completion of '[]='
6
+ # anyways.
5
7
  class OperatorMethodMission < MethodMission
6
8
  OPERATORS = Mission::OPERATORS - ["[]", "[]="]
7
9
  OBJECTS = Mission::OBJECTS + %w{\S+}
@@ -19,7 +21,7 @@ module Bond
19
21
  def after_match(input)
20
22
  set_action_and_search
21
23
  @completion_prefix, typed = input.to_s.sub(/#{Regexp.quote(@matched[-1])}$/, ''), @matched[-1]
22
- create_input typed, :object=>@evaled_object, :argument=>1
24
+ create_input typed, :object => @evaled_object, :argument => 1
23
25
  end
24
26
  end
25
- end
27
+ end
@@ -4,13 +4,13 @@ module Bond
4
4
  #
5
5
  # === Example ~/.bondrc
6
6
  # # complete arguments for any object's :respond_to?
7
- # complete(:method=>"Object#respond_to?") {|e| e.object.methods }
7
+ # complete(:method => "Object#respond_to?") {|e| e.object.methods }
8
8
  # # complete arguments for any module's :public
9
- # complete(:method=>"Module#public") {|e| e.object.instance_methods }
9
+ # complete(:method => "Module#public") {|e| e.object.instance_methods }
10
10
  #
11
11
  # # Share generate_tags action across completions
12
- # complete(:method=>"edit_tags", :action=>:generate_tags)
13
- # complete(:method=>"delete_tags", :search=>false) {|e| generate_tags(e).grep(/#{e}/i) }
12
+ # complete(:method => "edit_tags", :action => :generate_tags)
13
+ # complete(:method => "delete_tags", :search => false) {|e| generate_tags(e).grep(/#{e}/i) }
14
14
  #
15
15
  # def generate_tags(input)
16
16
  # ...
@@ -45,4 +45,4 @@ module Bond
45
45
  raise if Bond.config[:debug]
46
46
  end
47
47
  end
48
- end
48
+ end
@@ -1,48 +1,38 @@
1
- module Bond
2
- # This is the default readline plugin for Bond. A valid plugin must be a module that defines methods setup
3
- # and line_buffer as described below.
4
- module Readline
5
- DefaultBreakCharacters = " \t\n\"\\'`><=;|&{("
1
+ # This is the default readline plugin for Bond. A valid plugin must be an object
2
+ # that responds to methods setup and line_buffer as described below.
3
+ class Bond::Readline
4
+ DefaultBreakCharacters = " \t\n\"\\'`><=;|&{("
6
5
 
7
- # Loads the readline-like library and sets the completion_proc to the given agent.
8
- def setup(agent)
9
- require 'readline'
10
- unless ::Readline.respond_to?(:line_buffer)
11
- RUBY_PLATFORM =~ /java/ ? load_jruby_extension : load_extension
12
- end
6
+ # Loads the readline-like library and sets the completion_proc to the given agent.
7
+ def self.setup(agent)
8
+ readline_setup
13
9
 
14
- # Reinforcing irb defaults
15
- ::Readline.completion_append_character = nil
16
- if ::Readline.respond_to?("basic_word_break_characters=")
17
- ::Readline.basic_word_break_characters = DefaultBreakCharacters
18
- end
19
-
20
- ::Readline.completion_proc = agent
21
- if (::Readline::VERSION rescue nil).to_s[/editline/i]
22
- puts "Bond has detected EditLine and may not work with it. See the README's Limitations section."
23
- end
10
+ # Reinforcing irb defaults
11
+ Readline.completion_append_character = nil
12
+ if Readline.respond_to?("basic_word_break_characters=")
13
+ Readline.basic_word_break_characters = DefaultBreakCharacters
24
14
  end
25
15
 
26
- def load_jruby_extension
27
- require 'jruby'
16
+ Readline.completion_proc = agent
17
+ end
28
18
 
29
- class << Readline
30
- ReadlineExt = org.jruby.ext.Readline
31
- def line_buffer
32
- ReadlineExt.s_get_line_buffer(JRuby.runtime.current_context, JRuby.reference(self))
33
- end
34
- end
19
+ def self.readline_setup
20
+ require 'readline'
21
+ load_extension unless Readline.respond_to?(:line_buffer)
22
+ if (Readline::VERSION rescue nil).to_s[/editline/i]
23
+ puts "Bond has detected EditLine and may not work with it." +
24
+ " See the README's Limitations section."
35
25
  end
26
+ end
36
27
 
37
- def load_extension
38
- require 'readline_line_buffer'
39
- rescue LoadError
40
- $stderr.puts "Bond Error: Failed to load readline_line_buffer. Ensure that it exists and was built correctly."
41
- end
28
+ def self.load_extension
29
+ require 'readline_line_buffer'
30
+ rescue LoadError
31
+ $stderr.puts "Bond Error: Failed to load readline_line_buffer. Ensure that it exists and was built correctly."
32
+ end
42
33
 
43
- # Returns full line of what the user has typed.
44
- def line_buffer
45
- ::Readline.line_buffer
46
- end
34
+ # Returns full line of what the user has typed.
35
+ def self.line_buffer
36
+ Readline.line_buffer
47
37
  end
48
38
  end
@@ -0,0 +1,13 @@
1
+ # Readline for Jruby
2
+ class Bond::Jruby < Bond::Readline
3
+ def self.readline_setup
4
+ require 'readline'
5
+ require 'jruby'
6
+ class << Readline
7
+ ReadlineExt = org.jruby.ext.Readline
8
+ def line_buffer
9
+ ReadlineExt.s_get_line_buffer(JRuby.runtime.current_context, JRuby.reference(self))
10
+ end
11
+ end
12
+ end
13
+ end
@@ -0,0 +1,15 @@
1
+ # A pure ruby readline which requires {rawline}[http://github.com/h3rald/rawline].
2
+ class Bond::Rawline < Bond::Readline
3
+ def self.setup(agent)
4
+ require 'rawline'
5
+ Rawline.completion_append_character = nil
6
+ Rawline.basic_word_break_characters= " \t\n\"\\'`><;|&{("
7
+ Rawline.completion_proc = agent
8
+ rescue LoadError
9
+ abort "Bond Error: rawline gem is required for this readline plugin -> gem install rawline"
10
+ end
11
+
12
+ def self.line_buffer
13
+ Rawline.editor.line.text
14
+ end
15
+ end
@@ -0,0 +1,9 @@
1
+ # A pure ruby readline which requires {rb-readline}[https://github.com/luislavena/rb-readline].
2
+ class Bond::Ruby < Bond::Readline
3
+ def self.readline_setup
4
+ require 'rb-readline'
5
+ rescue LoadError
6
+ abort "Bond Error: rb-readline gem is required for this readline plugin" +
7
+ " -> gem install rb-readline"
8
+ end
9
+ end
@@ -10,7 +10,7 @@ module Bond
10
10
  # normal_search(input, list.select {|e| e !~ /-/ })
11
11
  # end
12
12
  #
13
- # Now you can pass this custom search to any complete() as :search=>:ignore_hyphen
13
+ # Now you can pass this custom search to any complete() as :search => :ignore_hyphen
14
14
  module Search
15
15
  class<<self
16
16
  # Default search used across missions, set by Bond.config[:default_search]
@@ -71,4 +71,4 @@ module Bond
71
71
  (current_matches + future_matches.map {|e| e[/^(([^#{delim_chars}]*#{delim}){0,#{i+1}})/, 1] }).uniq
72
72
  end
73
73
  end
74
- end
74
+ end
@@ -1,3 +1,3 @@
1
1
  module Bond
2
- VERSION = '0.3.5'
2
+ VERSION = '0.4.0'
3
3
  end
@@ -210,7 +210,8 @@ describe "Agent" do
210
210
 
211
211
  describe "spy" do
212
212
  before_all {
213
- M.reset; complete(:on=>/end$/) { [] };
213
+ reset
214
+ complete(:on=>/end$/) { [] };
214
215
  complete(:all_methods=>true); complete(:method=>'the') { %w{spy who loved me} }
215
216
  complete(:object=>"Symbol")
216
217
  }
@@ -3,22 +3,31 @@ require File.join(File.dirname(__FILE__), 'test_helper')
3
3
  describe "Bond" do
4
4
  describe "start" do
5
5
  def start(options={}, &block)
6
- Bond.start({:readline_plugin=>valid_readline_plugin}.merge(options), &block)
6
+ Bond.start({:readline=>valid_readline}.merge(options), &block)
7
7
  end
8
8
 
9
9
  before { M.instance_eval("@started = @agent = @config = nil"); M.expects(:load_completions) }
10
- it "prints error if readline_plugin is not a module" do
11
- capture_stderr { start :readline_plugin=>false }.should =~ /Invalid/
10
+ it "prints error if readline doesn't have all required methods" do
11
+ capture_stderr {
12
+ start :readline=>Module.new{ def self.setup(arg); end }
13
+ }.should =~ /Invalid/
12
14
  end
13
-
14
- it "prints error if readline_plugin doesn't have all required methods" do
15
- capture_stderr {start :readline_plugin=>Module.new{ def setup(arg); end } }.should =~ /Invalid/
15
+
16
+ it "prints error if readline symbol is invalid" do
17
+ capture_stderr {
18
+ start :readline => :blah
19
+ }.should =~ /Invalid.*'blah'/
16
20
  end
17
21
 
18
- it "prints no error if valid readline_plugin" do
22
+ it "prints no error if valid readline" do
19
23
  capture_stderr { start }.should == ''
20
24
  end
21
25
 
26
+ it 'prints no error if valid readline symbol' do
27
+ capture_stderr { start :readline => :ruby }.should == ''
28
+ Bond.config[:readline].should == Bond::Ruby
29
+ end
30
+
22
31
  it "sets default mission" do
23
32
  start :default_mission=>lambda {|e| %w{1 2 3}}
24
33
  tab('1').should == ['1']
@@ -48,7 +57,7 @@ describe "Bond" do
48
57
  Bond.started?.should == true
49
58
  end
50
59
 
51
- after_all { M.debrief :readline_plugin=>valid_readline_plugin; M.reset }
60
+ after_all { reset }
52
61
  end
53
62
 
54
63
  describe "start with :gems" do
@@ -88,13 +97,13 @@ describe "Bond" do
88
97
  M.expects(:gem)
89
98
  start(:gems=>%w{awesome})
90
99
  end
91
- after_all { M.debrief :readline_plugin=>valid_readline_plugin; M.reset }
100
+ after_all { reset }
92
101
  end
93
102
 
94
103
  it "prints error if Readline setup fails" do
95
104
  Bond::Readline.expects(:setup).raises('WTF')
96
- capture_stderr { Bond.start(:readline_plugin=>Bond::Readline) }.should =~ /Error.*Failed Readline.*'WTF'/
97
- M.debrief :readline_plugin=>valid_readline_plugin
105
+ capture_stderr { Bond.start(:readline=>Bond::Readline) }.should =~ /Error.*Failed Readline.*'WTF'/
106
+ M.debrief :readline=>valid_readline
98
107
  end
99
108
 
100
109
  it "start prints error for failed completion file" do
@@ -105,19 +114,19 @@ describe "Bond" do
105
114
  it "reset clears existing missions" do
106
115
  complete(:on=>/blah/) {[]}
107
116
  Bond.agent.missions.size.should.not == 0
108
- M.reset
117
+ reset
109
118
  Bond.agent.missions.size.should == 0
110
119
  end
111
120
 
112
121
  describe "restart" do
113
122
  def start(options={}, &block)
114
- Bond.start({:readline_plugin=>valid_readline_plugin}.merge(options), &block)
123
+ Bond.start({:readline=>valid_readline}.merge(options), &block)
115
124
  end
116
125
 
117
126
  it "deletes previous config" do
118
127
  start :blah=>''
119
128
  Bond.config[:blah].should.not == nil
120
- Bond.restart({:readline_plugin=>valid_readline_plugin})
129
+ Bond.restart({:readline=>valid_readline})
121
130
  Bond.config[:blah].should == nil
122
131
  end
123
132
 
@@ -125,7 +134,7 @@ describe "Bond" do
125
134
  start
126
135
  complete(:method=>'blah') { [] }
127
136
  MethodMission.actions['blah'].should.not == nil
128
- Bond.restart({:readline_plugin=>valid_readline_plugin})
137
+ Bond.restart({:readline=>valid_readline})
129
138
  MethodMission.actions['blah'].should == nil
130
139
  end
131
140
  end
@@ -2,7 +2,7 @@ require File.join(File.dirname(__FILE__), 'test_helper')
2
2
 
3
3
  describe "Completion" do
4
4
  before_all {
5
- M.reset
5
+ reset
6
6
  M.load_file File.dirname(__FILE__) + '/../lib/bond/completion.rb'
7
7
  M.load_dir File.dirname(__FILE__) + '/../lib/bond'
8
8
  }
@@ -48,7 +48,7 @@ describe "Completion" do
48
48
  end
49
49
 
50
50
  it "completes hash coming from a method" do
51
- tab('Bond.config[:r').should == ["Bond.config[:readline_plugin"]
51
+ tab('Bond.config[:r').should == ["Bond.config[:readline"]
52
52
  end
53
53
 
54
54
  it "methods don't swallow up default completion" do
@@ -2,7 +2,7 @@ require File.join(File.dirname(__FILE__), 'test_helper')
2
2
 
3
3
  describe "completions for" do
4
4
  before_all {
5
- M.reset
5
+ reset
6
6
  complete(:all_methods=>true)
7
7
  complete(:all_operator_methods=>true)
8
8
  M.load_file File.dirname(__FILE__) + '/../lib/bond/completion.rb'
@@ -15,7 +15,7 @@ module TestHelpers
15
15
  module InputCompletor; CompletionProc = lambda {|e| [] }; end
16
16
  end
17
17
  ]
18
- ::IRB.CurrentContext = stub(:workspace=>stub(:binding=>binding))
18
+ ::IRB.CurrentContext = stub(:workspace => stub(:binding => binding))
19
19
  end
20
20
  end
21
21
 
@@ -50,8 +50,13 @@ module TestHelpers
50
50
  Bond.complete(*args, &block)
51
51
  end
52
52
 
53
- def valid_readline_plugin
54
- Module.new{ def setup(arg); end; def line_buffer; end }
53
+ def valid_readline
54
+ Class.new { def self.setup(arg); end; def self.line_buffer; end }
55
+ end
56
+
57
+ def reset
58
+ M.reset
59
+ M.debrief :readline => TestHelpers.valid_readline
55
60
  end
56
61
  end
57
62
 
@@ -60,5 +65,5 @@ class Bacon::Context
60
65
  end
61
66
 
62
67
  # Default settings
63
- Bond::M.debrief(:readline_plugin=>TestHelpers.valid_readline_plugin, :debug=>true)
68
+ Bond::M.debrief(:readline => TestHelpers.valid_readline, :debug => true)
64
69
  include Bond
metadata CHANGED
@@ -1,13 +1,13 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: bond
3
3
  version: !ruby/object:Gem::Version
4
- hash: 25
4
+ hash: 15
5
5
  prerelease: false
6
6
  segments:
7
7
  - 0
8
- - 3
9
- - 5
10
- version: 0.3.5
8
+ - 4
9
+ - 0
10
+ version: 0.4.0
11
11
  platform: ruby
12
12
  authors:
13
13
  - Gabriel Horner
@@ -15,7 +15,7 @@ autorequire:
15
15
  bindir: bin
16
16
  cert_chain: []
17
17
 
18
- date: 2011-01-07 00:00:00 -05:00
18
+ date: 2011-01-11 00:00:00 -05:00
19
19
  default_executable:
20
20
  dependencies:
21
21
  - !ruby/object:Gem::Dependency
@@ -78,7 +78,7 @@ dependencies:
78
78
  version: "0"
79
79
  type: :development
80
80
  version_requirements: *id004
81
- description: Bond is on a mission to improve autocompletion in ruby, especially for ripl/irb. 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 can also load completions that ship with gems. 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.
81
+ description: Bond is on a mission to improve autocompletion in ruby, especially for irb/ripl. 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 ruby autocompletion 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 autocompletions and share it with others. Bond can also load completions that ship with gems. Bond is able to offer more than irb's completion since it uses the full line of input when completing as opposed to irb's last-word approach.
82
82
  email: gabriel.horner@gmail.com
83
83
  executables: []
84
84
 
@@ -106,9 +106,11 @@ files:
106
106
  - lib/bond/missions/method_mission.rb
107
107
  - lib/bond/missions/object_mission.rb
108
108
  - lib/bond/missions/operator_method_mission.rb
109
- - lib/bond/rawline.rb
110
109
  - lib/bond/rc.rb
111
110
  - lib/bond/readline.rb
111
+ - lib/bond/readlines/jruby.rb
112
+ - lib/bond/readlines/rawline.rb
113
+ - lib/bond/readlines/ruby.rb
112
114
  - lib/bond/search.rb
113
115
  - lib/bond/version.rb
114
116
  - lib/bond.rb
@@ -132,14 +134,14 @@ files:
132
134
  - test/deps.rip
133
135
  - Rakefile
134
136
  - .gemspec
135
- has_rdoc: yard
137
+ has_rdoc: true
136
138
  homepage: http://tagaholic.me/bond/
137
139
  licenses:
138
140
  - MIT
139
141
  post_install_message:
140
142
  rdoc_options:
141
143
  - --title
142
- - Bond 0.3.5 Documentation
144
+ - Bond 0.4.0 Documentation
143
145
  require_paths:
144
146
  - lib
145
147
  required_ruby_version: !ruby/object:Gem::Requirement
@@ -1,16 +0,0 @@
1
- module Bond
2
- # A readline plugin for use with {Rawline}[http://github.com/h3rald/rawline]. This plugin
3
- # should be used in conjunction with {a Rawline shell}[http://www.h3rald.com/articles/real-world-rawline-usage].
4
- module Rawline
5
- def setup(agent)
6
- require 'rawline'
7
- ::Rawline.completion_append_character = nil
8
- ::Rawline.basic_word_break_characters= " \t\n\"\\'`><;|&{("
9
- ::Rawline.completion_proc = agent
10
- end
11
-
12
- def line_buffer
13
- ::Rawline.editor.line.text
14
- end
15
- end
16
- end