dry-cli-ui 0.6.1 → 0.7.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 +20 -7
- data/README.md +207 -9
- data/examples/Gemfile.lock +20 -7
- data/lib/dry/cli/ui/configuration.rb +27 -2
- data/lib/dry/cli/ui/console.rb +31 -4
- data/lib/dry/cli/ui/flags.rb +143 -0
- data/lib/dry/cli/ui/invocation.rb +100 -0
- data/lib/dry/cli/ui/logging.rb +192 -0
- data/lib/dry/cli/ui/report.rb +16 -0
- data/lib/dry/cli/ui/reporting.rb +134 -0
- data/lib/dry/cli/ui/terminal.rb +19 -2
- data/lib/dry/cli/ui/version.rb +1 -1
- data/lib/dry/cli/ui/widgets/legend.rb +48 -0
- data/lib/dry/cli/ui/widgets/multi.rb +20 -3
- data/lib/dry/cli/ui/widgets/multi_progress.rb +35 -23
- data/lib/dry/cli/ui/widgets/outcome.rb +4 -2
- data/lib/dry/cli/ui/widgets/progress.rb +264 -42
- data/lib/dry/cli/ui/widgets/prompt.rb +6 -2
- data/lib/dry/cli/ui/widgets.rb +1 -0
- data/lib/dry/cli/ui.rb +29 -5
- data/sig/dry/cli/ui.rbs +86 -2
- metadata +49 -1
data/lib/dry/cli/ui.rb
CHANGED
|
@@ -34,14 +34,25 @@ module Dry
|
|
|
34
34
|
autoload :Configuration, File.expand_path("ui/configuration", __dir__)
|
|
35
35
|
autoload :Console, File.expand_path("ui/console", __dir__)
|
|
36
36
|
autoload :Duration, File.expand_path("ui/duration", __dir__)
|
|
37
|
+
autoload :Flags, File.expand_path("ui/flags", __dir__)
|
|
38
|
+
autoload :Invocation, File.expand_path("ui/invocation", __dir__)
|
|
37
39
|
autoload :Line, File.expand_path("ui/line", __dir__)
|
|
40
|
+
autoload :Logging, File.expand_path("ui/logging", __dir__)
|
|
41
|
+
autoload :Report, File.expand_path("ui/report", __dir__)
|
|
42
|
+
autoload :Reporting, File.expand_path("ui/reporting", __dir__)
|
|
38
43
|
autoload :Stop, File.expand_path("ui/stop", __dir__)
|
|
39
44
|
autoload :StatusBar, File.expand_path("ui/status_bar", __dir__)
|
|
40
45
|
autoload :Terminal, File.expand_path("ui/terminal", __dir__)
|
|
41
46
|
autoload :Theme, File.expand_path("ui/theme", __dir__)
|
|
42
47
|
autoload :Widgets, File.expand_path("ui/widgets", __dir__)
|
|
43
48
|
|
|
49
|
+
@started_at = ::Time.now
|
|
50
|
+
|
|
44
51
|
class << self
|
|
52
|
+
# @return [Time] when this gem loaded, which stands for when the process started. Stamps
|
|
53
|
+
# the file name of a report `-o` writes.
|
|
54
|
+
attr_reader :started_at
|
|
55
|
+
|
|
45
56
|
# Make process-wide settings. A block taking an argument receives the
|
|
46
57
|
# configuration; any other block runs against it.
|
|
47
58
|
#
|
|
@@ -85,8 +96,9 @@ module Dry
|
|
|
85
96
|
# The console this command presents through.
|
|
86
97
|
#
|
|
87
98
|
# In a dry-cli command it writes to the command's own `stdout` and `stderr`, and reads prompt
|
|
88
|
-
# answers from its `stdin`: the streams the CLI was called with.
|
|
89
|
-
#
|
|
99
|
+
# answers from its `stdin`: the streams the CLI was called with. Under dry-cli 1.4 and
|
|
100
|
+
# earlier, which give a command only `out` and `err`, it writes to those and reads `$stdin`.
|
|
101
|
+
# Anywhere else it uses `$stdout`, `$stderr` and `$stdin`.
|
|
90
102
|
#
|
|
91
103
|
# The console is built again whenever those streams change. A command registered as an
|
|
92
104
|
# instance is used for every call to its CLI, each time with that call's streams, as when a
|
|
@@ -99,7 +111,7 @@ module Dry
|
|
|
99
111
|
streams = ui_streams
|
|
100
112
|
@ui = nil unless @ui_streams && streams.all? { |name, io| @ui_streams[name].equal?(io) }
|
|
101
113
|
@ui_streams = streams
|
|
102
|
-
@ui ||= Console.new(**streams, **ui_options)
|
|
114
|
+
@ui ||= Console.new(**streams, invocation: Invocation.for(self), **ui_options)
|
|
103
115
|
end
|
|
104
116
|
|
|
105
117
|
private
|
|
@@ -113,12 +125,24 @@ module Dry
|
|
|
113
125
|
# @return [Hash{Symbol => IO}] `out:`, `err:` and `input:`
|
|
114
126
|
def ui_streams
|
|
115
127
|
{
|
|
116
|
-
out: UI.raw(
|
|
117
|
-
err: UI.raw(
|
|
128
|
+
out: UI.raw(ui_stream(:stdout, :out) || $stdout),
|
|
129
|
+
err: UI.raw(ui_stream(:stderr, :err) || $stderr),
|
|
118
130
|
input: respond_to?(:stdin) ? stdin : $stdin
|
|
119
131
|
}
|
|
120
132
|
end
|
|
121
133
|
|
|
134
|
+
# One of the command's output streams: the public one, or the protected one dry-cli 1.4 and
|
|
135
|
+
# earlier set on a command it runs.
|
|
136
|
+
#
|
|
137
|
+
# @param name [Symbol] the public reader, `:stdout` or `:stderr`
|
|
138
|
+
# @param legacy_name [Symbol] the protected reader, `:out` or `:err`
|
|
139
|
+
# @return [IO, Dry::CLI::Stream, nil] nil when the command has neither, or was never run
|
|
140
|
+
def ui_stream(name, legacy_name)
|
|
141
|
+
return public_send(name) if respond_to?(name)
|
|
142
|
+
|
|
143
|
+
__send__(legacy_name) if respond_to?(legacy_name, true)
|
|
144
|
+
end
|
|
145
|
+
|
|
122
146
|
# Options for {Console#initialize} other than its streams. Override it to configure the
|
|
123
147
|
# console {#ui} builds.
|
|
124
148
|
#
|
data/sig/dry/cli/ui.rbs
CHANGED
|
@@ -12,6 +12,7 @@ module Dry
|
|
|
12
12
|
def ui: () -> Console
|
|
13
13
|
|
|
14
14
|
private def ui_streams: () -> { out: untyped, err: untyped, input: untyped }
|
|
15
|
+
private def ui_stream: (Symbol name, Symbol legacy_name) -> untyped
|
|
15
16
|
private def ui_options: () -> Hash[Symbol, untyped]
|
|
16
17
|
|
|
17
18
|
def self.raw: (untyped stream) -> untyped
|
|
@@ -19,6 +20,60 @@ module Dry
|
|
|
19
20
|
def self.configure: () { (Configuration config) -> void } -> Configuration
|
|
20
21
|
def self.config: () -> Configuration
|
|
21
22
|
def self.reset!: () -> void
|
|
23
|
+
def self.started_at: () -> Time
|
|
24
|
+
|
|
25
|
+
module Flags
|
|
26
|
+
OPTIONS: Hash[Symbol, Hash[Symbol, Hash[Symbol, untyped]]]
|
|
27
|
+
OPTIONAL_VALUES: Array[Symbol]
|
|
28
|
+
SWITCHES: Array[String]
|
|
29
|
+
|
|
30
|
+
def self.arguments: (Array[String] argv, ?switches: Array[String]) -> Array[String]
|
|
31
|
+
def self.switches: (untyped command) -> Array[String]
|
|
32
|
+
def flags: (*Symbol names) -> Array[Symbol]
|
|
33
|
+
end
|
|
34
|
+
|
|
35
|
+
class Invocation
|
|
36
|
+
attr_reader executable: String
|
|
37
|
+
attr_reader action: String?
|
|
38
|
+
attr_reader name: String
|
|
39
|
+
attr_reader started_at: Time
|
|
40
|
+
attr_reader directory: String
|
|
41
|
+
|
|
42
|
+
def self.new: (executable: String, action: String?, name: String, started_at: Time, directory: String) -> Invocation
|
|
43
|
+
def self.for: (?untyped command, ?program: String, ?started_at: Time, ?directory: String) -> Invocation
|
|
44
|
+
def self.root: (String directory) -> String
|
|
45
|
+
def basename: () -> String
|
|
46
|
+
def report_path: (String? value) -> String?
|
|
47
|
+
def log_path: (String? value) -> String?
|
|
48
|
+
end
|
|
49
|
+
|
|
50
|
+
class Report
|
|
51
|
+
def color?: () -> true
|
|
52
|
+
end
|
|
53
|
+
|
|
54
|
+
class Logging
|
|
55
|
+
LEVELS: Array[String]
|
|
56
|
+
FORMATS: Hash[String, Symbol]
|
|
57
|
+
INSPECT_LIMIT: Integer
|
|
58
|
+
FRAME_LIMIT: Integer
|
|
59
|
+
|
|
60
|
+
def self.level: (String | Symbol name) -> Symbol
|
|
61
|
+
def self.formatter: (String | Symbol name) -> untyped
|
|
62
|
+
def self.formats: () -> Array[String]
|
|
63
|
+
def self.logger: (String name) -> untyped
|
|
64
|
+
def self.locals: (Exception exception) -> Array[Hash[Symbol, untyped]]?
|
|
65
|
+
def self.record: (Exception exception) -> void
|
|
66
|
+
def initialize: (String? target, io: untyped, level: String | Symbol, format: String | Symbol) -> void
|
|
67
|
+
def run: [T] () { () -> T } -> T
|
|
68
|
+
end
|
|
69
|
+
|
|
70
|
+
module Reporting
|
|
71
|
+
def output: [T] (?String? value) { (untyped io) -> T } -> T
|
|
72
|
+
def logging: [T] (String? value, ?level: String | Symbol, ?format: String | Symbol) { () -> T } -> T
|
|
73
|
+
def with_flags: [T] (?output: String?, ?log: String?, ?log_level: String | Symbol, ?log_format: String | Symbol, **untyped) { (untyped io) -> T } -> T
|
|
74
|
+
def logger: () -> untyped
|
|
75
|
+
def log_exception: (Exception exception, ?String? message, ?level: String | Symbol) -> nil
|
|
76
|
+
end
|
|
22
77
|
|
|
23
78
|
class Configuration
|
|
24
79
|
type spinner_definition = Symbol | { interval: Numeric, frames: Array[String] | String }
|
|
@@ -32,6 +87,10 @@ module Dry
|
|
|
32
87
|
def bar_color=: (Symbol? value) -> Symbol?
|
|
33
88
|
def bar_background: (?Symbol? value) -> Symbol?
|
|
34
89
|
def bar_background=: (Symbol? value) -> Symbol?
|
|
90
|
+
def bar_failed_color: (?Symbol? value) -> Symbol?
|
|
91
|
+
def bar_failed_color=: (Symbol? value) -> Symbol?
|
|
92
|
+
def bar_aux_color: (?Symbol? value) -> Symbol?
|
|
93
|
+
def bar_aux_color=: (Symbol? value) -> Symbol?
|
|
35
94
|
def spinner_frames: () -> Array[String]
|
|
36
95
|
def spinner_frame_seconds: () -> Float
|
|
37
96
|
def bar_complete: () -> String
|
|
@@ -49,6 +108,28 @@ module Dry
|
|
|
49
108
|
def summary: (String label) -> String
|
|
50
109
|
end
|
|
51
110
|
|
|
111
|
+
module Widgets
|
|
112
|
+
class Progress
|
|
113
|
+
class Handle
|
|
114
|
+
type outcome = :ok | :aux | :failed
|
|
115
|
+
|
|
116
|
+
OUTCOMES: Array[outcome]
|
|
117
|
+
|
|
118
|
+
def total: () -> Integer?
|
|
119
|
+
def total=: (Integer value) -> Integer
|
|
120
|
+
def color: () -> Symbol?
|
|
121
|
+
def current: () -> Integer
|
|
122
|
+
def counts: () -> { ok: Integer, aux: Integer, failed: Integer }
|
|
123
|
+
def advance: (?Integer step, ?as: outcome) -> self
|
|
124
|
+
def fail: (?_ToS? reason) -> self
|
|
125
|
+
def failed?: () -> bool
|
|
126
|
+
def reason: () -> String?
|
|
127
|
+
def finish: () -> self
|
|
128
|
+
def summary: (String label) -> String
|
|
129
|
+
end
|
|
130
|
+
end
|
|
131
|
+
end
|
|
132
|
+
|
|
52
133
|
class Stop
|
|
53
134
|
def stopped?: () -> bool
|
|
54
135
|
def stop!: () -> self
|
|
@@ -56,6 +137,8 @@ module Dry
|
|
|
56
137
|
end
|
|
57
138
|
|
|
58
139
|
class Console
|
|
140
|
+
include Reporting
|
|
141
|
+
|
|
59
142
|
def debug: (*_ToS paragraphs, ?width: Integer?) -> nil
|
|
60
143
|
def info: (*_ToS paragraphs, ?width: Integer?) -> nil
|
|
61
144
|
def success: (*_ToS paragraphs, ?width: Integer?) -> nil
|
|
@@ -67,14 +150,15 @@ module Dry
|
|
|
67
150
|
def popup: (*_ToS paragraphs, ?title: String?, ?width: Integer?) -> nil
|
|
68
151
|
def spinner: [T] (String label) { (Line line) -> T } -> T
|
|
69
152
|
def multi_spinner: (String title, ?concurrent: (bool | Integer), ?stop: Stop?) { (untyped spinners) -> void } -> Array[untyped]
|
|
70
|
-
def progress: [T] (String label, total: Integer, ?color: Symbol?) { (
|
|
153
|
+
def progress: [T] (String label, total: Integer, ?color: Symbol?) { (Widgets::Progress::Handle progress) -> T } -> T
|
|
154
|
+
def legend: (?failed: _ToS?, ?aux: _ToS?, ?ok: _ToS?) -> nil
|
|
71
155
|
def multi_progress: (String title, ?concurrent: (bool | Integer), ?count: (:units | :jobs), ?total: Integer?, ?stop: Stop?) { (untyped bars) -> void } -> Array[untyped]
|
|
72
156
|
def stoppable: [T] () { (Stop stop) -> T } -> T
|
|
73
157
|
def status_bar: [T] (?String? title, ?hints: Array[String] | String) { () -> T } -> T
|
|
74
158
|
def tasks: (?String? title, ?concurrent: (bool | Integer)) { (untyped tasks) -> void } -> nil
|
|
75
159
|
def table: (Array[Array[_ToS]] rows, ?header: Array[_ToS]?) -> nil
|
|
76
160
|
def prompt: (String question, ?default: untyped, ?choices: (Array[String] | Hash[String, untyped])?) -> untyped
|
|
77
|
-
def confirm: (String question, ?default: bool) -> bool
|
|
161
|
+
def confirm: (String question, ?default: bool, ?yes: bool) -> bool
|
|
78
162
|
end
|
|
79
163
|
end
|
|
80
164
|
end
|
metadata
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: dry-cli-ui
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 0.
|
|
4
|
+
version: 0.7.0
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Konstantin Gredeskoul
|
|
@@ -9,6 +9,20 @@ bindir: bin
|
|
|
9
9
|
cert_chain: []
|
|
10
10
|
date: 1980-01-02 00:00:00.000000000 Z
|
|
11
11
|
dependencies:
|
|
12
|
+
- !ruby/object:Gem::Dependency
|
|
13
|
+
name: binding_of_caller
|
|
14
|
+
requirement: !ruby/object:Gem::Requirement
|
|
15
|
+
requirements:
|
|
16
|
+
- - "~>"
|
|
17
|
+
- !ruby/object:Gem::Version
|
|
18
|
+
version: '2.0'
|
|
19
|
+
type: :runtime
|
|
20
|
+
prerelease: false
|
|
21
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
22
|
+
requirements:
|
|
23
|
+
- - "~>"
|
|
24
|
+
- !ruby/object:Gem::Version
|
|
25
|
+
version: '2.0'
|
|
12
26
|
- !ruby/object:Gem::Dependency
|
|
13
27
|
name: concurrent-ruby
|
|
14
28
|
requirement: !ruby/object:Gem::Requirement
|
|
@@ -37,6 +51,20 @@ dependencies:
|
|
|
37
51
|
- - ">="
|
|
38
52
|
- !ruby/object:Gem::Version
|
|
39
53
|
version: '1.0'
|
|
54
|
+
- !ruby/object:Gem::Dependency
|
|
55
|
+
name: logger
|
|
56
|
+
requirement: !ruby/object:Gem::Requirement
|
|
57
|
+
requirements:
|
|
58
|
+
- - "~>"
|
|
59
|
+
- !ruby/object:Gem::Version
|
|
60
|
+
version: '1.6'
|
|
61
|
+
type: :runtime
|
|
62
|
+
prerelease: false
|
|
63
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
64
|
+
requirements:
|
|
65
|
+
- - "~>"
|
|
66
|
+
- !ruby/object:Gem::Version
|
|
67
|
+
version: '1.6'
|
|
40
68
|
- !ruby/object:Gem::Dependency
|
|
41
69
|
name: pastel
|
|
42
70
|
requirement: !ruby/object:Gem::Requirement
|
|
@@ -51,6 +79,20 @@ dependencies:
|
|
|
51
79
|
- - "~>"
|
|
52
80
|
- !ruby/object:Gem::Version
|
|
53
81
|
version: '0.8'
|
|
82
|
+
- !ruby/object:Gem::Dependency
|
|
83
|
+
name: semantic_logger
|
|
84
|
+
requirement: !ruby/object:Gem::Requirement
|
|
85
|
+
requirements:
|
|
86
|
+
- - "~>"
|
|
87
|
+
- !ruby/object:Gem::Version
|
|
88
|
+
version: '5.1'
|
|
89
|
+
type: :runtime
|
|
90
|
+
prerelease: false
|
|
91
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
92
|
+
requirements:
|
|
93
|
+
- - "~>"
|
|
94
|
+
- !ruby/object:Gem::Version
|
|
95
|
+
version: '5.1'
|
|
54
96
|
- !ruby/object:Gem::Dependency
|
|
55
97
|
name: strings
|
|
56
98
|
requirement: !ruby/object:Gem::Requirement
|
|
@@ -187,7 +229,12 @@ files:
|
|
|
187
229
|
- lib/dry/cli/ui/configuration.rb
|
|
188
230
|
- lib/dry/cli/ui/console.rb
|
|
189
231
|
- lib/dry/cli/ui/duration.rb
|
|
232
|
+
- lib/dry/cli/ui/flags.rb
|
|
233
|
+
- lib/dry/cli/ui/invocation.rb
|
|
190
234
|
- lib/dry/cli/ui/line.rb
|
|
235
|
+
- lib/dry/cli/ui/logging.rb
|
|
236
|
+
- lib/dry/cli/ui/report.rb
|
|
237
|
+
- lib/dry/cli/ui/reporting.rb
|
|
191
238
|
- lib/dry/cli/ui/status_bar.rb
|
|
192
239
|
- lib/dry/cli/ui/stop.rb
|
|
193
240
|
- lib/dry/cli/ui/terminal.rb
|
|
@@ -195,6 +242,7 @@ files:
|
|
|
195
242
|
- lib/dry/cli/ui/version.rb
|
|
196
243
|
- lib/dry/cli/ui/widgets.rb
|
|
197
244
|
- lib/dry/cli/ui/widgets/box.rb
|
|
245
|
+
- lib/dry/cli/ui/widgets/legend.rb
|
|
198
246
|
- lib/dry/cli/ui/widgets/multi.rb
|
|
199
247
|
- lib/dry/cli/ui/widgets/multi_progress.rb
|
|
200
248
|
- lib/dry/cli/ui/widgets/multi_spinner.rb
|