command_kit 0.1.0.pre2 → 0.2.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (98) hide show
  1. checksums.yaml +4 -4
  2. data/.github/workflows/ruby.yml +15 -0
  3. data/.rubocop.yml +141 -0
  4. data/ChangeLog.md +98 -2
  5. data/Gemfile +3 -0
  6. data/README.md +189 -117
  7. data/Rakefile +3 -2
  8. data/command_kit.gemspec +4 -4
  9. data/examples/command.rb +1 -1
  10. data/gemspec.yml +10 -2
  11. data/lib/command_kit/arguments/argument.rb +2 -0
  12. data/lib/command_kit/arguments/argument_value.rb +2 -0
  13. data/lib/command_kit/arguments.rb +23 -4
  14. data/lib/command_kit/colors.rb +253 -45
  15. data/lib/command_kit/command.rb +6 -1
  16. data/lib/command_kit/command_name.rb +9 -0
  17. data/lib/command_kit/commands/auto_load.rb +24 -1
  18. data/lib/command_kit/commands/auto_require.rb +16 -0
  19. data/lib/command_kit/commands/command.rb +3 -0
  20. data/lib/command_kit/commands/help.rb +5 -2
  21. data/lib/command_kit/commands/parent_command.rb +7 -0
  22. data/lib/command_kit/commands/subcommand.rb +13 -1
  23. data/lib/command_kit/commands.rb +54 -9
  24. data/lib/command_kit/description.rb +12 -1
  25. data/lib/command_kit/env/home.rb +9 -0
  26. data/lib/command_kit/env/path.rb +16 -1
  27. data/lib/command_kit/env.rb +4 -0
  28. data/lib/command_kit/examples.rb +12 -1
  29. data/lib/command_kit/exception_handler.rb +4 -0
  30. data/lib/command_kit/help/man.rb +26 -30
  31. data/lib/command_kit/help.rb +7 -1
  32. data/lib/command_kit/inflector.rb +49 -17
  33. data/lib/command_kit/interactive.rb +248 -0
  34. data/lib/command_kit/main.rb +18 -9
  35. data/lib/command_kit/man.rb +44 -0
  36. data/lib/command_kit/open_app.rb +69 -0
  37. data/lib/command_kit/options/option.rb +3 -6
  38. data/lib/command_kit/options/option_value.rb +5 -2
  39. data/lib/command_kit/options/parser.rb +46 -19
  40. data/lib/command_kit/options/quiet.rb +3 -0
  41. data/lib/command_kit/options/verbose.rb +5 -0
  42. data/lib/command_kit/options/version.rb +6 -0
  43. data/lib/command_kit/options.rb +32 -7
  44. data/lib/command_kit/os/linux.rb +157 -0
  45. data/lib/command_kit/os.rb +165 -11
  46. data/lib/command_kit/package_manager.rb +200 -0
  47. data/lib/command_kit/pager.rb +80 -11
  48. data/lib/command_kit/printing/indent.rb +27 -4
  49. data/lib/command_kit/printing.rb +35 -1
  50. data/lib/command_kit/program_name.rb +7 -0
  51. data/lib/command_kit/stdio.rb +24 -0
  52. data/lib/command_kit/sudo.rb +40 -0
  53. data/lib/command_kit/terminal.rb +159 -0
  54. data/lib/command_kit/usage.rb +14 -0
  55. data/lib/command_kit/version.rb +1 -1
  56. data/lib/command_kit/xdg.rb +13 -0
  57. data/lib/command_kit.rb +1 -0
  58. data/spec/arguments/argument_spec.rb +2 -2
  59. data/spec/arguments_spec.rb +53 -27
  60. data/spec/colors_spec.rb +277 -13
  61. data/spec/command_name_spec.rb +1 -1
  62. data/spec/command_spec.rb +79 -5
  63. data/spec/commands/auto_load/subcommand_spec.rb +1 -1
  64. data/spec/commands/auto_load_spec.rb +34 -3
  65. data/spec/commands/auto_require_spec.rb +2 -2
  66. data/spec/commands/help_spec.rb +1 -1
  67. data/spec/commands/parent_command_spec.rb +1 -1
  68. data/spec/commands/subcommand_spec.rb +1 -1
  69. data/spec/commands_spec.rb +103 -29
  70. data/spec/description_spec.rb +1 -25
  71. data/spec/env/home_spec.rb +1 -1
  72. data/spec/env/path_spec.rb +7 -1
  73. data/spec/examples_spec.rb +1 -25
  74. data/spec/exception_handler_spec.rb +1 -1
  75. data/spec/help/man_spec.rb +45 -58
  76. data/spec/help_spec.rb +0 -25
  77. data/spec/inflector_spec.rb +71 -9
  78. data/spec/interactive_spec.rb +415 -0
  79. data/spec/main_spec.rb +7 -7
  80. data/spec/man_spec.rb +46 -0
  81. data/spec/open_app_spec.rb +85 -0
  82. data/spec/options/option_spec.rb +5 -5
  83. data/spec/options/option_value_spec.rb +56 -1
  84. data/spec/options_spec.rb +283 -1
  85. data/spec/os/linux_spec.rb +164 -0
  86. data/spec/os_spec.rb +201 -14
  87. data/spec/package_manager_spec.rb +806 -0
  88. data/spec/pager_spec.rb +76 -11
  89. data/spec/printing/indent_spec.rb +8 -6
  90. data/spec/printing_spec.rb +33 -3
  91. data/spec/program_name_spec.rb +1 -1
  92. data/spec/spec_helper.rb +0 -3
  93. data/spec/sudo_spec.rb +51 -0
  94. data/spec/{console_spec.rb → terminal_spec.rb} +65 -35
  95. data/spec/usage_spec.rb +2 -2
  96. data/spec/xdg_spec.rb +1 -1
  97. metadata +26 -8
  98. data/lib/command_kit/console.rb +0 -141
