command_kit 0.4.0 → 0.5.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 (88) hide show
  1. checksums.yaml +4 -4
  2. data/.github/workflows/ruby.yml +2 -0
  3. data/.rubocop.yml +3 -0
  4. data/ChangeLog.md +18 -0
  5. data/LICENSE.txt +1 -1
  6. data/README.md +4 -1
  7. data/command_kit.gemspec +7 -2
  8. data/examples/subcommands/cli/config/get.rb +47 -0
  9. data/examples/subcommands/cli/config/set.rb +44 -0
  10. data/examples/subcommands/cli/config.rb +23 -0
  11. data/examples/subcommands/cli/list.rb +35 -0
  12. data/examples/subcommands/cli/update.rb +47 -0
  13. data/examples/subcommands/cli.rb +55 -0
  14. data/lib/command_kit/completion/install.rb +276 -0
  15. data/lib/command_kit/env/home.rb +1 -1
  16. data/lib/command_kit/env/prefix.rb +41 -0
  17. data/lib/command_kit/env/shell.rb +58 -0
  18. data/lib/command_kit/inflector.rb +1 -1
  19. data/lib/command_kit/options/parser.rb +1 -1
  20. data/lib/command_kit/os/linux.rb +1 -1
  21. data/lib/command_kit/os.rb +1 -1
  22. data/lib/command_kit/printing/tables/table_formatter.rb +2 -2
  23. data/lib/command_kit/version.rb +1 -1
  24. data/lib/command_kit/xdg.rb +1 -1
  25. metadata +12 -66
  26. data/spec/arguments/argument_spec.rb +0 -133
  27. data/spec/arguments/argument_value_spec.rb +0 -66
  28. data/spec/arguments_spec.rb +0 -279
  29. data/spec/bug_report_spec.rb +0 -266
  30. data/spec/colors_spec.rb +0 -771
  31. data/spec/command_kit_spec.rb +0 -8
  32. data/spec/command_name_spec.rb +0 -130
  33. data/spec/command_spec.rb +0 -123
  34. data/spec/commands/auto_load/subcommand_spec.rb +0 -82
  35. data/spec/commands/auto_load_spec.rb +0 -159
  36. data/spec/commands/auto_require_spec.rb +0 -142
  37. data/spec/commands/fixtures/test_auto_load/cli/commands/test1.rb +0 -10
  38. data/spec/commands/fixtures/test_auto_load/cli/commands/test2.rb +0 -10
  39. data/spec/commands/fixtures/test_auto_require/lib/test_auto_require/cli/commands/test1.rb +0 -10
  40. data/spec/commands/help_spec.rb +0 -66
  41. data/spec/commands/parent_command_spec.rb +0 -40
  42. data/spec/commands/subcommand_spec.rb +0 -99
  43. data/spec/commands_spec.rb +0 -839
  44. data/spec/description_spec.rb +0 -179
  45. data/spec/edit_spec.rb +0 -72
  46. data/spec/env/home_spec.rb +0 -46
  47. data/spec/env/path_spec.rb +0 -84
  48. data/spec/env_spec.rb +0 -123
  49. data/spec/examples_spec.rb +0 -211
  50. data/spec/exception_handler_spec.rb +0 -103
  51. data/spec/file_utils_spec.rb +0 -59
  52. data/spec/fixtures/template.erb +0 -5
  53. data/spec/help/man_spec.rb +0 -345
  54. data/spec/help_spec.rb +0 -94
  55. data/spec/inflector_spec.rb +0 -166
  56. data/spec/interactive_spec.rb +0 -415
  57. data/spec/main_spec.rb +0 -179
  58. data/spec/man_spec.rb +0 -46
  59. data/spec/open_app_spec.rb +0 -85
  60. data/spec/options/option_spec.rb +0 -343
  61. data/spec/options/option_value_spec.rb +0 -171
  62. data/spec/options/parser_spec.rb +0 -255
  63. data/spec/options/quiet_spec.rb +0 -51
  64. data/spec/options/verbose_spec.rb +0 -51
  65. data/spec/options/version_spec.rb +0 -146
  66. data/spec/options_spec.rb +0 -465
  67. data/spec/os/linux_spec.rb +0 -164
  68. data/spec/os_spec.rb +0 -233
  69. data/spec/package_manager_spec.rb +0 -806
  70. data/spec/pager_spec.rb +0 -217
  71. data/spec/printing/fields_spec.rb +0 -167
  72. data/spec/printing/indent_spec.rb +0 -132
  73. data/spec/printing/lists_spec.rb +0 -99
  74. data/spec/printing/tables/border_style.rb +0 -43
  75. data/spec/printing/tables/cell_builer_spec.rb +0 -135
  76. data/spec/printing/tables/row_builder_spec.rb +0 -165
  77. data/spec/printing/tables/style_spec.rb +0 -377
  78. data/spec/printing/tables/table_builder_spec.rb +0 -252
  79. data/spec/printing/tables/table_formatter_spec.rb +0 -1180
  80. data/spec/printing/tables_spec.rb +0 -1069
  81. data/spec/printing_spec.rb +0 -106
  82. data/spec/program_name_spec.rb +0 -70
  83. data/spec/spec_helper.rb +0 -3
  84. data/spec/stdio_spec.rb +0 -264
  85. data/spec/sudo_spec.rb +0 -51
  86. data/spec/terminal_spec.rb +0 -231
  87. data/spec/usage_spec.rb +0 -237
  88. data/spec/xdg_spec.rb +0 -191
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 72a3fdeb65d9eb4c4e996aa95ea7e8131e220c2cb24be8b17d56e1742a156d35
4
- data.tar.gz: d05b75366f58c219c9680d07571a171239f0ab8f77580cb1c2d47c6322d7e74c
3
+ metadata.gz: 5f815869f166ce21da0c32699e8dcd7cebdb17cdbcc74fba1be3572ebb2d15a0
4
+ data.tar.gz: 2e2db9a8f190308d473959274dad507095baba55e0e73f7fcd969a4f23267054
5
5
  SHA512:
