cli-kit 5.1.0 → 5.2.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.
@@ -6,11 +6,9 @@ require 'fileutils'
6
6
  module CLI
7
7
  module Kit
8
8
  class Config
9
- extend T::Sig
10
-
11
9
  XDG_CONFIG_HOME = 'XDG_CONFIG_HOME'
12
10
 
13
- sig { params(tool_name: String).void }
11
+ #: (tool_name: String) -> void
14
12
  def initialize(tool_name:)
15
13
  @tool_name = tool_name
16
14
  end
@@ -28,13 +26,13 @@ module CLI
28
26
  # #### Example Usage
29
27
  # `config.get('name.of.config')`
30
28
  #
31
- sig { params(section: String, name: String, default: T.nilable(String)).returns(T.nilable(String)) }
29
+ #: (String section, String name, ?default: String?) -> String?
32
30
  def get(section, name, default: nil)
33
31
  all_configs.dig("[#{section}]", name) || default
34
32
  end
35
33
 
36
34
  # Coalesce and enforce the value of a config to a boolean
37
- sig { params(section: String, name: String, default: T.nilable(T::Boolean)).returns(T.nilable(T::Boolean)) }
35
+ #: (String section, String name, ?default: bool?) -> bool?
38
36
  def get_bool(section, name, default: false)
39
37
  case get(section, name)
40
38
  when 'true'
@@ -58,14 +56,15 @@ module CLI
58
56
  # #### Example Usage
59
57
  # `config.set('section', 'name.of.config', 'value')`
60
58
  #
61
- sig { params(section: String, name: String, value: T.nilable(T.any(String, T::Boolean))).void }
59
+ #: (String section, String name, (String | bool)? value) -> void
62
60
  def set(section, name, value)
63
61
  all_configs["[#{section}]"] ||= {}
62
+ section = all_configs["[#{section}]"] #: as !nil
64
63
  case value
65
64
  when nil
66
- T.must(all_configs["[#{section}]"]).delete(name)
65
+ section.delete(name)
67
66
  else
68
- T.must(all_configs["[#{section}]"])[name] = value.to_s
67
+ section[name] = value.to_s
69
68
  end
70
69
  write_config
71
70
  end
@@ -79,7 +78,7 @@ module CLI
79
78
  # #### Example Usage
80
79
  # `config.unset('section', 'name.of.config')`
81
80
  #
82
- sig { params(section: String, name: String).void }
81
+ #: (String section, String name) -> void
83
82
  def unset(section, name)
84
83
  set(section, name, nil)
85
84
  end
@@ -92,12 +91,12 @@ module CLI
92
91
  # #### Example Usage
93
92
  # `config.get_section('section')`
94
93
  #
95
- sig { params(section: String).returns(T::Hash[String, String]) }
94
+ #: (String section) -> Hash[String, String]
96
95
  def get_section(section)
97
96
  (all_configs["[#{section}]"] || {}).dup
98
97
  end
99
98
 
100
- sig { returns(String) }
99
+ #: -> String
101
100
  def to_s
102
101
  ini.to_s
103
102
  end
@@ -107,7 +106,7 @@ module CLI
107
106
  # if ENV['XDG_CONFIG_HOME'] is not set, we default to ~/.config, e.g.:
108
107
  # ~/.config/tool/config
109
108
  #
110
- sig { returns(String) }
109
+ #: -> String
111
110
  def file
112
111
  config_home = ENV.fetch(XDG_CONFIG_HOME, '~/.config')
113
112
  File.expand_path(File.join(@tool_name, 'config'), config_home)
@@ -115,17 +114,17 @@ module CLI
115
114
 
116
115
  private
117
116
 
118
- sig { returns(T::Hash[String, T::Hash[String, String]]) }
117
+ #: -> Hash[String, Hash[String, String]]
119
118
  def all_configs
120
119
  ini.ini
121
120
  end
122
121
 
123
- sig { returns(CLI::Kit::Ini) }
122
+ #: -> CLI::Kit::Ini
124
123
  def ini
125
124
  @ini ||= CLI::Kit::Ini.new(file).tap(&:parse)
126
125
  end
127
126
 
128
- sig { void }
127
+ #: -> void
129
128
  def write_config
130
129
  all_configs.each do |section, sub_config|
131
130
  all_configs.delete(section) if sub_config.empty?
