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 +1 -1
- data/features/support/env.rb +1 -1
- data/lib/bombshell.rb +8 -0
- data/lib/bombshell/completor.rb +5 -0
- data/lib/bombshell/environment.rb +3 -0
- data/lib/bombshell/irb.rb +3 -0
- data/lib/bombshell/shell.rb +66 -0
- data/lib/bombshell/shell/commands.rb +5 -0
- metadata +4 -4
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 =
|
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 = [
|
data/features/support/env.rb
CHANGED
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)
|
data/lib/bombshell/completor.rb
CHANGED
@@ -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
|
data/lib/bombshell/shell.rb
CHANGED
@@ -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:
|
4
|
+
hash: 17
|
5
5
|
prerelease:
|
6
6
|
segments:
|
7
7
|
- 0
|
8
8
|
- 1
|
9
|
-
-
|
10
|
-
version: 0.1.
|
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-
|
18
|
+
date: 2011-04-20 00:00:00 -04:00
|
19
19
|
default_executable:
|
20
20
|
dependencies:
|
21
21
|
- !ruby/object:Gem::Dependency
|