6
- metadata.gz: 1cc85835b40fded3170ee21619620dbb988dd3427fa8cb48456f09a7991b6eed72299a81ba19be543c260557504d5636237993f33360d463d72a87600ca14441
7
- data.tar.gz: 9d57ec57d540547d2fa664faf8e3bb1e0c0aa06929162d3dac849f858911aa5e7610e8294b2189927d8633de8e9784079df548a3e900fd73c57f76e72c87ad9d
6
+ metadata.gz: b0055ba75d1dc4aef15bf280ed86f5d4a514e5e95c00bc1285c9f29327d5b03ab4415a6001bc4ee05be04bb5504b2d6a0a8de0d33f6048a1ea333adb93915f54
7
+ data.tar.gz: a198cc0fe966abb5f20f5025b52144bce290d06602e93afd13e2eca03d8aa87477511a598562f023ef921490084c200896c453e78b75d9061216dc8e548f923b
@@ -12,6 +12,8 @@ jobs:
12
12
  ruby:
13
13
  - '3.0'
14
14
  - '3.1'
15
+ - '3.2'
16
+ - '3.3'
15
17
  # TODO: uncomment when jruby supports ruby >= 2.7
16
18
  # - jruby
17
19
  - truffleruby
data/.rubocop.yml CHANGED
@@ -152,3 +152,6 @@ Bundler/OrderedGems: { Enabled: false }
152
152
  Layout/SpaceInsideArrayLiteralBrackets: { Enabled: false }
153
153
 
154
154
  Naming/HeredocDelimiterNaming: { Enabled: false }
155
+
156
+ # I prefer to use explicit parenthesis for compound logical statements
157
+ Style/RedundantParentheses: { Enabled: false }
data/ChangeLog.md CHANGED
@@ -1,3 +1,21 @@
1
+ ### 0.5.0 / 2024-01-04
2
+
3
+ * Added {CommandKit::Env::Shell}.
4
+ * Added {CommandKit::Env::Prefix}.
5
+ * Added {CommandKit::Completion::Install}.
6
+
7
+ ### 0.4.1 / 2024-01-03
8
+
9
+ * Added more examples of how to define sub-commands and sub-sub-commands.
10
+
11
+ #### CommandKit::Options::Parser
12
+
13
+ * Do not override the command's `usage` if it's already been set.
14
+
15
+ #### CommandKit::Printing::Tables
16
+
17
+ * Format the table output as UTF-8 to allow UTF-8 data in the formatted table.
18
+
1
19
  ### 0.4.0 / 2022-11-11