@@ -2,28 +2,26 @@
2
2
  # frozen_string_literal: true
3
3
 
4
4
  class Exception
5
- extend(T::Sig)
6
-
7
5
  # You'd think instance variables @bug and @silent would work here. They
8
6
  # don't. I'm not sure why. If you, the reader, want to take some time to
9
7
  # figure it out, go ahead and refactor to that.
10
8
 
11
- sig { returns(T::Boolean) }
9
+ #: -> bool
12
10
  def bug?
13
11
  true
14
12
  end
15
13
 
16
- sig { returns(T::Boolean) }
14
+ #: -> bool
17
15
  def silent?
18
16
  false
19
17
  end
20
18
 
21
- sig { params(bug: T::Boolean).void }
19
+ #: (?bool bug) -> void
22
20
  def bug!(bug = true)
23
21
  singleton_class.define_method(:bug?) { bug }
24
22
  end
25
23
 
26
- sig { params(silent: T::Boolean).void }
24
+ #: (?bool silent) -> void
27
25
  def silent!(silent = true)
28
26
  singleton_class.define_method(:silent?) { silent }
29
27
  end
@@ -6,23 +6,12 @@ require 'English'
6
6
  module CLI
7
7
  module Kit
8
8
  class ErrorHandler
9
- extend T::Sig
9
+ #: type exception_reporter_or_proc = singleton(ExceptionReporter) | ^() -> singleton(ExceptionReporter)
10
10
 
11
- ExceptionReporterOrProc = T.type_alias do
12
- T.any(T.class_of(ExceptionReporter), T.proc.returns(T.class_of(ExceptionReporter)))
13
- end
14
-
15
- sig { params(override_exception_handler: T.proc.params(arg0: Exception).returns(Integer)).void }
11
+ #: ^(Exception arg0) -> Integer
16
12
  attr_writer :override_exception_handler
17
13
 
18
- sig do
19
- params(
20
- log_file: T.nilable(String),
21
- exception_reporter: ExceptionReporterOrProc,
22
- tool_name: T.nilable(String),
23
- dev_mode: T::Boolean,
24
- ).void
25
- end
14
+ #: (?log_file: String?, ?exception_reporter: exception_reporter_or_proc, ?tool_name: String?, ?dev_mode: bool) -> void
26
15
  def initialize(log_file: nil, exception_reporter: NullExceptionReporter, tool_name: nil, dev_mode: false)
27
16
  @log_file = log_file
28
17
  @exception_reporter_or_proc = exception_reporter
@@ -30,33 +19,28 @@ module CLI
30
19
  @dev_mode = dev_mode
31
20
  end
32
21
 
22
+ # @abstract
33
23
  class ExceptionReporter
34
- extend T::Sig
35
- extend T::Helpers
36
- abstract!
37
-
38
24
  class << self
39
- extend T::Sig
40
-
41
- sig { abstract.params(exception: T.nilable(Exception), logs: T.nilable(String)).void }
42
- def report(exception, logs = nil); end
25
+ # @abstract
26
+ #: (Exception?, ?String?) -> void
27
+ def report(exception, logs = nil)
28
+ raise(NotImplementedError)
29
+ end
43
30
  end
44
31
  end
45
32
 
46
33
  class NullExceptionReporter < ExceptionReporter
47
- extend T::Sig
48
-
49
34
  class << self
50
- extend T::Sig
51
-
52
- sig { override.params(_exception: T.nilable(Exception), _logs: T.nilable(String)).void }
35
+ # @override
36
+ #: (Exception? _exception, ?String? _logs) -> void
53
37
  def report(_exception, _logs = nil)
54
38
  nil
55
39
  end
56
40
  end
57
41
  end
58
42
 
59
- sig { params(block: T.proc.void).returns(Integer) }
43
+ #: { -> void } -> Integer
60
44
  def call(&block)
61
45
  # @at_exit_exception is set if handle_abort decides to submit an error.
62
46
  # $ERROR_INFO is set if we terminate because of a signal.
@@ -64,7 +48,7 @@ module CLI
64
48
  triage_all_exceptions(&block)
65
49
  end
66
50
 
67
- sig { params(error: T.nilable(Exception)).void }
51
+ #: (Exception? error) -> void
68
52
  def report_exception(error)
69
53
  if (notify_with = exception_for_submission(error))
70
54
  logs = nil
