bombshell 0.1.4 → 0.1.5

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/bombshell.gemspec CHANGED
@@ -8,7 +8,7 @@ Gem::Specification.new do |s|
8
8
 
9
9
  s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
10
10
  s.authors = ["Andy Rossmeissl"]
11
- s.date = %q{2011-03-31}
11
+ s.date = "2011-04-20"
12
12
  s.description = %q{Give your application or gem an interactive shell, complete with custom prompts, tab completion, and various callbacks. Commands are defined as Ruby methods and can be grouped into logical subshells.}
13
13
  s.email = %q{andy@rossmeissl.net}
14
14
  s.extra_rdoc_files = [
@@ -5,6 +5,6 @@ require 'rspec/expectations'
5
5
  require 'bombshell'
6
6
 
7
7
  Before do
8
- @aruba_io_wait_seconds = 2
8
+ @aruba_io_wait_seconds = 3
9
9
  @dirs = [File.join(ENV['HOME'], 'bombshell_features')]
10
10
  end
data/lib/bombshell.rb CHANGED
@@ -5,7 +5,15 @@ require 'bombshell/completor'
5
5
  require 'bombshell/environment'
6
6
  require 'bombshell/irb'
7
7
 
8
+ # Bombshell enables the lickety-split creation of interactive consoles
9
+ # (really just boring old custom IRB sessions).
10
+ # As a Ruby library developer, you may want to build a little shell into
11
+ # your library so that other developers can play around with it before
12
+ # adding it to their applications. In the past this has been a real PITA.
13
+ # With Bombshell it's a little easier.
8
14
  module Bombshell
15
+ # Launch a shell. This is typically called from a "gem binary" executable Ruby script as described in the README.
16
+ # @param [Class] shell The shell class to launch. Must include <tt>Bombshell::Shell</tt>.
9
17
  def launch(shell)
10
18
  begin
11
19
  failure = shell.launch(ARGV.dup)
@@ -1,15 +1,20 @@
1
1
  module Bombshell
2
+ # A class used by <tt>IRB.start_session</tt> to handle tab completion.
2
3
  class Completor
4
+ # Always initialize Completor with the shell it's completing for.
3
5
  def initialize(shell)
4
6
  @shell = shell
5
7
  end
6
8
 
7
9
  attr_reader :shell
8
10
 
11
+ # Provide completion for a given fragment.
12
+ # @param [String] fragment the fragment to complete for
9
13
  def complete(fragment)
10
14
  self.class.filter(shell.instance_methods).grep Regexp.new(Regexp.quote(fragment))
11
15
  end
12
16
 
17
+ # Filter out irrelevant methods that shouldn't appear in a completion list.
13
18
  def self.filter(m)
14
19
  (m - Bombshell::Environment.instance_methods - Bombshell::Shell::Commands::HIDE).reject do |m|
15
20
  m =~ /^_/
@@ -1,4 +1,7 @@
1
1
  module Bombshell
2
+ # A (mostly) blank class like Ruby's own CleanSlate. We leave a few important methods in here; your shell shouldn't redefine them.
3
+ # It's best practice to set your shell classes to inherit from <tt>Bombshell::Environment</tt>. See the README for more details.
4
+ # @see file:README.markdown
2
5
  class Environment
3
6
  instance_methods.each do |m|
4
7
  undef_method m if m.to_s !~ /(?:^__|^nil\?$|^send$|^instance_eval$|^define_method$|^class$|^object_id|^instance_methods$)/
data/lib/bombshell/irb.rb CHANGED
@@ -1,6 +1,9 @@
1
1
  # encoding: utf-8
2
2
 
3
+ # We have to monkey patch a method into IRB here. I've tried extending it, and it doesn't work.
3
4
  module IRB
5
+ # Launch a custom IRB session with the given binding, set up the prompt, and define tab completion.
6
+ # @param [Binding] binding Your shell's binding
4
7
  def self.start_session(binding)
5
8
  unless @__initialized
6
9
  args = ARGV
@@ -1,18 +1,28 @@
1
1
  require 'bombshell/shell/commands'
2
2
 
3
3
  module Bombshell
4
+ # Classes include this module to become Bombshell shells.
4
5
  module Shell
6
+ # Add class methods and a callback hash to your shell.
5
7
  def self.included(base)
6
8
  base.extend ClassMethods
7
9
  base.instance_variable_set :@bombshell_callbacks, :before_launch => [], :having_launched => []
8
10
  end
9
11
 
12
+ # IRB has pretty limited hooks for defining prompts, so we have to piggyback on your
13
+ # shell's <tt>#to_s</tt>. Hope you don't need it for something else.
10
14
  def to_s
11
15
  _prompt
12
16
  end
13
17
 
14
18
  include Commands
15
19
 
20
+ # Render and return your shell's prompt.
21
+ #
22
+ # You can define the prompt with <tt>MyShell.prompt_with</tt> and access it without rendering with <tt>MyShell.bombshell_prompt</tt>.
23
+ # @see ClassMethods#prompt_with
24
+ # @see ClassMethods#bombshell_prompt
25
+ # @return String
16
26
  def _prompt
17
27
  if self.class.bombshell_prompt.is_a? String
18
28
  self.class.bombshell_prompt
@@ -25,11 +35,22 @@ module Bombshell
25
35
  end
26
36
  end
27
37
 
38
+ # Returns your shell's binding, which IRB needs (desperately).
39
+ # @return Binding
28
40
  def get_binding
29
41
  binding
30
42
  end
31
43
 
44
+ # Class methods for your shell
32
45
  module ClassMethods
46
+ # Launch the shell.
47
+ #
48
+ # You should generally call <tt>Bombshell.launch(MyShell)</tt> instead
49
+ # of <tt>MyShell.launch</tt> directly, as the former approach will handle
50
+ # exits correctly and pass command-line parameters as arguments.
51
+ # @param [Array] arguments An array of arguments that, eventually, callbacks
52
+ # might use. If you're using the <tt>Bombshell.launch</tt> wrapper, these
53
+ # will be command-line parameters.
33
54
  def launch(*arguments)
34
55
  @bombshell_callbacks[:before_launch].each do |callback|
35
56
  callback.call(*arguments.first(callback.arity > -1 ? callback.arity : 0))
@@ -41,18 +62,63 @@ module Bombshell
41
62
  ::IRB.start_session(shell.get_binding)
42
63
  end
43
64
 
65
+ # Define a callback that will get called before your shell is instantiated (and
66
+ # therefore before it is handed over to IRB).
67
+ #
68
+ # This is a great place to
69
+ # dynamically define additional instance methods on your class. If your callback
70
+ # proc asks for blockvars, Bombshell will give it as many command-line parameters
71
+ # as it needs to. Within the callback, <tt>self</tt> is your shell <i>class</i>.
72
+ # @see #having_launched
73
+ # @example
74
+ # class MyShell < Bombshell::Environment
75
+ # include Bombshell::Shell
76
+ # before_launch do
77
+ # define_method :foo
78
+ # puts 'bar'
79
+ # end
80
+ # end
81
+ # end
82
+ # @example
83
+ # class MyShell < Bombshell::Environment
84
+ # include Bombshell::Shell
85
+ # before_launch do |first_command_line_parameter, second_command_line_parameter|
86
+ # define_method :display_first_command_line_parameter
87
+ # puts first_command_line_parameter
88
+ # end
89
+ # end
90
+ # end
44
91
  def before_launch(&callback)
45
92
  @bombshell_callbacks[:before_launch] << callback
46
93
  end
47
94
 
95
+ # Define a callback that will get called <i>after</i> your shell is instantiated,
96
+ # but <i>before</i> its binding is handed over to IRB. Within the callback, <tt>self</tt> is your shell <i>instance</i>.
97
+ # @see #before_launch
48
98
  def having_launched(&callback)
49
99
  @bombshell_callbacks[:having_launched] << callback
50
100
  end
51
101
 
102
+ # Define your shell's prompt.
103
+ #
104
+ # You can either set your prompt to a static string, or use a Proc for a dynamic prompt.
105
+ # @param [String] p a string to be used as your shell's prompt.
106
+ # @param [Proc] prompt a Proc to be rendered whenever your shell's prompt needs to be
107
+ # displayed. Within the callback, <tt>self</tt> is your shell <i>class</i>. If your
108
+ # proc asks for a blockvar, it will be given your shell <i>instance</i>.
109
+ # @see Bombshell::Shell#_prompt
110
+ # @see #bombshell_prompt
52
111
  def prompt_with(p = nil, &prompt)
53
112
  @bombshell_prompt = p || prompt
54
113
  end
55
114
 
115
+ # Read your shell's prompt
116
+ #
117
+ # Note that this method returns an <i>unrendered</i> prompt. That is, if it's defined as
118
+ # a Proc, you'll get a Proc back. If you want to get the rendered prompt, use <tt>#_prompt</tt>
119
+ # on your shell instance.
120
+ # @see #prompt_with
121
+ # @see Bombshell::Shell#_prompt
56
122
  def bombshell_prompt
57
123
  @bombshell_prompt
58
124
  end
@@ -1,11 +1,16 @@
1
1
  module Bombshell
2
2
  module Shell
3
+ # Standard commands that show up in all Bombshell shells.
3
4
  module Commands
5
+ # An explicit list of commands to hide from tab completion.
4
6
  HIDE = [:method_missing, :get_binding, :_prompt, :to_s]
5
7
 
8
+ # Exit safely, accounting for the fact that we might be inside a subshell.
6
9
  def quit
7
10
  throw :IRB_EXIT
8
11
  end
12
+
13
+ # Provide an error message for unknown commands rather than raise an exception.
9
14
  def method_missing(*args)
10
15
  return if [:extend, :respond_to?].include? args.first
11
16
  puts "Unknown command #{args.first}"
metadata CHANGED
@@ -1,13 +1,13 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: bombshell
3
3
  version: !ruby/object:Gem::Version
4
- hash: 19
4
+ hash: 17
5
5
  prerelease:
6
6
  segments:
7
7
  - 0
8
8
  - 1
9
- - 4
10
- version: 0.1.4
9
+ - 5
10
+ version: 0.1.5
11
11
  platform: ruby
12
12
  authors:
13
13
  - Andy Rossmeissl
@@ -15,7 +15,7 @@ autorequire:
15
15
  bindir: bin
16
16
  cert_chain: []
17
17
 
18
- date: 2011-03-31 00:00:00 -04:00
18
+ date: 2011-04-20 00:00:00 -04:00
19
19
  default_executable:
20
20
  dependencies:
21
21
  - !ruby/object:Gem::Dependency