dry-cli 0.5.1 → 0.6.0
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 +4 -4
- data/CHANGELOG.md +27 -1
- data/dry-cli.gemspec +3 -1
- data/lib/dry/cli.rb +72 -31
- data/lib/dry/cli/banner.rb +4 -4
- data/lib/dry/cli/command_registry.rb +1 -2
- data/lib/dry/cli/inline.rb +75 -0
- data/lib/dry/cli/usage.rb +5 -5
- data/lib/dry/cli/utils/files.rb +1 -0
- data/lib/dry/cli/version.rb +1 -1
- metadata +4 -3
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 448f01b536f8cc664a86d2b4e558e8db6062c6ac31256c32d507828f1d3b7519
|
4
|
+
data.tar.gz: 254448f2e0b031cfc0077021ca3d0876b81b5eb9c7b1a7e51afce0d9524c95cc
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: b114fa6217a59fdca38df56819e016a47337843ad357a52cd0f006bac2048dc2ee9253439a0353721412edac8e3a4d1f3c9601e7b3ccb729c86f5899d53fc2d6
|
7
|
+
data.tar.gz: 1edf50dce27e4d1cc9e9cc868c14d18e9399e62b0edcebf5a3166559bc8ef66a7fa79a04d0ac0c2ef5c6ffa1384aecb80ca967c16136f9dceb3721123e9c53a4
|
data/CHANGELOG.md
CHANGED
@@ -1,9 +1,35 @@
|
|
1
|
+
## 0.6.0 2020-03-06
|
2
|
+
|
3
|
+
|
4
|
+
### Added
|
5
|
+
|
6
|
+
- [Ivan Shamatov] Ability to pass command along with registry (for a singular command case)
|
7
|
+
- [Nikita Shilnikov] [Internal] Backported ability to run gem's CI against ruby 2.3
|
8
|
+
- [Ivan Shamatov] Inline syntax for commands
|
9
|
+
- [Ivan Shamatov] Introduced stderr to any diagnostic output
|
10
|
+
|
11
|
+
### Fixed
|
12
|
+
|
13
|
+
- [John Ledbetter & Luca Guidi] Fix ruby 2.7 warnings
|
14
|
+
- [Ivan Shamatov] Fix banner, when option is a type of Array
|
15
|
+
|
16
|
+
|
17
|
+
[Compare v0.5.1...v0.6.0](https://github.com/dry-rb/dry-cli/compare/v0.5.1...v0.6.0)
|
18
|
+
|
1
19
|
## 0.5.1 2020-01-23
|
2
20
|
|
3
21
|
|
22
|
+
### Added
|
23
|
+
|
24
|
+
- [Ivan Shamatov] Anonymous Registry sintax
|
25
|
+
- [Ivan Shamatov] [Internal] Specs refactored, more unit specs added
|
26
|
+
- [Luca Guidi] [Internal] removed `dry-inflector` as runtime dependency
|
27
|
+
- [Ivan Shamatov] [Internal] Refactored Command class (command_name property removed)
|
28
|
+
- [Piotr Solnica, Luca Guidi, Nikita Shilnikov & Christian Georgii] [Internal] Adapt gem to dry-rb style
|
29
|
+
|
4
30
|
### Fixed
|
5
31
|
|
6
|
-
- Added missing 'set' require
|
32
|
+
- [Piotr Solnica] Added missing 'set' require
|
7
33
|
|
8
34
|
|
9
35
|
[Compare v0.5.0...v0.5.1](https://github.com/dry-rb/dry-cli/compare/v0.5.0...v0.5.1)
|
data/dry-cli.gemspec
CHANGED
@@ -16,6 +16,8 @@ Gem::Specification.new do |spec|
|
|
16
16
|
spec.description = spec.summary
|
17
17
|
spec.homepage = 'https://dry-rb.org/gems/dry-cli'
|
18
18
|
spec.files = Dir["CHANGELOG.md", "LICENSE", "README.md", "dry-cli.gemspec", "lib/**/*"]
|
19
|
+
spec.bindir = 'bin'
|
20
|
+
spec.executables = []
|
19
21
|
spec.require_paths = ['lib']
|
20
22
|
|
21
23
|
spec.metadata['allowed_push_host'] = 'https://rubygems.org'
|
@@ -23,7 +25,7 @@ Gem::Specification.new do |spec|
|
|
23
25
|
spec.metadata['source_code_uri'] = 'https://github.com/dry-rb/dry-cli'
|
24
26
|
spec.metadata['bug_tracker_uri'] = 'https://github.com/dry-rb/dry-cli/issues'
|
25
27
|
|
26
|
-
spec.required_ruby_version =
|
28
|
+
spec.required_ruby_version = ">= 2.3.0"
|
27
29
|
|
28
30
|
# to update dependencies edit project.yml
|
29
31
|
spec.add_runtime_dependency "concurrent-ruby", "~> 1.0"
|
data/lib/dry/cli.rb
CHANGED
@@ -36,16 +36,20 @@ module Dry
|
|
36
36
|
|
37
37
|
# Create a new instance
|
38
38
|
#
|
39
|
-
# @param
|
39
|
+
# @param command_or_registry [Dry::CLI::Registry, Dry::CLI::Command]
|
40
|
+
# a registry or singular command
|
41
|
+
# @param &block [Block] a configuration block for registry
|
40
42
|
#
|
41
43
|
# @return [Dry::CLI] the new instance
|
42
|
-
# @since 0.
|
43
|
-
def initialize(
|
44
|
-
@
|
44
|
+
# @since 0.1.0
|
45
|
+
def initialize(command_or_registry = nil, &block)
|
46
|
+
@kommand = command_or_registry if command?(command_or_registry)
|
47
|
+
|
48
|
+
@registry =
|
45
49
|
if block_given?
|
46
50
|
anonymous_registry(&block)
|
47
51
|
else
|
48
|
-
|
52
|
+
command_or_registry
|
49
53
|
end
|
50
54
|
end
|
51
55
|
|
@@ -53,28 +57,67 @@ module Dry
|
|
53
57
|
#
|
54
58
|
# @param arguments [Array<string>] the command line arguments (defaults to `ARGV`)
|
55
59
|
# @param out [IO] the standard output (defaults to `$stdout`)
|
60
|
+
# @param err [IO] the error output (defaults to `$stderr`)
|
56
61
|
#
|
57
62
|
# @since 0.1.0
|
58
|
-
def call(arguments: ARGV, out: $stdout)
|
59
|
-
|
63
|
+
def call(arguments: ARGV, out: $stdout, err: $stderr)
|
64
|
+
@out, @err = out, err
|
65
|
+
return perform_command(arguments) if kommand
|
66
|
+
|
67
|
+
perform_registry(arguments)
|
68
|
+
end
|
69
|
+
|
70
|
+
private
|
71
|
+
|
72
|
+
# @since 0.6.0
|
73
|
+
# @api private
|
74
|
+
attr_reader :registry
|
75
|
+
|
76
|
+
# @since 0.6.0
|
77
|
+
# @api private
|
78
|
+
attr_reader :kommand
|
79
|
+
|
80
|
+
# @since 0.6.0
|
81
|
+
# @api private
|
82
|
+
attr_reader :out
|
83
|
+
|
84
|
+
# @since 0.6.0
|
85
|
+
# @api private
|
86
|
+
attr_reader :err
|
87
|
+
|
88
|
+
# Invoke the CLI if singular command passed
|
89
|
+
#
|
90
|
+
# @param arguments [Array<string>] the command line arguments
|
91
|
+
# @param out [IO] the standard output (defaults to `$stdout`)
|
92
|
+
#
|
93
|
+
# @since 0.6.0
|
94
|
+
# @api private
|
95
|
+
def perform_command(arguments)
|
96
|
+
command, args = parse(kommand, arguments, [])
|
97
|
+
command.call(**args)
|
98
|
+
end
|
99
|
+
|
100
|
+
# Invoke the CLI if registry passed
|
101
|
+
#
|
102
|
+
# @param arguments [Array<string>] the command line arguments
|
103
|
+
# @param out [IO] the standard output (defaults to `$stdout`)
|
104
|
+
#
|
105
|
+
# @since 0.6.0
|
106
|
+
# @api private
|
107
|
+
def perform_registry(arguments)
|
108
|
+
result = registry.get(arguments)
|
60
109
|
|
61
110
|
if result.found?
|
62
|
-
command, args = parse(result,
|
111
|
+
command, args = parse(result.command, result.arguments, result.names)
|
63
112
|
|
64
113
|
result.before_callbacks.run(command, args)
|
65
|
-
command.call(args)
|
114
|
+
command.call(**args)
|
66
115
|
result.after_callbacks.run(command, args)
|
67
116
|
else
|
68
|
-
usage(result
|
117
|
+
usage(result)
|
69
118
|
end
|
70
119
|
end
|
71
120
|
|
72
|
-
private
|
73
|
-
|
74
|
-
# @since 0.1.0
|
75
|
-
# @api private
|
76
|
-
attr_reader :commands
|
77
|
-
|
78
121
|
# Parse arguments for a command.
|
79
122
|
#
|
80
123
|
# It may exit in case of error, or in case of help.
|
@@ -85,26 +128,22 @@ module Dry
|
|
85
128
|
# @return [Array<Dry:CLI::Command, Array>] returns an array where the
|
86
129
|
# first element is a command and the second one is the list of arguments
|
87
130
|
#
|
88
|
-
# @since 0.
|
131
|
+
# @since 0.6.0
|
89
132
|
# @api private
|
90
|
-
def parse(
|
91
|
-
|
92
|
-
names = result.names
|
93
|
-
return [command, result.arguments] unless command?(command)
|
94
|
-
|
95
|
-
result = Parser.call(command, result.arguments, result.names)
|
133
|
+
def parse(command, arguments, names)
|
134
|
+
result = Parser.call(command, arguments, names)
|
96
135
|
|
97
136
|
if result.help?
|
98
|
-
Banner.call(command,
|
137
|
+
out.puts Banner.call(command, names)
|
99
138
|
exit(0)
|
100
139
|
end
|
101
140
|
|
102
141
|
if result.error?
|
103
|
-
|
142
|
+
err.puts(result.error)
|
104
143
|
exit(1)
|
105
144
|
end
|
106
145
|
|
107
|
-
[command, result.arguments]
|
146
|
+
[command.new, result.arguments]
|
108
147
|
end
|
109
148
|
|
110
149
|
# Prints the command usage and exit.
|
@@ -114,8 +153,8 @@ module Dry
|
|
114
153
|
#
|
115
154
|
# @since 0.1.0
|
116
155
|
# @api private
|
117
|
-
def usage(result
|
118
|
-
Usage.call(result
|
156
|
+
def usage(result)
|
157
|
+
err.puts Usage.call(result)
|
119
158
|
exit(1)
|
120
159
|
end
|
121
160
|
|
@@ -154,11 +193,13 @@ module Dry
|
|
154
193
|
|
155
194
|
# Create a new instance
|
156
195
|
#
|
157
|
-
# @param
|
196
|
+
# @param registry_or_command [Dry::CLI::Registry, Dry::CLI::Command]
|
197
|
+
# a registry or singular command
|
198
|
+
# @param &block [Block] a configuration block for registry
|
158
199
|
#
|
159
200
|
# @return [Dry::CLI] the new instance
|
160
201
|
# @since 0.4.0
|
161
|
-
def self.CLI(
|
162
|
-
CLI.new(
|
202
|
+
def self.CLI(registry_or_command = nil, &block)
|
203
|
+
CLI.new(registry_or_command, &block)
|
163
204
|
end
|
164
205
|
end
|
data/lib/dry/cli/banner.rb
CHANGED
@@ -16,9 +16,9 @@ module Dry
|
|
16
16
|
#
|
17
17
|
# @since 0.1.0
|
18
18
|
# @api private
|
19
|
-
def self.call(command,
|
19
|
+
def self.call(command, names)
|
20
20
|
full_command_name = full_command_name(names)
|
21
|
-
|
21
|
+
[
|
22
22
|
command_name(full_command_name),
|
23
23
|
command_name_and_arguments(command, full_command_name),
|
24
24
|
command_description(command),
|
@@ -26,8 +26,6 @@ module Dry
|
|
26
26
|
command_options(command),
|
27
27
|
command_examples(command, full_command_name)
|
28
28
|
].compact.join("\n")
|
29
|
-
|
30
|
-
out.puts output
|
31
29
|
end
|
32
30
|
|
33
31
|
# @since 0.1.0
|
@@ -107,6 +105,8 @@ module Dry
|
|
107
105
|
name = Inflector.dasherize(option.name)
|
108
106
|
name = if option.boolean?
|
109
107
|
"[no-]#{name}"
|
108
|
+
elsif option.array?
|
109
|
+
"#{name}=VALUE1,VALUE2,.."
|
110
110
|
else
|
111
111
|
"#{name}=VALUE"
|
112
112
|
end
|
@@ -20,13 +20,12 @@ module Dry
|
|
20
20
|
# @api private
|
21
21
|
def set(name, command, aliases)
|
22
22
|
node = @root
|
23
|
-
command = command.new if command
|
24
23
|
name.split(/[[:space:]]/).each do |token|
|
25
24
|
node = node.put(node, token)
|
26
25
|
end
|
27
26
|
|
28
27
|
node.aliases!(aliases)
|
29
|
-
node.leaf!(command)
|
28
|
+
node.leaf!(command) if command
|
30
29
|
|
31
30
|
nil
|
32
31
|
end
|
@@ -0,0 +1,75 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'backports/2.5.0/module/define_method' if RUBY_VERSION < '2.5'
|
4
|
+
|
5
|
+
module Dry
|
6
|
+
class CLI
|
7
|
+
require 'dry/cli'
|
8
|
+
# Inline Syntax (aka DSL) to implement one-file applications
|
9
|
+
#
|
10
|
+
# `dry/cli/inline` is not required by default
|
11
|
+
# and explicit requirement of this file means that
|
12
|
+
# it is expected of abusing global namespace with
|
13
|
+
# methods below
|
14
|
+
#
|
15
|
+
# DSL consists of 5 methods:
|
16
|
+
# `desc`, `example`, `argument`, `option`
|
17
|
+
# — are similar to methods from Command class
|
18
|
+
#
|
19
|
+
# `run` accepts a block to execute
|
20
|
+
#
|
21
|
+
# @example
|
22
|
+
# require 'bundler/inline'
|
23
|
+
# gemfile { gem 'dry/cli', require: 'dry/cli/inline' }
|
24
|
+
#
|
25
|
+
# desc 'List files in a directory'
|
26
|
+
# argument :path, required: false, desc: '[DIR]'
|
27
|
+
# option :all, aliases: ['a'], type: :boolean
|
28
|
+
#
|
29
|
+
# run do |path: '.', **options|
|
30
|
+
# puts options.key?(:all) ? Dir.entries(path) : Dir.children(path)
|
31
|
+
# end
|
32
|
+
#
|
33
|
+
# # $ ls -a
|
34
|
+
# # $ ls somepath
|
35
|
+
# # $ ls somepath --all
|
36
|
+
# @since 0.6.0
|
37
|
+
module Inline
|
38
|
+
extend Forwardable
|
39
|
+
|
40
|
+
# AnonymousCommand
|
41
|
+
#
|
42
|
+
# @since 0.6.0
|
43
|
+
AnonymousCommand = Class.new(Dry::CLI::Command)
|
44
|
+
|
45
|
+
# @since 0.6.0
|
46
|
+
delegate %i[desc example argument option] => AnonymousCommand
|
47
|
+
|
48
|
+
# The rule of thumb for implementation of run block
|
49
|
+
# is that for every argument from your CLI
|
50
|
+
# you need to specify that as an mandatory argument for a block.
|
51
|
+
# Optional arguments have to have default value as ruby syntax expect them
|
52
|
+
#
|
53
|
+
# @example
|
54
|
+
# argument :one
|
55
|
+
# argument :two, required: false
|
56
|
+
# option :three
|
57
|
+
#
|
58
|
+
# run do |one:, two: 'default', **options|
|
59
|
+
# puts one, two, options.inspect
|
60
|
+
# end
|
61
|
+
#
|
62
|
+
# @since 0.6.0
|
63
|
+
def run(arguments: ARGV, out: $stdout)
|
64
|
+
command = AnonymousCommand
|
65
|
+
command.define_method(:call) do |*args|
|
66
|
+
yield(*args)
|
67
|
+
end
|
68
|
+
|
69
|
+
Dry.CLI(command).call(arguments: arguments, out: out)
|
70
|
+
end
|
71
|
+
end
|
72
|
+
end
|
73
|
+
end
|
74
|
+
|
75
|
+
include Dry::CLI::Inline # rubocop:disable Style/MixinUsage
|
data/lib/dry/cli/usage.rb
CHANGED
@@ -15,14 +15,14 @@ module Dry
|
|
15
15
|
|
16
16
|
# @since 0.1.0
|
17
17
|
# @api private
|
18
|
-
def self.call(result
|
19
|
-
|
18
|
+
def self.call(result)
|
19
|
+
header = 'Commands:'
|
20
20
|
max_length, commands = commands_and_arguments(result)
|
21
21
|
|
22
|
-
commands.
|
22
|
+
commands.map do |banner, node|
|
23
23
|
usage = description(node.command) if node.leaf?
|
24
|
-
|
25
|
-
end
|
24
|
+
"#{justify(banner, max_length, usage)}#{usage}"
|
25
|
+
end.unshift(header).join("\n")
|
26
26
|
end
|
27
27
|
|
28
28
|
# @since 0.1.0
|
data/lib/dry/cli/utils/files.rb
CHANGED
data/lib/dry/cli/version.rb
CHANGED
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: dry-cli
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.6.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Luca Guidi
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2020-
|
11
|
+
date: 2020-03-06 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: concurrent-ruby
|
@@ -103,6 +103,7 @@ files:
|
|
103
103
|
- lib/dry/cli/command_registry.rb
|
104
104
|
- lib/dry/cli/errors.rb
|
105
105
|
- lib/dry/cli/inflector.rb
|
106
|
+
- lib/dry/cli/inline.rb
|
106
107
|
- lib/dry/cli/option.rb
|
107
108
|
- lib/dry/cli/parser.rb
|
108
109
|
- lib/dry/cli/program_name.rb
|
@@ -126,7 +127,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
126
127
|
requirements:
|
127
128
|
- - ">="
|
128
129
|
- !ruby/object:Gem::Version
|
129
|
-
version: 2.
|
130
|
+
version: 2.3.0
|
130
131
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
131
132
|
requirements:
|
132
133
|
- - ">="
|