completely 0.6.0 → 0.7.1

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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: b40f2059243b2820d2ce140394be5551e5ddb131351adb35d26343841f8a54c7
4
- data.tar.gz: 71e01f5c44395f97023afff5a1822c5fa651efb98155a3b8dd05f750a19a5419
3
+ metadata.gz: 8afc0f96ec2612d016fd4a9914b7257f18c2b9e8302b7579129dab4fcaa2ebf1
4
+ data.tar.gz: f94b94f03d432c374f11c006f089f31e78b24aab124f3abf996e4a13f96fdcf5
5
5
  SHA512:
6
- metadata.gz: 71d90d706eb26933817483395670eb5d5ed516b606b62c1f4b9408afdec92b977142e4b2501ff12b75bb47fa971e558696ef5294a3c569f3856da8cb9904254f
7
- data.tar.gz: df1e950e2f839a977181521bb09fb917e6d47046f4f6b80d7a8dfc557b2c5d67ee66f962b7a23fd2456137a283bae6ffc9fe38e9ad97355c53c82a1ec84cff7a
6
+ metadata.gz: 88f5725ccbd2532d6270e8de9cba476ca14a37917bc87b0dd284928cf27a7c08ca6fcdca54c5fa49d7fb63c74197617f81c641ded2f91fa74d5c6c1ec9bf33bc
7
+ data.tar.gz: 78ee662b15cc64f7172410c6f28aa2ed55f1224aaa0e66700c51380cc36e6ad6fbc4740d11cf4387e58c683d0050122d47d88b4f93a9031a6065c1e359a36b8d
data/README.md CHANGED
@@ -40,10 +40,11 @@ or with Docker:
40
40
  $ alias completely='docker run --rm -it --user $(id -u):$(id -g) --volume "$PWD:/app" dannyben/completely'
41
41
  ```
42
42
 
43
- ## Using the `completely` command line
44
43
 
45
- The `completely` command line works with a simple YAML configuration file as
46
- input, and generates a bash completions script as output.
44
+ ## Configuration syntax
45
+
46
+ Completely works with a simple YAML configuration file as input, and generates
47
+ a bash completions script as output.
47
48
 
48
49
  The configuration file is built of blocks that look like this:
49
50
 
@@ -59,7 +60,7 @@ for the auto complete process.
59
60
 
60
61
  You can save a sample YAML file by running:
61
62
 
62
- ```
63
+ ```bash
63
64
  $ completely init
64
65
  ```
65
66
 
@@ -67,37 +68,34 @@ This will generate a file named `completely.yaml` with this content:
67
68
 
68
69
  ```yaml
69
70
  mygit:
71
+ - -h
72
+ - -v
70
73
  - --help
71
74
  - --version
72
- - status
73
75
  - init
74
- - commit
76
+ - status
77
+
78
+ mygit init:
79
+ - --bare
80
+ - <directory>
75
81
 
76
82
  mygit status:
77
83
  - --help
78
84
  - --verbose
79
85
  - --branch
80
- - $(git branch 2> /dev/null)
86
+ - -b
81
87
 
82
- mygit init:
83
- - --bare
84
- - <directory>
88
+ mygit status*--branch: &branches
89
+ - $(git branch --format='%(refname:short)' 2>/dev/null)
85
90
 
86
- mygit commit:
87
- - <file>
88
- - --help
89
- - --message
90
- - --all
91
- - -a
92
- - --quiet
93
- - -q
91
+ mygit status*-b: *branches
94
92
  ```
95
93
 
96
94
  Each pattern in this configuration file will be checked against the user's
97
- input, and if the input **starts with** a matching pattern, the list that
98
- follows it will be suggested as completions.
95
+ input, and if the input matches the pattern, the list that follows it will be
96
+ suggested as completions.
99
97
 
