completion 0.0.1 → 0.0.2

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: 284727bae15655feaebf3d8757241257db50b763122a31cadc654d5319d7a2bf
4
- data.tar.gz: e3e0ec43c86bcbc334cba971bfe019bd822c3a64ed03577cfc0a6a804d9a0834
3
+ metadata.gz: f782fa1466bc285fd68a570bb4e3d76b3651a07b5833e0b73ed5718928aa2017
4
+ data.tar.gz: 24a3282bd7e93bb9bace2f3637ecbb43b1f787210e9227a8352b3f5bb793f62c
5
5
  SHA512:
6
- metadata.gz: 29ebeaf86a358ff8dd761326b06f7d718e9919f80c2b0d1d2a359d103032ef081101da49a46ac6808915703a8f30d8b06508c3e07ca65b7690414e9d8eab6ed4
7
- data.tar.gz: 071a5afaffb9ee016b327434b7d87d19d57d8b0e1ae81cf823ca0b1aea0a66b26b2396f0177c992ece283bf4b31f97b4fbad1cebbb7911994cd6f0245ba83d38
6
+ metadata.gz: 0e6415c243214aa9c506a11e99482c52fbf222358eb5d7a6e8766afd4126484cfb7d771eccb9500be4f22046aff58814954131aeb022d5c0e8705d2601eda88a
7
+ data.tar.gz: 6eb0ac55618be64bfec46b8be4f72562624b0f92175e24d4d30ea8fa677c72a0bdfc0f8bbb4341f678ca2bd7f60f1e2a51f74333cb7f2390beac9dc4e54aaa75
checksums.yaml.gz.sig CHANGED
@@ -1 +1,2 @@
1
- �0�6�[�cJgTL\��-gˆN���g���17�k(�Ƭ��^?����P�=�p�5o���c���8�s�(n��}X�:�w)�9�����+��MMk��];f]_GL�n���}9G>TGzl3cH���[z
1
+ *��uA���4������'9���hk_�kPu �����, b�J
2
+ S�Jw���96��&fǝ�{?�LhO����˩Y��^����AtE����ڃ[?�;�\�&� 5��p�O;N�V$R���q׽�c`
@@ -82,6 +82,34 @@ You can specify the shell and adapter directory explicitly:
82
82
  $ completion install --shell zsh --directory ~/.zsh/completions --command falcon
83
83
  ~~~
84
84
 
85
+ ## Uninstalling an Adapter
86
+
87
+ Uninstall the generic adapter for the current shell:
88
+
89
+ ~~~ bash
90
+ $ completion uninstall
91
+ ~~~
92
+
93
+ Uninstall an adapter for a specific command:
94
+
95
+ ~~~ bash
96
+ $ completion uninstall --command falcon
97
+ ~~~
98
+
99
+ You can specify the shell and adapter directory explicitly:
100
+
101
+ ~~~ bash
102
+ $ completion uninstall --shell zsh --directory ~/.zsh/completions --command falcon
103
+ ~~~
104
+
105
+ Remove all managed adapters and helpers for the current shell:
106
+
107
+ ~~~ bash
108
+ $ completion uninstall --all
109
+ ~~~
110
+
111
+ `uninstall --all` only removes files generated with the completion metadata marker.
112
+
85
113
  ## Installed Files
86
114
 
87
115
  Installation writes a small adapter script and shared shell helpers.
@@ -109,6 +137,12 @@ Fish command adapters are installed into:
109
137
  ~/.config/fish/completions
110
138
  ~~~
111
139
 
140
+ Fish generic adapters are installed into:
141
+
142
+ ~~~ text
143
+ ~/.config/fish/conf.d
144
+ ~~~
145
+
112
146
  ## Generating an Adapter
113
147
 
114
148
  You can generate an adapter script without installing it:
@@ -28,7 +28,7 @@ module Completion
28
28
  # @returns [void]
29
29
  def call
30
30
  shell = @options[:shell]
31
- directory = @options[:directory] || Shell.default_directory(shell)
31
+ directory = Shell.adapter_directory(shell, @options[:command], directory: @options[:directory])
32
32
  path = File.join(directory, Shell.file_name(shell, @options[:command]))
33
33
  script = Shell.script(shell: shell, executable: @options[:command])
34
34
 
@@ -11,6 +11,7 @@ end
11
11
 
12
12
  require_relative "generate"
13
13
  require_relative "install"
14
+ require_relative "uninstall"
14
15
 
15
16
  module Completion
16
17
  module Command
@@ -25,6 +26,7 @@ module Completion
25
26
  nested :command, {
26
27
  "install" => Install,
27
28
  "generate" => Generate,
29
+ "uninstall" => Uninstall,
28
30
  }, default: "generate"
29
31
 
30
32
  # Execute the selected completion sub-command.
@@ -0,0 +1,86 @@
1
+ # frozen_string_literal: true
2
+
3
+ # Released under the MIT License.
4
+ # Copyright, 2026, by Samuel Williams.
5
+
6
+ require "samovar"
7
+
8
+ require_relative "../shell"
9
+
10
+ module Completion
11
+ module Command
12
+ # Uninstall a shell completion adapter script from a user-local completion directory.
13
+ class Uninstall < Samovar::Command
14
+ self.description = "Uninstall a shell completion adapter script."
15
+
16
+ options do
17
+ option "--shell <name>", "The shell to uninstall completions for.", default: Shell.method(:default_shell), completions: ["bash", "zsh", "fish"]
18
+ option "--directory <path>", "The completion directory to uninstall from."
19
+ option "--command <name>", "The command executable to stop completing."
20
+ option "--all", "Remove all managed completion scripts for the selected shell."
21
+ end
22
+
23
+ # Remove the installed shell adapter script.
24
+ #
25
+ # @returns [void]
26
+ def call
27
+ shell = @options[:shell]
28
+
29
+ if @options[:all]
30
+ return uninstall_all(shell)
31
+ end
32
+
33
+ directory = Shell.adapter_directory(shell, @options[:command], directory: @options[:directory])
34
+ path = File.join(directory, Shell.file_name(shell, @options[:command]))
35
+
36
+ File.delete(path) if File.exist?(path)
37
+
38
+ output.puts path
39
+ end
40
+
41
+ private
42
+
43
+ def uninstall_all(shell)
44
+ paths = managed_paths(shell, @options[:directory])
45
+
46
+ paths.each do |path|
47
+ File.delete(path)
48
+ output.puts path
49
+ end
50
+
51
+ return paths
52
+ end
53
+
54
+ def managed_paths(shell, directory)
55
+ directories = managed_directories(shell, directory)
56
+
57
+ return directories.flat_map do |directory|
58
+ Dir.children(directory).filter_map do |name|
59
+ path = File.join(directory, name)
60
+
61
+ path if Shell.managed?(path)
62
+ end
63
+ end
64
+ end
65
+
66
+ def managed_directories(shell, directory)
67
+ if directory
68
+ return [directory].select{|path| Dir.exist?(path)}
69
+ end
70
+
71
+ case shell
72
+ when "fish"
73
+ [
74
+ Shell.default_directory(shell),
75
+ Shell.default_configuration_directory,
76
+ Shell.default_function_directory,
77
+ ].select{|path| Dir.exist?(path)}
78
+ else
79
+ [
80
+ Shell.default_directory(shell),
81
+ ].select{|path| Dir.exist?(path)}
82
+ end
83
+ end
84
+ end
85
+ end
86
+ end
@@ -15,7 +15,7 @@ module Completion
15
15
  command = Shell.command_name(executable)
16
16
 
17
17
  if executable
18
- return <<~SCRIPT
18
+ return Shell.annotate(<<~SCRIPT, kind: "adapter", shell: "bash", executable: executable)
19
19
  _completion_source="${BASH_SOURCE[0]}"
20
20
  if [[ "$_completion_source" == */* ]]; then
21
21
  _completion_directory="${_completion_source%/*}"
@@ -27,7 +27,7 @@ module Completion
27
27
  SCRIPT
28
28
  end
29
29
 
30
- <<~SCRIPT
30
+ Shell.annotate(<<~SCRIPT, kind: "adapter", shell: "bash")
31
31
  _completion_source="${BASH_SOURCE[0]}"
32
32
  if [[ "$_completion_source" == */* ]]; then
33
33
  _completion_directory="${_completion_source%/*}"
@@ -43,7 +43,7 @@ module Completion
43
43
  #
44
44
  # @returns [String] The generated Bash helper script.
45
45
  def self.shared_script
46
- <<~SCRIPT
46
+ Shell.annotate(<<~SCRIPT, kind: "helper", shell: "bash")
47
47
  __completion_resolve() {
48
48
  local command="$1"
49
49
  local basename="${command##*/}"
@@ -15,12 +15,12 @@ module Completion
15
15
  command = Shell.command_name(executable)
16
16
 
17
17
  if executable
18
- return <<~SCRIPT
18
+ return Shell.annotate(<<~SCRIPT, kind: "adapter", shell: "fish", executable: executable)
19
19
  __completion_register #{command}
20
20
  SCRIPT
21
21
  end
22
22
 
23
- <<~SCRIPT
23
+ Shell.annotate(<<~SCRIPT, kind: "adapter", shell: "fish")
24
24
  __completion_register_default
25
25
  SCRIPT
26
26
  end
@@ -42,7 +42,7 @@ module Completion
42
42
  #
43
43
  # @returns [String] The generated Fish function script.
44
44
  def self.complete_function
45
- <<~SCRIPT
45
+ Shell.annotate(<<~SCRIPT, kind: "helper", shell: "fish")
46
46
  function __completion_complete --description 'Complete commands with adjacent completion executables'
47
47
  set -l argv (commandline -opc)
48
48
  set -e argv[1]
@@ -95,7 +95,7 @@ module Completion
95
95
  #
96
96
  # @returns [String] The generated Fish function script.
97
97
  def self.register_function
98
- <<~SCRIPT
98
+ Shell.annotate(<<~SCRIPT, kind: "helper", shell: "fish")
99
99
  function __completion_register --description 'Register command completion'
100
100
  complete -c $argv[1] -f -a "(__completion_complete)"
101
101
  end
@@ -106,7 +106,7 @@ module Completion
106
106
  #
107
107
  # @returns [String] The generated Fish function script.
108
108
  def self.register_default_function
109
- <<~SCRIPT
109
+ Shell.annotate(<<~SCRIPT, kind: "helper", shell: "fish")
110
110
  function __completion_register_default --description 'Register generic completion'
111
111
  complete -c "*" -n "__completion_supported" -f -a "(__completion_complete)"
112
112
  end
@@ -117,7 +117,7 @@ module Completion
117
117
  #
118
118
  # @returns [String] The generated Fish function script.
119
119
  def self.resolve_function
120
- <<~SCRIPT
120
+ Shell.annotate(<<~SCRIPT, kind: "helper", shell: "fish")
121
121
  function __completion_resolve --description 'Resolve completion command'
122
122
  set -l argv (commandline -opc)
123
123
  set -l command $argv[1]
@@ -136,10 +136,15 @@ module Completion
136
136
  #
137
137
  # @returns [String] The generated Fish function script.
138
138
  def self.supported_function
139
- <<~SCRIPT
139
+ Shell.annotate(<<~SCRIPT, kind: "helper", shell: "fish")
140
140
  function __completion_supported --description 'Check completion support'
141
141
  set -l completer (__completion_resolve)
142
- test -x "$completer"
142
+
143
+ if string match -q "*/*" "$completer"
144
+ test -x "$completer"
145
+ else
146
+ type -q "$completer"
147
+ end
143
148
  end
144
149
  SCRIPT
145
150
  end
@@ -15,7 +15,7 @@ module Completion
15
15
  command = Shell.command_name(executable)
16
16
 
17
17
  if executable
18
- return <<~SCRIPT
18
+ return Shell.annotate_after_first_line(<<~SCRIPT, kind: "adapter", shell: "zsh", executable: executable)
19
19
  #compdef #{command}
20
20
 
21
21
  local _completion_source="${(%):-%x}"
@@ -25,7 +25,7 @@ module Completion
25
25
  SCRIPT
26
26
  end
27
27
 
28
- <<~SCRIPT
28
+ Shell.annotate_after_first_line(<<~SCRIPT, kind: "adapter", shell: "zsh")
29
29
  #compdef -default-
30
30
 
31
31
  local _completion_source="${(%):-%x}"
@@ -40,7 +40,7 @@ module Completion
40
40
  #
41
41
  # @returns [String] The generated Zsh helper script.
42
42
  def self.shared_script
43
- <<~SCRIPT
43
+ Shell.annotate(<<~SCRIPT, kind: "helper", shell: "zsh")
44
44
  __completion_resolve() {
45
45
  local command="$1"
46
46
  local basename="${command:t}"
@@ -3,9 +3,90 @@
3
3
  # Released under the MIT License.
4
4
  # Copyright, 2026, by Samuel Williams.
5
5
 
6
+ require "json"
7
+
6
8
  module Completion
7
9
  # Shell adapter generation helpers.
8
10
  module Shell
11
+ MARKER_PREFIX = "# Auto-generated completion: "
12
+
13
+ # Generate a managed-file metadata marker.
14
+ #
15
+ # @parameter kind [String] The generated file kind.
16
+ # @parameter shell [String | Symbol] The shell name.
17
+ # @parameter executable [String | Nil] The command executable, or nil for the generic adapter.
18
+ # @returns [String] The generated metadata marker.
19
+ def self.marker(kind:, shell:, executable: nil)
20
+ metadata = {
21
+ managed: true,
22
+ kind: kind,
23
+ shell: shell.to_s,
24
+ }
25
+
26
+ if executable
27
+ metadata[:command] = command_name(executable)
28
+ end
29
+
30
+ return "#{MARKER_PREFIX}#{JSON.generate(metadata)}"
31
+ end
32
+
33
+ # Add a managed-file metadata marker to a generated script.
34
+ #
35
+ # @parameter script [String] The generated script.
36
+ # @parameter kind [String] The generated file kind.
37
+ # @parameter shell [String | Symbol] The shell name.
38
+ # @parameter executable [String | Nil] The command executable, or nil for the generic adapter.
39
+ # @returns [String] The annotated script.
40
+ def self.annotate(script, kind:, shell:, executable: nil)
41
+ return "#{marker(kind: kind, shell: shell, executable: executable)}\n#{script}"
42
+ end
43
+
44
+ # Add a managed-file metadata marker after the first line of a generated script.
45
+ #
46
+ # @parameter script [String] The generated script.
47
+ # @parameter kind [String] The generated file kind.
48
+ # @parameter shell [String | Symbol] The shell name.
49
+ # @parameter executable [String | Nil] The command executable, or nil for the generic adapter.
50
+ # @returns [String] The annotated script.
51
+ def self.annotate_after_first_line(script, kind:, shell:, executable: nil)
52
+ first, rest = script.split("\n", 2)
53
+
54
+ return "#{first}\n#{marker(kind: kind, shell: shell, executable: executable)}\n#{rest}"
55
+ end
56
+
57
+ # Extract managed-file metadata from a generated script.
58
+ #
59
+ # @parameter path [String] The script path to inspect.
60
+ # @returns [Hash | Nil] The parsed metadata, if present.
61
+ def self.metadata(path)
62
+ return nil unless File.file?(path)
63
+
64
+ File.open(path) do |file|
65
+ 2.times do
66
+ line = file.gets
67
+ break unless line
68
+
69
+ if line.start_with?(MARKER_PREFIX)
70
+ return JSON.parse(line.delete_prefix(MARKER_PREFIX))
71
+ end
72
+ end
73
+ end
74
+
75
+ return nil
76
+ rescue JSON::ParserError
77
+ return nil
78
+ end
79
+
80
+ # Check whether a script is managed by completion.
81
+ #
82
+ # @parameter path [String] The script path to inspect.
83
+ # @returns [Boolean] Whether the script is managed by completion.
84
+ def self.managed?(path)
85
+ metadata = self.metadata(path)
86
+
87
+ return metadata && metadata["managed"] == true || false
88
+ end
89
+
9
90
  # Extract a shell name from a path.
10
91
  #
11
92
  # @parameter path [String | Nil] The shell path.
@@ -45,6 +126,29 @@ module Completion
45
126
  File.expand_path("~/.config/fish/functions")
46
127
  end
47
128
 
129
+ # Get the default Fish configuration directory.
130
+ #
131
+ # @returns [String] The default Fish configuration directory.
132
+ def self.default_configuration_directory
133
+ File.expand_path("~/.config/fish/conf.d")
134
+ end
135
+
136
+ # Get the adapter directory for a shell and executable.
137
+ #
138
+ # @parameter shell [String] The shell name.
139
+ # @parameter executable [String | Nil] The command executable, or nil for the generic adapter.
140
+ # @parameter directory [String | Nil] The explicit adapter directory.
141
+ # @returns [String] The adapter directory.
142
+ def self.adapter_directory(shell, executable = nil, directory: nil)
143
+ return directory if directory
144
+
145
+ if shell == "fish" && !executable
146
+ return default_configuration_directory
147
+ end
148
+
149
+ return default_directory(shell)
150
+ end
151
+
48
152
  # Get the installed adapter file name for a shell.
49
153
  #
50
154
  # @parameter shell [String] The shell name.
@@ -4,5 +4,5 @@
4
4
  # Copyright, 2026, by Samuel Williams.
5
5
 
6
6
  module Completion
7
- VERSION = "0.0.1"
7
+ VERSION = "0.0.2"
8
8
  end
data/readme.md CHANGED
@@ -20,9 +20,14 @@ Please see the [project documentation](https://socketry.github.io/completion/) f
20
20
 
21
21
  Please see the [project releases](https://socketry.github.io/completion/releases/index) for all releases.
22
22
 
23
+ ### v0.0.2
24
+
25
+ - Add `completion uninstall` for removing installed shell adapter scripts.
26
+ - Add managed metadata markers to generated shell scripts and support `completion uninstall --all`.
27
+
23
28
  ### v0.0.1
24
29
 
25
- - Initial release.
30
+ - Fix generic Fish completion installation by loading the adapter at shell startup and resolving completion executables from `PATH`.
26
31
 
27
32
  ## See Also
28
33
 
data/releases.md CHANGED
@@ -1,5 +1,10 @@
1
1
  # Releases
2
2
 
3
+ ## v0.0.2
4
+
5
+ - Add `completion uninstall` for removing installed shell adapter scripts.
6
+ - Add managed metadata markers to generated shell scripts and support `completion uninstall --all`.
7
+
3
8
  ## v0.0.1
4
9
 
5
- - Initial release.
10
+ - Fix generic Fish completion installation by loading the adapter at shell startup and resolving completion executables from `PATH`.
data.tar.gz.sig CHANGED
@@ -1,3 +1 @@
1
- Rthbh M��&�o8��x����L��q���|��eD��JK֢������z+H����!� Aw�̫��7�\p��k��9
2
- ���ӈ4)T�H�!IJ�?�j�|�V���3݃T��qs<�DZ.:^K k7���ə��#�{,���&�-:_����[E��M��((8ݱ���[�
3
- Ѡ6�+CN��sy� �+���7�]ސ��)��Hׯ�
1
+ Ymve��{����0Sa(�X�LZ��4�̯��5�
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: completion
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.1
4
+ version: 0.0.2
5
5
  platform: ruby
6
6
  authors:
7
7
  - Samuel Williams
@@ -66,6 +66,7 @@ files:
66
66
  - lib/completion/command/generate.rb
67
67
  - lib/completion/command/install.rb
68
68
  - lib/completion/command/top.rb
69
+ - lib/completion/command/uninstall.rb
69
70
  - lib/completion/shell.rb
70
71
  - lib/completion/shell/bash.rb
71
72
  - lib/completion/shell/fish.rb
metadata.gz.sig CHANGED
Binary file