completion 0.0.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 ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA256:
3
+ metadata.gz: 284727bae15655feaebf3d8757241257db50b763122a31cadc654d5319d7a2bf
4
+ data.tar.gz: e3e0ec43c86bcbc334cba971bfe019bd822c3a64ed03577cfc0a6a804d9a0834
5
+ SHA512:
6
+ metadata.gz: 29ebeaf86a358ff8dd761326b06f7d718e9919f80c2b0d1d2a359d103032ef081101da49a46ac6808915703a8f30d8b06508c3e07ca65b7690414e9d8eab6ed4
7
+ data.tar.gz: 071a5afaffb9ee016b327434b7d87d19d57d8b0e1ae81cf823ca0b1aea0a66b26b2396f0177c992ece283bf4b31f97b4fbad1cebbb7911994cd6f0245ba83d38
checksums.yaml.gz.sig ADDED
@@ -0,0 +1 @@
1
+ �0�6�[�cJgTL\��-gˆN���g���17�k(�Ƭ��^?����P�=�p�5o���c���8�s�(n��}X�:�w)�9�����+��MMk��];f]_G�L�n���}9G>T�Gzl3c�H���[z
data/bin/completion ADDED
@@ -0,0 +1,9 @@
1
+ #!/usr/bin/env ruby
2
+ # frozen_string_literal: true
3
+
4
+ # Released under the MIT License.
5
+ # Copyright, 2026, by Samuel Williams.
6
+
7
+ require_relative "../lib/completion/command"
8
+
9
+ Completion::Command.call
@@ -0,0 +1,9 @@
1
+ #!/usr/bin/env ruby
2
+ # frozen_string_literal: true
3
+
4
+ # Released under the MIT License.
5
+ # Copyright, 2026, by Samuel Williams.
6
+
7
+ require_relative "../lib/completion/command"
8
+
9
+ Completion::Command.complete
@@ -0,0 +1,161 @@
1
+ # Getting Started
2
+
3
+ This guide explains how to install and use `completion` to add shell completion adapters for command-line tools.
4
+
5
+ ## Installation
6
+
7
+ Add the gem to your project:
8
+
9
+ ~~~ bash
10
+ $ bundle add completion
11
+ ~~~
12
+
13
+ Or install it yourself as:
14
+
15
+ ~~~ bash
16
+ $ gem install completion
17
+ ~~~
18
+
19
+ The command line executable is named `completion`:
20
+
21
+ ~~~ bash
22
+ $ completion --help
23
+ ~~~
24
+
25
+ ## Core Concepts
26
+
27
+ `completion` installs shell adapter scripts. The adapters do not run the command being completed. Instead, they call a dedicated completion executable named `completion-<command>`.
28
+
29
+ For example, a command named `falcon` should provide:
30
+
31
+ ~~~ text
32
+ falcon
33
+ completion-falcon
34
+ ~~~
35
+
36
+ When the shell asks for completions for `falcon`, the installed adapter calls `completion-falcon` with the command-line arguments up to the cursor.
37
+
38
+ This convention also works for commands invoked by path:
39
+
40
+ ~~~ text
41
+ falcon -> completion-falcon
42
+ bin/falcon -> bin/completion-falcon
43
+ ./bin/falcon -> ./bin/completion-falcon
44
+ /path/falcon -> /path/completion-falcon
45
+ ~~~
46
+
47
+ ## Installing a Generic Adapter
48
+
49
+ Install a generic adapter for the current shell:
50
+
51
+ ~~~ bash
52
+ $ completion install
53
+ ~~~
54
+
55
+ The shell is detected from `ENV["SHELL"]`. The generic adapter checks whether a matching `completion-<command>` executable exists before handling completion for a command.
56
+
57
+ You can specify the shell explicitly:
58
+
59
+ ~~~ bash
60
+ $ completion install --shell fish
61
+ ~~~
62
+
63
+ Supported shells are:
64
+
65
+ - `bash`
66
+ - `fish`
67
+ - `zsh`
68
+
69
+ ## Installing a Command Adapter
70
+
71
+ Install an adapter for a specific command:
72
+
73
+ ~~~ bash
74
+ $ completion install --command falcon
75
+ ~~~
76
+
77
+ This installs completion support only for `falcon`.
78
+
79
+ You can specify the shell and adapter directory explicitly:
80
+
81
+ ~~~ bash
82
+ $ completion install --shell zsh --directory ~/.zsh/completions --command falcon
83
+ ~~~
84
+
85
+ ## Installed Files
86
+
87
+ Installation writes a small adapter script and shared shell helpers.
88
+
89
+ For Bash and Zsh, shared helpers are installed in the completion directory:
90
+
91
+ ~~~ text
92
+ completion.bash
93
+ completion.zsh
94
+ ~~~
95
+
96
+ For Fish, shared helpers are installed as autoloaded functions:
97
+
98
+ ~~~ text
99
+ ~/.config/fish/functions/__completion_complete.fish
100
+ ~/.config/fish/functions/__completion_register.fish
101
+ ~/.config/fish/functions/__completion_register_default.fish
102
+ ~/.config/fish/functions/__completion_resolve.fish
103
+ ~/.config/fish/functions/__completion_supported.fish
104
+ ~~~
105
+
106
+ Fish command adapters are installed into:
107
+
108
+ ~~~ text
109
+ ~/.config/fish/completions
110
+ ~~~
111
+
112
+ ## Generating an Adapter
113
+
114
+ You can generate an adapter script without installing it:
115
+
116
+ ~~~ bash
117
+ $ completion generate --shell zsh --command falcon
118
+ ~~~
119
+
120
+ Omit `--command` to generate the generic adapter:
121
+
122
+ ~~~ bash
123
+ $ completion generate --shell zsh
124
+ ~~~
125
+
126
+ ## Providing a Completion Executable
127
+
128
+ The completion executable should print completion candidates to standard output.
129
+
130
+ Commands built with `samovar` can use `Command.complete`:
131
+
132
+ ~~~ ruby
133
+ #!/usr/bin/env ruby
134
+ # frozen_string_literal: true
135
+
136
+ require_relative "../lib/my/application"
137
+
138
+ My::Application.complete
139
+ ~~~
140
+
141
+ Completion candidates use tab-separated fields:
142
+
143
+ ~~~ text
144
+ type value description key=value
145
+ ~~~
146
+
147
+ The first three fields are always the completion type, value, and description. Additional fields are optional metadata entries.
148
+
149
+ ## Testing
150
+
151
+ You can test the completion executable directly:
152
+
153
+ ~~~ bash
154
+ $ completion-falcon ""
155
+ ~~~
156
+
157
+ You can also generate an adapter and inspect it:
158
+
159
+ ~~~ bash
160
+ $ completion generate --shell fish --command falcon
161
+ ~~~
@@ -0,0 +1,32 @@
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
+ require_relative "../shell/bash"
10
+ require_relative "../shell/fish"
11
+ require_relative "../shell/zsh"
12
+
13
+ module Completion
14
+ module Command
15
+ # Generate shell completion adapter scripts.
16
+ class Generate < Samovar::Command
17
+ self.description = "Generate shell completion adapter scripts."
18
+
19
+ options do
20
+ option "--shell <name>", "The shell to generate completions for.", default: Shell.method(:default_shell), completions: ["bash", "zsh", "fish"]
21
+ option "--command <name>", "The command executable to complete."
22
+ end
23
+
24
+ # Print the generated shell adapter script.
25
+ #
26
+ # @returns [void]
27
+ def call
28
+ output.puts Shell.script(shell: @options[:shell], executable: @options[:command])
29
+ end
30
+ end
31
+ end
32
+ end
@@ -0,0 +1,68 @@
1
+ # frozen_string_literal: true
2
+
3
+ # Released under the MIT License.
4
+ # Copyright, 2026, by Samuel Williams.
5
+
6
+ require "fileutils"
7
+ require "samovar"
8
+
9
+ require_relative "../shell"
10
+ require_relative "../shell/bash"
11
+ require_relative "../shell/fish"
12
+ require_relative "../shell/zsh"
13
+
14
+ module Completion
15
+ module Command
16
+ # Install a shell completion adapter script to a user-local completion directory.
17
+ class Install < Samovar::Command
18
+ self.description = "Install a shell completion adapter script."
19
+
20
+ options do
21
+ option "--shell <name>", "The shell to install completions for.", default: Shell.method(:default_shell), completions: ["bash", "zsh", "fish"]
22
+ option "--directory <path>", "The completion directory to install into."
23
+ option "--command <name>", "The command executable to complete."
24
+ end
25
+
26
+ # Install the generated shell adapter script.
27
+ #
28
+ # @returns [void]
29
+ def call
30
+ shell = @options[:shell]
31
+ directory = @options[:directory] || Shell.default_directory(shell)
32
+ path = File.join(directory, Shell.file_name(shell, @options[:command]))
33
+ script = Shell.script(shell: shell, executable: @options[:command])
34
+
35
+ FileUtils.mkdir_p(directory)
36
+ shared_paths = install_shared(shell, directory)
37
+ File.write(path, script)
38
+
39
+ output.puts(shared_paths)
40
+ output.puts path
41
+ end
42
+
43
+ private
44
+
45
+ def install_shared(shell, directory)
46
+ if shell == "fish"
47
+ return install_fish_function(Shell.default_function_directory)
48
+ end
49
+
50
+ shared_path = File.join(directory, Shell.shared_file_name(shell))
51
+
52
+ File.write(shared_path, Shell.shared_script(shell: shell))
53
+
54
+ return [shared_path]
55
+ end
56
+
57
+ def install_fish_function(directory)
58
+ FileUtils.mkdir_p(directory)
59
+
60
+ return Shell::Fish.shared_functions.collect do |file_name, script|
61
+ path = File.join(directory, file_name)
62
+ File.write(path, script)
63
+ path
64
+ end
65
+ end
66
+ end
67
+ end
68
+ end
@@ -0,0 +1,42 @@
1
+ # frozen_string_literal: true
2
+
3
+ # Released under the MIT License.
4
+ # Copyright, 2026, by Samuel Williams.
5
+
6
+ require "samovar"
7
+
8
+ unless defined?(Completion::Command) && Completion::Command.respond_to?(:call)
9
+ require_relative "../command"
10
+ end
11
+
12
+ require_relative "generate"
13
+ require_relative "install"
14
+
15
+ module Completion
16
+ module Command
17
+ # The completion command-line interface.
18
+ class Top < Samovar::Command
19
+ self.description = "Install and generate shell completion adapter scripts."
20
+
21
+ options do
22
+ option "-h/--help", "Print out help information."
23
+ end
24
+
25
+ nested :command, {
26
+ "install" => Install,
27
+ "generate" => Generate,
28
+ }, default: "generate"
29
+
30
+ # Execute the selected completion sub-command.
31
+ #
32
+ # @returns [Object | Nil] The sub-command result.
33
+ def call
34
+ if @options[:help]
35
+ self.print_usage
36
+ else
37
+ @command.call
38
+ end
39
+ end
40
+ end
41
+ end
42
+ end
@@ -0,0 +1,27 @@
1
+ # frozen_string_literal: true
2
+
3
+ # Released under the MIT License.
4
+ # Copyright, 2026, by Samuel Williams.
5
+
6
+ module Completion
7
+ # Command-line entry points for the completion executable.
8
+ module Command
9
+ # Parse and execute the top-level completion command.
10
+ #
11
+ # @parameter arguments [Array] The arguments to forward to the top-level command.
12
+ # @returns [Object | Nil] The command result.
13
+ def self.call(...)
14
+ Top.call(...)
15
+ end
16
+
17
+ # Complete the top-level completion command.
18
+ #
19
+ # @parameter arguments [Array] The arguments to forward to the top-level command.
20
+ # @returns [Samovar::Completion::Result] The completion result.
21
+ def self.complete(...)
22
+ Top.complete(...)
23
+ end
24
+ end
25
+ end
26
+
27
+ require_relative "command/top"
@@ -0,0 +1,122 @@
1
+ # frozen_string_literal: true
2
+
3
+ # Released under the MIT License.
4
+ # Copyright, 2026, by Samuel Williams.
5
+
6
+ module Completion
7
+ module Shell
8
+ # Bash completion adapter generation.
9
+ module Bash
10
+ # Generate a Bash completion adapter script.
11
+ #
12
+ # @parameter executable [String | Nil] The command executable, or nil for the generic adapter.
13
+ # @returns [String] The generated Bash script.
14
+ def self.script(executable)
15
+ command = Shell.command_name(executable)
16
+
17
+ if executable
18
+ return <<~SCRIPT
19
+ _completion_source="${BASH_SOURCE[0]}"
20
+ if [[ "$_completion_source" == */* ]]; then
21
+ _completion_directory="${_completion_source%/*}"
22
+ else
23
+ _completion_directory="."
24
+ fi
25
+ source "${_completion_directory}/completion.bash"
26
+ __completion_register #{command}
27
+ SCRIPT
28
+ end
29
+
30
+ <<~SCRIPT
31
+ _completion_source="${BASH_SOURCE[0]}"
32
+ if [[ "$_completion_source" == */* ]]; then
33
+ _completion_directory="${_completion_source%/*}"
34
+ else
35
+ _completion_directory="."
36
+ fi
37
+ source "${_completion_directory}/completion.bash"
38
+ __completion_register_default
39
+ SCRIPT
40
+ end
41
+
42
+ # Generate the shared Bash helper script.
43
+ #
44
+ # @returns [String] The generated Bash helper script.
45
+ def self.shared_script
46
+ <<~SCRIPT
47
+ __completion_resolve() {
48
+ local command="$1"
49
+ local basename="${command##*/}"
50
+
51
+ if [[ "$command" == */* ]]; then
52
+ printf "%s\\n" "${command%/*}/completion-${basename}"
53
+ else
54
+ printf "%s\\n" "completion-${basename}"
55
+ fi
56
+ }
57
+
58
+ __completion_complete() {
59
+ local command="${COMP_WORDS[0]}"
60
+ local completer="$(__completion_resolve "$command")"
61
+
62
+ [[ -x "$completer" ]] || return 0
63
+
64
+ local argv=("${COMP_WORDS[@]:1:COMP_CWORD}")
65
+ COMPREPLY=()
66
+
67
+ while IFS=$'\\t' read -r type value description metadata; do
68
+ case "$type" in
69
+ path)
70
+ while IFS= read -r completion; do
71
+ COMPREPLY+=("$completion")
72
+ done < <(compgen -f -- "$value")
73
+ ;;
74
+ directory)
75
+ while IFS= read -r completion; do
76
+ COMPREPLY+=("$completion")
77
+ done < <(compgen -d -- "$value")
78
+ ;;
79
+ executable)
80
+ while IFS= read -r completion; do
81
+ COMPREPLY+=("$completion")
82
+ done < <(compgen -c -- "$value")
83
+ ;;
84
+ delegate)
85
+ if [[ "$metadata" == *index=* ]]; then
86
+ local index="${metadata##*index=}"
87
+ index="${index%%$'\\t'*}"
88
+ local offset=$((index + 1))
89
+ COMP_WORDS=("${COMP_WORDS[@]:$offset}")
90
+ COMP_CWORD=$((COMP_CWORD - offset))
91
+
92
+ if declare -F _completion_loader >/dev/null; then
93
+ _completion_loader "${COMP_WORDS[0]}" >/dev/null 2>&1 || true
94
+ fi
95
+
96
+ local specification
97
+ specification="$(complete -p "${COMP_WORDS[0]}" 2>/dev/null || true)"
98
+
99
+ if [[ "$specification" =~ -F[[:space:]]+([^[:space:]]+) ]]; then
100
+ "${BASH_REMATCH[1]}"
101
+ fi
102
+ fi
103
+ ;;
104
+ *)
105
+ COMPREPLY+=("$value")
106
+ ;;
107
+ esac
108
+ done < <("$completer" "${argv[@]}")
109
+ }
110
+
111
+ __completion_register() {
112
+ complete -F __completion_complete "$1"
113
+ }
114
+
115
+ __completion_register_default() {
116
+ complete -D -o bashdefault -o default -F __completion_complete 2>/dev/null || true
117
+ }
118
+ SCRIPT
119
+ end
120
+ end
121
+ end
122
+ end
@@ -0,0 +1,148 @@
1
+ # frozen_string_literal: true
2
+
3
+ # Released under the MIT License.
4
+ # Copyright, 2026, by Samuel Williams.
5
+
6
+ module Completion
7
+ module Shell
8
+ # Fish completion adapter generation.
9
+ module Fish
10
+ # Generate a Fish completion adapter script.
11
+ #
12
+ # @parameter executable [String | Nil] The command executable, or nil for the generic adapter.
13
+ # @returns [String] The generated Fish script.
14
+ def self.script(executable)
15
+ command = Shell.command_name(executable)
16
+
17
+ if executable
18
+ return <<~SCRIPT
19
+ __completion_register #{command}
20
+ SCRIPT
21
+ end
22
+
23
+ <<~SCRIPT
24
+ __completion_register_default
25
+ SCRIPT
26
+ end
27
+
28
+ # Get the shared Fish helper function files.
29
+ #
30
+ # @returns [Hash] The helper file names and scripts.
31
+ def self.shared_functions
32
+ {
33
+ "__completion_complete.fish" => complete_function,
34
+ "__completion_register.fish" => register_function,
35
+ "__completion_register_default.fish" => register_default_function,
36
+ "__completion_resolve.fish" => resolve_function,
37
+ "__completion_supported.fish" => supported_function,
38
+ }
39
+ end
40
+
41
+ # Generate the Fish completion function.
42
+ #
43
+ # @returns [String] The generated Fish function script.
44
+ def self.complete_function
45
+ <<~SCRIPT
46
+ function __completion_complete --description 'Complete commands with adjacent completion executables'
47
+ set -l argv (commandline -opc)
48
+ set -e argv[1]
49
+ set -l current (commandline -ct)
50
+
51
+ if test -n "$current"
52
+ set -a argv $current
53
+ else
54
+ set -a argv ""
55
+ end
56
+
57
+ set -l completer (__completion_resolve)
58
+ $completer $argv | while read -l line
59
+ set -l fields (string split (printf "\\t") -- $line)
60
+ set -l type $fields[1]
61
+ set -l value $fields[2]
62
+ set -l description $fields[3]
63
+ set -l metadata $fields[4..-1]
64
+
65
+ switch "$type"
66
+ case path
67
+ __fish_complete_path "$value"
68
+ case directory
69
+ __fish_complete_directories "$value"
70
+ case executable
71
+ complete -C "$value"
72
+ case delegate
73
+ set -l index
74
+ for field in $metadata
75
+ switch "$field"
76
+ case "index=*"
77
+ set index (string replace "index=" "" -- "$field")
78
+ end
79
+ end
80
+
81
+ if test -n "$index"
82
+ set -l start (math $index + 1)
83
+ set -l delegated $argv[$start..-1]
84
+ complete -C (string join " " -- (string escape -- $delegated))
85
+ end
86
+ case "*"
87
+ echo "$value $description"
88
+ end
89
+ end
90
+ end
91
+ SCRIPT
92
+ end
93
+
94
+ # Generate the Fish command registration function.
95
+ #
96
+ # @returns [String] The generated Fish function script.
97
+ def self.register_function
98
+ <<~SCRIPT
99
+ function __completion_register --description 'Register command completion'
100
+ complete -c $argv[1] -f -a "(__completion_complete)"
101
+ end
102
+ SCRIPT
103
+ end
104
+
105
+ # Generate the Fish generic registration function.
106
+ #
107
+ # @returns [String] The generated Fish function script.
108
+ def self.register_default_function
109
+ <<~SCRIPT
110
+ function __completion_register_default --description 'Register generic completion'
111
+ complete -c "*" -n "__completion_supported" -f -a "(__completion_complete)"
112
+ end
113
+ SCRIPT
114
+ end
115
+
116
+ # Generate the Fish completion command resolver function.
117
+ #
118
+ # @returns [String] The generated Fish function script.
119
+ def self.resolve_function
120
+ <<~SCRIPT
121
+ function __completion_resolve --description 'Resolve completion command'
122
+ set -l argv (commandline -opc)
123
+ set -l command $argv[1]
124
+ set -l basename (basename "$command")
125
+
126
+ if string match -q "*/*" "$command"
127
+ echo (dirname "$command")/completion-$basename
128
+ else
129
+ echo completion-$basename
130
+ end
131
+ end
132
+ SCRIPT
133
+ end
134
+
135
+ # Generate the Fish support detection function.
136
+ #
137
+ # @returns [String] The generated Fish function script.
138
+ def self.supported_function
139
+ <<~SCRIPT
140
+ function __completion_supported --description 'Check completion support'
141
+ set -l completer (__completion_resolve)
142
+ test -x "$completer"
143
+ end
144
+ SCRIPT
145
+ end
146
+ end
147
+ end
148
+ end
@@ -0,0 +1,130 @@
1
+ # frozen_string_literal: true
2
+
3
+ # Released under the MIT License.
4
+ # Copyright, 2026, by Samuel Williams.
5
+
6
+ module Completion
7
+ module Shell
8
+ # Zsh completion adapter generation.
9
+ module Zsh
10
+ # Generate a Zsh completion adapter script.
11
+ #
12
+ # @parameter executable [String | Nil] The command executable, or nil for the generic adapter.
13
+ # @returns [String] The generated Zsh script.
14
+ def self.script(executable)
15
+ command = Shell.command_name(executable)
16
+
17
+ if executable
18
+ return <<~SCRIPT
19
+ #compdef #{command}
20
+
21
+ local _completion_source="${(%):-%x}"
22
+ local _completion_directory="${_completion_source:h}"
23
+ source "${_completion_directory}/completion.zsh"
24
+ __completion_complete "$@"
25
+ SCRIPT
26
+ end
27
+
28
+ <<~SCRIPT
29
+ #compdef -default-
30
+
31
+ local _completion_source="${(%):-%x}"
32
+ local _completion_directory="${_completion_source:h}"
33
+ source "${_completion_directory}/completion.zsh"
34
+ __completion_register_default
35
+ __completion_complete default "$@"
36
+ SCRIPT
37
+ end
38
+
39
+ # Generate the shared Zsh helper script.
40
+ #
41
+ # @returns [String] The generated Zsh helper script.
42
+ def self.shared_script
43
+ <<~SCRIPT
44
+ __completion_resolve() {
45
+ local command="$1"
46
+ local basename="${command:t}"
47
+
48
+ if [[ "$command" == */* ]]; then
49
+ printf "%s\\n" "${command:h}/completion-${basename}"
50
+ else
51
+ printf "%s\\n" "completion-${basename}"
52
+ fi
53
+ }
54
+
55
+ __completion_complete() {
56
+ local fallback="$1"
57
+ if [[ "$fallback" == "default" ]]; then
58
+ shift
59
+ else
60
+ fallback=""
61
+ fi
62
+
63
+ local command="${words[1]}"
64
+ local completer="$(__completion_resolve "$command")"
65
+
66
+ if [[ ! -x "$completer" ]]; then
67
+ if [[ "$fallback" == "default" ]]; then
68
+ _default "$@"
69
+ fi
70
+
71
+ return
72
+ fi
73
+
74
+ local -a argv
75
+ argv=("${(@)words[2,CURRENT]}")
76
+
77
+ local -a completions
78
+ local paths=false
79
+ local directories=false
80
+ local executables=false
81
+ while IFS=$'\\t' read -r type value description metadata; do
82
+ case "$type" in
83
+ path)
84
+ paths=true
85
+ ;;
86
+ directory)
87
+ directories=true
88
+ ;;
89
+ executable)
90
+ executables=true
91
+ ;;
92
+ delegate)
93
+ if [[ "$metadata" == *index=* ]]; then
94
+ local index="${metadata##*index=}"
95
+ index="${index%%$'\\t'*}"
96
+ words=("${(@)words[$((index + 2)),-1]}")
97
+ CURRENT=$((CURRENT - index - 1))
98
+ _normal
99
+ return
100
+ fi
101
+ ;;
102
+ *)
103
+ completions+=("${value}:${description}")
104
+ ;;
105
+ esac
106
+ done < <("$completer" "${argv[@]}")
107
+
108
+ if [[ "$paths" == true ]]; then
109
+ _path_files
110
+ fi
111
+
112
+ if [[ "$directories" == true ]]; then
113
+ _files -/
114
+ fi
115
+
116
+ if [[ "$executables" == true ]]; then
117
+ _path_commands
118
+ fi
119
+
120
+ _describe 'completion' completions
121
+ }
122
+
123
+ __completion_register_default() {
124
+ (( $+functions[compdef] )) && compdef _completion -default-
125
+ }
126
+ SCRIPT
127
+ end
128
+ end
129
+ end
130
+ end
@@ -0,0 +1,124 @@
1
+ # frozen_string_literal: true
2
+
3
+ # Released under the MIT License.
4
+ # Copyright, 2026, by Samuel Williams.
5
+
6
+ module Completion
7
+ # Shell adapter generation helpers.
8
+ module Shell
9
+ # Extract a shell name from a path.
10
+ #
11
+ # @parameter path [String | Nil] The shell path.
12
+ # @returns [String] The shell name.
13
+ def self.shell_name(path)
14
+ File.basename(path.to_s)
15
+ end
16
+
17
+ # Detect the current shell from the environment.
18
+ #
19
+ # @returns [String] The detected shell name.
20
+ def self.default_shell
21
+ shell_name(ENV["SHELL"])
22
+ end
23
+
24
+ # Get the default completion directory for a shell.
25
+ #
26
+ # @parameter shell [String] The shell name.
27
+ # @returns [String] The default completion directory.
28
+ def self.default_directory(shell)
29
+ case shell
30
+ when "bash"
31
+ File.expand_path("~/.local/share/bash-completion/completions")
32
+ when "fish"
33
+ File.expand_path("~/.config/fish/completions")
34
+ when "zsh"
35
+ File.expand_path("~/.zsh/completions")
36
+ else
37
+ raise ArgumentError, "Unsupported shell: #{shell.inspect}"
38
+ end
39
+ end
40
+
41
+ # Get the default Fish function directory.
42
+ #
43
+ # @returns [String] The default Fish function directory.
44
+ def self.default_function_directory
45
+ File.expand_path("~/.config/fish/functions")
46
+ end
47
+
48
+ # Get the installed adapter file name for a shell.
49
+ #
50
+ # @parameter shell [String] The shell name.
51
+ # @parameter executable [String | Nil] The command executable, or nil for the generic adapter.
52
+ # @returns [String] The adapter file name.
53
+ def self.file_name(shell, executable = nil)
54
+ command = executable || "completion"
55
+
56
+ case shell
57
+ when "bash"
58
+ command
59
+ when "fish"
60
+ "#{command}.fish"
61
+ when "zsh"
62
+ "_#{command}"
63
+ else
64
+ raise ArgumentError, "Unsupported shell: #{shell.inspect}"
65
+ end
66
+ end
67
+
68
+ # Get the installed shared helper file name for a shell.
69
+ #
70
+ # @parameter shell [String] The shell name.
71
+ # @returns [String] The shared helper file name.
72
+ def self.shared_file_name(shell)
73
+ case shell
74
+ when "bash"
75
+ "completion.bash"
76
+ when "zsh"
77
+ "completion.zsh"
78
+ else
79
+ raise ArgumentError, "Unsupported shell: #{shell.inspect}"
80
+ end
81
+ end
82
+
83
+ # Generate a shell adapter script.
84
+ #
85
+ # @parameter shell [String | Symbol] The shell name.
86
+ # @parameter executable [String | Nil] The command executable, or nil for the generic adapter.
87
+ # @returns [String] The generated adapter script.
88
+ def self.script(shell:, executable: nil)
89
+ case shell.to_sym
90
+ when :bash
91
+ Bash.script(executable)
92
+ when :fish
93
+ Fish.script(executable)
94
+ when :zsh
95
+ Zsh.script(executable)
96
+ else
97
+ raise ArgumentError, "Unsupported shell: #{shell.inspect}"
98
+ end
99
+ end
100
+
101
+ # Generate a shared shell helper script.
102
+ #
103
+ # @parameter shell [String | Symbol] The shell name.
104
+ # @returns [String] The generated shared helper script.
105
+ def self.shared_script(shell:)
106
+ case shell.to_sym
107
+ when :bash
108
+ Bash.shared_script
109
+ when :zsh
110
+ Zsh.shared_script
111
+ else
112
+ raise ArgumentError, "Unsupported shell: #{shell.inspect}"
113
+ end
114
+ end
115
+
116
+ # Get the command name from an executable path.
117
+ #
118
+ # @parameter executable [String | Nil] The executable path, or nil for the generic adapter.
119
+ # @returns [String] The command name.
120
+ def self.command_name(executable)
121
+ File.basename(executable || "completion")
122
+ end
123
+ end
124
+ end
@@ -0,0 +1,8 @@
1
+ # frozen_string_literal: true
2
+
3
+ # Released under the MIT License.
4
+ # Copyright, 2026, by Samuel Williams.
5
+
6
+ module Completion
7
+ VERSION = "0.0.1"
8
+ end
data/lib/completion.rb ADDED
@@ -0,0 +1,14 @@
1
+ # frozen_string_literal: true
2
+
3
+ # Released under the MIT License.
4
+ # Copyright, 2026, by Samuel Williams.
5
+
6
+ require_relative "completion/version"
7
+ require_relative "completion/shell"
8
+ require_relative "completion/shell/bash"
9
+ require_relative "completion/shell/fish"
10
+ require_relative "completion/shell/zsh"
11
+
12
+ # Shell completion adapter generation and installation.
13
+ module Completion
14
+ end
data/license.md ADDED
@@ -0,0 +1,21 @@
1
+ # MIT License
2
+
3
+ Copyright, 2026, by Samuel Williams.
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
data/readme.md ADDED
@@ -0,0 +1,63 @@
1
+ # Completion
2
+
3
+ Completion installs shell adapter scripts for command-line tools which expose a dedicated completion executable. It provides small per-command or generic shell shims, plus shared shell helpers for Bash, Fish, and Zsh.
4
+
5
+ [![Development Status](https://github.com/socketry/completion/workflows/Test/badge.svg)](https://github.com/socketry/completion/actions?workflow=Test)
6
+
7
+ ## Motivation
8
+
9
+ Shell completion is useful, but each shell has different installation paths, script conventions, and interfaces for native path, directory, executable, and delegated completion. This gem provides a small command-line tool for installing those adapters consistently.
10
+
11
+ The command being completed is expected to provide a companion executable named `completion-<command>`. For example, `falcon` can expose completions using `completion-falcon`. This keeps completion support explicit and avoids running arbitrary commands just to discover whether they support completion.
12
+
13
+ ## Usage
14
+
15
+ Please see the [project documentation](https://socketry.github.io/completion/) for more details.
16
+
17
+ - [Getting Started](https://socketry.github.io/completion/guides/getting-started/index) - This guide explains how to install and use `completion` to add shell completion adapters for command-line tools.
18
+
19
+ ## Releases
20
+
21
+ Please see the [project releases](https://socketry.github.io/completion/releases/index) for all releases.
22
+
23
+ ### v0.0.1
24
+
25
+ - Initial release.
26
+
27
+ ## See Also
28
+
29
+ - [Samovar](https://github.com/socketry/samovar) provides the command completion interface used by Samovar-based commands.
30
+
31
+ ## Contributing
32
+
33
+ We welcome contributions to this project.
34
+
35
+ 1. Fork it.
36
+ 2. Create your feature branch (`git checkout -b my-new-feature`).
37
+ 3. Commit your changes (`git commit -am 'Add some feature'`).
38
+ 4. Push to the branch (`git push origin my-new-feature`).
39
+ 5. Create new Pull Request.
40
+
41
+ ### Running Tests
42
+
43
+ To run the test suite:
44
+
45
+ ``` shell
46
+ bundle exec sus
47
+ ```
48
+
49
+ ### Making Releases
50
+
51
+ To make a new release:
52
+
53
+ ``` shell
54
+ bundle exec bake gem:release:patch # or minor or major
55
+ ```
56
+
57
+ ### Developer Certificate of Origin
58
+
59
+ In order to protect users of this project, we require all contributors to comply with the [Developer Certificate of Origin](https://developercertificate.org/). This ensures that all contributions are properly licensed and attributed.
60
+
61
+ ### Community Guidelines
62
+
63
+ This project is best served by a collaborative and respectful environment. Treat each other professionally, respect differing viewpoints, and engage constructively. Harassment, discrimination, or harmful behavior is not tolerated. Communicate clearly, listen actively, and support one another. If any issues arise, please inform the project maintainers.
data/releases.md ADDED
@@ -0,0 +1,5 @@
1
+ # Releases
2
+
3
+ ## v0.0.1
4
+
5
+ - Initial release.
data.tar.gz.sig ADDED
@@ -0,0 +1,3 @@
1
+ R�thbh 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ׯ�
metadata ADDED
@@ -0,0 +1,100 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: completion
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.1
5
+ platform: ruby
6
+ authors:
7
+ - Samuel Williams
8
+ bindir: bin
9
+ cert_chain:
10
+ - |
11
+ -----BEGIN CERTIFICATE-----
12
+ MIIE2DCCA0CgAwIBAgIBATANBgkqhkiG9w0BAQsFADBhMRgwFgYDVQQDDA9zYW11
13
+ ZWwud2lsbGlhbXMxHTAbBgoJkiaJk/IsZAEZFg1vcmlvbnRyYW5zZmVyMRIwEAYK
14
+ CZImiZPyLGQBGRYCY28xEjAQBgoJkiaJk/IsZAEZFgJuejAeFw0yMjA4MDYwNDUz
15
+ MjRaFw0zMjA4MDMwNDUzMjRaMGExGDAWBgNVBAMMD3NhbXVlbC53aWxsaWFtczEd
16
+ MBsGCgmSJomT8ixkARkWDW9yaW9udHJhbnNmZXIxEjAQBgoJkiaJk/IsZAEZFgJj
17
+ bzESMBAGCgmSJomT8ixkARkWAm56MIIBojANBgkqhkiG9w0BAQEFAAOCAY8AMIIB
18
+ igKCAYEAomvSopQXQ24+9DBB6I6jxRI2auu3VVb4nOjmmHq7XWM4u3HL+pni63X2
19
+ 9qZdoq9xt7H+RPbwL28LDpDNflYQXoOhoVhQ37Pjn9YDjl8/4/9xa9+NUpl9XDIW
20
+ sGkaOY0eqsQm1pEWkHJr3zn/fxoKPZPfaJOglovdxf7dgsHz67Xgd/ka+Wo1YqoE
21
+ e5AUKRwUuvaUaumAKgPH+4E4oiLXI4T1Ff5Q7xxv6yXvHuYtlMHhYfgNn8iiW8WN
22
+ XibYXPNP7NtieSQqwR/xM6IRSoyXKuS+ZNGDPUUGk8RoiV/xvVN4LrVm9upSc0ss
23
+ RZ6qwOQmXCo/lLcDUxJAgG95cPw//sI00tZan75VgsGzSWAOdjQpFM0l4dxvKwHn
24
+ tUeT3ZsAgt0JnGqNm2Bkz81kG4A2hSyFZTFA8vZGhp+hz+8Q573tAR89y9YJBdYM
25
+ zp0FM4zwMNEUwgfRzv1tEVVUEXmoFCyhzonUUw4nE4CFu/sE3ffhjKcXcY//qiSW
26
+ xm4erY3XAgMBAAGjgZowgZcwCQYDVR0TBAIwADALBgNVHQ8EBAMCBLAwHQYDVR0O
27
+ BBYEFO9t7XWuFf2SKLmuijgqR4sGDlRsMC4GA1UdEQQnMCWBI3NhbXVlbC53aWxs
28
+ aWFtc0BvcmlvbnRyYW5zZmVyLmNvLm56MC4GA1UdEgQnMCWBI3NhbXVlbC53aWxs
29
+ aWFtc0BvcmlvbnRyYW5zZmVyLmNvLm56MA0GCSqGSIb3DQEBCwUAA4IBgQB5sxkE
30
+ cBsSYwK6fYpM+hA5B5yZY2+L0Z+27jF1pWGgbhPH8/FjjBLVn+VFok3CDpRqwXCl
31
+ xCO40JEkKdznNy2avOMra6PFiQyOE74kCtv7P+Fdc+FhgqI5lMon6tt9rNeXmnW/
32
+ c1NaMRdxy999hmRGzUSFjozcCwxpy/LwabxtdXwXgSay4mQ32EDjqR1TixS1+smp
33
+ 8C/NCWgpIfzpHGJsjvmH2wAfKtTTqB9CVKLCWEnCHyCaRVuKkrKjqhYCdmMBqCws
34
+ JkxfQWC+jBVeG9ZtPhQgZpfhvh+6hMhraUYRQ6XGyvBqEUe+yo6DKIT3MtGE2+CP
35
+ eX9i9ZWBydWb8/rvmwmX2kkcBbX0hZS1rcR593hGc61JR6lvkGYQ2MYskBveyaxt
36
+ Q2K9NVun/S785AP05vKkXZEFYxqG6EW012U4oLcFl5MySFajYXRYbuUpH6AY+HP8
37
+ voD0MPg1DssDLKwXyt1eKD/+Fq0bFWhwVM/1XiAXL7lyYUyOq24KHgQ2Csg=
38
+ -----END CERTIFICATE-----
39
+ date: 1980-01-02 00:00:00.000000000 Z
40
+ dependencies:
41
+ - !ruby/object:Gem::Dependency
42
+ name: samovar
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - "~>"
46
+ - !ruby/object:Gem::Version
47
+ version: '2.5'
48
+ type: :runtime
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - "~>"
53
+ - !ruby/object:Gem::Version
54
+ version: '2.5'
55
+ executables:
56
+ - completion
57
+ - completion-completion
58
+ extensions: []
59
+ extra_rdoc_files: []
60
+ files:
61
+ - bin/completion
62
+ - bin/completion-completion
63
+ - guides/getting-started/readme.md
64
+ - lib/completion.rb
65
+ - lib/completion/command.rb
66
+ - lib/completion/command/generate.rb
67
+ - lib/completion/command/install.rb
68
+ - lib/completion/command/top.rb
69
+ - lib/completion/shell.rb
70
+ - lib/completion/shell/bash.rb
71
+ - lib/completion/shell/fish.rb
72
+ - lib/completion/shell/zsh.rb
73
+ - lib/completion/version.rb
74
+ - license.md
75
+ - readme.md
76
+ - releases.md
77
+ homepage: https://github.com/socketry/completion
78
+ licenses:
79
+ - MIT
80
+ metadata:
81
+ documentation_uri: https://socketry.github.io/completion/
82
+ source_code_uri: https://github.com/socketry/completion.git
83
+ rdoc_options: []
84
+ require_paths:
85
+ - lib
86
+ required_ruby_version: !ruby/object:Gem::Requirement
87
+ requirements:
88
+ - - ">="
89
+ - !ruby/object:Gem::Version
90
+ version: '3.3'
91
+ required_rubygems_version: !ruby/object:Gem::Requirement
92
+ requirements:
93
+ - - ">="
94
+ - !ruby/object:Gem::Version
95
+ version: '0'
96
+ requirements: []
97
+ rubygems_version: 4.0.10
98
+ specification_version: 4
99
+ summary: Command-line completion adapter installation.
100
+ test_files: []
metadata.gz.sig ADDED
Binary file