100
- Note that the suggested completions will not show flags (string that start with
98
+ Note that the suggested completions will not show flags (strings that start with
101
99
  a hyphen `-`) unless the input ends with a hyphen.
102
100
 
103
101
  To generate the bash script, simply run:
@@ -169,7 +167,7 @@ branches to your suggestions, use the following:
169
167
 
170
168
  ```yaml
171
169
  mygit:
172
- - $(git branch 2> /dev/null)
170
+ - $(git branch --format='%(refname:short)' 2>/dev/null)
173
171
  ```
174
172
 
175
173
  The `2> /dev/null` is used so that if the command is executed in a directory
@@ -186,10 +184,10 @@ mygit checkout:
186
184
  - -b
187
185
 
188
186
  mygit checkout*--branch:
189
- - $(git branch 2> /dev/null)
187
+ - $(git branch --format='%(refname:short)' 2>/dev/null)
190
188
 
191
189
  mygit checkout*-b:
192
- - $(git branch 2> /dev/null)
190
+ - $(git branch --format='%(refname:short)' 2>/dev/null)
193
191
  ```
194
192
 
195
193
  The above will suggest git branches for commands that end with `-b` or `--branch`.
@@ -202,11 +200,54 @@ mygit checkout:
202
200
  - -b
203
201
 
204
202
  mygit checkout*--branch: &branches
205
- - $(git branch 2> /dev/null)
203
+ - $(git branch --format='%(refname:short)' 2>/dev/null)
206
204
 
207
205
  mygit checkout*-b: *branches
208
206
  ```
209
207
 
208
+ ### Alternative nested syntax
209
+
210
+ Completely also supports an alternative nested syntax. You can generate this
211
+ example by running:
212
+
213
+ ```bash
214
+ $ completely init --nested
215
+ ```
216
+
217
+ The example configuration below will generate the exact same script as the one
218
+ shown at the beginning of this document.
219
+
220
+ ```yaml
221
+ mygit:
222
+ - -h
223
+ - -v
224
+ - --help
225
+ - --version
226
+ - init:
227
+ - --bare
228
+ - <directory>
229
+ - status:
230
+ - --help
231
+ - --verbose
232
+ - +--branch: &branches
233
+ - $(git branch --format='%(refname:short)' 2>/dev/null)
234
+ - +-b: *branches
235
+ ```
236
+
237
+ The rules here are as follows:
238
+
239
+ - Each pattern (e.g., `mygit`) can have a mixed array of strings and hashes.
240
+ - Strings and hash keys (e.e., `--help` and `init` respectively) will be used
241
+ as completion strings for that pattern.
242
+ - Hashes may contain a nested mixed array of the same structure.
243
+ - When a hash is provided, the hash key will be appended to the parent prefix.
244
+ In the example above, the `init` hash will create the pattern `mygit init`.
245
+ - In order to provide a wildcard (like `mygit status*--branch` in the standard
246
+ configuration syntax), you can provide either a `*` or a `+` prefix to the
247
+ hash key (e.g., `+--branch` or `"*--branch"`). Note that when using a `*`,
248
+ the hash key must be quoted since asterisks have special meaning in YAML.
249
+
250
+
210
251
  ## Using the generated completion scripts
211
252
 
212
253
  In order to enable the completions, simply source the generated script:
@@ -227,6 +268,8 @@ Alternatively, you can copy the script manually to one of these directories
227
268
 
228
269
  - `/usr/share/bash-completion/completions`
229
270
  - `/usr/local/etc/bash_completion.d`
271
+ - `~/.local/share/bash-completion/completions`
272
+
230
273
 
231
274
  ## Testing and debugging completion scripts
232
275
 
@@ -265,6 +308,7 @@ puts completions.wrapper_function "custom_function_name"
265
308
  p completions.tester.test "mygit status "
266
309
  ```
267
310
 
311
+
268
312
  ## Completions in ZSH
269
313
 
270
314
  If you are using Oh-My-Zsh, bash completions should already be enabled,
@@ -277,6 +321,17 @@ autoload -Uz +X compinit && compinit
277
321
  autoload -Uz +X bashcompinit && bashcompinit
278
322
  ```
279
323
 
324
+ ## Customizing the `complete` command
325
+
326
+ In case you wish to customize the `complete` command call in the generated
327
+ script, you can do so by adding any additional flags to the `completely.yaml`
328
+ configuration file using the special `completely_options` key. For example:
329
+
330
+ ```yaml
331
+ completely_options:
332
+ complete_options: -o nosort
333
+ ```
334
+
280
335
  ## Contributing / Support
281
336
 
282
337
  If you experience any issue, have a question or a suggestion, or if you wish
@@ -1,10 +1,11 @@
1
1
  require 'mister_bin'
2
- require 'completely/version'
3
2
  require 'completely/commands/generate'
4
3
  require 'completely/commands/init'
5
4
  require 'completely/commands/install'
6
5
  require 'completely/commands/preview'
7
6
  require 'completely/commands/test'
7
+ require 'completely/commands/uninstall'
8
+ require 'completely/version'
8
9
 
9
10
  module Completely
10
11
  class CLI
@@ -18,6 +19,7 @@ module Completely
18
19
  runner.route 'generate', to: Commands::Generate
19
20
  runner.route 'test', to: Commands::Test
20
21
  runner.route 'install', to: Commands::Install
22
+ runner.route 'uninstall', to: Commands::Uninstall
21
23
 
22
24
  runner
23
25
  end
@@ -5,9 +5,11 @@ module Completely
5
5
  class Init < Base
6
6
  help 'Create a new sample YAML configuration file'
7
7
 
8
- usage 'completely init [CONFIG_PATH]'
8
+ usage 'completely init [--nested] [CONFIG_PATH]'
9
9
  usage 'completely init (-h|--help)'
10
10
 
11
+ option '-n --nested', 'Generate a nested configuration'
12
+
11
13
  param_config_path
12
14
  environment_config_path
13
15
 
@@ -24,8 +26,15 @@ module Completely
24
26
  @sample ||= File.read sample_path
25
27
  end
26
28
 
29
+ def nested?
30
+ args['--nested']
31
+ end
32
+
27
33
  def sample_path
28
- @sample_path ||= File.expand_path '../templates/sample.yaml', __dir__
34
+ @sample_path ||= begin
35
+ sample_name = nested? ? 'sample-nested' : 'sample'
36
+ File.expand_path "../templates/#{sample_name}.yaml", __dir__
37
+ end
29
38
  end
30
39
  end
31
40
  end
@@ -21,12 +21,12 @@ module Completely
21
21
 
22
22
  def run
23
23
  if args['--dry']
24
- puts installer.command_string
24
+ puts installer.install_command_string
25
25
  return
26
26
  end
27
27
 
28
28
  success = installer.install force: args['--force']
29
- raise InstallError, "Failed running command:\nnb`#{installer.command_string}`" unless success
29
+ raise InstallError, "Failed running command:\nnb`#{installer.install_command_string}`" unless success
30
30
 
31
31
  say "Saved m`#{installer.target_path}`"
32
32
  say 'You may need to restart your session to test it'
@@ -0,0 +1,39 @@
1
+ require 'completely/commands/base'
2
+
3
+ module Completely
4
+ module Commands
5
+ class Uninstall < Base
6
+ summary 'Uninstall a bash completion script'
7
+
8
+ help <<~HELP
9
+ This command will remove the completion script for the specified program from all the bash completion directories.
10
+ HELP
11
+
12
+ usage 'completely uninstall PROGRAM [--dry]'
13
+ usage 'completely uninstall (-h|--help)'
14
+
15
+ option '-d --dry', 'Show the uninstallation command but do not run it'
16
+
17
+ param 'PROGRAM', 'Name of the program the completions are for.'
18
+
19
+ def run
20
+ if args['--dry']
21
+ puts installer.uninstall_command_string
22
+ return
23
+ end
24
+
25
+ success = installer.uninstall
26
+ raise InstallError, "Failed running command:\nnb`#{installer.uninstall_command_string}`" unless success
27
+
28
+ say 'Done'
29
+ say 'You may need to restart your session to test it'
30
+ end
31
+
32
+ private
33
+
34
+ def installer
35
+ Installer.new program: args['PROGRAM']
36
+ end
37
+ end
38
+ end
39
+ end
@@ -7,23 +7,20 @@ module Completely
7
7
 
8
8
  class << self
9
9
  def load(config_path, function_name: nil)
10
- begin
11
- data = YAML.load_file config_path, aliases: true
12
- rescue ArgumentError
13
- # :nocov:
14
- data = YAML.load_file config_path
15
- # :nocov:
16
- end
17
-
18
- new data, function_name: function_name
10
+ config = Config.load config_path
11
+ new config, function_name: function_name
19
12
  end
20
13
  end
21
14
 
22
15
  def initialize(config, function_name: nil)
23
- @config = config
16
+ @config = config.is_a?(Config) ? config : Config.new(config)
24
17
  @function_name = function_name
25
18
  end
26
19
 
20
+ def flat_config
21
+ @flat_config ||= config.flat_config
22
+ end
23
+
27
24
  def patterns
28
25
  @patterns ||= patterns!
29
26
  end
@@ -54,7 +51,7 @@ module Completely
54
51
  private
55
52
 
56
53
  def patterns!
57
- result = config.map do |text, completions|
54
+ result = flat_config.map do |text, completions|
58
55
  Pattern.new text, completions, pattern_function_name
59
56
  end
60
57
 
@@ -70,7 +67,7 @@ module Completely
70
67
  end
71
68
 
72
69
  def command
73
- @command ||= config.keys.first.split.first
70
+ @command ||= flat_config.keys.first.split.first
74
71
  end
75
72
 
76
73
  def function_name
@@ -84,5 +81,12 @@ module Completely
84
81
  def pattern_prefixes
85
82
  patterns.map(&:prefix)
86
83
  end
84
+
85
+ def complete_options_line
86
+ options = config.options[:complete_options]
87
+ return nil if options.nil? || options.strip.empty?
88
+
89
+ "#{options} "
90
+ end
87
91
  end
88
92
  end
@@ -0,0 +1,70 @@
1
+ module Completely
2
+ class Config
3
+ attr_reader :config, :options
4
+
5
+ class << self
6
+ def load(config_path)
7
+ begin
8
+ config = YAML.load_file config_path, aliases: true
9
+ rescue ArgumentError
10
+ # :nocov:
11
+ config = YAML.load_file config_path
12
+ # :nocov:
13
+ end
14
+
15
+ new config
16
+ end
17
+ end
18
+
19
+ def initialize(config)
20
+ @options = config.delete('completely_options')&.transform_keys(&:to_sym) || {}
21
+ @config = config
22
+ end
23
+
24
+ def flat_config
25
+ result = {}
26
+
27
+ config.each do |root_key, root_list|
28
+ result.merge! process_key(root_key, root_list)
29
+ end
30
+
31
+ result
32
+ end
33
+
34
+ private
35
+
36
+ def process_key(prefix, list)
37
+ result = {}
38
+ result[prefix] = collect_immediate_children list
39
+ result.merge! process_nested_items(prefix, list)
40
+ result
41
+ end
42
+
43
+ def collect_immediate_children(list)
44
+ list.map do |item|
45
+ x = item.is_a?(Hash) ? item.keys.first : item
46
+ x.gsub(/^[*+]/, '')
47
+ end
48
+ end
49
+
50
+ def process_nested_items(prefix, list)
51
+ result = {}
52
+
53
+ list.each do |item|
54
+ next unless item.is_a? Hash
55
+
56
+ nested_prefix = generate_nested_prefix(prefix, item)
57
+ nested_list = item.values.first
58
+ result.merge!(process_key(nested_prefix, nested_list))
59
+ end
60
+
61
+ result
62
+ end
63
+
64
+ def generate_nested_prefix(prefix, item)
65
+ appended_prefix = item.keys.first.gsub(/^\+/, '*')
66
+ appended_prefix = " #{appended_prefix}" unless appended_prefix.start_with? '*'
67
+ "#{prefix}#{appended_prefix}"
68
+ end
69
+ end
70
+ end
@@ -11,17 +11,27 @@ module Completely
11
11
  @target_directories ||= %W[
12
12
  /usr/share/bash-completion/completions
13
13
  /usr/local/etc/bash_completion.d
14
+ #{Dir.home}/.local/share/bash-completion/completions
14
15
  #{Dir.home}/.bash_completion.d
15
16
  ]
16
17
  end
17
18
 
18
- def command
19
+ def install_command
19
20
  result = root_user? ? [] : %w[sudo]
20
21
  result + %W[cp #{script_path} #{target_path}]
21
22
  end
22
23
 
23
- def command_string
24
- command.join ' '
24
+ def install_command_string
25
+ install_command.join ' '
26
+ end
27
+
28
+ def uninstall_command
29
+ result = root_user? ? [] : %w[sudo]
30
+ result + %w[rm -f] + target_directories.map { |dir| "#{dir}/#{program}" }
31
+ end
32
+
33
+ def uninstall_command_string
34
+ uninstall_command.join ' '
25
35
  end
26
36
 
27
37
  def target_path
@@ -41,7 +51,11 @@ module Completely
41
51
  raise InstallError, "File exists: m`#{target_path}`"
42
52
  end
43
53
 
44
- system(*command)
54
+ system(*install_command)
55
+ end
56
+
57
+ def uninstall
58
+ system(*uninstall_command)
45
59
  end
46
60
 
47
61
  private
@@ -0,0 +1,14 @@
1
+ mygit:
2
+ - -h
3
+ - -v
4
+ - --help
5
+ - --version
6
+ - init:
7
+ - --bare
8
+ - <directory>
9
+ - status:
10
+ - --help
11
+ - --verbose
12
+ - +--branch: &branches
13
+ - $(git branch --format='%(refname:short)' 2>/dev/null)
14
+ - +-b: *branches
@@ -1,25 +1,22 @@
1
1
  mygit:
2
+ - -h
3
+ - -v
2
4
  - --help
3
5
  - --version
4
- - status
5
6
  - init
6
- - commit
7
+ - status
8
+
9
+ mygit init:
10
+ - --bare
11
+ - <directory>
7
12
 
8
13
  mygit status:
9
14
  - --help
10
15
  - --verbose
11
16
  - --branch
12
- - $(git branch 2> /dev/null)
17
+ - -b
13
18
 
14
- mygit init:
15
- - --bare
16
- - <directory>
19
+ mygit status*--branch: &branches
20
+ - $(git branch --format='%(refname:short)' 2>/dev/null)
17
21
 
18
- mygit commit:
19
- - <file>
20
- - --help
21
- - --message
22
- - --all
23
- - -a
24
- - --quiet
25
- - -q
22
+ mygit status*-b: *branches
@@ -11,7 +11,7 @@
11
11
 
12
12
  if [[ "${cur:0:1}" == "-" ]]; then
13
13
  echo "$words"
14
-
14
+
15
15
  else
16
16
  for word in $words; do
17
17
  [[ "${word:0:1}" != "-" ]] && result+=("$word")
@@ -38,12 +38,12 @@
38
38
  % patterns.each do |pattern|
39
39
  % next if pattern.empty?
40
40
  <%= pattern.case_string %>)
41
- while read -r; do COMPREPLY+=( "$REPLY" ); done < <( compgen <%= pattern.compgen %> -- "$cur" )
41
+ while read -r; do COMPREPLY+=("$REPLY"); done < <(compgen <%= pattern.compgen %> -- "$cur")
42
42
  ;;
43
43
 
44
44
  % end
45
45
  esac
46
46
  } &&
