cl 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.
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 2f86887c16aed295c0207a4c5005decf8fd1cc05
4
+ data.tar.gz: 12260c6e0abc90a6b2df31fd3ce1797189953539
5
+ SHA512:
6
+ metadata.gz: b4277518e42daa3e8f19bf612ffdae68c6244e28a043915e1842fdc28b200493e5fbe41f821b2040443f861e7e8cafae0d705b08d592b7cfd2dcc51cc719a73e
7
+ data.tar.gz: 54a224126510e271f4847ffc6a089cb130af5ac00e0c50c8d001e1d183f8c5d2ebd8c3dd48b56742764503c7379ef4bf06333994d195b4f82496c81d956e475e
data/Gemfile ADDED
@@ -0,0 +1,3 @@
1
+ group :test do
2
+ gem 'rspec'
3
+ end
@@ -0,0 +1,25 @@
1
+ GEM
2
+ specs:
3
+ diff-lcs (1.3)
4
+ rspec (3.5.0)
5
+ rspec-core (~> 3.5.0)
6
+ rspec-expectations (~> 3.5.0)
7
+ rspec-mocks (~> 3.5.0)
8
+ rspec-core (3.5.4)
9
+ rspec-support (~> 3.5.0)
10
+ rspec-expectations (3.5.0)
11
+ diff-lcs (>= 1.2.0, < 2.0)
12
+ rspec-support (~> 3.5.0)
13
+ rspec-mocks (3.5.0)
14
+ diff-lcs (>= 1.2.0, < 2.0)
15
+ rspec-support (~> 3.5.0)
16
+ rspec-support (3.5.0)
17
+
18
+ PLATFORMS
19
+ ruby
20
+
21
+ DEPENDENCIES
22
+ rspec
23
+
24
+ BUNDLED WITH
25
+ 1.14.5
@@ -0,0 +1,21 @@
1
+ # MIT LICENSE
2
+
3
+ Copyright (c) 2017 Sven Fuchs <me@svenfuchs.com>
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in
13
+ all copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
21
+ THE SOFTWARE.
@@ -0,0 +1,23 @@
1
+ # CLI
2
+
3
+ This library wraps Ruby's `OptionParser` in order to make it easier to use it in an object oriented context.
4
+
5
+ ## Usage
6
+
7
+ ```
8
+ module Owners
9
+ class Add < Struct.new(:args, :opts)
10
+ include Cli::Cmd
11
+
12
+ register 'owners:add'
13
+
14
+ purpose 'Add one or more owners to an existing owner group'
15
+
16
+ args :owners
17
+
18
+ on '-t', '--to TO', 'An owner in an existing group' do |value|
19
+ opts[:to] = value
20
+ end
21
+ end
22
+ end
23
+ ```
@@ -0,0 +1,19 @@
1
+ require 'cli/cmd'
2
+ require 'cli/help'
3
+ require 'cli/runner'
4
+
5
+ module Cli
6
+ def included(const)
7
+ const.send(:include, Cmd)
8
+ end
9
+
10
+ def run(*args)
11
+ Runner.new(*args).run
12
+ end
13
+
14
+ def help
15
+ Runner.new(:help).run
16
+ end
17
+
18
+ extend self
19
+ end
@@ -0,0 +1,28 @@
1
+ require 'cli/registry'
2
+
3
+ module Cli
4
+ module Cmd
5
+ def self.included(const)
6
+ const.send :include, Registry
7
+ const.send :extend, ClassMethods
8
+ end
9
+
10
+ module ClassMethods
11
+ def args(*args)
12
+ args.any? ? @args = args : @args ||= []
13
+ end
14
+
15
+ def purpose(purpose = nil)
16
+ purpose ? @purpose = purpose : @purpose
17
+ end
18
+
19
+ def on(*args, &block)
20
+ opts << [args, block]
21
+ end
22
+
23
+ def opts
24
+ @opts ||= superclass.respond_to?(:opts) ? superclass.opts : []
25
+ end
26
+ end
27
+ end
28
+ end
@@ -0,0 +1,28 @@
1
+ require 'cli/options'
2
+
3
+ module Cli
4
+ class Cmds < Struct.new(:args)
5
+ def lookup
6
+ cmd || abort("Unknown command: #{args.join(' ')}")
7
+ opts = Options.new(cmd.opts, args).opts
8
+ [cmd, args - cmds, opts]
9
+ end
10
+
11
+ private
12
+
13
+ def cmds
14
+ name = cmd.registry_key.to_s
15
+ args.take_while do |arg|
16
+ name = name.sub(/#{arg}(:|$)/, '') if name =~ /#{arg}(:|$)/
17
+ end
18
+ end
19
+
20
+ def cmd
21
+ @cmd ||= keys.map { |key| Cli[key] }.compact.last
22
+ end
23
+
24
+ def keys
25
+ @keys ||= args.inject([]) { |keys, key| keys << [keys.last, key].compact.join(':') }
26
+ end
27
+ end
28
+ end
@@ -0,0 +1,31 @@
1
+ require 'cli/format/table'
2
+ require 'cli/format/usage'
3
+
4
+ module Cli
5
+ class Format
6
+ class Cmd < Struct.new(:cmd)
7
+ def format
8
+ [banner, Table.new(opts).format].join("\n")
9
+ end
10
+
11
+ def banner
12
+ banner = []
13
+ banner << "#{cmd.purpose}\n" if cmd.purpose
14
+ banner << "Usage: #{Usage.new(cmd).format}\n"
15
+ banner
16
+ end
17
+
18
+ def opts
19
+ cmd.opts.map do |opts, block|
20
+ comment = opts.detect { |opt| !opt?(opt) }
21
+ opts = opts.select { |opt| opt?(opt) }
22
+ [opts.sort_by(&:size).join(' '), comment]
23
+ end
24
+ end
25
+
26
+ def opt?(str)
27
+ str.start_with?('-')
28
+ end
29
+ end
30
+ end
31
+ end
@@ -0,0 +1,22 @@
1
+ require 'cli/format/table'
2
+ require 'cli/format/usage'
3
+
4
+ module Cli
5
+ class Format
6
+ class List < Struct.new(:cmds)
7
+ HEAD = %(Type "#{$0} help COMMAND [SUBCOMMAND]" for more details:\n)
8
+
9
+ def format
10
+ [HEAD, Format::Table.new(list).format].join("\n")
11
+ end
12
+
13
+ def list
14
+ cmds.map { |cmd| format_cmd(cmd) }
15
+ end
16
+
17
+ def format_cmd(cmd)
18
+ ["#{$0} #{Usage.new(cmd).format}", cmd.purpose]
19
+ end
20
+ end
21
+ end
22
+ end
@@ -0,0 +1,19 @@
1
+ module Cli
2
+ class Format
3
+ class Table < Struct.new(:data, :separator)
4
+ def format
5
+ rows.join("\n")
6
+ end
7
+
8
+ def rows
9
+ rows = data.map { |lft, rgt| [lft.ljust(width), rgt] }
10
+ rows = rows.map { |lft, rgt| "#{lft} #{"# #{rgt}" if rgt}".strip }
11
+ rows.map(&:strip)
12
+ end
13
+
14
+ def width
15
+ @width ||= data.map(&:first).max_by(&:size).size
16
+ end
17
+ end
18
+ end
19
+ end
@@ -0,0 +1,20 @@
1
+ module Cli
2
+ class Format
3
+ class Usage < Struct.new(:cmd)
4
+ def format
5
+ usage = [name]
6
+ usage += cmd.args.map { |arg| "[#{arg}]" }
7
+ usage << '[options]' if opts?
8
+ usage.join(' ')
9
+ end
10
+
11
+ def name
12
+ cmd.registry_key.to_s.gsub(':', ' ')
13
+ end
14
+
15
+ def opts?
16
+ cmd.opts.any?
17
+ end
18
+ end
19
+ end
20
+ end
@@ -0,0 +1,31 @@
1
+ require 'cli/format/cmd'
2
+ require 'cli/format/list'
3
+
4
+ module Cli
5
+ class Help < Struct.new(:args, :opts)
6
+ include Cli::Cmd
7
+
8
+ register :help
9
+
10
+ def run
11
+ puts help
12
+ end
13
+
14
+ def help
15
+ cmd ? Format::Cmd.new(cmd).format : Format::List.new(cmds).format
16
+ end
17
+
18
+ private
19
+
20
+ def cmds
21
+ cmds = Cli.cmds.reject { |cmd| cmd.registry_key == :help }
22
+ key = args.join(':') if args
23
+ cmds = cmds.select { |cmd| cmd.registry_key.to_s.start_with?(key) } if key
24
+ cmds
25
+ end
26
+
27
+ def cmd
28
+ args && Cli[args.join(':')]
29
+ end
30
+ end
31
+ end
@@ -0,0 +1,11 @@
1
+ module Cli
2
+ class Options < OptionParser
3
+ attr_reader :opts
4
+
5
+ def initialize(opts, args)
6
+ @opts = {}
7
+ super { opts.each { |args, block| on(*args) { |*args| instance_exec(*args, &block) } } }
8
+ parse!(args)
9
+ end
10
+ end
11
+ end
@@ -0,0 +1,53 @@
1
+ module Cli
2
+ class << self
3
+ def []=(key, object)
4
+ registry[key.to_sym] = object
5
+ end
6
+
7
+ def [](key)
8
+ key && registry[key.to_sym]
9
+ end
10
+
11
+ def cmds
12
+ registry.values
13
+ end
14
+
15
+ def registry
16
+ @registry ||= {}
17
+ end
18
+ end
19
+
20
+ module Registry
21
+ class << self
22
+ def included(const)
23
+ const.send(:extend, ClassMethods)
24
+ const.send(:include, InstanceMethods)
25
+ end
26
+ end
27
+
28
+ module ClassMethods
29
+ attr_reader :registry_key
30
+
31
+ def [](key)
32
+ Cli[key.to_sym]
33
+ end
34
+
35
+ def register(key)
36
+ Cli[key] = self
37
+ @registry_key = key.to_sym
38
+ end
39
+
40
+ def underscore(string)
41
+ string.gsub(/([A-Z]+)([A-Z][a-z])/,'\1_\2').
42
+ gsub(/([a-z\d])([A-Z])/,'\1_\2').
43
+ downcase
44
+ end
45
+ end
46
+
47
+ module InstanceMethods
48
+ def registry_key
49
+ self.class.registry_key
50
+ end
51
+ end
52
+ end
53
+ end
@@ -0,0 +1,20 @@
1
+ require 'cli/cmds'
2
+
3
+ module Cli
4
+ class Runner
5
+ attr_reader :const, :args, :opts
6
+
7
+ def initialize(*args)
8
+ args = args.flatten.map(&:to_s)
9
+ @const, @args, @opts = Cmds.new(args).lookup
10
+ end
11
+
12
+ def run
13
+ cmd.run
14
+ end
15
+
16
+ def cmd
17
+ const.new(args, opts)
18
+ end
19
+ end
20
+ end
@@ -0,0 +1,3 @@
1
+ module Cli
2
+ VERSION = '0.0.1'
3
+ end
metadata ADDED
@@ -0,0 +1,59 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: cl
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.1
5
+ platform: ruby
6
+ authors:
7
+ - Sven Fuchs
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2017-04-09 00:00:00.000000000 Z
12
+ dependencies: []
13
+ description: OptionParser based CLI support.
14
+ email: me@svenfuchs.com
15
+ executables: []
16
+ extensions: []
17
+ extra_rdoc_files: []
18
+ files:
19
+ - Gemfile
20
+ - Gemfile.lock
21
+ - MIT_LICENSE.md
22
+ - README.md
23
+ - lib/cli.rb
24
+ - lib/cli/cmd.rb
25
+ - lib/cli/cmds.rb
26
+ - lib/cli/format/cmd.rb
27
+ - lib/cli/format/list.rb
28
+ - lib/cli/format/table.rb
29
+ - lib/cli/format/usage.rb
30
+ - lib/cli/help.rb
31
+ - lib/cli/options.rb
32
+ - lib/cli/registry.rb
33
+ - lib/cli/runner.rb
34
+ - lib/cli/version.rb
35
+ homepage: https://github.com/svenfuchs/cl
36
+ licenses:
37
+ - MIT
38
+ metadata: {}
39
+ post_install_message:
40
+ rdoc_options: []
41
+ require_paths:
42
+ - lib
43
+ required_ruby_version: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - ">="
46
+ - !ruby/object:Gem::Version
47
+ version: '0'
48
+ required_rubygems_version: !ruby/object:Gem::Requirement
49
+ requirements:
50
+ - - ">="
51
+ - !ruby/object:Gem::Version
52
+ version: '0'
53
+ requirements: []
54
+ rubyforge_project:
55
+ rubygems_version: 2.6.8
56
+ signing_key:
57
+ specification_version: 4
58
+ summary: OptionParser based CLI support
59
+ test_files: []