@@ -0,0 +1,200 @@
1
+ require 'command_kit/os'
2
+ require 'command_kit/os/linux'
3
+ require 'command_kit/env/path'
4
+ require 'command_kit/sudo'
5
+
6
+ module CommandKit
7
+ #
8
+ # Allows installing packages using the system's package manager.
9
+ #
10
+ # Supports the following package managers:
11
+ #
12
+ # * Linux
13
+ # * Debian / Ubuntu
14
+ # * `apt`
15
+ # * RedHat / Fedora
16
+ # * `dnf`
17
+ # * `yum`
18
+ # * Arch
19
+ # * `pacman`
20
+ # * SUSE / OpenSUSE
21
+ # * `zypper`
22
+ # * macOS
23
+ # * `brew`
24
+ # * `port`
25
+ # * FreeBSD
26
+ # * `pkg`
27
+ # * OpenBSD
28
+ # * `pkg_add`
29
+ #
30
+ # ## Examples
31
+ #
32
+ # unless install_packages("nmap")
33
+ # print_error "failed to install nmap"
34
+ # exit -1
35
+ # end
36
+ #
37
+ # ### Installing multiple packages
38
+ #
39
+ # install_packages apt: ["libxml2-dev", ...],
40
+ # dnf: ["libxml2-devel", ...],
41
+ # brew: ["libxml2", ...],
42
+ # ...
43
+ #
44
+ # @since 0.2.0
45
+ #
46
+ module PackageManager
47
+ include OS
48
+ include OS::Linux
49
+ include Env::Path
50
+ include Sudo
51
+
52
+ # The detected package manager.
53
+ #
54
+ # @return [:apt, :dnf, :yum, :zypper, :pacman, :brew, :pkg, :pkg_add, nil]
55
+ attr_reader :package_manager
56
+
57
+ #
58
+ # Initializes the command and determines which open command to use.
59
+ #
60
+ # @param [:apt, :dnf, :yum, :zypper, :pacman, :brew, :pkg, :pkg_add, nil] package_manager
61
+ # The explicit package manager to use. If `nil`, the package manager will
62
+ # be detected.
63
+ #
64
+ def initialize(package_manager: nil, **kwargs)
65
+ super(**kwargs)
66
+
67
+ @package_manager = package_manager || begin
68
+ if macos?
69
+ if command_installed?('brew') then :brew
70
+ elsif command_installed?('port') then :port
71
+ end
72
+ elsif linux?
73
+ if redhat_linux?
74
+ if command_installed?('dnf') then :dnf
75
+ elsif command_installed?('yum') then :yum
76
+ end
77
+ elsif debian_linux?
78
+ :apt if command_installed?('apt')
79
+ elsif suse_linux?
80
+ :zypper if command_installed?('zypper')
81
+ elsif arch_linux?
82
+ :pacman if command_installed?('pacman')
83
+ end
84
+ elsif freebsd?
85
+ :pkg if command_installed?('pkg')
86
+ elsif openbsd?
87
+ :pkg_add if command_installed?('pkg_add')
88
+ end
89
+ end
90
+ end
91
+
92
+ #
93
+ # Installs the packages using the system's package manager.
94
+ #
95
+ # @param [Array<String>, String] packages
96
+ # A list of package name(s) to install.
97
+ #
98
+ # @param [Boolean] yes
99
+ # Assume yes for all user prompts.
100
+ #
101
+ # @param [Array<String>, String] apt
102
+ # List of `apt` specific package names.
103
+ #
104
+ # @param [Array<String>, String] brew
105
+ # List of `brew` specific package names.
106
+ #
107
+ # @param [Array<String>, String] dnf
108
+ # List of `dnf` specific package names.
109
+ #
110
+ # @param [Array<String>, String] pacman
111
+ # List of `pacman` specific package names.
112
+ #
113
+ # @param [Array<String>, String] pkg
114
+ # List of `pkg` specific package names.
115
+ #
116
+ # @param [Array<String>, String] pkg_add
117
+ # List of `pkg_add` specific package names.
118
+ #
119
+ # @param [Array<String>, String] port
120
+ # List of `port` specific package names.
121
+ #
122
+ # @param [Array<String>, String] yum
123
+ # List of `yum` specific package names.
124
+ #
125
+ # @param [Array<String>, String] zypper
126
+ # List of `zypper` specific package names.
127
+ #
128
+ # @return [Boolean, nil]
129
+ # Specifies whether the packages were successfully installed or not.
130
+ # If the package manager command could not be determined, `nil` is
131
+ # returned.
132
+ #
133
+ # @example Install a package
134
+ # install_packages "nmap", ...
135
+ #
136
+ # @example Install a list of packages per package-manager
137
+ # install_packages apt: ["libxml2-dev", ...],
138
+ # dnf: ["libxml2-devel", ...],
139
+ # brew: ["libxml2", ...],
140
+ # ...
141
+ #
142
+ def install_packages(*packages, yes: false,
143
+ apt: nil,
144
+ brew: nil,
145
+ dnf: nil,
146
+ pacman: nil,
147
+ pkg: nil,
148
+ pkg_add: nil,
149
+ port: nil,
150
+ yum: nil,
151
+ zypper: nil)
152
+ specific_package_names = case @package_manager
153
+ when :apt then apt
154
+ when :brew then brew
155
+ when :dnf then dnf
156
+ when :pacman then pacman
157
+ when :pkg then pkg
158
+ when :pkg_add then pkg_add
159
+ when :port then port
160
+ when :yum then yum
161
+ when :zypper then zypper
162
+ end
163
+ packages += Array(specific_package_names)
164
+
165
+ case @package_manager
166
+ when :apt
167
+ args = []
168
+ args << '-y' if yes
169
+
170
+ sudo('apt','install',*args,*packages)
171
+ when :brew
172
+ system('brew','install',*packages)
173
+ when :dnf, :yum
174
+ args = []
175
+ args << '-y' if yes
176
+
177
+ sudo(@package_manager.to_s,'install',*args,*packages)
178
+ when :pacman
179
+ missing_packages = `pacman -T #{Shellwords.shelljoin(packages)}`.split
180
+
181
+ if missing_packages.empty?
182
+ return true
183
+ end
184
+
185
+ sudo('pacman','-S',*missing_packages)
186
+ when :pkg
187
+ args = []
188
+ args << '-y' if yes
189
+
190
+ sudo('pkg','install',*args,*packages)
191
+ when :pkg_add
192
+ sudo('pkg_add',*packages)
193
+ when :port
194
+ sudo('port','install',*packages)
195
+ when :zypper
196
+ sudo('zypper','-n','in','-l',*packages)
197
+ end
198
+ end
199
+ end
200
+ end
@@ -1,9 +1,11 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require 'command_kit/stdio'
4
- require 'command_kit/console'
5
3
  require 'command_kit/env'