47
- complete -F <%= function_name %> <%= command %>
47
+ complete <%= complete_options_line %>-F <%= function_name %> <%= command %>
48
48
 
49
49
  # ex: filetype=sh
@@ -1,3 +1,3 @@
1
1
  module Completely
2
- VERSION = '0.6.0'
2
+ VERSION = '0.7.1'
3
3
  end
data/lib/completely.rb CHANGED
@@ -1,9 +1,5 @@
1
- if ENV['BYEBUG']
2
- require 'byebug'
3
- require 'lp'
4
- end
5
-
6
1
  require 'completely/exceptions'
2
+ require 'completely/config'
7
3
  require 'completely/pattern'
8
4
  require 'completely/completions'
9
5
  require 'completely/tester'
metadata CHANGED
@@ -1,14 +1,13 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: completely
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.6.0
4
+ version: 0.7.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Danny Ben Shitrit
8
- autorequire:
9
8
  bindir: bin
10
9
  cert_chain: []
11
- date: 2023-06-23 00:00:00.000000000 Z
10
+ date: 2025-04-04 00:00:00.000000000 Z
12
11
  dependencies:
13
12
  - !ruby/object:Gem::Dependency
14
13
  name: colsole
@@ -61,10 +60,13 @@ files:
61
60
  - lib/completely/commands/install.rb
