command_kit 0.1.0.rc1 → 0.1.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 +1 -1
- data/README.md +7 -4
- data/gemspec.yml +1 -1
- data/lib/command_kit.rb +1 -0
- data/lib/command_kit/arguments.rb +16 -1
- data/lib/command_kit/arguments/argument.rb +2 -0
- data/lib/command_kit/arguments/argument_value.rb +2 -0
- data/lib/command_kit/colors.rb +32 -0
- data/lib/command_kit/command.rb +5 -0
- data/lib/command_kit/command_name.rb +9 -0
- data/lib/command_kit/commands.rb +30 -0
- data/lib/command_kit/commands/auto_load.rb +16 -0
- data/lib/command_kit/commands/auto_require.rb +16 -0
- data/lib/command_kit/commands/command.rb +3 -0
- data/lib/command_kit/commands/help.rb +2 -0
- data/lib/command_kit/commands/parent_command.rb +7 -0
- data/lib/command_kit/commands/subcommand.rb +12 -0
- data/lib/command_kit/description.rb +12 -1
- data/lib/command_kit/env.rb +4 -0
- data/lib/command_kit/env/home.rb +9 -0
- data/lib/command_kit/env/path.rb +15 -0
- data/lib/command_kit/examples.rb +12 -1
- data/lib/command_kit/exception_handler.rb +4 -0
- data/lib/command_kit/help.rb +7 -1
- data/lib/command_kit/help/man.rb +13 -0
- data/lib/command_kit/inflector.rb +2 -0
- data/lib/command_kit/interactive.rb +62 -1
- data/lib/command_kit/main.rb +11 -0
- data/lib/command_kit/options.rb +12 -0
- data/lib/command_kit/options/option.rb +2 -0
- data/lib/command_kit/options/option_value.rb +2 -0
- data/lib/command_kit/options/parser.rb +29 -0
- data/lib/command_kit/options/quiet.rb +3 -0
- data/lib/command_kit/options/verbose.rb +5 -0
- data/lib/command_kit/options/version.rb +6 -0
- data/lib/command_kit/os.rb +6 -0
- data/lib/command_kit/pager.rb +27 -0
- data/lib/command_kit/printing.rb +23 -0
- data/lib/command_kit/printing/indent.rb +23 -0
- data/lib/command_kit/program_name.rb +7 -0
- data/lib/command_kit/stdio.rb +24 -0
- data/lib/command_kit/terminal.rb +12 -0
- data/lib/command_kit/usage.rb +14 -0
- data/lib/command_kit/version.rb +1 -1
- data/lib/command_kit/xdg.rb +13 -0
- data/spec/arguments/argument_spec.rb +1 -1
- data/spec/arguments_spec.rb +3 -27
- data/spec/colors_spec.rb +21 -13
- data/spec/command_name_spec.rb +1 -1
- data/spec/command_spec.rb +4 -1
- data/spec/commands/auto_load/subcommand_spec.rb +1 -1
- data/spec/commands/auto_load_spec.rb +1 -1
- data/spec/commands/auto_require_spec.rb +2 -2
- data/spec/commands/help_spec.rb +1 -1
- data/spec/commands/parent_command_spec.rb +1 -1
- data/spec/commands/subcommand_spec.rb +1 -1
- data/spec/commands_spec.rb +1 -1
- data/spec/description_spec.rb +1 -25
- data/spec/env/home_spec.rb +1 -1
- data/spec/env/path_spec.rb +1 -1
- data/spec/examples_spec.rb +1 -25
- data/spec/help/man_spec.rb +1 -1
- data/spec/help_spec.rb +0 -25
- data/spec/inflector_spec.rb +1 -1
- data/spec/main_spec.rb +7 -7
- data/spec/options/option_spec.rb +3 -3
- data/spec/options/option_value_spec.rb +1 -1
- data/spec/options_spec.rb +1 -1
- data/spec/os_spec.rb +1 -1
- data/spec/pager_spec.rb +1 -1
- data/spec/printing/indent_spec.rb +1 -1
- data/spec/printing_spec.rb +10 -2
- data/spec/program_name_spec.rb +1 -1
- data/spec/spec_helper.rb +0 -3
- data/spec/terminal_spec.rb +1 -1
- data/spec/usage_spec.rb +1 -1
- data/spec/xdg_spec.rb +1 -1
- metadata +3 -3
@@ -27,11 +27,15 @@ module CommandKit
|
|
27
27
|
# The directory to attempt to require command files within.
|
28
28
|
#
|
29
29
|
# @return [String]
|
30
|
+
#
|
31
|
+
# @api private
|
30
32
|
attr_reader :dir
|
31
33
|
|
32
34
|
# The namespace to lookup command classes within.
|
33
35
|
#
|
34
36
|
# @return [String]
|
37
|
+
#
|
38
|
+
# @api private
|
35
39
|
attr_reader :namespace
|
36
40
|
|
37
41
|
#
|
@@ -43,6 +47,8 @@ module CommandKit
|
|
43
47
|
# @param [String] namespace
|
44
48
|
# The namespace to search for command classes in.
|
45
49
|
#
|
50
|
+
# @api public
|
51
|
+
#
|
46
52
|
def initialize(dir: , namespace: )
|
47
53
|
@dir = dir
|
48
54
|
@namespace = namespace
|
@@ -57,6 +63,8 @@ module CommandKit
|
|
57
63
|
# @return [String]
|
58
64
|
# The path to the file that should contain the command.
|
59
65
|
#
|
66
|
+
# @api private
|
67
|
+
#
|
60
68
|
def join(name)
|
61
69
|
File.join(@dir,name)
|
62
70
|
end
|
@@ -70,6 +78,8 @@ module CommandKit
|
|
70
78
|
#
|
71
79
|
# @raise [LoadError]
|
72
80
|
#
|
81
|
+
# @api private
|
82
|
+
#
|
73
83
|
def require(file_name)
|
74
84
|
super(join(file_name))
|
75
85
|
end
|
@@ -86,6 +96,8 @@ module CommandKit
|
|
86
96
|
# @raise [NameError]
|
87
97
|
# The command class could not be found within the {#namespace}.
|
88
98
|
#
|
99
|
+
# @api private
|
100
|
+
#
|
89
101
|
def const_get(constant)
|
90
102
|
Object.const_get("::#{@namespace}::#{constant}",false)
|
91
103
|
end
|
@@ -100,6 +112,8 @@ module CommandKit
|
|
100
112
|
# The command's class, or `nil` if the command cannot be loaded from
|
101
113
|
# {#dir} or found within {#namespace}.
|
102
114
|
#
|
115
|
+
# @api private
|
116
|
+
#
|
103
117
|
def command(command_name)
|
104
118
|
file_name = Inflector.underscore(command_name)
|
105
119
|
|
@@ -125,6 +139,8 @@ module CommandKit
|
|
125
139
|
# @param [Class] command
|
126
140
|
# The command class including {AutoRequire}.
|
127
141
|
#
|
142
|
+
# @api private
|
143
|
+
#
|
128
144
|
def included(command)
|
129
145
|
command.include Commands
|
130
146
|
command.commands.default_proc = ->(hash,key) {
|
@@ -1,15 +1,22 @@
|
|
1
1
|
module CommandKit
|
2
2
|
module Commands
|
3
|
+
#
|
4
|
+
# Allows a command to be aware of it's parent command.
|
5
|
+
#
|
3
6
|
module ParentCommand
|
4
7
|
|
5
8
|
# The parent command instance.
|
6
9
|
#
|
7
10
|
# @return [Object<Commands>]
|
11
|
+
#
|
12
|
+
# @api semipublic
|
8
13
|
attr_reader :parent_command
|
9
14
|
|
10
15
|
#
|
11
16
|
# Initializes the command and sets {#parent_command}.
|
12
17
|
#
|
18
|
+
# @api public
|
19
|
+
#
|
13
20
|
def initialize(parent_command: , **kwargs)
|
14
21
|
@parent_command = parent_command
|
15
22
|
|
@@ -3,6 +3,8 @@ module CommandKit
|
|
3
3
|
#
|
4
4
|
# Represents a registered subcommand.
|
5
5
|
#
|
6
|
+
# @api private
|
7
|
+
#
|
6
8
|
class Subcommand
|
7
9
|
|
8
10
|
# The command class.
|
@@ -40,6 +42,16 @@ module CommandKit
|
|
40
42
|
@aliases = aliases.map(&:to_s)
|
41
43
|
end
|
42
44
|
|
45
|
+
#
|
46
|
+
# Derives a summary from the command's description.
|
47
|
+
#
|
48
|
+
# @param [Class] command
|
49
|
+
# The command class.
|
50
|
+
#
|
51
|
+
# @return [String, nil]
|
52
|
+
# If the command responds to a `#description` method, the first sentence
|
53
|
+
# of the description will be returned. Otherwise `nil` is returned.
|
54
|
+
#
|
43
55
|
def self.summary(command)
|
44
56
|
if command.respond_to?(:description)
|
45
57
|
if (desc = command.description)
|
@@ -13,6 +13,9 @@ module CommandKit
|
|
13
13
|
module Description
|
14
14
|
include Help
|
15
15
|
|
16
|
+
#
|
17
|
+
# @api private
|
18
|
+
#
|
16
19
|
module ModuleMethods
|
17
20
|
#
|
18
21
|
# Extends {ClassMethods} or {ModuleMethods}, depending on whether
|
@@ -50,6 +53,8 @@ module CommandKit
|
|
50
53
|
# @example
|
51
54
|
# description "Does things and stuff"
|
52
55
|
#
|
56
|
+
# @api public
|
57
|
+
#
|
53
58
|
def description(new_description=nil)
|
54
59
|
if new_description
|
55
60
|
@description = new_description
|
@@ -64,6 +69,8 @@ module CommandKit
|
|
64
69
|
#
|
65
70
|
# @see ClassMethods#description
|
66
71
|
#
|
72
|
+
# @api semipublic
|
73
|
+
#
|
67
74
|
def description
|
68
75
|
self.class.description
|
69
76
|
end
|
@@ -71,6 +78,8 @@ module CommandKit
|
|
71
78
|
#
|
72
79
|
# Prints the {ClassMethods#description description}, if set.
|
73
80
|
#
|
81
|
+
# @api semipublic
|
82
|
+
#
|
74
83
|
def help_description
|
75
84
|
if (description = self.description)
|
76
85
|
puts
|
@@ -82,8 +91,10 @@ module CommandKit
|
|
82
91
|
# Calls the superclass'es `#help` method, if it's defined, then calls
|
83
92
|
# {#help_description}.
|
84
93
|
#
|
94
|
+
# @api public
|
95
|
+
#
|
85
96
|
def help
|
86
|
-
super
|
97
|
+
super
|
87
98
|
|
88
99
|
help_description
|
89
100
|
end
|
data/lib/command_kit/env.rb
CHANGED
@@ -23,6 +23,8 @@ module CommandKit
|
|
23
23
|
# The environment variables hash.
|
24
24
|
#
|
25
25
|
# @return [Hash{String => String}]
|
26
|
+
#
|
27
|
+
# @api public
|
26
28
|
attr_reader :env
|
27
29
|
|
28
30
|
#
|
@@ -34,6 +36,8 @@ module CommandKit
|
|
34
36
|
# @param [Hash{Symbol => Object}] kwargs
|
35
37
|
# Additional keyword arguments.
|
36
38
|
#
|
39
|
+
# @api public
|
40
|
+
#
|
37
41
|
def initialize(env: ENV, **kwargs)
|
38
42
|
@env = env
|
39
43
|
|
data/lib/command_kit/env/home.rb
CHANGED
@@ -14,6 +14,9 @@ module CommandKit
|
|
14
14
|
module Home
|
15
15
|
include Env
|
16
16
|
|
17
|
+
#
|
18
|
+
# @api private
|
19
|
+
#
|
17
20
|
module ModuleMethods
|
18
21
|
#
|
19
22
|
# Extends {ClassMethods} or {ModuleMethods}, depending on whether
|
@@ -44,6 +47,8 @@ module CommandKit
|
|
44
47
|
#
|
45
48
|
# @return [String]
|
46
49
|
#
|
50
|
+
# @api semipublic
|
51
|
+
#
|
47
52
|
def home_dir
|
48
53
|
Gem.user_home
|
49
54
|
end
|
@@ -52,6 +57,8 @@ module CommandKit
|
|
52
57
|
# The home directory.
|
53
58
|
#
|
54
59
|
# @return [String]
|
60
|
+
#
|
61
|
+
# @api public
|
55
62
|
attr_reader :home_dir
|
56
63
|
|
57
64
|
#
|
@@ -61,6 +68,8 @@ module CommandKit
|
|
61
68
|
# @param [Hash{Symbol => Object}] kwargs
|
62
69
|
# Additional keyword arguments.
|
63
70
|
#
|
71
|
+
# @api public
|
72
|
+
#
|
64
73
|
def initialize(**kwargs)
|
65
74
|
super(**kwargs)
|
66
75
|
|
data/lib/command_kit/env/path.rb
CHANGED
@@ -17,6 +17,8 @@ module CommandKit
|
|
17
17
|
# The home directory.
|
18
18
|
#
|
19
19
|
# @return [String]
|
20
|
+
#
|
21
|
+
# @api semipublic
|
20
22
|
attr_reader :path_dirs
|
21
23
|
|
22
24
|
#
|
@@ -25,6 +27,8 @@ module CommandKit
|
|
25
27
|
# @param [Hash{Symbol => Object}] kwargs
|
26
28
|
# Additional keyword arguments.
|
27
29
|
#
|
30
|
+
# @api public
|
31
|
+
#
|
28
32
|
def initialize(**kwargs)
|
29
33
|
super(**kwargs)
|
30
34
|
|
@@ -41,6 +45,8 @@ module CommandKit
|
|
41
45
|
# The absolute path to the executable file, or `nil` if the command
|
42
46
|
# could not be found in any of the {#path_dirs}.
|
43
47
|
#
|
48
|
+
# @api public
|
49
|
+
#
|
44
50
|
def find_command(name)
|
45
51
|
name = name.to_s
|
46
52
|
|
@@ -63,6 +69,15 @@ module CommandKit
|
|
63
69
|
# Specifies whether a command with the given name exists in one of the
|
64
70
|
# {#path_dirs}.
|
65
71
|
#
|
72
|
+
# @example
|
73
|
+
# if command_installed?("docker")
|
74
|
+
# # ...
|
75
|
+
# else
|
76
|
+
# abort "Docker is not installed. Aborting"
|
77
|
+
# end
|
78
|
+
#
|
79
|
+
# @api public
|
80
|
+
#
|
66
81
|
def command_installed?(name)
|
67
82
|
!find_command(name).nil?
|
68
83
|
end
|
data/lib/command_kit/examples.rb
CHANGED
@@ -17,6 +17,9 @@ module CommandKit
|
|
17
17
|
include Help
|
18
18
|
include CommandName
|
19
19
|
|
20
|
+
#
|
21
|
+
# @api private
|
22
|
+
#
|
20
23
|
module ModuleMethods
|
21
24
|
#
|
22
25
|
# Extends {ClassMethods} or {ModuleMethods}, depending on whether
|
@@ -57,6 +60,8 @@ module CommandKit
|
|
57
60
|
# "-o output.txt path/to/file"
|
58
61
|
# ]
|
59
62
|
#
|
63
|
+
# @api public
|
64
|
+
#
|
60
65
|
def examples(new_examples=nil)
|
61
66
|
if new_examples
|
62
67
|
@examples = Array(new_examples)
|
@@ -71,6 +76,8 @@ module CommandKit
|
|
71
76
|
#
|
72
77
|
# @see ClassMethods#examples
|
73
78
|
#
|
79
|
+
# @api semipublic
|
80
|
+
#
|
74
81
|
def examples
|
75
82
|
self.class.examples
|
76
83
|
end
|
@@ -78,6 +85,8 @@ module CommandKit
|
|
78
85
|
#
|
79
86
|
# Prints the command class'es example commands.
|
80
87
|
#
|
88
|
+
# @api semipublic
|
89
|
+
#
|
81
90
|
def help_examples
|
82
91
|
if (examples = self.examples)
|
83
92
|
puts
|
@@ -92,8 +101,10 @@ module CommandKit
|
|
92
101
|
# Calls the superclass'es `#help` method, if it's defined, then calls
|
93
102
|
# {#help_examples}.
|
94
103
|
#
|
104
|
+
# @api public
|
105
|
+
#
|
95
106
|
def help
|
96
|
-
super
|
107
|
+
super
|
97
108
|
|
98
109
|
help_examples
|
99
110
|
end
|
@@ -33,6 +33,8 @@ module CommandKit
|
|
33
33
|
# @return [Integer]
|
34
34
|
# The exit status of the command.
|
35
35
|
#
|
36
|
+
# @api public
|
37
|
+
#
|
36
38
|
def main(argv=[])
|
37
39
|
super(argv)
|
38
40
|
rescue Interrupt, Errno::EPIPE => error
|
@@ -47,6 +49,8 @@ module CommandKit
|
|
47
49
|
# @param [Exception] error
|
48
50
|
# The raised exception.
|
49
51
|
#
|
52
|
+
# @api semipublic
|
53
|
+
#
|
50
54
|
def on_exception(error)
|
51
55
|
print_exception(error)
|
52
56
|
exit(1)
|
data/lib/command_kit/help.rb
CHANGED
@@ -15,6 +15,9 @@ module CommandKit
|
|
15
15
|
# MyCmd.help
|
16
16
|
#
|
17
17
|
module Help
|
18
|
+
#
|
19
|
+
# @api private
|
20
|
+
#
|
18
21
|
module ModuleMethods
|
19
22
|
#
|
20
23
|
# Extends {ClassMethods} or {ModuleMethods}, depending on whether {Help}
|
@@ -48,6 +51,8 @@ module CommandKit
|
|
48
51
|
#
|
49
52
|
# @see Help#help
|
50
53
|
#
|
54
|
+
# @api public
|
55
|
+
#
|
51
56
|
def help(**kwargs)
|
52
57
|
new(**kwargs).help
|
53
58
|
end
|
@@ -58,8 +63,9 @@ module CommandKit
|
|
58
63
|
#
|
59
64
|
# @abstract
|
60
65
|
#
|
66
|
+
# @api public
|
67
|
+
#
|
61
68
|
def help
|
62
|
-
super if defined?(super)
|
63
69
|
end
|
64
70
|
end
|
65
71
|
end
|
data/lib/command_kit/help/man.rb
CHANGED
@@ -24,6 +24,9 @@ module CommandKit
|
|
24
24
|
include Help
|
25
25
|
include Stdio
|
26
26
|
|
27
|
+
#
|
28
|
+
# @api private
|
29
|
+
#
|
27
30
|
module ModuleMethods
|
28
31
|
#
|
29
32
|
# Extends {ClassMethods} or {ModuleMethods}, depending on whether
|
@@ -61,6 +64,8 @@ module CommandKit
|
|
61
64
|
# @example
|
62
65
|
# man_dir "#{__dir__}/../../man"
|
63
66
|
#
|
67
|
+
# @api public
|
68
|
+
#
|
64
69
|
def man_dir(new_man_dir=nil)
|
65
70
|
if new_man_dir
|
66
71
|
@man_dir = new_man_dir
|
@@ -80,6 +85,8 @@ module CommandKit
|
|
80
85
|
# @return [String]
|
81
86
|
# The class'es or superclass'es man-page file name.
|
82
87
|
#
|
88
|
+
# @api public
|
89
|
+
#
|
83
90
|
def man_page(new_man_page=nil)
|
84
91
|
if new_man_page
|
85
92
|
@man_page = new_man_page
|
@@ -102,6 +109,8 @@ module CommandKit
|
|
102
109
|
# Specifies whether the `man` command was successful or not.
|
103
110
|
# Returns `nil` when the `man` command is not installed.
|
104
111
|
#
|
112
|
+
# @api public
|
113
|
+
#
|
105
114
|
def man(page, section: nil)
|
106
115
|
if section
|
107
116
|
system('man',section.to_s,page.to_s)
|
@@ -124,6 +133,8 @@ module CommandKit
|
|
124
133
|
# @raise [NotImplementedError]
|
125
134
|
# {ClassMethods#man_dir .man_dir} does not have a value.
|
126
135
|
#
|
136
|
+
# @api semipublic
|
137
|
+
#
|
127
138
|
def help_man(man_page=self.class.man_page)
|
128
139
|
unless self.class.man_dir
|
129
140
|
raise(NotImplementedError,"#{self.class}.man_dir not set")
|
@@ -145,6 +156,8 @@ module CommandKit
|
|
145
156
|
# if `TERM` is `dumb` or `$stdout` is not a TTY, fallsback to printing
|
146
157
|
# the usual `--help` output.
|
147
158
|
#
|
159
|
+
# @api public
|
160
|
+
#
|
148
161
|
def help
|
149
162
|
if stdout.tty?
|
150
163
|
if help_man.nil?
|
@@ -1,6 +1,39 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
require 'command_kit/stdio'
|
2
4
|
|
3
5
|
module CommandKit
|
6
|
+
#
|
7
|
+
# Provides methods for asking the user for input.
|
8
|
+
#
|
9
|
+
# ## Examples
|
10
|
+
#
|
11
|
+
# first_name = ask("First name")
|
12
|
+
# last_name = ask("Last name")
|
13
|
+
#
|
14
|
+
# ### Asking for secret input
|
15
|
+
#
|
16
|
+
# password = ask_secret("Password")
|
17
|
+
#
|
18
|
+
# ### Asking Y/N?
|
19
|
+
#
|
20
|
+
# if ask_yes_or_no("Proceed anyways?")
|
21
|
+
# # ...
|
22
|
+
# else
|
23
|
+
# stderr.puts "Aborting!"
|
24
|
+
# end
|
25
|
+
#
|
26
|
+
# ### Asking multi-choice questions
|
27
|
+
#
|
28
|
+
# ask_multiple_choice("Select a flavor", %w[Apple Orange Lemon Lime])
|
29
|
+
# # 1) Apple
|
30
|
+
# # 2) Orange
|
31
|
+
# # 3) Lemon
|
32
|
+
# # 4) Lime
|
33
|
+
# # Select a flavor: 4
|
34
|
+
# #
|
35
|
+
# # => "Lime"
|
36
|
+
#
|
4
37
|
module Interactive
|
5
38
|
include Stdio
|
6
39
|
|
@@ -19,6 +52,23 @@ module CommandKit
|
|
19
52
|
# @return [String]
|
20
53
|
# The user input.
|
21
54
|
#
|
55
|
+
# @example
|
56
|
+
# first_name = ask("First name")
|
57
|
+
# last_name = ask("Last name")
|
58
|
+
#
|
59
|
+
# @example Default value:
|
60
|
+
# ask("Country", default: "EU")
|
61
|
+
# # Country [EU]: <enter>
|
62
|
+
# # => "EU"
|
63
|
+
#
|
64
|
+
# @example Required non-empty input:
|
65
|
+
# ask("Email", required: true)
|
66
|
+
# # Email: <enter>
|
67
|
+
# # Email: bob@example.com<enter>
|
68
|
+
# # => "bob@example.com"
|
69
|
+
#
|
70
|
+
# @api public
|
71
|
+
#
|
22
72
|
def ask(prompt, default: nil, required: false)
|
23
73
|
prompt = prompt.chomp
|
24
74
|
prompt << " [#{default}]" if default
|
@@ -56,7 +106,14 @@ module CommandKit
|
|
56
106
|
# @example
|
57
107
|
# ask_yes_or_no("Proceed anyways?")
|
58
108
|
# # Proceed anyways? (Y/N): Y
|
59
|
-
# # =>
|
109
|
+
# # => true
|
110
|
+
#
|
111
|
+
# @example Default value:
|
112
|
+
# ask_yes_or_no("Proceed anyways?", default: true)
|
113
|
+
# # Proceed anyways? (Y/N) [Y]: <enter>
|
114
|
+
# # => true
|
115
|
+
#
|
116
|
+
# @api public
|
60
117
|
#
|
61
118
|
def ask_yes_or_no(prompt, default: nil, **kwargs)
|
62
119
|
default = case default
|
@@ -123,6 +180,8 @@ module CommandKit
|
|
123
180
|
# #
|
124
181
|
# # => "All of the above"
|
125
182
|
#
|
183
|
+
# @api public
|
184
|
+
#
|
126
185
|
def ask_multiple_choice(prompt,choices,**kwargs)
|
127
186
|
choices = case choices
|
128
187
|
when Array
|
@@ -164,6 +223,8 @@ module CommandKit
|
|
164
223
|
# # Password:
|
165
224
|
# # => "s3cr3t"
|
166
225
|
#
|
226
|
+
# @api public
|
227
|
+
#
|
167
228
|
def ask_secret(prompt, required: true)
|
168
229
|
if stdin.respond_to?(:noecho)
|
169
230
|
stdin.noecho do
|