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
@@ -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
@@ -0,0 +1,159 @@
1
+ require 'command_kit/stdio'
2
+ require 'command_kit/env'
3
+
4
+ begin
5
+ require 'io/console'
6
+ rescue LoadError
7
+ end
8
+
9
+ module CommandKit
10
+ #
11
+ # Provides direct access to the terminal.
12
+ #
13
+ # ## Environment Variables
14
+ #
15
+ # * `LINES` - The explicit number of lines or rows the console should have.
16
+ # * `COLUMNS` - The explicit number of columns the console should have.
17
+ #
18
+ # @see https://rubydoc.info/gems/io-console/IO
19
+ #
20
+ module Terminal
21
+ include Stdio
22
+ include Env
23
+
24
+ # The default terminal height to fallback to.
25
+ DEFAULT_TERMINAL_HEIGHT = 25
26
+
27
+ # The default terminal width to fallback to.
28
+ DEFAULT_TERMINAL_WIDTH = 80
29
+
30
+ #
31
+ # Initializes any terminal settings.
32
+ #
33
+ # @param [Hash{Symbol => Object}] kwargs
34
+ # Additional keyword arguments.
35
+ #
36
+ # @note
37
+ # If the `$LINES` env variable is set, and is non-zero, it will be
38
+ # returned by {#terminal_height}.
39
+ #
40
+ # @note
41
+ # If the `$COLUMNS` env variable is set, and is non-zero, it will be
42
+ # returned by {#terminal_width}.
43
+ #
44
+ # @api public
45
+ #
46
+ def initialize(**kwargs)
47
+ super(**kwargs)
48
+
49
+ @terminal_height = if (lines = env['LINES'])
50
+ lines.to_i
51
+ else
52
+ DEFAULT_TERMINAL_HEIGHT
53
+ end
54
+
55
+ @terminal_width = if (columns = env['COLUMNS'])
56
+ columns.to_i
57
+ else
58
+ DEFAULT_TERMINAL_WIDTH
59
+ end
60
+ end
61
+
62
+ #
63
+ # Determines if program is running in a terminal.
64
+ #
65
+ # @return [Boolean]
66
+ # Specifies whether {Stdio#stdout stdout} is connected to a terminal.
67
+ #
68
+ # @api public
69
+ #
70
+ def terminal?
71
+ IO.respond_to?(:console) && stdout.tty?
72
+ end
73
+
74
+ #
75
+ # @since 0.2.0
76
+ #
77
+ alias tty? terminal?
78
+
79
+ #
80
+ # Returns the terminal object, if {Stdio#stdout stdout} is connected to a
81
+ # terminal.
82
+ #
83
+ # @return [IO, nil]
84
+ # The IO objects or `nil` if {Stdio#stdout stdout} is not connected to a
85
+ # terminal.
86
+ #
87
+ # @example
88
+ # terminal
89
+ # # => #<File:/dev/tty>
90
+ #
91
+ # @see https://rubydoc.info/gems/io-console/IO
92
+ #
93
+ # @api semipublic
94
+ #
95
+ def terminal
96
+ IO.console if terminal?
97
+ end
98
+
99
+ #
100
+ # Returns the terminal's height in number of lines.
101
+ #
102
+ # @return [Integer]
103
+ # The terminal's height in number of lines.
104
+ #
105
+ # @example
106
+ # terminal_height
107
+ # # => 22
108
+ #
109
+ # @api public
110
+ #
111
+ def terminal_height
112
+ if (terminal = self.terminal)
113
+ terminal.winsize[0]
114
+ else
115
+ @terminal_height
116
+ end
117
+ end
118
+
119
+ #
120
+ # Returns the terminal's width in number of lines.
121
+ #
122
+ # @return [Integer]
123
+ # The terminal's width in number of columns.
124
+ #
125
+ # @example
126
+ # terminal_width
127
+ # # => 91
128
+ #
129
+ # @api public
130
+ #
131
+ def terminal_width
132
+ if (terminal = self.terminal)
133
+ terminal.winsize[1]
134
+ else
135
+ @terminal_width
136
+ end
137
+ end
138
+
139
+ #
140
+ # The terminal height (lines) and width (columns).
141
+ #
142
+ # @return [(Integer, Integer)]
143
+ # Returns the height and width of the terminal.
144
+ #
145
+ # @example
146
+ # terminal_size
147
+ # # => [23, 91]
148
+ #
149
+ # @api public
150
+ #
151
+ def terminal_size
152
+ if (terminal = self.terminal)
153
+ terminal.winsize
154
+ else
155
+ [@terminal_height, @terminal_width]
156
+ end
157
+ end
158
+ end
159
+ end
@@ -15,6 +15,9 @@ module CommandKit
15
15
  include CommandName