6
4
  require 'command_kit/env/path'
5
+ require 'command_kit/stdio'
6
+ require 'command_kit/terminal'
7
+
8
+ require 'shellwords'
7
9
 
8
10
  module CommandKit
9
11
  #
@@ -35,10 +37,10 @@ module CommandKit
35
37
  # * [tty-pager](https://github.com/piotrmurach/tty-pager#readme)
36
38
  #
37
39
  module Pager
38
- include Stdio
39
- include Console
40
40
  include Env
41
41
  include Env::Path
42
+ include Stdio
43
+ include Terminal
42
44
 
43
45
  # Common pager commands.
44
46
  PAGERS = ['less -r', 'more -r']
@@ -50,13 +52,15 @@ module CommandKit
50
52
  # Keyword arguments.
51
53
  #
52
54
  # @note
53
- # Respects the `PAGER` env variable, or attemps to find `less` or
55
+ # Respects the `PAGER` env variable, or attempts to find `less` or
54
56
  # `more` by searching the `PATH` env variable.
55
57
  #
58
+ # @api public
59
+ #
56
60
  def initialize(**kwargs)
57
61
  super(**kwargs)
58
62
 
59
- @pager = env.fetch('PAGER') do
63
+ @pager_command = env.fetch('PAGER') do
60
64
  PAGERS.find do |command|