62
61
  - lib/completely/commands/preview.rb
63
62
  - lib/completely/commands/test.rb
63
+ - lib/completely/commands/uninstall.rb
64
64
  - lib/completely/completions.rb
65
+ - lib/completely/config.rb
65
66
  - lib/completely/exceptions.rb
66
67
  - lib/completely/installer.rb
67
68
  - lib/completely/pattern.rb
69
+ - lib/completely/templates/sample-nested.yaml
68
70
  - lib/completely/templates/sample.yaml
69
71
  - lib/completely/templates/template.erb
70
72
  - lib/completely/templates/tester-template.erb
@@ -78,7 +80,6 @@ metadata:
78
80
  changelog_uri: https://github.com/DannyBen/completely/blob/master/CHANGELOG.md
79
81
  source_code_uri: https://github.com/DannyBen/completely
80
82
  rubygems_mfa_required: 'true'
81
- post_install_message:
82
83
  rdoc_options: []
83
84
  require_paths:
84
85
  - lib
@@ -93,8 +94,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
93
94
  - !ruby/object:Gem::Version
94
95
  version: '0'
95
96
  requirements: []
96
- rubygems_version: 3.4.14
97
- signing_key:
97
+ rubygems_version: 3.6.3
98
98
  specification_version: 4
99
99
  summary: Bash Completions Generator
100
100
  test_files: []