command_kit 0.1.0.pre1 → 0.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.
Files changed (104) hide show
  1. checksums.yaml +4 -4
  2. data/.github/workflows/ruby.yml +15 -0
  3. data/.rubocop.yml +138 -0
  4. data/ChangeLog.md +34 -2
  5. data/Gemfile +3 -0
  6. data/README.md +135 -214
  7. data/Rakefile +3 -2
  8. data/command_kit.gemspec +4 -4
  9. data/examples/colors.rb +30 -0
  10. data/examples/command.rb +65 -0
  11. data/examples/pager.rb +30 -0
  12. data/gemspec.yml +10 -2
  13. data/lib/command_kit/arguments/argument.rb +16 -44
  14. data/lib/command_kit/arguments/argument_value.rb +3 -30
  15. data/lib/command_kit/arguments.rb +66 -20
  16. data/lib/command_kit/colors.rb +253 -45
  17. data/lib/command_kit/command.rb +50 -3
  18. data/lib/command_kit/command_name.rb +9 -0
  19. data/lib/command_kit/commands/auto_load/subcommand.rb +3 -0
  20. data/lib/command_kit/commands/auto_load.rb +16 -0
  21. data/lib/command_kit/commands/auto_require.rb +16 -0
  22. data/lib/command_kit/commands/command.rb +3 -0
  23. data/lib/command_kit/commands/help.rb +2 -0
  24. data/lib/command_kit/commands/parent_command.rb +7 -0
  25. data/lib/command_kit/commands/subcommand.rb +15 -0
  26. data/lib/command_kit/commands.rb +40 -4
  27. data/lib/command_kit/description.rb +15 -2
  28. data/lib/command_kit/env/home.rb +9 -0
  29. data/lib/command_kit/env/path.rb +15 -0
  30. data/lib/command_kit/env.rb +4 -0
  31. data/lib/command_kit/examples.rb +15 -2
  32. data/lib/command_kit/exception_handler.rb +4 -0
  33. data/lib/command_kit/help/man.rb +74 -47
  34. data/lib/command_kit/help.rb +10 -1
  35. data/lib/command_kit/inflector.rb +49 -17
  36. data/lib/command_kit/interactive.rb +239 -0
  37. data/lib/command_kit/main.rb +20 -9
  38. data/lib/command_kit/man.rb +44 -0
  39. data/lib/command_kit/open_app.rb +69 -0
  40. data/lib/command_kit/options/option.rb +36 -9
  41. data/lib/command_kit/options/option_value.rb +42 -3
  42. data/lib/command_kit/options/parser.rb +44 -17
  43. data/lib/command_kit/options/quiet.rb +3 -0
  44. data/lib/command_kit/options/verbose.rb +5 -0
  45. data/lib/command_kit/options/version.rb +6 -0
  46. data/lib/command_kit/options.rb +59 -10
  47. data/lib/command_kit/os/linux.rb +157 -0
  48. data/lib/command_kit/os.rb +165 -11
  49. data/lib/command_kit/package_manager.rb +200 -0
  50. data/lib/command_kit/pager.rb +84 -9
  51. data/lib/command_kit/printing/indent.rb +25 -2
  52. data/lib/command_kit/printing.rb +23 -0
  53. data/lib/command_kit/program_name.rb +7 -0
  54. data/lib/command_kit/stdio.rb +24 -0
  55. data/lib/command_kit/sudo.rb +40 -0
  56. data/lib/command_kit/terminal.rb +159 -0
  57. data/lib/command_kit/usage.rb +14 -0
  58. data/lib/command_kit/version.rb +1 -1
  59. data/lib/command_kit/xdg.rb +21 -1
  60. data/lib/command_kit.rb +1 -0
  61. data/spec/arguments/argument_spec.rb +5 -41
  62. data/spec/arguments/argument_value_spec.rb +1 -61
  63. data/spec/arguments_spec.rb +8 -25
  64. data/spec/colors_spec.rb +277 -13
  65. data/spec/command_name_spec.rb +1 -1
  66. data/spec/command_spec.rb +4 -1
  67. data/spec/commands/auto_load/subcommand_spec.rb +1 -1
  68. data/spec/commands/auto_load_spec.rb +1 -1
  69. data/spec/commands/auto_require_spec.rb +2 -2
  70. data/spec/commands/help_spec.rb +1 -1
  71. data/spec/commands/parent_command_spec.rb +1 -1
  72. data/spec/commands/subcommand_spec.rb +1 -1
  73. data/spec/commands_spec.rb +2 -2
  74. data/spec/description_spec.rb +1 -25
  75. data/spec/env/home_spec.rb +1 -1
  76. data/spec/env/path_spec.rb +1 -1
  77. data/spec/examples_spec.rb +1 -25
  78. data/spec/exception_handler_spec.rb +1 -1
  79. data/spec/help/man_spec.rb +316 -0
  80. data/spec/help_spec.rb +0 -25
  81. data/spec/inflector_spec.rb +71 -9
  82. data/spec/interactive_spec.rb +415 -0
  83. data/spec/main_spec.rb +7 -7
  84. data/spec/man_spec.rb +46 -0
  85. data/spec/open_app_spec.rb +85 -0
  86. data/spec/options/option_spec.rb +48 -9
  87. data/spec/options/option_value_spec.rb +53 -4
  88. data/spec/options_spec.rb +1 -1
  89. data/spec/os/linux_spec.rb +154 -0
  90. data/spec/os_spec.rb +201 -14
  91. data/spec/package_manager_spec.rb +806 -0
  92. data/spec/pager_spec.rb +78 -15
  93. data/spec/printing/indent_spec.rb +1 -1
  94. data/spec/printing_spec.rb +10 -2
  95. data/spec/program_name_spec.rb +1 -1
  96. data/spec/spec_helper.rb +0 -3
  97. data/spec/sudo_spec.rb +51 -0
  98. data/spec/{console_spec.rb → terminal_spec.rb} +65 -35
  99. data/spec/usage_spec.rb +2 -2
  100. data/spec/xdg_spec.rb +1 -1
  101. metadata +32 -13
  102. data/lib/command_kit/arguments/usage.rb +0 -6
  103. data/lib/command_kit/console.rb +0 -141
  104. data/lib/command_kit/options/usage.rb +0 -6