61
65
  bin = command.split(' ',2).first
62
66
 
@@ -74,15 +78,32 @@ module CommandKit
74
78
  # @yieldparam [IO]
75
79
  # The IO pipe to the pager.
76
80
  #
81
+ # @example
82
+ # pager do |io|
83
+ # io.puts "Hello world"
84
+ # # ...
85
+ # end
86
+ #
87
+ # @example Piping a command into the pager:
88
+ # IO.peopn(["ping", ip]) do |ping|
89
+ # pager do |io|
90
+ # ping.each_line do |line|
91
+ # io.write line
92
+ # end
93
+ # end
94
+ # end
95
+ #
96
+ # @api public
97
+ #
77
98
  def pager
78
- if !stdout.tty? || @pager.nil?
79
- # fallback to stdout if the process does not have a console or we could
99
+ if !stdout.tty? || @pager_command.nil?
100
+ # fallback to stdout if the process does not have a terminal or we could
80
101
  # not find a suitable pager command.
81
102
  yield stdout
82
103
  return
83
104
  end
84
105
 
85
- io = IO.popen(@pager,'w')
106
+ io = IO.popen(@pager_command,'w')
86
107
  pid = io.pid
87
108
 
88
109
  begin
@@ -99,23 +120,71 @@ module CommandKit
99
120
  end
100
121
 
101
122
  #
102
- # Pages the data if it's longer the console's height, otherwise prints the
123
+ # Pages the data if it's longer the terminal's height, otherwise prints the
103
124
  # data to {Stdio#stdout stdout}.
104
125
  #
105
126
  # @param [Array<String>, #to_s] data
106
127
  # The data to print.
107
128
  #
129
+ # @example
130
+ # print_or_page(data)
131
+ #
132
+ # @example Print or pages the contents of a file:
133
+ # print_or_page(File.read(file))
134
+ #
135
+ # @api public
136
+ #
108
137
  def print_or_page(data)
109
138
  line_count = case data
110
139
  when Array then data.length
111
140
  else data.to_s.each_line.count
112
141
  end
113
142
 
114
- if line_count > console_height
143
+ if line_count > terminal_height
115
144
  pager { |io| io.puts(data) }
116
145
  else
117
146
  stdout.puts(data)
118
147
  end
119
148
  end
149
+
150
+ #
151
+ # Pipes a command into the pager.
152
+ #
153
+ # @param [#to_s] command
154
+ # The program or command to run.
155
+ #
156
+ # @param [Array<#to_s>] arguments
157
+ # Additional arguments for the program.
158
+ #
159
+ # @return [Boolean]
160
+ # Indicates whether the command exited successfully or not.
161
+ #
162
+ # @note
163
+ # If multiple arguments are given, they will be shell-escaped and executed
164
+ # as a single command.
165
+ # If a single command is given, it will not be shell-escaped to allow
166
+ # executing compound shell commands.
167
+ #
168
+ # @example Pipe a single command into the pager:
169
+ # run_in_pager 'find', '.', '-name', '*.md'
170
+ #
171
+ # @example Pipe a compound command into the pager:
172
+ # run_in_pager "wc -l /path/to/wordlists/*.txt | sort -n"
173
+ #
174
+ # @api public
175
+ #
176
+ # @since 0.2.0
177
+ #
178
+ def pipe_to_pager(command,*arguments)
179
+ if @pager_command
180
+ unless arguments.empty?
181
+ command = Shellwords.shelljoin([command, *arguments])
182
+ end
183
+
184
+ system("#{command} | #{@pager_command}")
185
+ else
186
+ system(command.to_s,*arguments.map(&:to_s))
187
+ end
188
+ end
120
189
  end
121
190
  end
@@ -20,7 +20,7 @@ module CommandKit
20
20
  #
21
21
  module Indent