@@ -92,7 +76,7 @@ module CLI
92
76
  # they're #bug?
93
77
  #
94
78
  # Returns an exit status for the program.
95
- sig { params(block: T.proc.void).returns(Integer) }
79
+ #: { -> void } -> Integer
96
80
  def triage_all_exceptions(&block)
97
81
  begin
98
82
  block.call
@@ -130,7 +114,7 @@ module CLI
130
114
  e.bug? ? CLI::Kit::EXIT_BUG : CLI::Kit::EXIT_FAILURE_BUT_NOT_BUG
131
115
  end
132
116
 
133
- sig { params(error: T.nilable(Exception)).returns(T.nilable(Exception)) }
117
+ #: (Exception? error) -> Exception?
134
118
  def exception_for_submission(error)
135
119
  # happens on normal non-error termination
136
120
  return if error.nil?
@@ -161,14 +145,14 @@ module CLI
161
145
  end
162
146
  end
163
147
 
164
- sig { params(message: String).void }
148
+ #: (String message) -> void
165
149
  def stderr_puts(message)
166
150
  $stderr.puts(CLI::UI.fmt("{{red:#{message}}}"))
167
151
  rescue Errno::EPIPE, Errno::EIO
168
152
  nil
169
153
  end
170
154
 
171
- sig { returns(T.class_of(ExceptionReporter)) }
155
+ #: -> singleton(ExceptionReporter)
172
156
  def exception_reporter
173
157
  case @exception_reporter_or_proc
174
158
  when Proc
@@ -7,15 +7,13 @@ require 'fileutils'
7
7
  module CLI
8
8
  module Kit
9
9
  class Executor
10
- extend T::Sig
11
-
12
- sig { params(log_file: String).void }
10
+ #: (log_file: String) -> void
13
11
  def initialize(log_file:)
14
12
  FileUtils.mkpath(File.dirname(log_file))
15
13
  @log_file = log_file
16
14
  end
17
15
 
18
- sig { params(command: T.class_of(CLI::Kit::BaseCommand), command_name: String, args: T::Array[String]).void }
16
+ #: (singleton(CLI::Kit::BaseCommand) command, String command_name, Array[String] args) -> void
19
17
  def call(command, command_name, args)
20
18
  with_traps do
21
19
  with_logging do |id|
@@ -36,10 +34,7 @@ module CLI
36
34
 
37
35
  private
38
36
 
39
- sig do
40
- type_parameters(:T).params(block: T.proc.params(id: String).returns(T.type_parameter(:T)))
41
- .returns(T.type_parameter(:T))
42
- end
37
+ #: [T] { (String id) -> T } -> T
43
38
  def with_logging(&block)
44
39
  CLI::UI.log_output_to(@log_file) do
45
40
  CLI::UI::StdoutRouter.with_id(on_streams: [CLI::UI::StdoutRouter.duplicate_output_to].compact) do |id|
@@ -48,18 +43,14 @@ module CLI
48
43
  end
49
44
  end
50
45
 
51
- sig { type_parameters(:T).params(block: T.proc.returns(T.type_parameter(:T))).returns(T.type_parameter(:T)) }
46
+ #: [T] { -> T } -> T
52
47
  def with_traps(&block)
53
48
  twrap('QUIT', method(:quit_handler)) do
54
49
  twrap('INFO', method(:info_handler), &block)
55
50
  end
56
51
  end
57
52
 
58
- sig do
59
- type_parameters(:T)
60
- .params(signal: String, handler: Method, block: T.proc.returns(T.type_parameter(:T)))
61
- .returns(T.type_parameter(:T))
62
- end
53
+ #: [T] (String signal, Method handler) { -> T } -> T
63
54
  def twrap(signal, handler, &block)
64
55
  return yield unless Signal.list.key?(signal)
65
56
 
@@ -78,7 +69,7 @@ module CLI
78
69
  end
79
70
  end
80
71
 
81
- sig { params(_sig: T.untyped).void }
72
+ #: (untyped _sig) -> void
82
73
  def quit_handler(_sig)
83
74
  z = caller
84
75
  CLI::UI.raw do
@@ -88,7 +79,7 @@ module CLI
88
79
  exit(CLI::Kit::EXIT_FAILURE_BUT_NOT_BUG)
89
80
  end
90
81
 