@@ -18,6 +18,9 @@ module CommandKit
18
18
  module Quiet
19
19
  include Options
20
20
 
21
+ #
22
+ # @api private
23
+ #
21
24
  module ModuleMethods
22
25
  #
23
26
  # Defines a `-q, --quiet` option.
@@ -18,6 +18,9 @@ module CommandKit
18
18
  module Verbose
19
19
  include Options
20
20
 
21
+ #
22
+ # @api private
23
+ #
21
24
  module ModuleMethods
22
25
  #
23
26
  # Defines a `-v, --verbose` option or extends {ModuleMethods}, depending
@@ -47,6 +50,8 @@ module CommandKit
47
50
  #
48
51
  # @return [Boolean]
49
52
  #
53
+ # @api public
54
+ #
50
55
  def verbose?
51
56
  @verbose
52
57
  end
@@ -35,6 +35,8 @@ module CommandKit
35
35
  # @return [String, nil]
36
36
  # The classes version string.
37
37
  #
38
+ # @api public
39
+ #
38
40
  def version(new_version=nil)
39
41
  if new_version
40
42
  @version = new_version
@@ -47,6 +49,8 @@ module CommandKit
47
49
  #
48
50
  # @see ClassMethods#version
49
51
  #
52
+ # @api public
53
+ #
50
54
  def version
51
55
  self.class.version
52
56
  end
@@ -54,6 +58,8 @@ module CommandKit
54
58
  #
55
59
  # Prints the version.
56
60
  #
61
+ # @api public
62
+ #
57
63
  def print_version
58
64
  puts "#{command_name} #{version}"
59
65
  end
@@ -9,24 +9,28 @@ module CommandKit
9
9
  #
10
10
  # include CommandKit::Options
11
11
  #
12
- # option :foo, type: String,
13
- # short: '-f',
14
- # desc: "Foo option"
12
+ # option :foo, short: '-f',
13
+ # value: {type: String},
14
+ # desc: "Foo option"
15
15
  #
16
- # option :bar, type: String,
17
- # short: '-b',
18
- # usage: 'STR:STR:...',
16
+ # option :bar, short: '-b',
17
+ # value: {
18
+ # type: String,
19
+ # usage: 'STR:STR:...'
20
+ # },
19
21
  # desc: "Bar option" do |arg|
20
22
  # @bar = arg.split(':')
21
23
  # end
24
+ #
25
+ # ### initialize and using instance variables
22
26
  #
23
- # option :number, type: Integer,
27
+ # option :number, value: {type: Integer},
24
28
  # desc: 'Numbers' do |num|
25
29
  # @numbers << num
26
30
  # end
27
31
  #
28
- # def initialize
29
- # super
32
+ # def initialize(**kwargs)
33
+ # super(**kwargs)
30
34
  #
31
35
  # @numbers = []
32
36
  # end