22
22
  #
23
- # Initializes the indententation level to zero.
23
+ # Initializes the indentation level to zero.
24
24
  #
25
25
  def initialize(**kwargs)
26
26
  @indent = 0
@@ -40,14 +40,35 @@ module CommandKit
40
40
  # increased.
41
41
  #
42
42
  # @return [Integer]
43
- # If no block is given, the indententation level will be returned.
43
+ # If no block is given, the indentation level will be returned.
44
+ #
45
+ # @example
46
+ # puts "values:"
47
+ # indent do
48
+ # values.each do |key,value|
49
+ # puts "#{key}: #{value}"
50
+ # end
51
+ # end
52
+ #
53
+ # @example
54
+ # puts "Code:"
55
+ # puts
56
+ # puts "```"
57
+ # indent(4) do
58
+ # code.each_line do |line|
59
+ # puts line
60
+ # end
61
+ # end
62
+ # puts "```"
63
+ #
64
+ # @api public
44
65
  #
45
66
  def indent(n=2)
46
67
  if block_given?
68
+ original_indent = @indent
69
+
47
70
  begin
48
- original_indent = @indent
49
71
  @indent += n
50
-
51
72
  yield
52
73
  ensure
53
74
  @indent = original_indent
@@ -63,6 +84,8 @@ module CommandKit
63
84
  # @param [Array<String>] lines
64
85
  # The lines to indent and print.
65
86
  #
87
+ # @api public
88
+ #
66
89
  def puts(*lines)
67
90
  if (@indent > 0 && !lines.empty?)
68
91
  padding = " " * @indent
@@ -9,14 +9,37 @@ module CommandKit
9
9
  module Printing
10
10
  include Stdio
11
11
 
12
+ # Platform independent new-line constant
13
+ #
14
+ # @return [String]
15
+ #
16
+ # @api public
17
+ EOL = $/
18
+
12
19
  #
13
20
  # Prints the error message to {Stdio#stderr stderr}.
14
21
  #
15
22
  # @param [String] message
16
23
  # The error message.
17
24
  #
25
+ # @example
26
+ # print_error "error: invalid input"
27
+ # # error: invalid input
28
+ #
29
+ # @example When CommandKit::CommandName is included:
30
+ # print_error "invalid input"
31
+ # # foo: invalid input
32
+ #
33
+ # @api public
34
+ #
18
35
  def print_error(message)
19
- stderr.puts message
36
+ if respond_to?(:command_name)
37
+ # if #command_name is available, prefix all error messages with it
38
+ stderr.puts "#{command_name}: #{message}"
39
+ else
40
+ # if #command_name is not available, just print the error message as-is
41
+ stderr.puts message
42
+ end
20
43
  end
21
44
 
22
45
  #
@@ -25,6 +48,17 @@ module CommandKit
25
48
  # @param [Exception] error
26
49
  # The error to print.
27
50
  #
51
+ # @example
52
+ # begin
53
+ # # ...
54
+ # rescue => error
55
+ # print_error "Error encountered"
56
+ # print_exception(error)
57
+ # exit(1)
58
+ # end
59
+ #
60
+ # @api public
61
+ #
28
62
  def print_exception(error)
29
63
  print_error error.full_message(highlight: stderr.tty?)
30
64
  end
@@ -3,6 +3,9 @@ module CommandKit
3
3
  # Retrieves the current program name (`$PROGRAM_NAME`).
4
4
  #
5
5
  module ProgramName
6
+ #
7
+ # @api private
8
+ #
6
9
  module ModuleMethods
7
10
  #
8
11
  # Extends {ClassMethods} or {ModuleMethods}, depending on whether
@@ -42,6 +45,8 @@ module CommandKit
42
45
  # The `$PROGRAM_NAME` or `nil` if the `$PROGRAM_NAME` is `-e`, `irb`,
43
46
  # or `rspec`.
44
47
  #
48
+ # @api semipublic
49
+ #
45
50
  def program_name
46
51
  $PROGRAM_NAME unless IGNORED_PROGRAM_NAMES.include?($PROGRAM_NAME)
47
52
  end
@@ -50,6 +55,8 @@ module CommandKit
50
55
  #
51
56
  # @see ClassMethods#program_name
52
57
  #
58
+ # @api public
59
+ #
53
60
  def program_name
54
61
  self.class.program_name
55
62
  end
@@ -34,6 +34,8 @@ module CommandKit
34
34
  # @param [IO] stderr