2
20
 
3
21
  * Added {CommandKit::BugReport}.
data/LICENSE.txt CHANGED
@@ -1,4 +1,4 @@
1
- Copyright (c) 2021-2022 Hal Brodigan
1
+ Copyright (c) 2021-2024 Hal Brodigan
2
2
 
3
3
  Permission is hereby granted, free of charge, to any person obtaining
4
4
  a copy of this software and associated documentation files (the
data/README.md CHANGED
@@ -214,11 +214,14 @@ end
214
214
  * [CommandKit::Commands](https://rubydoc.info/gems/command_kit/CommandKit/Commands)
215
215
  * [CommandKit::Commands::AutoLoad](https://rubydoc.info/gems/command_kit/CommandKit/Commands/AutoLoad)
216
216
  * [CommandKit::Commands::AutoRequire](https://rubydoc.info/gems/command_kit/CommandKit/Commands/AutoRequire)
217
+ * [CommandKit::Completion::Install](https://rubydoc.info/gems/command_kit/CommandKit/Completion/Install)
217
218
  * [CommandKit::Description](https://rubydoc.info/gems/command_kit/CommandKit/Description)
218
219
  * [CommandKit::Edit](https://rubydoc.info/gems/command_kit/CommandKit/Edit)
219
220
  * [CommandKit::Env](https://rubydoc.info/gems/command_kit/CommandKit/Env)
220
221
  * [CommandKit::Env::Home](https://rubydoc.info/gems/command_kit/CommandKit/Env/Home)
221
222
  * [CommandKit::Env::Path](https://rubydoc.info/gems/command_kit/CommandKit/Env/Path)
223
+ * [CommandKit::Env::Prefix](https://rubydoc.info/gems/command_kit/CommandKit/Env/Prefix)
224
+ * [CommandKit::Env::Shell](https://rubydoc.info/gems/command_kit/CommandKit/Env/Shell)
222
225
  * [CommandKit::Examples](https://rubydoc.info/gems/command_kit/CommandKit/Examples)
223
226
  * [CommandKit::ExceptionHandler](https://rubydoc.info/gems/command_kit/CommandKit/ExceptionHandler)
224
227
  * [CommandKit::FileUtils](https://rubydoc.info/gems/command_kit/CommandKit/FileUtils)
@@ -253,7 +256,7 @@ Twitter.
253
256
 
254
257
  ## Copyright
255
258
 
256
- Copyright (c) 2021-2022 Hal Brodigan
259
+ Copyright (c) 2021-2024 Hal Brodigan
257
260
 
258
261
  See {file:LICENSE.txt} for details.
259
262
 
data/command_kit.gemspec CHANGED
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require 'yaml'
2
4
 
3
5
  Gem::Specification.new do |gem|
@@ -20,12 +22,15 @@ Gem::Specification.new do |gem|
20
22
  gem.homepage = gemspec['homepage']
21
23
  gem.metadata = gemspec['metadata'] if gemspec['metadata']
22
24
 
23
- glob = lambda { |patterns| gem.files & Dir[*patterns] }
25
+ glob = ->(patterns) { gem.files & Dir[*patterns] }
24
26
 
25
27
  gem.files = if gemspec['files'] then glob[gemspec['files']]
26
28
  else `git ls-files`.split($/)
27
29
  end
28
30
 
31
+ # exclude test files from the packages gem
32
+ gem.files -= glob[gemspec['test_files'] || 'spec/{**/}*']
33
+
29
34
  gem.executables = gemspec.fetch('executables') do
30
35
  glob['bin/*'].map { |path| File.basename(path) }
31
36
  end
@@ -43,7 +48,7 @@ Gem::Specification.new do |gem|
43
48
  gem.required_rubygems_version = gemspec['required_rubygems_version']
44
49
  gem.post_install_message = gemspec['post_install_message']
45
50
 
46
- split = lambda { |string| string.split(/,\s*/) }
51
+ split = ->(string) { string.split(/,\s*/) }
47
52
 
48
53
  if gemspec['dependencies']
49
54
  gemspec['dependencies'].each do |name,versions|
@@ -0,0 +1,47 @@
1
+ require 'command_kit/command'
2
+
3
+ module Foo
4
+ class CLI
5
+ class Config < CommandKit::Command
6
+ #
7
+ # The `config get` sub-command.
8
+ #
9
+ class Get < CommandKit::Command
10
+
11
+ usage '[options] NAME'
12
+
13
+ argument :name, required: false,
14
+ desc: 'Configuration variable name'
15
+
16
+ description 'Gets a configuration variable'
17
+
18
+ CONFIG = {
19
+ 'name' => 'John Smith',
20
+ 'email' => 'john.smith@example.com'
21
+ }
22
+
23
+ #
24
+ # Runs the `config get` sub-command.
25
+ #
26
+ # @param [String, nil] name
27
+ # The optional name argument.
28
+ #
29
+ def run(name=nil)
30
+ if name
31
+ unless CONFIG.has_key?(name)
32
+ print_error "unknown config variable: #{name}"
33
+ exit(1)
34
+ end
35
+
36
+ puts CONFIG.fetch(name)
37
+ else
38
+ CONFIG.each do |name,value|
39
+ puts "#{name}:\t#{value}"
40
+ end
41
+ end
42
+ end
43
+
44
+ end
45
+ end
46
+ end
47
+ end
@@ -0,0 +1,44 @@
1
+ require 'command_kit/command'
2
+
3
+ module Foo
4
+ class CLI
5
+ class Config < CommandKit::Command
6
+ #
7
+ # The `config set` sub-command.
8
+ #
9
+ class Set < CommandKit::Command
10
+
11
+ usage '[options] NAME'
12
+
13
+ argument :name, required: true,
14
+ desc: 'Configuration variable name to set'
15
+
16
+ argument :value, required: true,
17
+ desc: 'Configuration variable value to set'
18
+
19
+ description 'Sets a configuration variable'
20
+
21
+ CONFIG = {
22
+ 'name' => 'John Smith',
23
+ 'email' => 'john.smith@example.com'
24
+ }
25
+
26
+ #
27
+ # Runs the `config get` sub-command.
28
+ #
29
+ # @param [String] name
30
+ # The name argument.
31
+ #
32
+ def run(name,value)
33
+ unless CONFIG.has_key?(name)
34
+ print_error "unknown config variable: #{name}"
35
+ exit(1)
36
+ end
37
+
38
+ puts "Configuration variable #{name} was #{CONFIG.fetch(name)}, but is now #{value}"
39
+ end
40
+
41
+ end
42
+ end
43
+ end
44
+ end
@@ -0,0 +1,23 @@
1
+ require 'command_kit/command'
2
+ require 'command_kit/commands'
3
+
4
+ require_relative 'config/get'
5
+ require_relative 'config/set'
6
+
7
+ module Foo
8
+ class CLI
9
+ #
10
+ # The `config` sub-command.
11
+ #
12
+ class Config < CommandKit::Command
13
+
14
+ include CommandKit::Commands
15
+
16
+ command Get
17
+ command Set
18
+
19
+ description 'Get or set the configuration'
20
+
21
+ end
22
+ end
23
+ end
@@ -0,0 +1,35 @@
1
+ require 'command_kit/command'
2
+
3
+ module Foo
4
+ class CLI
5
+ #
6
+ # The `list` sub-command.
7
+ #
8
+ class List < CommandKit::Command
9
+
10
+ usage '[options] [NAME]'
11
+
12
+ argument :name, required: false,
13
+ desc: 'Optional name to list'
14
+
15
+ description 'Lists the contents'
16
+
17
+ ITEMS = %w[foo bar baz]
18
+
19
+ #
20
+ # Runs the `list` sub-command.
21
+ #
22
+ # @param [String, nil] name
23
+ # The optional name argument.
24
+ #
25
+ def run(name=nil)
26
+ if name
27
+ puts ITEMS.grep(name)
28
+ else
29
+ puts ITEMS
30
+ end
31
+ end
32
+
33
+ end
34
+ end
35
+ end
@@ -0,0 +1,47 @@
1
+ require 'command_kit/command'
2
+
3
+ module Foo
4
+ class CLI
5
+ #
6
+ # The `update` sub-command.
7
+ #
8
+ class Update < CommandKit::Command
9
+
10
+ usage '[options] [NAME]'
11
+
12
+ option :quiet, short: '-q',
13
+ desc: 'Suppresses logging messages'
14
+
15
+ argument :name, required: false,
16
+ desc: 'Optional name to update'
17
+
18
+ description 'Updates an item or all items'
19
+
20
+ ITEMS = %w[foo bar baz]
21
+
22
+ #
23
+ # Runs the `update` sub-command.
24
+ #
25
+ # @param [String, nil] name
26
+ # The optional name argument.
27
+ #
28
+ def run(name=nil)
29
+ if name
30
+ unless ITEMS.include?(name)
31
+ print_error "unknown item: #{name}"
32
+ exit(1)
33
+ end
34
+
35
+ puts "Updating #{name} ..." unless options[:quiet]
36
+ sleep 1
37
+ puts "Item #{name} updated." unless options[:quiet]
38
+ else
39
+ puts "Updating ..." unless options[:quiet]
40
+ sleep 2
41
+ puts "All items updated." unless options[:quiet]
42
+ end
43
+ end
44
+
45
+ end
46
+ end
47
+ end
@@ -0,0 +1,55 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ $LOAD_PATH.unshift(File.expand_path('../../../lib',__FILE__))
4
+
5
+ require 'command_kit/commands'
6
+
7
+ require_relative 'cli/config'
8
+ require_relative 'cli/list'
9
+ require_relative 'cli/update'
10
+
11
+ module Foo
12
+ #
13
+ # The main CLI command.
14
+ #
15
+ class CLI
16
+
17
+ include CommandKit::Commands
18
+
19
+ class << self
20
+ # The global configuration file setting.
21
+ #
22
+ # @return [String, nil]
23
+ attr_accessor :config_file
24
+ end
25
+
26
+ command_name 'foo'
27
+
28
+ # Commands must be explicitly registered, unless
29
+ # CommandKit::Commands::AutoLoad.new(...) is included.
30
+ command Config
31
+ command List
32
+ command Update
33
+
34
+ # Commands may have aliases
35
+ command_aliases['ls'] = 'list'
36
+ command_aliases['up'] = 'update'
37
+
38
+ # Global options may be defined which are parsed before the sub-command's
39
+ # options are parsed and the sub-command is executed.
40
+ option :config_file, short: '-C',
41
+ value: {
42
+ type: String,
43
+ usage: 'FILE'
44
+ },
45
+ desc: 'Global option to set the config file' do |file|
46
+ CLI.config_file = file
47
+ end
48
+
49
+ end
50
+ end
51
+
52
+ if $0 == __FILE__
53
+ # Normally you would invoke Foo::CLI.start from a bin/ script.
54
+ Foo::CLI.start
55
+ end
@@ -0,0 +1,276 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'command_kit/printing'
4
+ require 'command_kit/env/home'
5
+ require 'command_kit/env/shell'
6
+ require 'command_kit/env/prefix'
7
+ require 'fileutils'
8
+
9
+ module CommandKit
10
+ module Completion
11
+ #
12
+ # Mixins that adds methods for installing shell completion files.
13
+ #
14
+ # ## Environment Variables
15
+ #
16
+ # * `SHELL` - The current shell.
17
+ # * `PREFIX` - The optional root prefix of the file-system.
18
+ #
19
+ # @api public
20
+ #
21
+ # @since 0.5.0
22
+ #
23
+ module Install
24
+ include Printing
25
+ include Env::Home
26
+ include Env::Shell
27
+ include Env::Prefix
28
+
29
+ # The installation directory for completion files for the current shell.
30
+ #
31
+ # @return [String, nil]
32
+ # * Bash
33
+ # * Regular users: `~/.local/share/bash-completion/completions`
34
+ # * Root users:`$PREFIX/usr/local/share/bash-completion/completions`
35
+ # * Zsh: `$PREFIX/usr/local/share/zsh/site-functions`
36
+ # * Fish:
37
+ # * Regular users: `~/.config/fish/completions`
38
+ # * Root users: `$PREFIX/usr/local/share/fish/completions`
39
+ #
40
+ # @api private
41
+ attr_reader :completions_dir
42
+
43
+ #
44
+ # Initialize {#completions_dir} based on the `SHELL` environment variable
45
+ # and the UID of the process.
46
+ #
47
+ # @param [Hash{Symbol => Object}] kwargs
48
+ # Additional keyword arguments.
49
+ #
50
+ # @api public
51
+ #
52
+ def initialize(**kwargs)
53
+ super(**kwargs)
54
+
55
+ @completions_dir = case shell_type
56
+ when :bash
57
+ if Process.uid == 0
58
+ File.join(root,'usr','local','share','bash-completion','completions')
59
+ else
60
+ xdg_data_home = env.fetch('XDG_DATA_HOME') do
61
+ File.join(home_dir,'.local','share')
62
+ end
63
+
64
+ File.join(xdg_data_home,'bash-completion','completions')
65
+ end
66
+ when :zsh
67
+ File.join(root,'usr','local','share','zsh','site-functions')
68
+ when :fish
69
+ if Process.uid == 0
70
+ File.join(root,'usr','local','share','fish','completions')
71
+ else
72
+ xdg_config_home = env.fetch('XDG_CONFIG_HOME') do
73
+ File.join(home_dir,'.config')
74
+ end
75
+
76
+ File.join(xdg_config_home,'fish','completions')
77
+ end
78
+ end
79
+ end
80
+
81
+ #
82
+ # Prints the shell completion file to stdout.
83
+ #
84
+ # @param [String] path
85
+ # The path to the shell completion file.
86
+ #
87
+ # @param [Hash{Symbol => Object}] kwargs
88
+ # Additional keyword arguments.
89
+ #
90
+ # @option kwargs [:bash, :zsh, :fish] :type (:bash)
91
+ # The type of the completion file.
92
+ #
93
+ # @example Prints a Bash completion file:
94
+ # print_completion_file 'path/to/completions/foo'
95
+ #
96
+ # @example Prints a Zsh completion file:
97
+ # print_completion_file 'path/to/completions/foo', type: :zsh
98
+ #
99
+ # @example Prints a Fish completion file:
100
+ # print_completion_file 'path/to/completions/foo', type: :fish
101
+ #
102
+ # @api public
103
+ #
104
+ def print_completion_file(path,**kwargs)
105
+ write_completion_file(path,stdout,**kwargs)
106
+ end
107
+
108
+ #
109
+ # Installs the shell completion file into {#completions_dir}.
110
+ #
111
+ # @param [String] path
112
+ # The path to the shell completion file.
113
+ #
114
+ # @param [:bash, :zsh, :fish] type
115
+ # The type of the shell completion file.
116
+ #
117
+ # @example Install a Bash completion file:
118
+ # install_completion_file 'path/to/completions/foo'
119
+ #
120
+ # @example Install a Zsh completion file:
121
+ # install_completion_file 'path/to/completions/foo', type: :zsh
122
+ #
123
+ # @example Install a Fish completion file:
124
+ # install_completion_file 'path/to/completions/foo', type: :fish
125
+ #
126
+ # @api public
127
+ #
128
+ def install_completion_file(path, type: :bash)
129
+ completion_file = normalize_completion_file(path, type: type)
130
+ completion_path = File.join(@completions_dir,completion_file)
131
+
132
+ begin
133
+ ::FileUtils.mkdir_p(@completions_dir)
134
+ rescue Errno::EACCES
135
+ print_error "cannot write to #{shell_type} completions directory: #{@completions_dir}"
136
+ exit(-1)
137
+ end
138
+
139
+ begin
140
+ File.open(completion_path,'w') do |output|
141
+ write_completion_file(path,output, type: type)
142
+ end
143
+ rescue Errno::EACCES
144
+ print_error "cannot write to #{shell_type} completion file: #{completion_path}"
145
+ exit(-1)
146
+ end
147
+ end
148
+
149
+ #
150
+ # Uninstalls a shell completion file for the specified command.
151
+ #
152
+ # @param [String] command
153
+ # The command to uninstall the completions for.
154
+ #
155
+ # @example Removes the completion file for the command 'foo':
156
+ # uninstall_completion_file_for 'foo'
157
+ #
158
+ # @api public
159
+ #
160
+ def uninstall_completion_file_for(command)
161
+ completion_file = completion_file_for_command(command)
162
+ completion_path = File.join(@completions_dir,completion_file)
163
+
164
+ begin
165
+ ::FileUtils.rm_f(completion_path)
166
+ rescue Errno::EACCES
167
+ print_error "cannot remove #{shell_type} completion file: #{completion_path}"
168
+ exit(-1)
169
+ end
170
+ end
171
+
172
+ private
173
+
174
+ #
175
+ # Calculates the installed completion file for the given command.
176
+ #
177
+ # @param [String] command
178
+ # The command name.
179
+ #
180
+ # @return [String]
181
+ # The path to the completion file for the command.
182
+ #
183
+ # @api private
184
+ #
185
+ def completion_file_for_command(command)
186
+ case shell_type
187
+ when :bash then command
188
+ when :zsh then "_#{command}"
189
+ when :fish then "#{command}.fish"
190
+ when nil
191
+ if shell then print_error("cannot identify shell: #{shell}")
192
+ else print_error("cannot identify shell")
193
+ end
194
+
195
+ exit(-1)
196
+ else
197
+ print_error("completions not support for the #{shell_type} shell: #{shell}")
198
+ exit(-1)
199
+ end
200
+ end
201
+
202
+ #
203
+ # Calculates the installation path for the given completion file.
204
+ #
205
+ # @param [String] path
206
+ # The path to the completion file that will be installed.
207
+ #
208
+ # @param [:bash, :zsh, :fish] type
209
+ # The type of the shell completion file.
210
+ #
211
+ # @return [String]
212
+ # The installation path for the completion file.
213
+ #
214
+ # @api private
215
+ #
216
+ def normalize_completion_file(path, type: :bash)
217
+ ext = File.extname(path)
218
+ file = File.basename(path,ext)
219
+
220
+ case [shell_type, type]
221
+ when [:bash, :bash] # no-op
222
+ when [:zsh, :zsh],
223
+ [:zsh, :bash]
224
+ unless file.start_with?('_')
225
+ file = "_#{file}"
226
+ end
227
+ when [:fish, :fish]
228
+ file = "#{file}.fish"
229
+ else
230
+ if shell_type
231
+ print_error("cannot install #{type} completion file into the #{shell_type} shell: #{path}")
232
+ elsif shell
233
+ print_error("cannot identify shell: #{shell}")
234
+ else
235
+ print_error("cannot identify shell")
236
+ end
237
+
238
+ exit(-1)
239
+ end
240
+
241
+ return file
242
+ end
243
+
244
+ #
245
+ # Writes the shell completion file to the output
246
+ #
247
+ # @param [String] path
248
+ # The path to the shell completion file.
249
+ #
250
+ # @param [IO] output
251
+ # The output stream to write to.
252
+ #
253
+ # @param [:bash, :zsh, :fish] type
254
+ # The type of the shell completion file.
255
+ #
256
+ # @api private
257
+ #
258
+ def write_completion_file(path,output, type: :bash)
259
+ if shell_type == :zsh && type == :bash
260
+ file_name = File.basename(path,File.extname(path))
261
+ command = file_name.sub(/\A_/,'')
262
+
263
+ # add the #compdef magic comments for zsh
264
+ output.puts "#compdef #{command}"
265
+ output.puts
266
+ end
267
+
268
+ File.open(path) do |file|
269
+ file.each_line do |line|
270
+ output.write(line)
271
+ end
272
+ end
273
+ end
274
+ end
275
+ end
276
+ end
@@ -20,7 +20,7 @@ module CommandKit
20
20
  module ModuleMethods
21
21
  #
22
22
  # Extends {ClassMethods} or {ModuleMethods}, depending on whether
23
- # {Env::Home} is being included into a class or a module..
23
+ # {Env::Home} is being included into a class or a module.
24
24
  #
25
25
  # @param [Class, Module] context
26
26
  # The class or module which is including {Home}.