16
16
  include Help
17
17
 
18
+ #
19
+ # @api private
20
+ #
18
21
  module ModuleMethods
19
22
  #
20
23
  # Extends {ClassMethods} or {ModuleMethods}, depending on whether {Usage}
@@ -50,6 +53,11 @@ module CommandKit
50
53
  # @return [String, Array<String>]
51
54
  # The class'es or superclass'es usage string(s).
52
55
  #
56
+ # @example
57
+ # usage "[options] ARG1 ARG2 [ARG3 ...]"
58
+ #
59
+ # @api public
60
+ #
53
61
  def usage(new_usage=nil)
54
62
  if new_usage
55
63
  @usage = new_usage
@@ -65,6 +73,8 @@ module CommandKit
65
73
  #
66
74
  # @return [Array<String>, String, nil]
67
75
  #
76
+ # @api public
77
+ #
68
78
  def usage
69
79
  case (usage = self.class.usage)
70
80
  when Array
@@ -77,6 +87,8 @@ module CommandKit
77
87
  #
78
88
  # Prints the `usage: ...` output.
79
89
  #
90
+ # @api semipublic
91
+ #
80
92
  def help_usage
81
93
  case (usage = self.usage)
82
94
  when Array
@@ -95,6 +107,8 @@ module CommandKit
95
107
  #
96
108
  # @see #help_usage
97
109
  #
110
+ # @api public
111
+ #
98
112
  def help
99
113
  help_usage
100
114
  end
@@ -1,4 +1,4 @@
1
1
  module CommandKit
2
2
  # command_kit version
3
- VERSION = "0.1.0.pre1"
3
+ VERSION = "0.2.0"
4
4
  end
@@ -24,6 +24,9 @@ module CommandKit
24
24
  include CommandName
25
25
  include Env::Home
26
26
 
27
+ #
28
+ # @api private
29
+ #
27
30
  module ModuleMethods
28
31
  #
29
32
  # Extends {ClassMethods} or {ModuleMethods}, depending on whether {XDG} is
@@ -45,6 +48,9 @@ module CommandKit
45
48
 
46
49
  extend ModuleMethods
47
50
 
51
+ #
52
+ # Class-level methods.
53
+ #
48
54
  module ClassMethods
49
55
  #
50
56
  # Gets or sets the XDG sub-directory name used by the command.
@@ -58,11 +64,17 @@ module CommandKit
58
64
  # {CommandName::ClassMethods#command_name} if no {#xdg_namespace} has
59
65
  # been defined.
60
66
  #
67
+ # @api public
68
+ #
61
69
  def xdg_namespace(new_namespace=nil)
62
70
  if new_namespace
63
71
  @xdg_namespace = new_namespace.to_s
64
72
  else
65
- @xdg_namespace || (superclass.xdg_namespace if superclass.kind_of?(ClassMethods)) || command_name
73
+ @xdg_namespace || if superclass.kind_of?(ClassMethods)
74
+ superclass.xdg_namespace
75
+ else
76
+ command_name
77
+ end
66
78
  end
67
79
  end
68
80
  end
@@ -70,16 +82,22 @@ module CommandKit
70
82
  # The `~/.config/<xdg_namespace>` directory.
71
83
  #
72
84
  # @return [String]
85
+ #
86
+ # @api public
73
87
  attr_reader :config_dir
74
88
 
75
89
  # The `~/.local/share/<xdg_namespace>` directory.
76
90
  #
77
91
  # @return [String]
92
+ #
93
+ # @api public
78
94
  attr_reader :local_share_dir
79
95
 
80
96
  # The `~/.cache/<xdg_namespace>` directory.
81
97
  #
82
98
  # @return [String]
99
+ #
100
+ # @api public
83
101
  attr_reader :cache_dir
84
102
 
85
103
  #
@@ -131,6 +149,8 @@ module CommandKit
131
149
  #
132
150
  # @see ClassMethods#xdg_namespace
133
151
  #
152
+ # @api semipublic
153
+ #
134
154
  def xdg_namespace
135
155
  self.class.xdg_namespace
136
156
  end