command_kit 0.1.0.rc1 → 0.2.2
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/.github/workflows/ruby.yml +17 -3
- data/.rubocop.yml +141 -0
- data/ChangeLog.md +102 -1
- data/Gemfile +3 -0
- data/README.md +187 -116
- data/Rakefile +3 -2
- data/command_kit.gemspec +4 -4
- data/examples/command.rb +1 -1
- data/gemspec.yml +8 -1
- data/lib/command_kit/arguments/argument.rb +2 -0
- data/lib/command_kit/arguments/argument_value.rb +2 -0
- data/lib/command_kit/arguments.rb +25 -6
- data/lib/command_kit/colors.rb +253 -45
- data/lib/command_kit/command.rb +6 -1
- data/lib/command_kit/command_name.rb +9 -0
- data/lib/command_kit/commands/auto_load.rb +24 -1
- 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 +5 -2
- data/lib/command_kit/commands/parent_command.rb +7 -0
- data/lib/command_kit/commands/subcommand.rb +13 -1
- data/lib/command_kit/commands.rb +54 -9
- data/lib/command_kit/description.rb +12 -1
- data/lib/command_kit/env/home.rb +9 -0
- data/lib/command_kit/env/path.rb +16 -1
- data/lib/command_kit/env.rb +4 -0
- data/lib/command_kit/examples.rb +12 -1
- data/lib/command_kit/exception_handler.rb +4 -0
- data/lib/command_kit/help/man.rb +28 -31
- data/lib/command_kit/help.rb +7 -1
- data/lib/command_kit/inflector.rb +49 -17
- data/lib/command_kit/interactive.rb +71 -1
- data/lib/command_kit/main.rb +18 -9
- data/lib/command_kit/man.rb +44 -0
- data/lib/command_kit/open_app.rb +69 -0
- data/lib/command_kit/options/option.rb +3 -6
- data/lib/command_kit/options/option_value.rb +5 -2
- data/lib/command_kit/options/parser.rb +46 -19
- 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/options.rb +32 -7
- data/lib/command_kit/os/linux.rb +157 -0
- data/lib/command_kit/os.rb +165 -11
- data/lib/command_kit/package_manager.rb +200 -0
- data/lib/command_kit/pager.rb +73 -4
- data/lib/command_kit/printing/indent.rb +27 -4
- data/lib/command_kit/printing.rb +35 -1
- data/lib/command_kit/program_name.rb +7 -0
- data/lib/command_kit/stdio.rb +24 -0
- data/lib/command_kit/sudo.rb +40 -0
- data/lib/command_kit/terminal.rb +17 -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/lib/command_kit.rb +1 -0
- data/spec/arguments/argument_spec.rb +2 -2
- data/spec/arguments_spec.rb +54 -28
- data/spec/colors_spec.rb +277 -13
- data/spec/command_name_spec.rb +1 -1
- data/spec/command_spec.rb +79 -5
- data/spec/commands/auto_load/subcommand_spec.rb +1 -1
- data/spec/commands/auto_load_spec.rb +34 -3
- 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 +102 -30
- data/spec/description_spec.rb +1 -25
- data/spec/env/home_spec.rb +1 -1
- data/spec/env/path_spec.rb +7 -1
- data/spec/examples_spec.rb +1 -25
- data/spec/exception_handler_spec.rb +1 -1
- data/spec/help/man_spec.rb +55 -58
- data/spec/help_spec.rb +0 -25
- data/spec/inflector_spec.rb +71 -9
- data/spec/main_spec.rb +7 -7
- data/spec/man_spec.rb +46 -0
- data/spec/open_app_spec.rb +85 -0
- data/spec/options/option_spec.rb +5 -5
- data/spec/options/option_value_spec.rb +56 -1
- data/spec/options_spec.rb +283 -1
- data/spec/os/linux_spec.rb +164 -0
- data/spec/os_spec.rb +201 -14
- data/spec/package_manager_spec.rb +806 -0
- data/spec/pager_spec.rb +72 -7
- data/spec/printing/indent_spec.rb +8 -6
- data/spec/printing_spec.rb +33 -3
- data/spec/program_name_spec.rb +1 -1
- data/spec/spec_helper.rb +0 -3
- data/spec/sudo_spec.rb +51 -0
- data/spec/terminal_spec.rb +31 -1
- data/spec/usage_spec.rb +2 -2
- data/spec/xdg_spec.rb +1 -1
- metadata +21 -5
data/lib/command_kit/help/man.rb
CHANGED
@@ -3,6 +3,7 @@
|
|
3
3
|
require 'command_kit/command_name'
|
4
4
|
require 'command_kit/help'
|
5
5
|
require 'command_kit/stdio'
|
6
|
+
require 'command_kit/man'
|
6
7
|
|
7
8
|
module CommandKit
|
8
9
|
module Help
|
@@ -23,7 +24,11 @@ module CommandKit
|
|
23
24
|
include CommandName
|
24
25
|
include Help
|
25
26
|
include Stdio
|
27
|
+
include CommandKit::Man
|
26
28
|
|
29
|
+
#
|
30
|
+
# @api private
|
31
|
+
#
|
27
32
|
module ModuleMethods
|
28
33
|
#
|
29
34
|
# Extends {ClassMethods} or {ModuleMethods}, depending on whether
|
@@ -61,9 +66,11 @@ module CommandKit
|
|
61
66
|
# @example
|
62
67
|
# man_dir "#{__dir__}/../../man"
|
63
68
|
#
|
69
|
+
# @api public
|
70
|
+
#
|
64
71
|
def man_dir(new_man_dir=nil)
|
65
72
|
if new_man_dir
|
66
|
-
@man_dir = new_man_dir
|
73
|
+
@man_dir = File.expand_path(new_man_dir)
|
67
74
|
else
|
68
75
|
@man_dir || if superclass.kind_of?(ClassMethods)
|
69
76
|
superclass.man_dir
|
@@ -80,6 +87,8 @@ module CommandKit
|
|
80
87
|
# @return [String]
|
81
88
|
# The class'es or superclass'es man-page file name.
|
82
89
|
#
|
90
|
+
# @api public
|
91
|
+
#
|
83
92
|
def man_page(new_man_page=nil)
|
84
93
|
if new_man_page
|
85
94
|
@man_page = new_man_page
|
@@ -89,27 +98,6 @@ module CommandKit
|
|
89
98
|
end
|
90
99
|
end
|
91
100
|
|
92
|
-
#
|
93
|
-
# Displays the given man page.
|
94
|
-
#
|
95
|
-
# @param [String] page
|
96
|
-
# The man page file name.
|
97
|
-
#
|
98
|
-
# @param [Integer, String, nil] section
|
99
|
-
# The optional section number to specify.
|
100
|
-
#
|
101
|
-
# @return [Boolean, nil]
|
102
|
-
# Specifies whether the `man` command was successful or not.
|
103
|
-
# Returns `nil` when the `man` command is not installed.
|
104
|
-
#
|
105
|
-
def man(page, section: nil)
|
106
|
-
if section
|
107
|
-
system('man',section.to_s,page.to_s)
|
108
|
-
else
|
109
|
-
system('man',page.to_s)
|
110
|
-
end
|
111
|
-
end
|
112
|
-
|
113
101
|
#
|
114
102
|
# Provides help information by showing one of the man pages within
|
115
103
|
# {ClassMethods#man_dir .man_dir}.
|
@@ -122,11 +110,13 @@ module CommandKit
|
|
122
110
|
# Returns `nil` when the `man` command is not installed.
|
123
111
|
#
|
124
112
|
# @raise [NotImplementedError]
|
125
|
-
# {ClassMethods#man_dir .man_dir}
|
113
|
+
# {ClassMethods#man_dir .man_dir} was not set in the class.
|
114
|
+
#
|
115
|
+
# @api semipublic
|
126
116
|
#
|
127
117
|
def help_man(man_page=self.class.man_page)
|
128
118
|
unless self.class.man_dir
|
129
|
-
raise(NotImplementedError,"#{self.class}
|
119
|
+
raise(NotImplementedError,"man_dir was not set in #{self.class}")
|
130
120
|
end
|
131
121
|
|
132
122
|
man_path = File.join(self.class.man_dir,man_page)
|
@@ -138,20 +128,27 @@ module CommandKit
|
|
138
128
|
# Displays the {ClassMethods#man_page .man_page} in
|
139
129
|
# {ClassMethods#man_dir .man_dir} instead of the usual `--help` output.
|
140
130
|
#
|
141
|
-
# @raise [NotImplementedError]
|
142
|
-
# {ClassMethods#man_dir .man_dir} does not have a value.
|
143
|
-
#
|
144
131
|
# @note
|
145
|
-
# if `TERM` is `dumb` or `$stdout` is not a TTY,
|
146
|
-
# the usual `--help` output.
|
132
|
+
# if `TERM` is `dumb` or `$stdout` is not a TTY, will fall back to
|
133
|
+
# printing the usual `--help` output.
|
134
|
+
#
|
135
|
+
# @api public
|
147
136
|
#
|
148
137
|
def help
|
149
138
|
if stdout.tty?
|
150
|
-
if
|
151
|
-
|
139
|
+
if self.class.man_dir
|
140
|
+
status = help_man
|
141
|
+
|
142
|
+
if status.nil?
|
143
|
+
# the `man` command is not installed
|
144
|
+
super
|
145
|
+
end
|
146
|
+
else
|
147
|
+
# man_dir was not set
|
152
148
|
super
|
153
149
|
end
|
154
150
|
else
|
151
|
+
# stdout is not a TTY
|
155
152
|
super
|
156
153
|
end
|
157
154
|
end
|
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
|
@@ -1,5 +1,7 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
+
require 'strscan'
|
4
|
+
|
3
5
|
module CommandKit
|
4
6
|
#
|
5
7
|
# A very simple inflector.
|
@@ -8,6 +10,8 @@ module CommandKit
|
|
8
10
|
# If you need something more powerful, checkout
|
9
11
|
# [dry-inflector](https://dry-rb.org/gems/dry-inflector/0.1/)
|
10
12
|
#
|
13
|
+
# @api semipublic
|
14
|
+
#
|
11
15
|
module Inflector
|
12
16
|
#
|
13
17
|
# Removes the namespace from a constant name.
|
@@ -31,16 +35,37 @@ module CommandKit
|
|
31
35
|
# @return [String]
|
32
36
|
# The resulting under_scored name.
|
33
37
|
#
|
38
|
+
# @raise [ArgumentError]
|
39
|
+
# The given string contained non-alpha-numeric characters.
|
40
|
+
#
|
34
41
|
def self.underscore(name)
|
35
|
-
|
36
|
-
|
42
|
+
scanner = StringScanner.new(name.to_s)
|
43
|
+
new_string = String.new
|
37
44
|
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
45
|
+
until scanner.eos?
|
46
|
+
if (separator = scanner.scan(/[_-]+/))
|
47
|
+
new_string << ('_' * separator.length)
|
48
|
+
else
|
49
|
+
if (capitalized = scanner.scan(/[A-Z][a-z\d]+/))
|
50
|
+
new_string << capitalized
|
51
|
+
elsif (uppercase = scanner.scan(/[A-Z][A-Z\d]*(?=[A-Z_-]|$)/))
|
52
|
+
new_string << uppercase
|
53
|
+
elsif (lowercase = scanner.scan(/[a-z][a-z\d]*/))
|
54
|
+
new_string << lowercase
|
55
|
+
else
|
56
|
+
raise(ArgumentError,"cannot convert string to underscored: #{scanner.string.inspect}")
|
57
|
+
end
|
42
58
|
|
43
|
-
|
59
|
+
if (separator = scanner.scan(/[_-]+/))
|
60
|
+
new_string << ('_' * separator.length)
|
61
|
+
elsif !scanner.eos?
|
62
|
+
new_string << '_'
|
63
|
+
end
|
64
|
+
end
|
65
|
+
end
|
66
|
+
|
67
|
+
new_string.downcase!
|
68
|
+
new_string
|
44
69
|
end
|
45
70
|
|
46
71
|
#
|
@@ -65,20 +90,27 @@ module CommandKit
|
|
65
90
|
# @return [String]
|
66
91
|
# The CamelCased name.
|
67
92
|
#
|
93
|
+
# @raise [ArgumentError]
|
94
|
+
# The given under_scored string contained non-alpha-numeric characters.
|
95
|
+
#
|
68
96
|
def self.camelize(name)
|
69
|
-
|
70
|
-
|
71
|
-
# sourced from: https://github.com/dry-rb/dry-inflector/blob/c918f967ff82611da374eb0847a77b7e012d3fa8/lib/dry/inflector.rb#L329-L334
|
72
|
-
name.sub!(/^[a-z\d]*/,&:capitalize)
|
73
|
-
name.gsub!(%r{(?:[_-]|(/))([a-z\d]*)}i) do |match|
|
74
|
-
slash = Regexp.last_match(1)
|
75
|
-
word = Regexp.last_match(2)
|
97
|
+
scanner = StringScanner.new(name.to_s)
|
98
|
+
new_string = String.new
|
76
99
|
|
77
|
-
|
100
|
+
until scanner.eos?
|
101
|
+
if (word = scanner.scan(/[A-Za-z\d]+/))
|
102
|
+
word.capitalize!
|
103
|
+
new_string << word
|
104
|
+
elsif scanner.scan(/[_-]+/)
|
105
|
+
# skip
|
106
|
+
elsif scanner.scan(/\//)
|
107
|
+
new_string << '::'
|
108
|
+
else
|
109
|
+
raise(ArgumentError,"cannot convert string to CamelCase: #{scanner.string.inspect}")
|
110
|
+
end
|
78
111
|
end
|
79
112
|
|
80
|
-
|
81
|
-
name
|
113
|
+
new_string
|
82
114
|
end
|
83
115
|
end
|
84
116
|
end
|
@@ -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
|
@@ -159,11 +218,22 @@ module CommandKit
|
|
159
218
|
#
|
160
219
|
# Asks the user for secret input.
|
161
220
|
#
|
221
|
+
# @param [String] prompt
|
222
|
+
# The prompt that will be printed before reading input.
|
223
|
+
#
|
224
|
+
# @param [Boolean] required
|
225
|
+
# Requires non-empty input.
|
226
|
+
#
|
227
|
+
# @return [String]
|
228
|
+
# The user input.
|
229
|
+
#
|
162
230
|
# @example
|
163
231
|
# ask_secret("Password")
|
164
232
|
# # Password:
|
165
233
|
# # => "s3cr3t"
|
166
234
|
#
|
235
|
+
# @api public
|
236
|
+
#
|
167
237
|
def ask_secret(prompt, required: true)
|
168
238
|
if stdin.respond_to?(:noecho)
|
169
239
|
stdin.noecho do
|
data/lib/command_kit/main.rb
CHANGED
@@ -12,6 +12,9 @@ module CommandKit
|
|
12
12
|
# end
|
13
13
|
#
|
14
14
|
module Main
|
15
|
+
#
|
16
|
+
# @api private
|
17
|
+
#
|
15
18
|
module ModuleMethods
|
16
19
|
#
|
17
20
|
# Extends {ClassMethods} or {ModuleMethods}, depending on whether {Main}
|
@@ -43,16 +46,16 @@ module CommandKit
|
|
43
46
|
# @param [Array<String>] argv
|
44
47
|
# The Array of command-line arguments.
|
45
48
|
#
|
49
|
+
# @api public
|
50
|
+
#
|
46
51
|
def start(argv=ARGV, **kwargs)
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
exit 0
|
55
|
-
end
|
52
|
+
exit main(argv, **kwargs)
|
53
|
+
rescue Interrupt
|
54
|
+
# https://tldp.org/LDP/abs/html/exitcodes.html
|
55
|
+
exit 130
|
56
|
+
rescue Errno::EPIPE
|
57
|
+
# STDOUT pipe broken
|
58
|
+
exit 0
|
56
59
|
end
|
57
60
|
|
58
61
|
#
|
@@ -68,6 +71,8 @@ module CommandKit
|
|
68
71
|
# @return [Integer]
|
69
72
|
# The exit status of the command.
|
70
73
|
#
|
74
|
+
# @api public
|
75
|
+
#
|
71
76
|
def main(argv=[], **kwargs)
|
72
77
|
new(**kwargs).main(argv)
|
73
78
|
end
|
@@ -84,6 +89,8 @@ module CommandKit
|
|
84
89
|
#
|
85
90
|
# @note `argv` is splatted into {#run}.
|
86
91
|
#
|
92
|
+
# @api public
|
93
|
+
#
|
87
94
|
def main(argv=[])
|
88
95
|
run(*argv)
|
89
96
|
return 0
|
@@ -99,6 +106,8 @@ module CommandKit
|
|
99
106
|
#
|
100
107
|
# @abstract
|
101
108
|
#
|
109
|
+
# @api public
|
110
|
+
#
|
102
111
|
def run(*args)
|
103
112
|
end
|
104
113
|
end
|
@@ -0,0 +1,44 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module CommandKit
|
4
|
+
#
|
5
|
+
# Allows displaying man pages.
|
6
|
+
#
|
7
|
+
# ## Examples
|
8
|
+
#
|
9
|
+
# man "passwd"
|
10
|
+
# man "passwd", section: 5
|
11
|
+
#
|
12
|
+
# @since 0.2.0
|
13
|
+
#
|
14
|
+
module Man
|
15
|
+
#
|
16
|
+
# Displays the given man page.
|
17
|
+
#
|
18
|
+
# @param [String] page
|
19
|
+
# The man page file name.
|
20
|
+
#
|
21
|
+
# @param [Integer, String, nil] section
|
22
|
+
# The optional section number to specify.
|
23
|
+
#
|
24
|
+
# @return [Boolean, nil]
|
25
|
+
# Specifies whether the `man` command was successful or not.
|
26
|
+
# Returns `nil` when the `man` command is not installed.
|
27
|
+
#
|
28
|
+
# @example
|
29
|
+
# man "passwd"
|
30
|
+
#
|
31
|
+
# @example Display a man-page from a specific section:
|
32
|
+
# man "passwd", section: 5
|
33
|
+
#
|
34
|
+
# @api public
|
35
|
+
#
|
36
|
+
def man(page, section: nil)
|
37
|
+
if section
|
38
|
+
system('man',section.to_s,page.to_s)
|
39
|
+
else
|
40
|
+
system('man',page.to_s)
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|
@@ -0,0 +1,69 @@
|
|
1
|
+
require 'command_kit/os'
|
2
|
+
require 'command_kit/env/path'
|
3
|
+
|
4
|
+
module CommandKit
|
5
|
+
#
|
6
|
+
# Allows opening a file or a URI with the system's preferred application for
|
7
|
+
# that file type or URI scheme.
|
8
|
+
#
|
9
|
+
# ## Examples
|
10
|
+
#
|
11
|
+
# open_app_for "movie.avi"
|
12
|
+
# open_app_for "https://github.com/postmodern/command_kit.rb#readme"
|
13
|
+
#
|
14
|
+
# @since 0.2.0
|
15
|
+
#
|
16
|
+
module OpenApp
|
17
|
+
include OS
|
18
|
+
include Env::Path
|
19
|
+
|
20
|
+
#
|
21
|
+
# Initializes the command and determines which open command to use.
|
22
|
+
#
|
23
|
+
# @param [Hash{Symbol => Object}] kwargs
|
24
|
+
# Additional keyword arguments.
|
25
|
+
#
|
26
|
+
# @api public
|
27
|
+
#
|
28
|
+
def initialize(**kwargs)
|
29
|
+
super(**kwargs)
|
30
|
+
|
31
|
+
@open_command = if macos?
|
32
|
+
'open'
|
33
|
+
elsif linux? || bsd?
|
34
|
+
if command_installed?('xdg-open')
|
35
|
+
'xdg-open'
|
36
|
+
end
|
37
|
+
elsif windows?
|
38
|
+
if command_installed?('invoke-item')
|
39
|
+
'invoke-item'
|
40
|
+
else
|
41
|
+
'start'
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|
45
|
+
|
46
|
+
#
|
47
|
+
# Opens a file or URI using the system's preferred application for that
|
48
|
+
# file type or URI scheme.
|
49
|
+
#
|
50
|
+
# @param [String, URI] file_or_uri
|
51
|
+
# The file path or URI to open.
|
52
|
+
#
|
53
|
+
# @return [Boolean, nil]
|
54
|
+
# Specifies whether the file or URI was successfully opened or not.
|
55
|
+
# If the open command could not be determined, `nil` is returned.
|
56
|
+
#
|
57
|
+
# @example Open a file:
|
58
|
+
# open_app_for "movie.avi"
|
59
|
+
#
|
60
|
+
# @example Open a URI:
|
61
|
+
# open_app_for "https://github.com/postmodern/command_kit.rb"
|
62
|
+
#
|
63
|
+
def open_app_for(file_or_uri)
|
64
|
+
if @open_command
|
65
|
+
system(@open_command,file_or_uri.to_s)
|
66
|
+
end
|
67
|
+
end
|
68
|
+
end
|
69
|
+
end
|
@@ -11,6 +11,8 @@ module CommandKit
|
|
11
11
|
#
|
12
12
|
# Represents a defined option.
|
13
13
|
#
|
14
|
+
# @api private
|
15
|
+
#
|
14
16
|
class Option
|
15
17
|
|
16
18
|
# The option's name.
|
@@ -33,11 +35,6 @@ module CommandKit
|
|
33
35
|
# @return [OptionValue, nil]
|
34
36
|
attr_reader :value
|
35
37
|
|
36
|
-
# The option's description.
|
37
|
-
#
|
38
|
-
# @return [String]
|
39
|
-
attr_reader :desc
|
40
|
-
|
41
38
|
# The optional block that will receive the parsed option value.
|
42
39
|
#
|
43
40
|
# @return [Proc, nil]
|
@@ -126,7 +123,7 @@ module CommandKit
|
|
126
123
|
end
|
127
124
|
|
128
125
|
#
|
129
|
-
# The separator
|
126
|
+
# The separator character between the option and option value.
|
130
127
|
#
|
131
128
|
# @return ['=', ' ', nil]
|
132
129
|
#
|
@@ -14,6 +14,8 @@ module CommandKit
|
|
14
14
|
#
|
15
15
|
# Represents an additional argument associated with an option flag.
|
16
16
|
#
|
17
|
+
# @api private
|
18
|
+
#
|
17
19
|
class OptionValue < Arguments::ArgumentValue
|
18
20
|
|
19
21
|
# Maps OptionParser types to USAGE strings.
|
@@ -39,7 +41,7 @@ module CommandKit
|
|
39
41
|
|
40
42
|
# The desired type of the argument value.
|
41
43
|
#
|
42
|
-
# @return [Class, Hash, Array, Regexp
|
44
|
+
# @return [Class, Hash, Array, Regexp]
|
43
45
|
attr_reader :type
|
44
46
|
|
45
47
|
# The default parsed value for the argument value.
|
@@ -90,10 +92,11 @@ module CommandKit
|
|
90
92
|
def self.default_usage(type)
|
91
93
|
USAGES.fetch(type) do
|
92
94
|
case type
|
93
|
-
when Class then Inflector.underscore(type.name).upcase
|
94
95
|
when Hash then type.keys.join('|')
|
95
96
|
when Array then type.join('|')
|
96
97
|
when Regexp then type.source
|
98
|
+
when Class
|
99
|
+
Inflector.underscore(Inflector.demodularize(type.name)).upcase
|
97
100
|
else
|
98
101
|
raise(TypeError,"unsupported option type: #{type.inspect}")
|
99
102
|
end
|