mister_bin 0.0.1
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.
- checksums.yaml +7 -0
- data/README.md +33 -0
- data/lib/mister_bin/command.rb +21 -0
- data/lib/mister_bin/commands.rb +52 -0
- data/lib/mister_bin/docopt_maker.rb +66 -0
- data/lib/mister_bin/runner.rb +66 -0
- data/lib/mister_bin/script.rb +62 -0
- data/lib/mister_bin/version.rb +3 -0
- data/lib/mister_bin.rb +8 -0
- metadata +205 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA256:
|
3
|
+
metadata.gz: f1363a49f614a04f932d61c6e52efbb9266a7c68605d3c232e95eb8b75fec9f7
|
4
|
+
data.tar.gz: dc34308fd4e779d20488e365895a4e3ef64c87290a20e1874fb1583687dcd8eb
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: d2e2f3a8fe7799258c4995c36f9bef36a92c69977ed46e36537e53a9b0db40f402aece3fad632e1acd0827f12be086603fe55785809eeeaf323e4fda5cc44e4e
|
7
|
+
data.tar.gz: 786af8b7fe27061c2232166ba49d656c3c7972039bd3303f81a7b63a0b242496820c1f8b0f37c8ad739e74d9e6828446090339c55d45a528dfbcf12f4c380ef2
|
data/README.md
ADDED
@@ -0,0 +1,33 @@
|
|
1
|
+
Mister Bin
|
2
|
+
==================================================
|
3
|
+
|
4
|
+
[](https://rubygems.org/gems/mister_bin)
|
5
|
+
[](https://travis-ci.org/DannyBen/mister_bin)
|
6
|
+
[](https://codeclimate.com/github/DannyBen/mister_bin)
|
7
|
+
|
8
|
+
---
|
9
|
+
|
10
|
+
Build modular command line utilities.
|
11
|
+
|
12
|
+
---
|
13
|
+
|
14
|
+
Installation
|
15
|
+
--------------------------------------------------
|
16
|
+
|
17
|
+
$ gem install mister_bin
|
18
|
+
|
19
|
+
|
20
|
+
|
21
|
+
Design Goals
|
22
|
+
--------------------------------------------------
|
23
|
+
|
24
|
+
- Provide an easy and minimalistic DSL for building command line utilities.
|
25
|
+
- Provide a mechanism for separating each subcommand to its separate file.
|
26
|
+
- Support the ability to extend a given command from different sources.
|
27
|
+
|
28
|
+
|
29
|
+
|
30
|
+
Usage
|
31
|
+
--------------------------------------------------
|
32
|
+
|
33
|
+
Soon
|
@@ -0,0 +1,21 @@
|
|
1
|
+
module MisterBin
|
2
|
+
class Command
|
3
|
+
attr_reader :command, :file, :type
|
4
|
+
|
5
|
+
def initialize(command, file)
|
6
|
+
@command = command
|
7
|
+
@file = file
|
8
|
+
@type = command =~ / / ? :secondary : :primary
|
9
|
+
end
|
10
|
+
|
11
|
+
def run(argv=[])
|
12
|
+
script = Script.new file
|
13
|
+
script.build_docopt
|
14
|
+
script.execute argv
|
15
|
+
end
|
16
|
+
|
17
|
+
def argv
|
18
|
+
command.split ' '
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
@@ -0,0 +1,52 @@
|
|
1
|
+
module MisterBin
|
2
|
+
|
3
|
+
# This class handles listing and finding command files
|
4
|
+
class Commands
|
5
|
+
attr_reader :basename, :basedir
|
6
|
+
|
7
|
+
def initialize(basename, basedir='.')
|
8
|
+
@basename = basename
|
9
|
+
@basedir = basedir
|
10
|
+
end
|
11
|
+
|
12
|
+
def all
|
13
|
+
@all ||= all!
|
14
|
+
end
|
15
|
+
|
16
|
+
def names
|
17
|
+
all.keys
|
18
|
+
end
|
19
|
+
|
20
|
+
def find(query)
|
21
|
+
query = [query] unless query.is_a? Array
|
22
|
+
query_regex = /^#{query.join '.* '}/
|
23
|
+
keys = names.select { |k| k =~ /^#{query_regex}/ }
|
24
|
+
keys = names.select { |k| k =~ /^#{query.first}/ } if keys.empty?
|
25
|
+
keys.map { |k| [k, all[k]] }.to_h
|
26
|
+
end
|
27
|
+
|
28
|
+
def find_one(query)
|
29
|
+
result = find query
|
30
|
+
result.size == 1 ? result.values.first : false
|
31
|
+
end
|
32
|
+
|
33
|
+
private
|
34
|
+
|
35
|
+
def all!
|
36
|
+
result = {}
|
37
|
+
files.map do |file|
|
38
|
+
if file =~ /#{basename}-(.+)-(.+)\.rb/
|
39
|
+
command = "#{$1} #{$2}"
|
40
|
+
elsif file =~ /#{basename}-(.+)\.rb/
|
41
|
+
command = $1
|
42
|
+
end
|
43
|
+
result[command] = Command.new command, file
|
44
|
+
end
|
45
|
+
result
|
46
|
+
end
|
47
|
+
|
48
|
+
def files
|
49
|
+
@files ||= Dir["#{basedir}/#{basename}-*.rb"]
|
50
|
+
end
|
51
|
+
end
|
52
|
+
end
|
@@ -0,0 +1,66 @@
|
|
1
|
+
require 'singleton'
|
2
|
+
require 'colsole'
|
3
|
+
|
4
|
+
module MisterBin
|
5
|
+
|
6
|
+
# This singleton class is responsible for generating a text string ready to be used
|
7
|
+
# by Docopt.
|
8
|
+
class DocoptMaker
|
9
|
+
include Singleton
|
10
|
+
include Colsole
|
11
|
+
|
12
|
+
attr_reader :usages, :options, :examples
|
13
|
+
attr_accessor :help, :version
|
14
|
+
|
15
|
+
def initialize
|
16
|
+
reset
|
17
|
+
end
|
18
|
+
|
19
|
+
def reset
|
20
|
+
@usages = []
|
21
|
+
@options = []
|
22
|
+
@examples = []
|
23
|
+
@version = '0.0.0'
|
24
|
+
@help = nil
|
25
|
+
end
|
26
|
+
|
27
|
+
def docopt
|
28
|
+
[help_string, usage_string, options_string, examples_string].join "\n"
|
29
|
+
end
|
30
|
+
|
31
|
+
private
|
32
|
+
|
33
|
+
def help_string
|
34
|
+
word_wrap help
|
35
|
+
end
|
36
|
+
|
37
|
+
def usage_string
|
38
|
+
result = ["", "Usage:"]
|
39
|
+
usages.each { |text| result << word_wrap(" #{text}") }
|
40
|
+
result.join "\n"
|
41
|
+
end
|
42
|
+
|
43
|
+
def options_string
|
44
|
+
result = ["", "Options:"]
|
45
|
+
options.each do |option|
|
46
|
+
result << " #{option[0]}"
|
47
|
+
result << word_wrap(" #{option[1]}")
|
48
|
+
result << ""
|
49
|
+
end
|
50
|
+
|
51
|
+
result << " -h --help"
|
52
|
+
result << " Show this help\n"
|
53
|
+
result << " --version"
|
54
|
+
result << " Show version number"
|
55
|
+
result.join "\n"
|
56
|
+
end
|
57
|
+
|
58
|
+
def examples_string
|
59
|
+
return '' if examples.empty?
|
60
|
+
|
61
|
+
result = ["", "Examples:"]
|
62
|
+
examples.each { |text| result << word_wrap(" #{text}") }
|
63
|
+
result.join "\n"
|
64
|
+
end
|
65
|
+
end
|
66
|
+
end
|
@@ -0,0 +1,66 @@
|
|
1
|
+
module MisterBin
|
2
|
+
class Runner
|
3
|
+
attr_reader :basefile, :basedir, :name
|
4
|
+
|
5
|
+
def self.run(basefile, argv=[])
|
6
|
+
new(basefile).run argv
|
7
|
+
end
|
8
|
+
|
9
|
+
def initialize(basefile)
|
10
|
+
@basefile = basefile
|
11
|
+
@basedir = File.dirname basefile
|
12
|
+
@name = File.basename basefile
|
13
|
+
end
|
14
|
+
|
15
|
+
def run(argv=[])
|
16
|
+
if argv.empty?
|
17
|
+
show_subs
|
18
|
+
else
|
19
|
+
execute argv
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
private
|
24
|
+
|
25
|
+
def execute(argv)
|
26
|
+
argv = expand_argv argv
|
27
|
+
command = commands.find_one argv[0..1]
|
28
|
+
|
29
|
+
if command
|
30
|
+
execute_command command, argv
|
31
|
+
else
|
32
|
+
puts "Unknown command: #{argv[0]}"
|
33
|
+
return 1
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
def execute_command(command, argv)
|
38
|
+
command.run argv
|
39
|
+
end
|
40
|
+
|
41
|
+
def show_subs
|
42
|
+
if commands.all.empty?
|
43
|
+
puts "No subcommands found"
|
44
|
+
else
|
45
|
+
puts "Usage:"
|
46
|
+
commands.names.each { |command| puts " #{name} #{command}" }
|
47
|
+
end
|
48
|
+
|
49
|
+
return 1
|
50
|
+
end
|
51
|
+
|
52
|
+
def commands
|
53
|
+
@commands ||= Commands.new name, basedir
|
54
|
+
end
|
55
|
+
|
56
|
+
def expand_argv(argv)
|
57
|
+
command = commands.find_one argv[0..1]
|
58
|
+
if command
|
59
|
+
argv.shift command.argv.size
|
60
|
+
command.argv + argv
|
61
|
+
else
|
62
|
+
argv
|
63
|
+
end
|
64
|
+
end
|
65
|
+
end
|
66
|
+
end
|
@@ -0,0 +1,62 @@
|
|
1
|
+
require 'docopt'
|
2
|
+
|
3
|
+
module MisterBin
|
4
|
+
class Script
|
5
|
+
attr_reader :file, :action_block
|
6
|
+
|
7
|
+
def initialize(file)
|
8
|
+
@file = file
|
9
|
+
end
|
10
|
+
|
11
|
+
def build_docopt
|
12
|
+
DocoptMaker.instance.reset
|
13
|
+
instance_eval script
|
14
|
+
docopt
|
15
|
+
end
|
16
|
+
|
17
|
+
def execute(argv=[])
|
18
|
+
args = Docopt.docopt docopt, version: DocoptMaker.instance.version, argv: argv
|
19
|
+
exitcode = action_block.call args if action_block
|
20
|
+
exitcode.is_a?(Numeric) ? exitcode : 0
|
21
|
+
rescue Docopt::Exit => e
|
22
|
+
puts e.message
|
23
|
+
1
|
24
|
+
end
|
25
|
+
|
26
|
+
def docopt
|
27
|
+
DocoptMaker.instance.docopt
|
28
|
+
end
|
29
|
+
|
30
|
+
# DSL
|
31
|
+
|
32
|
+
def help(text)
|
33
|
+
DocoptMaker.instance.help = text
|
34
|
+
end
|
35
|
+
|
36
|
+
def usage(text)
|
37
|
+
DocoptMaker.instance.usages << text
|
38
|
+
end
|
39
|
+
|
40
|
+
def option(flags, text)
|
41
|
+
DocoptMaker.instance.options << [flags, text]
|
42
|
+
end
|
43
|
+
|
44
|
+
def example(text)
|
45
|
+
DocoptMaker.instance.examples << text
|
46
|
+
end
|
47
|
+
|
48
|
+
def version(text)
|
49
|
+
DocoptMaker.instance.version = text
|
50
|
+
end
|
51
|
+
|
52
|
+
def action(&block)
|
53
|
+
@action_block = block
|
54
|
+
end
|
55
|
+
|
56
|
+
private
|
57
|
+
|
58
|
+
def script
|
59
|
+
@script ||= File.read file
|
60
|
+
end
|
61
|
+
end
|
62
|
+
end
|
data/lib/mister_bin.rb
ADDED
metadata
ADDED
@@ -0,0 +1,205 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: mister_bin
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.0.1
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Danny Ben Shitrit
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
date: 2018-04-14 00:00:00.000000000 Z
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: colsole
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - "~>"
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: '0.5'
|
20
|
+
type: :runtime
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - "~>"
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: '0.5'
|
27
|
+
- !ruby/object:Gem::Dependency
|
28
|
+
name: docopt
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - "~>"
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: '0.6'
|
34
|
+
type: :runtime
|
35
|
+
prerelease: false
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
37
|
+
requirements:
|
38
|
+
- - "~>"
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
version: '0.6'
|
41
|
+
- !ruby/object:Gem::Dependency
|
42
|
+
name: byebug
|
43
|
+
requirement: !ruby/object:Gem::Requirement
|
44
|
+
requirements:
|
45
|
+
- - "~>"
|
46
|
+
- !ruby/object:Gem::Version
|
47
|
+
version: '9.0'
|
48
|
+
type: :development
|
49
|
+
prerelease: false
|
50
|
+
version_requirements: !ruby/object:Gem::Requirement
|
51
|
+
requirements:
|
52
|
+
- - "~>"
|
53
|
+
- !ruby/object:Gem::Version
|
54
|
+
version: '9.0'
|
55
|
+
- !ruby/object:Gem::Dependency
|
56
|
+
name: rdoc
|
57
|
+
requirement: !ruby/object:Gem::Requirement
|
58
|
+
requirements:
|
59
|
+
- - "~>"
|
60
|
+
- !ruby/object:Gem::Version
|
61
|
+
version: '5.1'
|
62
|
+
type: :development
|
63
|
+
prerelease: false
|
64
|
+
version_requirements: !ruby/object:Gem::Requirement
|
65
|
+
requirements:
|
66
|
+
- - "~>"
|
67
|
+
- !ruby/object:Gem::Version
|
68
|
+
version: '5.1'
|
69
|
+
- !ruby/object:Gem::Dependency
|
70
|
+
name: rspec
|
71
|
+
requirement: !ruby/object:Gem::Requirement
|
72
|
+
requirements:
|
73
|
+
- - "~>"
|
74
|
+
- !ruby/object:Gem::Version
|
75
|
+
version: '3.6'
|
76
|
+
type: :development
|
77
|
+
prerelease: false
|
78
|
+
version_requirements: !ruby/object:Gem::Requirement
|
79
|
+
requirements:
|
80
|
+
- - "~>"
|
81
|
+
- !ruby/object:Gem::Version
|
82
|
+
version: '3.6'
|
83
|
+
- !ruby/object:Gem::Dependency
|
84
|
+
name: rspec_fixtures
|
85
|
+
requirement: !ruby/object:Gem::Requirement
|
86
|
+
requirements:
|
87
|
+
- - "~>"
|
88
|
+
- !ruby/object:Gem::Version
|
89
|
+
version: '0.3'
|
90
|
+
type: :development
|
91
|
+
prerelease: false
|
92
|
+
version_requirements: !ruby/object:Gem::Requirement
|
93
|
+
requirements:
|
94
|
+
- - "~>"
|
95
|
+
- !ruby/object:Gem::Version
|
96
|
+
version: '0.3'
|
97
|
+
- !ruby/object:Gem::Dependency
|
98
|
+
name: runfile
|
99
|
+
requirement: !ruby/object:Gem::Requirement
|
100
|
+
requirements:
|
101
|
+
- - "~>"
|
102
|
+
- !ruby/object:Gem::Version
|
103
|
+
version: '0.10'
|
104
|
+
type: :development
|
105
|
+
prerelease: false
|
106
|
+
version_requirements: !ruby/object:Gem::Requirement
|
107
|
+
requirements:
|
108
|
+
- - "~>"
|
109
|
+
- !ruby/object:Gem::Version
|
110
|
+
version: '0.10'
|
111
|
+
- !ruby/object:Gem::Dependency
|
112
|
+
name: runfile-tasks
|
113
|
+
requirement: !ruby/object:Gem::Requirement
|
114
|
+
requirements:
|
115
|
+
- - "~>"
|
116
|
+
- !ruby/object:Gem::Version
|
117
|
+
version: '0.4'
|
118
|
+
type: :development
|
119
|
+
prerelease: false
|
120
|
+
version_requirements: !ruby/object:Gem::Requirement
|
121
|
+
requirements:
|
122
|
+
- - "~>"
|
123
|
+
- !ruby/object:Gem::Version
|
124
|
+
version: '0.4'
|
125
|
+
- !ruby/object:Gem::Dependency
|
126
|
+
name: simplecov
|
127
|
+
requirement: !ruby/object:Gem::Requirement
|
128
|
+
requirements:
|
129
|
+
- - "~>"
|
130
|
+
- !ruby/object:Gem::Version
|
131
|
+
version: '0.15'
|
132
|
+
type: :development
|
133
|
+
prerelease: false
|
134
|
+
version_requirements: !ruby/object:Gem::Requirement
|
135
|
+
requirements:
|
136
|
+
- - "~>"
|
137
|
+
- !ruby/object:Gem::Version
|
138
|
+
version: '0.15'
|
139
|
+
- !ruby/object:Gem::Dependency
|
140
|
+
name: yard
|
141
|
+
requirement: !ruby/object:Gem::Requirement
|
142
|
+
requirements:
|
143
|
+
- - "~>"
|
144
|
+
- !ruby/object:Gem::Version
|
145
|
+
version: '0.9'
|
146
|
+
type: :development
|
147
|
+
prerelease: false
|
148
|
+
version_requirements: !ruby/object:Gem::Requirement
|
149
|
+
requirements:
|
150
|
+
- - "~>"
|
151
|
+
- !ruby/object:Gem::Version
|
152
|
+
version: '0.9'
|
153
|
+
- !ruby/object:Gem::Dependency
|
154
|
+
name: github_changelog_generator
|
155
|
+
requirement: !ruby/object:Gem::Requirement
|
156
|
+
requirements:
|
157
|
+
- - "~>"
|
158
|
+
- !ruby/object:Gem::Version
|
159
|
+
version: '1.14'
|
160
|
+
type: :development
|
161
|
+
prerelease: false
|
162
|
+
version_requirements: !ruby/object:Gem::Requirement
|
163
|
+
requirements:
|
164
|
+
- - "~>"
|
165
|
+
- !ruby/object:Gem::Version
|
166
|
+
version: '1.14'
|
167
|
+
description: Build pluggable and modular command line tools with subcommands
|
168
|
+
email: db@dannyben.com
|
169
|
+
executables: []
|
170
|
+
extensions: []
|
171
|
+
extra_rdoc_files: []
|
172
|
+
files:
|
173
|
+
- README.md
|
174
|
+
- lib/mister_bin.rb
|
175
|
+
- lib/mister_bin/command.rb
|
176
|
+
- lib/mister_bin/commands.rb
|
177
|
+
- lib/mister_bin/docopt_maker.rb
|
178
|
+
- lib/mister_bin/runner.rb
|
179
|
+
- lib/mister_bin/script.rb
|
180
|
+
- lib/mister_bin/version.rb
|
181
|
+
homepage: https://github.com/dannyben/mister_bin
|
182
|
+
licenses:
|
183
|
+
- MIT
|
184
|
+
metadata: {}
|
185
|
+
post_install_message:
|
186
|
+
rdoc_options: []
|
187
|
+
require_paths:
|
188
|
+
- lib
|
189
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
190
|
+
requirements:
|
191
|
+
- - ">="
|
192
|
+
- !ruby/object:Gem::Version
|
193
|
+
version: 2.4.0
|
194
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
195
|
+
requirements:
|
196
|
+
- - ">="
|
197
|
+
- !ruby/object:Gem::Version
|
198
|
+
version: '0'
|
199
|
+
requirements: []
|
200
|
+
rubyforge_project:
|
201
|
+
rubygems_version: 2.7.6
|
202
|
+
signing_key:
|
203
|
+
specification_version: 4
|
204
|
+
summary: Modular command line framefowk
|
205
|
+
test_files: []
|