91
- sig { params(_sig: T.untyped).void }
82
+ #: (untyped _sig) -> void
92
83
  def info_handler(_sig)
93
84
  z = caller
94
85
  CLI::UI.raw do
data/lib/cli/kit/ini.rb CHANGED
@@ -17,14 +17,10 @@ module CLI
17
17
  # See the ini_test.rb file for more examples
18
18
  #
19
19
  class Ini
20
- extend T::Sig
21
-
22
- sig { returns(T::Hash[String, T::Hash[String, String]]) }
20
+ #: Hash[String, Hash[String, String]]
23
21
  attr_accessor :ini
24
22
 
25
- sig do
26
- params(path: T.nilable(String), config: T.nilable(String), default_section: String).void
27
- end
23
+ #: (?String? path, ?config: String?, ?default_section: String) -> void
28
24
  def initialize(path = nil, config: nil, default_section: '[global]')
29
25
  @config = if path && File.exist?(path)
30
26
  File.readlines(path)
@@ -35,7 +31,7 @@ module CLI
35
31
  @current_key = default_section
36
32
  end
37
33
 
38
- sig { returns(T::Hash[String, T::Hash[String, String]]) }
34
+ #: -> Hash[String, Hash[String, String]]
39
35
  def parse
40
36
  return @ini if @config.nil?
41
37
 
@@ -53,19 +49,19 @@ module CLI
53
49
  @ini
54
50
  end
55
51
 
56
- sig { returns(String) }
52
+ #: -> String
57
53
  def git_format
58
54
  to_ini(git_format: true)
59
55
  end
60
56
 
61
- sig { returns(String) }
57
+ #: -> String
62
58
  def to_s
63
59
  to_ini
64
60
  end
65
61
 
66
62
  private
67
63
 
68
- sig { params(git_format: T::Boolean).returns(String) }
64
+ #: (?git_format: bool) -> String
69
65
  def to_ini(git_format: false)
70
66
  optional_tab = git_format ? "\t" : ''
71
67
  str = []
@@ -79,14 +75,14 @@ module CLI
79
75
  str.join("\n")
80
76
  end
81
77
 
82
- sig { params(key: String, val: String).void }
78
+ #: (String key, String val) -> void
83
79
  def set_val(key, val)
84
80
  current_key = @current_key
85
81
  @ini[current_key] ||= {}
86
82
  @ini[current_key][key] = val
87
83
  end
88
84
 
89
- sig { params(k: String).returns(T::Boolean) }
85
+ #: (String k) -> bool
90
86
  def section_designator?(k)
91
87
  k.start_with?('[') && k.end_with?(']')
92
88
  end
@@ -28,13 +28,13 @@ require 'cli/kit'
28
28
  module CLI
29
29
  module Kit
30
30
  module Levenshtein
31
- extend T::Sig
31
+
32
32
 
33
33
  # This code is based directly on the Text gem implementation
34
34
  # Copyright (c) 2006-2013 Paul Battley, Michael Neumann, Tim Fletcher.
35
35
  #
36
36
  # Returns a value representing the "cost" of transforming str1 into str2
37
- sig { params(str1: String, str2: String).returns(Integer) }
37
+ #: (String str1, String str2) -> Integer
38
38
  def distance(str1, str2)
39
39
  n = str1.length
40
40
  m = str2.length
@@ -51,10 +51,12 @@ module CLI
51
51
  j = 0
52
52
  while j < m
53
53
  cost = char1 == str2_codepoints[j] ? 0 : 1
54
+ a = d[j] #: as !nil
55
+ b = d[j + 1] #: as !nil
54
56
  x = min3(
55
- T.must(d[j + 1]) + 1, # insertion
57
+ b + 1,
56
58
  i + 1, # deletion
57
- T.must(d[j]) + cost, # substitution
59
+ a + cost, # substitution
58
60
  )
59
61
  d[j] = i
60
62
  i = x
@@ -74,7 +76,7 @@ module CLI
74
76
  # faster than `[a, b, c].min` and puts less GC pressure.
75
77
  # See https://github.com/yuki24/did_you_mean/pull/1 for a performance
76
78
  # benchmark.
77
- sig { params(a: Integer, b: Integer, c: Integer).returns(Integer) }
79
+ #: (Integer a, Integer b, Integer c) -> Integer
78
80
  def min3(a, b, c)