@@ -34,6 +38,9 @@ module CommandKit
34
38
  module Options
35
39
  include Parser
36
40
 
41
+ #
42
+ # @api private
43
+ #
37
44
  module ModuleMethods
38
45
  #
39
46
  # Extends {ClassMethods} or {ModuleMethods}, depending on whether
@@ -64,6 +71,8 @@ module CommandKit
64
71
  #
65
72
  # @return [Hash{Symbol => Option}]
66
73
  #
74
+ # @api semipublic
75
+ #
67
76
  def options
68
77
  @options ||= if superclass.kind_of?(ClassMethods)
69
78
  superclass.options.dup
@@ -78,6 +87,31 @@ module CommandKit
78
87
  # @param [Symbol] name
79
88
  # The option name.
80
89
  #
90
+ # @param [Hash{Symbol => Object}] kwargs
91
+ # Keyword arguments.
92
+ #
93
+ # @option kwargs [String, nil] short
94
+ # Optional short-flag for the option.
95
+ #
96
+ # @option kwargs [String, nil] long
97
+ # Optional explicit long-flag for the option.
98
+ #
99
+ # @option kwargs [Boolean] equals
100
+ # Specifies whether the option is of the form (`--opt=value`).
101
+ #
102
+ # @option kwargs [Hash{Symbol => Object}, true, false, nil] value
103
+ # Keyword arguments for {OptionValue#initialize}, or `nil` if the option
104
+ # has no additional value.
105
+ #
106
+ # @option value [Class, Hash, Array, Regexp] type
107
+ # The type of the option's value.
108
+ #
109
+ # @option value [String, nil] usage
110
+ # The usage string for the option's value.
111
+ #
112
+ # @option kwargs [String] desc
113
+ # The description for the option.
114
+ #
81
115
  # @yield [(value)]
82
116
  # If a block is given, it will be passed the parsed option value.
83
117
  #
@@ -86,6 +120,10 @@ module CommandKit
86
120
  #
87
121
  # @return [Option]
88
122
  #
123
+ # @raise [TypeError]
124
+ # The `value` keyword argument was not a `Hash`, `true`, `false`, or
125
+ # `nil`.
126
+ #
89
127
  # @example Define an option:
90
128
  # option :foo, desc: "Foo option"
91
129
  #
@@ -139,6 +177,8 @@ module CommandKit
139
177
  # # ...
140
178
  # end
141
179
  #
180
+ # @api public
181
+ #
142
182
  def option(name,**kwargs,&block)
143
183
  options[name] = Option.new(name,**kwargs,&block)
144
184
  end
@@ -147,6 +187,9 @@ module CommandKit
147
187
  # Hash of parsed option values.
148
188
  #
149
189
  # @return [Hash{Symbol => Object}]
190
+ #
191
+ # @api semipublic
192
+ #
150
193
  attr_reader :options
151
194
 
152
195
  #
@@ -154,7 +197,13 @@ module CommandKit
154
197
  # {Parser#option_parser option parser}.
155
198
  #
156
199
  # @param [Hash{Symbol => Object}] options
157
- # Optional pre-populated options hash.
200
+ # Optional prepopulated options hash.
201
+ #
202
+ # @note
203
+ # The {#option_parser} will populate {#options} and also call any
204
+ # {ClassMethods#option option} blocks with the parsed option values.
205
+ #
206
+ # @api public
158
207
  #
159
208
  def initialize(options: {}, **kwargs)
160
209
  @options = options