35
35
  # The stderr error output stream. Defaults to `$stderr`.
36
36
  #
37
+ # @api public
38
+ #
37
39
  def initialize(stdin: nil, stdout: nil, stderr: nil, **kwargs)
38
40
  @stdin = stdin
39
41
  @stdout = stdout
@@ -48,6 +50,8 @@ module CommandKit
48
50
  # @return [$stdin, IO]
49
51
  # The initialized `@stdin` value or `$stdin`.
50
52
  #
53
+ # @api public
54
+ #
51
55
  def stdin
52
56
  @stdin || $stdin
53
57
  end
@@ -58,6 +62,8 @@ module CommandKit
58
62
  # @return [$stdout, IO]
59
63
  # The initialized `@stdout` value or `$stdout`.
60
64
  #
65
+ # @api public
66
+ #
61
67
  def stdout
62
68
  @stdout || $stdout
63
69
  end
@@ -68,6 +74,8 @@ module CommandKit
68
74
  # @return [$stderr, IO]
69
75
  # The initialized `@stderr` value or `$stderr`.
70
76
  #
77
+ # @api public
78
+ #
71
79
  def stderr
72
80
  @stderr || $stderr
73
81
  end
@@ -75,6 +83,8 @@ module CommandKit
75
83
  #
76
84
  # Calls `stdin.gets`.
77
85
  #
86
+ # @api public
87
+ #
78
88
  def gets(*arguments)
79
89
  stdin.gets(*arguments)
80
90
  end
@@ -82,6 +92,8 @@ module CommandKit
82
92
  #
83
93
  # Calls `stdin.readline`.
84
94
  #
95
+ # @api public
96
+ #
85
97
  def readline(*arguments)
86
98
  stdin.readline(*arguments)
87
99
  end
@@ -89,6 +101,8 @@ module CommandKit
89
101
  #
90
102
  # Calls `stdin.readlines`.
91
103
  #
104
+ # @api public
105
+ #
92
106
  def readlines(*arguments)
93
107
  stdin.readlines(*arguments)
94
108
  end
@@ -99,6 +113,8 @@ module CommandKit
99
113
  #
100
114
  # Calls `stdout.putc`.
101
115
  #
116
+ # @api public
117
+ #
102
118
  def putc(*arguments)
103
119
  stdout.putc(*arguments)
104
120
  end
@@ -106,6 +122,8 @@ module CommandKit
106
122
  #
107
123
  # Calls `stdout.puts`.
108
124
  #
125
+ # @api public
126
+ #
109
127
  def puts(*arguments)
110
128
  stdout.puts(*arguments)
111
129
  end
@@ -113,6 +131,8 @@ module CommandKit
113
131
  #
114
132
  # Calls `stdout.print`.
115
133
  #
134
+ # @api public
135
+ #
116
136
  def print(*arguments)
117
137
  stdout.print(*arguments)
118
138
  end
@@ -120,6 +140,8 @@ module CommandKit
120
140
  #
121
141
  # Calls `stdout.printf`.
122
142
  #
143
+ # @api public
144
+ #
123
145
  def printf(*arguments)
124
146
  stdout.printf(*arguments)
125
147
  end
@@ -130,6 +152,8 @@ module CommandKit
130
152
  # @param [String, nil] message
131
153
  # The optional abort message.
132
154
  #
155
+ # @api public
156
+ #
133
157
  def abort(message=nil)
134
158
  stderr.puts(message) if message
135
159
  exit(1)
@@ -0,0 +1,40 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'command_kit/os'
4
+
5
+ module CommandKit
6
+ #
7
+ # Allows running commands with `sudo`.
8
+ #
9
+ # @since 0.2.0
10
+ #
11
+ module Sudo
12
+ include OS
13
+
14
+ #
15
+ # Runs the command under sudo, if the user isn't already root.
16
+ #
17
+ # @param [String] command
18
+ # The command to execute.
19
+ #
20
+ # @param [Array<String>] arguments
21
+ # Additional arguments for the command.
22
+ #
23
+ # @return [Boolean, nil]
24
+ # Specifies whether the command was successfully ran or not.
25
+ #
26
+ # @api public
27
+ #
28
+ def sudo(command,*arguments)
29
+ if windows?
30
+ system('runas','/user:administrator',command,*arguments)
31
+ else
32
+ if Process.uid == 0
33
+ system(command,*arguments)
34
+ else
35
+ system('sudo',command,*arguments)
36
+ end
37
+ end
38
+ end
39
+ end
40
+ end