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.
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. Anywhere else it uses
89
- # `$stdout`, `$stderr` and `$stdin`.
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(respond_to?(:stdout) ? stdout : $stdout),
117
- err: UI.raw(respond_to?(:stderr) ? stderr : $stderr),
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?) { (untyped progress) -> T } -> T
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.6.1
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