@@ -0,0 +1,157 @@
1
+ require 'command_kit/os'
2
+
3
+ module CommandKit
4
+ module OS
5
+ #
6
+ # Provides methods for determining the specific type of Linux.
7
+ #
8
+ # ## Example
9
+ #
10
+ # require 'command_kit/command'
11
+ # require 'command_kit/os/linux'
12
+ #
13
+ # class Command < CommandKit::Command
14
+ #
15
+ # include CommandKit::OS::Linux
16
+ #
17
+ # def run
18
+ # if debian_linux?
19
+ # # ...
20
+ # elsif redhat_linux?
21
+ # # ...
22
+ # elsif suse_linux?
23
+ # # ...
24
+ # elsif arch_linux?
25
+ # # ...
26
+ # end
27
+ # end
28
+ # end
29
+ #
30
+ # @since 0.2.0
31
+ #
32
+ module Linux
33
+ #
34
+ # @api private
35
+ #
36
+ module ModuleMethods
37
+ #
38
+ # Extends {ClassMethods} or {ModuleMethods}, depending on whether
39
+ # {OS} is being included into a class or a module..
40
+ #
41
+ # @param [Class, Module] context
42
+ # The class or module which is including {OS}.
43
+ #
44
+ def included(context)
45
+ super(context)
46
+
47
+ if context.class == Module
48
+ context.extend ModuleMethods
49
+ else
50
+ context.extend ClassMethods
51
+ end
52
+ end
53
+ end
54
+
55
+ extend ModuleMethods
56
+
57
+ module ClassMethods
58
+ #
59
+ # Determines the specific Linux distro.
60
+ #
61
+ # @return [:fedora, :redhat, :debian, :suse, :arch, nil]
62
+ # Returns the type of Linux distro or `nil` if the Linux distro could
63
+ # not be determined.
64
+ #
65
+ # @api semipublic
66
+ #
67
+ def linux_distro
68
+ if File.file?('/etc/fedora-release') then :fedora
69
+ elsif File.file?('/etc/redhat-release') then :redhat
70
+ elsif File.file?('/etc/debian_version') then :debian
71
+ elsif File.file?('/etc/SuSE-release') then :suse
72
+ elsif File.file?('/etc/arch-release') then :arch
73
+ end
74
+ end
75
+ end
76
+
77
+ # The Linux distro.
78
+ #
79
+ # @return [:fedora, :redhat, :debian, :suse, :arch, nil]
80
+ #
81
+ # @api public
82
+ attr_reader :linux_distro
83
+
84
+ #
85
+ # Initializes the command.
86
+ #
87
+ # @param [:fedora, :redhat, :debian, :suse, :arch, nil] linux_distro
88
+ # Overrides the default detected Linux distro.
89
+ #
90
+ # @param [Hash{Symbol => Object}] kwargs
91
+ # Additional keyword arguments.
92
+ #
93
+ # @api public
94
+ #
95
+ def initialize(linux_distro: self.class.linux_distro, **kwargs)
96
+ super(**kwargs)
97
+
98
+ @linux_distro = linux_distro
99
+ end
100
+
101
+ #
102
+ # Determines if the current OS is RedHat Linux based distro.
103
+ #
104
+ # @return [Boolean]
105
+ #
106
+ # @api public
107
+ #
108
+ def redhat_linux?
109
+ @linux_distro == :redhat
110
+ end
111
+
112
+ #
113
+ # Determines if the current OS is Fedora Linux based distro.
114
+ #
115
+ # @return [Boolean]
116
+ #
117
+ # @api public
118
+ #
119
+ def fedora_linux?
120
+ @linux_distro == :fedora
121
+ end
122
+
123
+ #
124
+ # Determines if the current OS is Debian Linux based distro.
125
+ #
126
+ # @return [Boolean]
127
+ #
128
+ # @api public
129
+ #
130
+ def debian_linux?
131
+ @linux_distro == :debian
132
+ end
133
+
134
+ #
135
+ # Determines if the current OS is SUSE Linux based distro.
136
+ #
137
+ # @return [Boolean]
138
+ #
139
+ # @api public
140
+ #
141
+ def suse_linux?
142
+ @linux_distro == :suse
143
+ end
144
+
145
+ #
146
+ # Determines if the current OS is Arch Linux based distro.
147
+ #
148
+ # @return [Boolean]
149
+ #
150
+ # @api public
151
+ #
152
+ def arch_linux?
153
+ @linux_distro == :arch
154
+ end
155
+ end
156
+ end
157
+ end
@@ -4,26 +4,111 @@ module CommandKit
4
4
  #
5
5
  # ## Examples
6
6
  #
7
- # include CommandKit::OS
7
+ # require 'command_kit/command'
8
+ # require 'command_kit/os'
8
9
  #
9
- # def main(*argv)
10
- # if linux?
11
- # # ...
12
- # elsif macos?
13
- # # ...
14
- # elsif windows?
15
- # # ...
10
+ # class Command < CommandKit::Command
11
+ #
12
+ # include CommandKit::OS
13
+ #
14
+ # def main(*argv)
15
+ # if linux?
16
+ # # ...
17
+ # elsif macos?
18
+ # # ...
19
+ # elsif freebsd?
20
+ # # ...
21
+ # elsif windows?
22
+ # # ...
23
+ # end
16
24
  # end
25
+ #
17
26
  # end
18
27
  #
19
28
  module OS