79
81
  if a < b && a < c
80
82
  a
@@ -7,15 +7,13 @@ require 'fileutils'
7
7
  module CLI
8
8
  module Kit
9
9
  class Logger
10
- extend T::Sig
11
-
12
10
  MAX_LOG_SIZE = 5 * 1024 * 1000 # 5MB
13
11
  MAX_NUM_LOGS = 10
14
12
 
15
13
  # Constructor for CLI::Kit::Logger
16
14
  #
17
15
  # @param debug_log_file [String] path to the file where debug logs should be stored
18
- sig { params(debug_log_file: String, env_debug_name: String).void }
16
+ #: (debug_log_file: String, ?env_debug_name: String) -> void
19
17
  def initialize(debug_log_file:, env_debug_name: 'DEBUG')
20
18
  FileUtils.mkpath(File.dirname(debug_log_file))
21
19
  @debug_logger = ::Logger.new(debug_log_file, MAX_NUM_LOGS, MAX_LOG_SIZE)
@@ -27,7 +25,7 @@ module CLI
27
25
  #
28
26
  # @param msg [String] the message to log
29
27
  # @param debug [Boolean] determines if the debug logger will receive the log (default true)
30
- sig { params(msg: String, debug: T::Boolean).void }
28
+ #: (String msg, ?debug: bool) -> void
31
29
  def info(msg, debug: true)
32
30
  $stdout.puts CLI::UI.fmt(msg)
33
31
  @debug_logger.info(format_debug(msg)) if debug
@@ -38,7 +36,7 @@ module CLI
38
36
  #
39
37
  # @param msg [String] the message to log
40
38
  # @param debug [Boolean] determines if the debug logger will receive the log (default true)
41
- sig { params(msg: String, debug: T::Boolean).void }
39
+ #: (String msg, ?debug: bool) -> void
42
40
  def warn(msg, debug: true)
43
41
  $stdout.puts CLI::UI.fmt("{{yellow:#{msg}}}")
44
42
  @debug_logger.warn(format_debug(msg)) if debug
@@ -49,7 +47,7 @@ module CLI
49
47
  #
50
48
  # @param msg [String] the message to log
51
49
  # @param debug [Boolean] determines if the debug logger will receive the log (default true)
52
- sig { params(msg: String, debug: T::Boolean).void }
50
+ #: (String msg, ?debug: bool) -> void
53
51
  def error(msg, debug: true)
54
52
  $stderr.puts CLI::UI.fmt("{{red:#{msg}}}")
55
53
  @debug_logger.error(format_debug(msg)) if debug
@@ -60,7 +58,7 @@ module CLI
60
58
  #
61
59
  # @param msg [String] the message to log
62
60
  # @param debug [Boolean] determines if the debug logger will receive the log (default true)
63
- sig { params(msg: String, debug: T::Boolean).void }
61
+ #: (String msg, ?debug: bool) -> void
64
62
  def fatal(msg, debug: true)
65
63
  $stderr.puts CLI::UI.fmt("{{red:{{bold:Fatal:}} #{msg}}}")
66
64
  @debug_logger.fatal(format_debug(msg)) if debug
@@ -70,7 +68,7 @@ module CLI
70
68
  # Logs to the debug file, taking into account CLI::UI::StdoutRouter.current_id
71
69
  #
72
70
  # @param msg [String] the message to log
73
- sig { params(msg: String).void }
71
+ #: (String msg) -> void
74
72
  def debug(msg)
75
73
  $stdout.puts CLI::UI.fmt(msg) if debug?
76
74
  @debug_logger.debug(format_debug(msg))
@@ -78,7 +76,7 @@ module CLI
78
76
 
79
77
  private
80
78
 
81
- sig { params(msg: String).returns(String) }
79
+ #: (String msg) -> String
82
80
  def format_debug(msg)
83
81
  msg = CLI::UI.fmt(msg)
84
82
  return msg unless CLI::UI::StdoutRouter.current_id
@@ -86,7 +84,7 @@ module CLI
86
84
  "[#{CLI::UI::StdoutRouter.current_id&.fetch(:id, nil)}] #{msg}"
87
85
  end
88
86
 
89
- sig { returns(T::Boolean) }
87
+ #: -> bool
90
88
  def debug?
91
89
  val = ENV[@env_debug_name]
92
90
  !!val && val != '0' && val != ''