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.
- checksums.yaml +4 -4
- data/.rubocop.sorbet.yml +1 -0
- data/.rubocop.yml +1 -2
- data/Gemfile +1 -1
- data/Gemfile.lock +22 -24
- data/Rakefile +0 -1
- data/bin/testunit +0 -1
- data/examples/minimal/example.rb +1 -1
- data/examples/single-file/example.rb +4 -3
- data/gen/lib/gen/commands/help.rb +1 -3
- data/gen/lib/gen/commands/new.rb +2 -6
- data/gen/lib/gen/commands.rb +1 -7
- data/gen/lib/gen/entry_point.rb +1 -5
- data/gen/lib/gen/generator.rb +15 -19
- data/gen/lib/gen/help.rb +3 -7
- data/lib/cli/kit/args/definition.rb +37 -95
- data/lib/cli/kit/args/evaluation.rb +40 -59
- data/lib/cli/kit/args/parser/node.rb +19 -23
- data/lib/cli/kit/args/parser.rb +12 -16
- data/lib/cli/kit/args/tokenizer.rb +15 -18
- data/lib/cli/kit/base_command.rb +4 -8
- data/lib/cli/kit/command_help.rb +24 -27
- data/lib/cli/kit/command_registry.rb +40 -36
- data/lib/cli/kit/config.rb +14 -15
- data/lib/cli/kit/core_ext.rb +4 -6
- data/lib/cli/kit/error_handler.rb +17 -33
- data/lib/cli/kit/executor.rb +7 -16
- data/lib/cli/kit/ini.rb +8 -12
- data/lib/cli/kit/levenshtein.rb +7 -5
- data/lib/cli/kit/logger.rb +8 -10
- data/lib/cli/kit/opts.rb +26 -86
- data/lib/cli/kit/parse_args.rb +5 -10
- data/lib/cli/kit/resolver.rb +4 -6
- data/lib/cli/kit/support/test_helper.rb +10 -5
- data/lib/cli/kit/system.rb +25 -114
- data/lib/cli/kit/util.rb +15 -31
- data/lib/cli/kit/version.rb +1 -1
- data/lib/cli/kit.rb +17 -35
- metadata +1 -2
- data/lib/cli/kit/sorbet_runtime_stub.rb +0 -154
data/lib/cli/kit/config.rb
CHANGED
@@ -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
|
-
|
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
|
-
|
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
|
-
|
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
|
-
|
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
|
-
|
65
|
+
section.delete(name)
|
67
66
|
else
|
68
|
-
|
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
|
-
|
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
|
-
|
94
|
+
#: (String section) -> Hash[String, String]
|
96
95
|
def get_section(section)
|
97
96
|
(all_configs["[#{section}]"] || {}).dup
|
98
97
|
end
|
99
98
|
|
100
|
-
|
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
|
-
|
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
|
-
|
117
|
+
#: -> Hash[String, Hash[String, String]]
|
119
118
|
def all_configs
|
120
119
|
ini.ini
|
121
120
|
end
|
122
121
|
|
123
|
-
|
122
|
+
#: -> CLI::Kit::Ini
|
124
123
|
def ini
|
125
124
|
@ini ||= CLI::Kit::Ini.new(file).tap(&:parse)
|
126
125
|
end
|
127
126
|
|
128
|
-
|
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?
|
data/lib/cli/kit/core_ext.rb
CHANGED
@@ -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
|
-
|
9
|
+
#: -> bool
|
12
10
|
def bug?
|
13
11
|
true
|
14
12
|
end
|
15
13
|
|
16
|
-
|
14
|
+
#: -> bool
|
17
15
|
def silent?
|
18
16
|
false
|
19
17
|
end
|
20
18
|
|
21
|
-
|
19
|
+
#: (?bool bug) -> void
|
22
20
|
def bug!(bug = true)
|
23
21
|
singleton_class.define_method(:bug?) { bug }
|
24
22
|
end
|
25
23
|
|
26
|
-
|
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
|
-
|
9
|
+
#: type exception_reporter_or_proc = singleton(ExceptionReporter) | ^() -> singleton(ExceptionReporter)
|
10
10
|
|
11
|
-
|
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
|
-
|
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
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
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
|
-
|
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
|
-
|
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
|
-
|
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
|
-
|
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
|
-
|
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
|
-
|
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
|
-
|
155
|
+
#: -> singleton(ExceptionReporter)
|
172
156
|
def exception_reporter
|
173
157
|
case @exception_reporter_or_proc
|
174
158
|
when Proc
|
data/lib/cli/kit/executor.rb
CHANGED
@@ -7,15 +7,13 @@ require 'fileutils'
|
|
7
7
|
module CLI
|
8
8
|
module Kit
|
9
9
|
class Executor
|
10
|
-
|
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
|
-
|
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
|
-
|
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
|
-
|
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
|
-
|
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
|
-
|
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
|
-
|
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
|
-
|
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
|
-
|
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
|
-
|
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
|
-
|
52
|
+
#: -> String
|
57
53
|
def git_format
|
58
54
|
to_ini(git_format: true)
|
59
55
|
end
|
60
56
|
|
61
|
-
|
57
|
+
#: -> String
|
62
58
|
def to_s
|
63
59
|
to_ini
|
64
60
|
end
|
65
61
|
|
66
62
|
private
|
67
63
|
|
68
|
-
|
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
|
-
|
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
|
-
|
85
|
+
#: (String k) -> bool
|
90
86
|
def section_designator?(k)
|
91
87
|
k.start_with?('[') && k.end_with?(']')
|
92
88
|
end
|
data/lib/cli/kit/levenshtein.rb
CHANGED
@@ -28,13 +28,13 @@ require 'cli/kit'
|
|
28
28
|
module CLI
|
29
29
|
module Kit
|
30
30
|
module Levenshtein
|
31
|
-
|
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
|
-
|
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
|
-
|
57
|
+
b + 1,
|
56
58
|
i + 1, # deletion
|
57
|
-
|
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
|
-
|
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
|
data/lib/cli/kit/logger.rb
CHANGED
@@ -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
|
-
|
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
|
-
|
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
|
-
|
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
|
-
|
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
|
-
|
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
|
-
|
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
|
-
|
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
|
-
|
87
|
+
#: -> bool
|
90
88
|
def debug?
|
91
89
|
val = ENV[@env_debug_name]
|
92
90
|
!!val && val != '0' && val != ''
|