29
+ #
30
+ # @api private
31
+ #
32
+ module ModuleMethods
33
+ #
34
+ # Extends {ClassMethods} or {ModuleMethods}, depending on whether
35
+ # {OS} is being included into a class or a module..
36
+ #
37
+ # @param [Class, Module] context
38
+ # The class or module which is including {OS}.
39
+ #
40
+ def included(context)
41
+ super(context)
42
+
43
+ if context.class == Module
44
+ context.extend ModuleMethods
45
+ else
46
+ context.extend ClassMethods
47
+ end
48
+ end
49
+ end
50
+
51
+ extend ModuleMethods
52
+
53
+ module ClassMethods
54
+ #
55
+ # Determines the current OS.
56
+ #
57
+ # @return [:linux, :macos, :freebsd, :openbsd, :netbsd, :windows, nil]
58
+ # The OS type or `nil` if the OS could not be determined.
59
+ #
60
+ # @api semipublic
61
+ #
62
+ # @since 0.2.0
63
+ #
64
+ def os
65
+ if RUBY_PLATFORM.include?('linux') then :linux
66
+ elsif RUBY_PLATFORM.include?('darwin') then :macos
67
+ elsif RUBY_PLATFORM.include?('freebsd') then :freebsd
68
+ elsif RUBY_PLATFORM.include?('openbsd') then :openbsd
69
+ elsif RUBY_PLATFORM.include?('netbsd') then :netbsd
70
+ elsif Gem.win_platform? then :windows
71
+ end
72
+ end
73
+ end
74
+
75
+ # The current OS.
76
+ #
77
+ # @return [:linux, :macos, :freebsd, :openbsd, :netbsd, :windows, nil]
78
+ #
79
+ # @api public
80
+ #
81
+ # @since 0.2.0
82
+ attr_reader :os
83
+
84
+ #
85
+ # Initializes the command.
86
+ #
87
+ # @param [:linux, :macos, :freebsd, :openbsd, :netbsd, :windows, nil] os
88
+ # Overrides the default OS.
89
+ #
90
+ # @param [Hash{Symbol => Object}] kwargs
91
+ # Additional keyword arguments.
92
+ #
93
+ # @api public
94
+ #
95
+ # @since 0.2.0
96
+ #
97
+ def initialize(os: self.class.os, **kwargs)
98
+ super(**kwargs)
99
+
100
+ @os = os
101
+ end
102
+
20
103
  #
21
104
  # Determines if the current OS is Linux.
22
105
  #
23
106
  # @return [Boolean]
24
107
  #
108
+ # @api public
109
+ #
25
110
  def linux?
26
- RUBY_PLATFORM.include?('linux')
111
+ @os == :linux
27
112
  end
28
113
 
29
114
  #
@@ -31,8 +116,75 @@ module CommandKit
31
116
  #
32
117
  # @return [Boolean]
33
118
  #
119
+ # @api public
120
+ #
34
121
  def macos?
35
- RUBY_PLATFORM.include?('darwin')
122
+ @os == :macos
123
+ end
124
+
125
+ #
126
+ # Determines if the current OS is FreeBSD.
127
+ #
128
+ # @return [Boolean]
129
+ #
130
+ # @api public
131
+ #
132
+ # @since 0.2.0
133
+ #
134
+ def freebsd?
135
+ @os == :freebsd
136
+ end
137
+
138
+ #
139
+ # Determines if the current OS is OpenBSD.
140
+ #
141
+ # @return [Boolean]
142
+ #
143
+ # @api public
144
+ #
145
+ # @since 0.2.0
146
+ #
147
+ def openbsd?
148
+ @os == :openbsd
149
+ end
150
+
151
+ #
152
+ # Determines if the current OS is NetBSD.
153
+ #
154
+ # @return [Boolean]
155
+ #
156
+ # @api public
157
+ #
158
+ # @since 0.2.0
159
+ #
160
+ def netbsd?
161
+ @os == :netbsd
162
+ end
163
+
164
+ #
165
+ # Determines if the current OS is BSD based.
166
+ #
167
+ # @return [Boolean]
168
+ #
169
+ # @since 0.2.0
170
+ #
171
+ # @api public
172
+ #
173
+ def bsd?
174
+ freebsd? || openbsd? || netbsd?
175
+ end
176
+
177
+ #
178
+ # Determines if the current OS is UNIX based.
179
+ #
180
+ # @return [Boolean]
181
+ #
182
+ # @since 0.2.0
183
+ #
184
+ # @api public
185
+ #
186
+ def unix?
187
+ linux? || macos? || bsd?
36
188
  end
37
189
 
38
190
  #
@@ -40,8 +192,10 @@ module CommandKit
40
192
  #
41
193
  # @return [Boolean]
42
194
  #
195
+ # @api public
196
+ #
43
197
  def windows?
44
- Gem.win_platform?
198
+ @os == :windows
45
199
  end
46
200
  end
47
201
  end