shelldon 0.0.7 → 0.0.8
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.rbenv-gemsets +1 -0
- data/README.md +63 -88
- data/lib/command/command.rb +2 -0
- data/lib/command/command_list.rb +4 -1
- data/lib/config/config.rb +3 -2
- data/lib/config/config_factory.rb +3 -2
- data/lib/config/param.rb +2 -1
- data/lib/dsl.rb +25 -1
- data/lib/exceptions/exceptions.rb +19 -0
- data/lib/index.rb +40 -0
- data/lib/module/module.rb +43 -0
- data/lib/module/module_factory.rb +33 -0
- data/lib/module/module_index.rb +16 -0
- data/lib/shell/shell.rb +11 -3
- data/lib/shell/shell_factory.rb +31 -1
- data/lib/shell/shell_factory_index.rb +16 -0
- data/lib/shell/shell_index.rb +4 -30
- data/lib/shelldon.rb +5 -0
- data/lib/shelldon/version.rb +1 -1
- data/test_shell/dependency_test/dependency_test.rb +2 -1
- data/test_shell/dependency_test/dt_config.rb +0 -6
- data/test_shell/dependency_test/dt_runner.rb +21 -2
- data/test_shell/dependency_test/test_module.rb +16 -0
- data/test_shell/simple_shell.rb +1 -1
- data/test_shell/simplest_shell.rb +12 -0
- data/test_shell/test_shell.rb +1 -1
- metadata +11 -3
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 0c0b0a7f5f6649588679a69a1173b3fbb8908cc7
|
4
|
+
data.tar.gz: b71f5389f97fd747ed80973fbf14993ffc88cc4d
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 23f12ce391adccd268f03d11fbcf48496956b9f4428f95cf31591e3456c111edd9c72f3330c724f48e1c253e0c5a4a09b29a45295453797524ae4d821ae119b4
|
7
|
+
data.tar.gz: c22ce281321e342ae0345a051eadd38cb2d0563f3e1bcc240321ec3de3262bbf95bd411bef116f6931586cbb619ab9997bda8f7c8e219c42b0b7092313987e63
|
data/.rbenv-gemsets
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
-global
|
data/README.md
CHANGED
@@ -1,4 +1,6 @@
|
|
1
|
-
# Shelldon
|
1
|
+
# <img src="http://www.wesleyboynton.com/wp-content/uploads/2016/04/shelldon.png" width="100"> Shelldon
|
2
|
+
|
3
|
+
[![Gem Version](https://badge.fury.io/rb/shelldon.svg)](https://badge.fury.io/rb/shelldon)
|
2
4
|
|
3
5
|
Shelldon is an expressive DSL for building interactive terminal applications, or REPLs (Read-Evaluate-Print-Loops).
|
4
6
|
|
@@ -16,116 +18,89 @@ Or just `gem install shelldon` -- You know the drill.
|
|
16
18
|
|
17
19
|
## Usage
|
18
20
|
|
19
|
-
Here's a
|
21
|
+
Shelldon is made to be dead-simple to use. Here's a breakdown of the usage!
|
20
22
|
|
21
|
-
|
22
|
-
require 'shelldon'
|
23
|
-
require 'pp'
|
23
|
+
Start defining a shell like this:
|
24
24
|
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
25
|
+
``` ruby
|
26
|
+
Shelldon.shell :example do
|
27
|
+
end
|
28
|
+
Shelldon.run(:example)
|
29
29
|
|
30
|
-
|
31
|
-
# Set the config file, which can hold values one level higher than their default
|
32
|
-
# The order of precedence for params is: Set in-session > set by command-line flag > set by config file > default
|
33
|
-
config_file '.my-config-file'
|
30
|
+
```
|
34
31
|
|
35
|
-
|
36
|
-
type :boolean # Make it a boolean
|
37
|
-
default false # Make its default value false
|
38
|
-
opt 'myopt' # Override it with the value of command-line opt '--myopt' if present
|
39
|
-
end
|
40
|
-
end
|
32
|
+
### Commands
|
41
33
|
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
action do |args|
|
53
|
-
tokens = args.split(' ')
|
54
|
-
config[tokens[0].to_sym] = tokens[1]
|
55
|
-
end
|
34
|
+
Define a command with a `command` block:
|
35
|
+
|
36
|
+
``` ruby
|
37
|
+
Shelldon.shell :example do
|
38
|
+
command :test do
|
39
|
+
aliased 'test_command'
|
40
|
+
help "Run a test command to show some text. Optionally, add an arg."
|
41
|
+
usage "test"
|
42
|
+
examples ['test', 'test blah']
|
43
|
+
action { |arg = ''| puts "This is a test! #{arg}" }
|
56
44
|
end
|
45
|
+
end
|
46
|
+
Shelldon.run(:example)
|
57
47
|
|
48
|
+
```
|
58
49
|
|
59
|
-
|
60
|
-
command :arg do
|
61
|
-
help 'Show your args off!'
|
62
|
-
action { |args| puts args }
|
63
|
-
end
|
50
|
+
### Sub-Commands
|
64
51
|
|
65
|
-
|
66
|
-
# show the value of a specific option if called with an argument
|
67
|
-
command :config do
|
68
|
-
help 'Show the configuration of the current session.'
|
69
|
-
usage 'config'
|
70
|
-
action do |args|
|
71
|
-
if args.empty?
|
72
|
-
pp config.to_a
|
73
|
-
else
|
74
|
-
param = config.find(args.to_sym)
|
75
|
-
puts "#{param.name}: #{param.val}"
|
76
|
-
end
|
77
|
-
end
|
52
|
+
You can nest commands into other commands with the `subcommand` block. This is great for organizing functionality. You can retain the functionality of your higher-level commands, or if you want a higher-level command to act as a placeholder you can just tell Shelldon so!
|
78
53
|
|
79
|
-
|
80
|
-
|
81
|
-
|
82
|
-
|
83
|
-
|
84
|
-
|
54
|
+
For instance, you could run the command `test foobar` like this:
|
55
|
+
``` ruby
|
56
|
+
command :test do
|
57
|
+
placeholder
|
58
|
+
|
59
|
+
subcommand :foobar do
|
60
|
+
help "Print out 'Foobar!'"
|
61
|
+
action {puts "Foobar!"}
|
85
62
|
end
|
86
63
|
end
|
64
|
+
```
|
87
65
|
|
66
|
+
### Default Command ("No Such Command Found")
|
67
|
+
You can use the `command_missing` block to define behaviour when a command isn't explicitly registered. This can be anything from writing "No Such Command" to doing a similarity-search to passing the command to some other resource.
|
88
68
|
|
89
|
-
|
90
|
-
|
91
|
-
|
92
|
-
|
93
|
-
|
94
|
-
help 'Show help. Optionally specify specific command for more information.'
|
95
|
-
usage 'help [cmd]'
|
96
|
-
examples ['help', 'help quit']
|
97
|
-
end
|
98
|
-
|
99
|
-
# Define a default command - This is what happens when a command doesn't match up
|
100
|
-
command_missing do
|
101
|
-
action { |cmd| puts "No such command \"#{cmd}\"" }
|
102
|
-
end
|
69
|
+
``` ruby
|
70
|
+
command_missing do
|
71
|
+
action { |cmd| puts "No such command \"#{cmd}\"" }
|
72
|
+
end
|
73
|
+
```
|
103
74
|
|
104
|
-
|
105
|
-
|
106
|
-
# You can make your prompt a string or a block
|
107
|
-
prompt 'shelldon> ' # This is okay
|
108
|
-
prompt { "shelldon#{4+2}>" } # This is okay too
|
75
|
+
### Configuration
|
76
|
+
What good is a shell without config? The `config` block will allow you to set up parameters, validate and adjust input, set a configuration yml file, and interact with command-line opts.
|
109
77
|
|
110
|
-
|
111
|
-
home '~/.shelldon-test'
|
78
|
+
Here's an example that implements the bash 'set -o vi/emacs' functionality in the shell
|
112
79
|
|
113
|
-
|
114
|
-
history true
|
80
|
+
``` ruby
|
115
81
|
|
116
|
-
|
117
|
-
|
82
|
+
config do
|
83
|
+
config_file '.shelldon_config'
|
118
84
|
|
119
|
-
|
120
|
-
|
121
|
-
|
122
|
-
|
123
|
-
|
124
|
-
|
85
|
+
param :'-o' do
|
86
|
+
type :string
|
87
|
+
default 'emacs'
|
88
|
+
# adjust runs before validate, and can 'fix' your input. In this case, allow 'vim' for 'vi'
|
89
|
+
adjust { |s| s.to_s.downcase.strip.gsub('vim', 'vi') }
|
90
|
+
# validate looks for a 'true' result, but in this case we're also using it to take action
|
91
|
+
validate do |s|
|
92
|
+
return false unless s == 'emacs' || s == 'vi'
|
93
|
+
if s == 'emacs'
|
94
|
+
Readline.emacs_editing_mode; true
|
95
|
+
else
|
96
|
+
Readline.vi_editing_mode; true
|
97
|
+
end
|
125
98
|
end
|
126
99
|
end
|
127
100
|
end
|
128
101
|
```
|
102
|
+
|
103
|
+
|
129
104
|
## Contributing
|
130
105
|
Bug reports and pull requests are welcome on GitHub at https://github.com/wwboynton/shelldon.
|
131
106
|
|
data/lib/command/command.rb
CHANGED
data/lib/command/command_list.rb
CHANGED
@@ -56,7 +56,10 @@ module Shelldon
|
|
56
56
|
else
|
57
57
|
cmd = find(str).first
|
58
58
|
if cmd.show && !is_default?(cmd)
|
59
|
-
|
59
|
+
subcommands = cmd.sub_to_a
|
60
|
+
res = [compile_help(cmd).values]
|
61
|
+
res << subcommands unless subcommands.empty?
|
62
|
+
res
|
60
63
|
else
|
61
64
|
fail Shelldon::NoSuchCommandError
|
62
65
|
end
|
data/lib/config/config.rb
CHANGED
@@ -17,7 +17,7 @@ module Shelldon
|
|
17
17
|
end
|
18
18
|
|
19
19
|
def setup
|
20
|
-
load_config_file
|
20
|
+
load_config_file if @config_file_manager
|
21
21
|
end
|
22
22
|
|
23
23
|
def toggle(key)
|
@@ -73,7 +73,8 @@ module Shelldon
|
|
73
73
|
hash.each do |k, v|
|
74
74
|
key = k.to_sym
|
75
75
|
if @config.key?(key)
|
76
|
-
set(key, v) unless @config[key].override ||
|
76
|
+
set(key, v) unless @config[key].override ||
|
77
|
+
(Shelldon.opts &&Shelldon.opts.key?(@config[key].opt))
|
77
78
|
else
|
78
79
|
fail(Shelldon::NoSuchParamError)
|
79
80
|
end
|
@@ -9,8 +9,9 @@ module Shelldon
|
|
9
9
|
end
|
10
10
|
|
11
11
|
def initialize(shell, &block)
|
12
|
-
@shell
|
13
|
-
@config
|
12
|
+
@shell = shell
|
13
|
+
@shell.config ||= Shelldon::Config.new(@shell)
|
14
|
+
@config = @shell.config
|
14
15
|
instance_eval(&block)
|
15
16
|
@shell.config = @config
|
16
17
|
end
|
data/lib/config/param.rb
CHANGED
@@ -15,7 +15,8 @@ module Shelldon
|
|
15
15
|
def val
|
16
16
|
return @val if @val
|
17
17
|
return @override if @override
|
18
|
-
|
18
|
+
return @default unless Shelldon.opts
|
19
|
+
@val = Shelldon.opts.has_key?(@opt) ? Shelldon.opts[@opt] : @default
|
19
20
|
end
|
20
21
|
|
21
22
|
def val=(value)
|
data/lib/dsl.rb
CHANGED
@@ -12,7 +12,11 @@ module Shelldon
|
|
12
12
|
end
|
13
13
|
|
14
14
|
def self.shell(name = (:default), &block)
|
15
|
-
|
15
|
+
if shell_factory_index.has_key?(name)
|
16
|
+
shell_factory_index[name].load(&block)
|
17
|
+
else
|
18
|
+
ShellFactory.new(name.to_sym, &block)
|
19
|
+
end
|
16
20
|
end
|
17
21
|
|
18
22
|
def self.opts=(opts_arr)
|
@@ -35,4 +39,24 @@ module Shelldon
|
|
35
39
|
sym = sym.to_sym unless sym
|
36
40
|
ShellIndex.instance.key?(sym)
|
37
41
|
end
|
42
|
+
|
43
|
+
def self.module(name, &block)
|
44
|
+
ModuleFactory.new(name.to_sym, &block)
|
45
|
+
end
|
46
|
+
|
47
|
+
def self.module_index
|
48
|
+
Shelldon::ModuleIndex.instance
|
49
|
+
end
|
50
|
+
|
51
|
+
def self.modules
|
52
|
+
module_index
|
53
|
+
end
|
54
|
+
|
55
|
+
def self.shell_factory_index
|
56
|
+
Shelldon::ShellFactoryIndex.instance
|
57
|
+
end
|
58
|
+
|
59
|
+
def self.run(shell_name = (:default))
|
60
|
+
shell_factory_index[shell_name].run
|
61
|
+
end
|
38
62
|
end
|
@@ -1,5 +1,8 @@
|
|
1
1
|
module Shelldon
|
2
2
|
class Error < StandardError
|
3
|
+
def initialize(msg = nil)
|
4
|
+
@msg = msg
|
5
|
+
end
|
3
6
|
end
|
4
7
|
|
5
8
|
class ConfirmationError < Error
|
@@ -54,6 +57,22 @@ module Shelldon
|
|
54
57
|
define_method(:message) { 'Cannot add non-shells to the shell index' }
|
55
58
|
end
|
56
59
|
|
60
|
+
class NotAShellFactoryError < Error
|
61
|
+
define_method(:message) { 'Cannot add non-shell-factories to the shell factory index' }
|
62
|
+
end
|
63
|
+
|
64
|
+
class NotAModuleError < Error
|
65
|
+
define_method(:message) { 'Cannot add non-modules to the module index' }
|
66
|
+
end
|
67
|
+
|
68
|
+
class NoSuchModuleError < Error
|
69
|
+
define_method(:message) { "No such module #{@msg} found." }
|
70
|
+
end
|
71
|
+
|
72
|
+
class DuplicateIndexError < Error
|
73
|
+
define_method(:message) { 'There is already an object with that name in the index' }
|
74
|
+
end
|
75
|
+
|
57
76
|
class TimeoutError < Error
|
58
77
|
define_method(:message) { 'Operation timed out.' }
|
59
78
|
end
|
data/lib/index.rb
ADDED
@@ -0,0 +1,40 @@
|
|
1
|
+
module Shelldon
|
2
|
+
class Index
|
3
|
+
include Singleton
|
4
|
+
|
5
|
+
def self.method_missing(meth_name, *args, &block)
|
6
|
+
if block_given?
|
7
|
+
instance.send(meth_name, *args, &block)
|
8
|
+
else
|
9
|
+
instance.send(meth_name, *args)
|
10
|
+
end
|
11
|
+
end
|
12
|
+
|
13
|
+
def initialize
|
14
|
+
@index = {}
|
15
|
+
end
|
16
|
+
|
17
|
+
def [](key)
|
18
|
+
@index[key.to_sym]
|
19
|
+
end
|
20
|
+
|
21
|
+
def []=(key, val)
|
22
|
+
@index[key.to_sym] = val
|
23
|
+
end
|
24
|
+
|
25
|
+
def has_key?(key)
|
26
|
+
@index.key?(key)
|
27
|
+
end
|
28
|
+
|
29
|
+
def <<(obj)
|
30
|
+
@first = obj.name if @index.empty?
|
31
|
+
fail Shelldon::DuplicateIndexError if @index.key?(obj.name)
|
32
|
+
@index[obj.name] = obj
|
33
|
+
end
|
34
|
+
|
35
|
+
def first?(sym)
|
36
|
+
sym = sym.to_sym unless sym.is_a?(Symbol)
|
37
|
+
sym == @first
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
@@ -0,0 +1,43 @@
|
|
1
|
+
module Shelldon
|
2
|
+
class Module
|
3
|
+
attr_reader :name
|
4
|
+
def initialize(name)
|
5
|
+
@name = name.to_sym
|
6
|
+
@commands = []
|
7
|
+
@configs = []
|
8
|
+
@shell_blocks = []
|
9
|
+
@command_missing = []
|
10
|
+
end
|
11
|
+
|
12
|
+
def add_command(name, lambda)
|
13
|
+
@commands << [name, lambda]
|
14
|
+
end
|
15
|
+
|
16
|
+
def add_config(lambda)
|
17
|
+
@configs << lambda
|
18
|
+
end
|
19
|
+
|
20
|
+
def add_shell_block(lambda)
|
21
|
+
@shell_blocks << lambda
|
22
|
+
end
|
23
|
+
|
24
|
+
def add_command_missing(lambda)
|
25
|
+
@command_missing[0] = lambda
|
26
|
+
end
|
27
|
+
|
28
|
+
def install(shell_name)
|
29
|
+
@commands.each do |(name, lambda)|
|
30
|
+
Shelldon.shell(shell_name) { command(name, &lambda.to_proc) }
|
31
|
+
end
|
32
|
+
@configs.each do |lambda|
|
33
|
+
Shelldon.shell(shell_name) { config(&lambda.to_proc) }
|
34
|
+
end
|
35
|
+
@shell_blocks.each do |lambda|
|
36
|
+
Shelldon.shell(shell_name) { shell(&lambda.to_proc) }
|
37
|
+
end
|
38
|
+
@command_missing.each do |lambda|
|
39
|
+
Shelldon.shell(shell_name) { command_missing(&lambda.to_proc) }
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
@@ -0,0 +1,33 @@
|
|
1
|
+
module Shelldon
|
2
|
+
class ModuleFactory
|
3
|
+
def initialize(name, &block)
|
4
|
+
@name = name
|
5
|
+
register Shelldon::Module.new(name) unless Shelldon.modules.has_key?(name)
|
6
|
+
instance_exec(@name, &block.to_proc)
|
7
|
+
end
|
8
|
+
|
9
|
+
def this_module
|
10
|
+
Shelldon.modules[@name]
|
11
|
+
end
|
12
|
+
|
13
|
+
def command(name, &block)
|
14
|
+
this_module.add_command(name, block)
|
15
|
+
end
|
16
|
+
|
17
|
+
def config(&block)
|
18
|
+
this_module.add_config(block)
|
19
|
+
end
|
20
|
+
|
21
|
+
def shell(&block)
|
22
|
+
this_module.add_shell_block(block)
|
23
|
+
end
|
24
|
+
|
25
|
+
def command_missing(&block)
|
26
|
+
this_module.add_command_missing(block)
|
27
|
+
end
|
28
|
+
|
29
|
+
def register(mod)
|
30
|
+
Shelldon.modules << mod
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
@@ -0,0 +1,16 @@
|
|
1
|
+
# This allows subshelling - You can define multiple shells in one program and nest them.
|
2
|
+
# This is the opposite approach to shell-as-singleton, which makes access easy but prevents multiple shells.
|
3
|
+
# This is why all of the factories pass the shell parent into their respective products.
|
4
|
+
|
5
|
+
module Shelldon
|
6
|
+
class ModuleIndex < Index
|
7
|
+
def <<(mod)
|
8
|
+
if mod.is_a?(Shelldon::Module)
|
9
|
+
fail Shelldon::DuplicateIndexError if @index.key?(mod.name)
|
10
|
+
@index[mod.name] = mod
|
11
|
+
else
|
12
|
+
fail Shelldon::NotAModuleError
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
data/lib/shell/shell.rb
CHANGED
@@ -77,7 +77,7 @@ module Shelldon
|
|
77
77
|
end
|
78
78
|
|
79
79
|
def run
|
80
|
-
@history_helper.load
|
80
|
+
@history_helper.load if @history_helper
|
81
81
|
run_opt_conditions
|
82
82
|
handle_piped_input
|
83
83
|
instance_eval(&@startup) if @startup
|
@@ -85,12 +85,12 @@ module Shelldon
|
|
85
85
|
run_repl
|
86
86
|
rescue *@accept_errors.keys => e
|
87
87
|
print_error(e)
|
88
|
-
|
88
|
+
log_warn(e)
|
89
89
|
on_error(e, @accept_errors[e.class], :accept)
|
90
90
|
retry
|
91
91
|
rescue *@reject_errors.keys => e
|
92
92
|
print_error(e)
|
93
|
-
|
93
|
+
log_fatal(e)
|
94
94
|
on_error(e, @reject_errors[e.class], :reject)
|
95
95
|
rescue StandardError => e
|
96
96
|
print_error(e)
|
@@ -104,6 +104,14 @@ module Shelldon
|
|
104
104
|
end
|
105
105
|
end
|
106
106
|
|
107
|
+
def log_warn(e)
|
108
|
+
@logger.warn(e) if @logger
|
109
|
+
end
|
110
|
+
|
111
|
+
def log_fatal(e)
|
112
|
+
@logger.fatal(e) if @logger
|
113
|
+
end
|
114
|
+
|
107
115
|
def on_error(e, proc, type = nil)
|
108
116
|
run_accept_error(e) if type == :accept
|
109
117
|
run_reject_error(e) if type == :reject
|
data/lib/shell/shell_factory.rb
CHANGED
@@ -1,14 +1,21 @@
|
|
1
1
|
module Shelldon
|
2
2
|
class ShellFactory
|
3
|
+
attr_reader :name
|
4
|
+
|
3
5
|
def initialize(name, &block)
|
4
6
|
@name = name
|
7
|
+
Shelldon.shell_factory_index << self
|
5
8
|
setup_vars
|
6
9
|
register(Shell.new(name)) unless Shelldon[name]
|
10
|
+
load(&block)
|
11
|
+
end
|
12
|
+
|
13
|
+
def load(&block)
|
7
14
|
instance_eval(&block)
|
8
|
-
make_it_rain
|
9
15
|
end
|
10
16
|
|
11
17
|
def setup_vars
|
18
|
+
@modules = []
|
12
19
|
@new_opts = []
|
13
20
|
@new_configs = []
|
14
21
|
@new_on_opts = []
|
@@ -16,9 +23,16 @@ module Shelldon
|
|
16
23
|
@new_script_dirs = []
|
17
24
|
end
|
18
25
|
|
26
|
+
def run
|
27
|
+
make_it_rain
|
28
|
+
Shelldon[@name].run
|
29
|
+
end
|
30
|
+
|
19
31
|
def make_it_rain
|
32
|
+
install_modules
|
20
33
|
make_opts
|
21
34
|
make_configs
|
35
|
+
this_shell.config.setup
|
22
36
|
make_on_opts
|
23
37
|
make_commands
|
24
38
|
make_scripts
|
@@ -62,6 +76,22 @@ module Shelldon
|
|
62
76
|
|
63
77
|
alias_method :scripts, :script
|
64
78
|
|
79
|
+
def modules(mods)
|
80
|
+
mods = [mods] unless mods.is_a?(Array)
|
81
|
+
@modules += mods.map(&:to_sym)
|
82
|
+
end
|
83
|
+
|
84
|
+
def install_modules
|
85
|
+
@modules.each do |mod_name|
|
86
|
+
if Shelldon.modules.has_key?(mod_name)
|
87
|
+
Shelldon.modules[mod_name].install(@name)
|
88
|
+
else
|
89
|
+
raise Shelldon::NoSuchModuleError mod_name
|
90
|
+
end
|
91
|
+
|
92
|
+
end
|
93
|
+
end
|
94
|
+
|
65
95
|
def config(&block)
|
66
96
|
@new_configs << block
|
67
97
|
end
|
@@ -0,0 +1,16 @@
|
|
1
|
+
# This allows subshelling - You can define multiple shells in one program and nest them.
|
2
|
+
# This is the opposite approach to shell-as-singleton, which makes access easy but prevents multiple shells.
|
3
|
+
# This is why all of the factories pass the shell parent into their respective products.
|
4
|
+
|
5
|
+
module Shelldon
|
6
|
+
class ShellFactoryIndex < Index
|
7
|
+
def <<(shell_factory)
|
8
|
+
if shell_factory.is_a?(Shelldon::ShellFactory)
|
9
|
+
fail Shelldon::DuplicateIndexError if @index.key?(shell_factory.name)
|
10
|
+
@index[shell_factory.name] = shell_factory
|
11
|
+
else
|
12
|
+
fail Shelldon::NotAShellFactoryError
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
data/lib/shell/shell_index.rb
CHANGED
@@ -3,41 +3,15 @@
|
|
3
3
|
# This is why all of the factories pass the shell parent into their respective products.
|
4
4
|
|
5
5
|
module Shelldon
|
6
|
-
class ShellIndex
|
7
|
-
include Singleton
|
8
|
-
|
9
|
-
def self.method_missing(meth_name, *args, &block)
|
10
|
-
if block_given?
|
11
|
-
instance.send(meth_name, *args, &block)
|
12
|
-
else
|
13
|
-
instance.send(meth_name, *args)
|
14
|
-
end
|
15
|
-
end
|
16
|
-
|
17
|
-
def initialize
|
18
|
-
@shell_index = {}
|
19
|
-
end
|
20
|
-
|
21
|
-
def [](key)
|
22
|
-
@shell_index[key.to_sym]
|
23
|
-
end
|
24
|
-
|
25
|
-
def has_key?(key)
|
26
|
-
@shell_index.key?(key)
|
27
|
-
end
|
28
|
-
|
6
|
+
class ShellIndex < Index
|
29
7
|
def <<(shell)
|
30
8
|
if shell.is_a?(Shelldon::Shell)
|
31
|
-
|
32
|
-
@
|
9
|
+
fail Shelldon::DuplicateIndexError if @index.key?(shell.name)
|
10
|
+
@first = shell.name if @index.empty?
|
11
|
+
@index[shell.name] = shell
|
33
12
|
else
|
34
13
|
fail Shelldon::NotAShellError
|
35
14
|
end
|
36
15
|
end
|
37
|
-
|
38
|
-
def first?(sym)
|
39
|
-
sym = sym.to_sym unless sym.is_a?(Symbol)
|
40
|
-
sym == @first
|
41
|
-
end
|
42
16
|
end
|
43
17
|
end
|
data/lib/shelldon.rb
CHANGED
@@ -4,9 +4,14 @@ require 'readline'
|
|
4
4
|
require 'getopt/long'
|
5
5
|
require 'yaml'
|
6
6
|
require 'fuzzy_match'
|
7
|
+
require 'index'
|
7
8
|
require 'shell/shell_index'
|
9
|
+
require 'shell/shell_factory_index'
|
8
10
|
require 'dsl'
|
9
11
|
require 'shell/shell'
|
12
|
+
require 'module/module'
|
13
|
+
require 'module/module_factory'
|
14
|
+
require 'module/module_index'
|
10
15
|
require 'config/config'
|
11
16
|
require 'config/param'
|
12
17
|
require 'config/param/string_param'
|
data/lib/shelldon/version.rb
CHANGED
@@ -1,11 +1,30 @@
|
|
1
1
|
# This is a split-up version of the test_shell.rb
|
2
2
|
# It exists so you can screw around with when the different parts are required and ensure that
|
3
|
-
# the order doesn't matter.
|
3
|
+
# the order doesn't matter and multiple blocks of the same type all load in correctly.
|
4
4
|
|
5
5
|
require 'shelldon'
|
6
6
|
require_relative 'dependency_test'
|
7
7
|
require_relative 'dt_commands'
|
8
8
|
require_relative 'dt_opts'
|
9
9
|
require_relative 'dt_config'
|
10
|
+
require_relative 'test_module'
|
10
11
|
|
11
|
-
Shelldon
|
12
|
+
Shelldon.shell :test do
|
13
|
+
command :superderp do
|
14
|
+
action { puts 'beh' }
|
15
|
+
help 'test'
|
16
|
+
end
|
17
|
+
|
18
|
+
config do
|
19
|
+
param :value do
|
20
|
+
type :string
|
21
|
+
default 'This is the default value!'
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
shell do
|
26
|
+
prompt 'shelldon> '
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
Shelldon.run(:test)
|
data/test_shell/simple_shell.rb
CHANGED
@@ -0,0 +1,12 @@
|
|
1
|
+
require 'shelldon'
|
2
|
+
|
3
|
+
Shelldon.shell :example do
|
4
|
+
command :test do
|
5
|
+
help "Run a test command to show some text. Optionally, add an arg."
|
6
|
+
usage "test"
|
7
|
+
examples ['test', 'test blah']
|
8
|
+
action { |arg = ''| puts "This is a test! #{arg}" }
|
9
|
+
end
|
10
|
+
end
|
11
|
+
|
12
|
+
Shelldon.run(:example)
|
data/test_shell/test_shell.rb
CHANGED
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: shelldon
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.0.
|
4
|
+
version: 0.0.8
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Wesley Boynton
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2016-
|
11
|
+
date: 2016-09-24 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: getopt
|
@@ -91,6 +91,7 @@ extensions: []
|
|
91
91
|
extra_rdoc_files: []
|
92
92
|
files:
|
93
93
|
- ".gitignore"
|
94
|
+
- ".rbenv-gemsets"
|
94
95
|
- ".rubocop.yml"
|
95
96
|
- Gemfile
|
96
97
|
- LICENSE.txt
|
@@ -120,10 +121,15 @@ files:
|
|
120
121
|
- lib/file_management/yaml_manager.rb
|
121
122
|
- lib/helpers/confirmation.rb
|
122
123
|
- lib/helpers/timer.rb
|
124
|
+
- lib/index.rb
|
125
|
+
- lib/module/module.rb
|
126
|
+
- lib/module/module_factory.rb
|
127
|
+
- lib/module/module_index.rb
|
123
128
|
- lib/opts/opt_factory.rb
|
124
129
|
- lib/opts/opts.rb
|
125
130
|
- lib/shell/shell.rb
|
126
131
|
- lib/shell/shell_factory.rb
|
132
|
+
- lib/shell/shell_factory_index.rb
|
127
133
|
- lib/shell/shell_index.rb
|
128
134
|
- lib/shelldon.rb
|
129
135
|
- lib/shelldon/version.rb
|
@@ -137,8 +143,10 @@ files:
|
|
137
143
|
- test_shell/dependency_test/dt_config.rb
|
138
144
|
- test_shell/dependency_test/dt_opts.rb
|
139
145
|
- test_shell/dependency_test/dt_runner.rb
|
146
|
+
- test_shell/dependency_test/test_module.rb
|
140
147
|
- test_shell/run.sh
|
141
148
|
- test_shell/simple_shell.rb
|
149
|
+
- test_shell/simplest_shell.rb
|
142
150
|
- test_shell/test_shell.rb
|
143
151
|
- test_shell/useful_commands.rb
|
144
152
|
homepage: https://github.com/wwboynton/shelldon
|
@@ -162,7 +170,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
162
170
|
version: '0'
|
163
171
|
requirements: []
|
164
172
|
rubyforge_project:
|
165
|
-
rubygems_version: 2.4.5
|
173
|
+
rubygems_version: 2.4.5.1
|
166
174
|
signing_key:
|
167
175
|
specification_version: 4
|
168
176
|
summary: An expressive DSL for building interactive command-line apps
|