Skip to content

Commit fe41699

Browse files
feat(cli): Add shell completion for bash, zsh, fish, and PowerShell
Fixes #843 Adds a new 'completion' subcommand that generates shell completion scripts. Usage: openai completion bash # Bash completion openai completion zsh # Zsh completion openai completion fish # Fish completion openai completion pwsh # PowerShell completion To enable, add to shell config: eval "$(openai completion bash)" # Bash eval "$(openai completion zsh)" # Zsh openai completion fish | source # Fish
1 parent dc68b90 commit fe41699

File tree

2 files changed

+146
-0
lines changed

2 files changed

+146
-0
lines changed

src/openai/cli/_cli.py

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212
import openai
1313

1414
from . import _tools
15+
from ._completion import register_completion_commands
1516
from .. import _ApiType, __version__
1617
from ._api import register_commands
1718
from ._utils import can_use_http2
@@ -120,6 +121,9 @@ def help() -> None:
120121
sub_tools = subparsers.add_parser("tools", help="Client side tools for convenience")
121122
_tools.register_commands(sub_tools, subparsers)
122123

124+
sub_completion = subparsers.add_parser("completion", help="Generate shell completion scripts")
125+
register_completion_commands(sub_completion)
126+
123127
return parser
124128

125129

src/openai/cli/_completion.py

Lines changed: 142 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,142 @@
1+
"""Shell completion support for the OpenAI CLI."""
2+
3+
from __future__ import annotations
4+
5+
import argparse
6+
7+
8+
BASH_COMPLETION = '''
9+
_openai_completion() {
10+
local cur prev words cword
11+
_init_completion || return
12+
13+
local commands="api tools completion"
14+
local global_opts="-v --verbose -b --api-base -k --api-key -p --proxy -o --organization -t --api-type --api-version --azure-endpoint --azure-ad-token -V --version -h --help"
15+
16+
case "${prev}" in
17+
openai)
18+
COMPREPLY=($(compgen -W "${commands} ${global_opts}" -- "${cur}"))
19+
return
20+
;;
21+
completion)
22+
COMPREPLY=($(compgen -W "bash zsh fish pwsh" -- "${cur}"))
23+
return
24+
;;
25+
-t|--api-type)
26+
COMPREPLY=($(compgen -W "openai azure" -- "${cur}"))
27+
return
28+
;;
29+
esac
30+
31+
if [[ "${cur}" == -* ]]; then
32+
COMPREPLY=($(compgen -W "${global_opts}" -- "${cur}"))
33+
else
34+
COMPREPLY=($(compgen -W "${commands}" -- "${cur}"))
35+
fi
36+
}
37+
38+
complete -F _openai_completion openai
39+
'''
40+
41+
ZSH_COMPLETION = '''
42+
#compdef openai
43+
44+
_openai() {
45+
local -a commands global_opts shells
46+
47+
commands=(
48+
'api:Direct API calls'
49+
'tools:Client side tools for convenience'
50+
'completion:Generate shell completion scripts'
51+
)
52+
53+
shells=(
54+
'bash:Generate bash completion script'
55+
'zsh:Generate zsh completion script'
56+
'fish:Generate fish completion script'
57+
'pwsh:Generate PowerShell completion script'
58+
)
59+
60+
_arguments -C \
61+
'-v[Set verbosity]' \
62+
'--verbose[Set verbosity]' \
63+
'-b[API base URL]:url:' \
64+
'--api-base[API base URL]:url:' \
65+
'-k[API key]:key:' \
66+
'--api-key[API key]:key:' \
67+
'-t[API type]:type:(openai azure)' \
68+
'--api-type[API type]:type:(openai azure)' \
69+
'-V[Show version]' \
70+
'--version[Show version]' \
71+
'1:command:->command' \
72+
'*::arg:->args'
73+
74+
case "$state" in
75+
command)
76+
_describe -t commands 'openai commands' commands
77+
;;
78+
args)
79+
case "$words[1]" in
80+
completion)
81+
_describe -t shells 'shells' shells
82+
;;
83+
esac
84+
;;
85+
esac
86+
}
87+
88+
_openai "$@"
89+
'''
90+
91+
FISH_COMPLETION = '''
92+
# Fish completion for openai CLI
93+
complete -c openai -f
94+
complete -c openai -s v -l verbose -d "Set verbosity"
95+
complete -c openai -s b -l api-base -d "API base URL" -r
96+
complete -c openai -s k -l api-key -d "API key" -r
97+
complete -c openai -s t -l api-type -d "API type" -r -a "openai azure"
98+
complete -c openai -s V -l version -d "Show version"
99+
complete -c openai -n "__fish_use_subcommand" -a api -d "Direct API calls"
100+
complete -c openai -n "__fish_use_subcommand" -a tools -d "Client side tools"
101+
complete -c openai -n "__fish_use_subcommand" -a completion -d "Generate shell completion"
102+
complete -c openai -n "__fish_seen_subcommand_from completion" -a "bash zsh fish pwsh"
103+
'''
104+
105+
POWERSHELL_COMPLETION = '''
106+
Register-ArgumentCompleter -Native -CommandName openai -ScriptBlock {
107+
param($wordToComplete, $commandAst, $cursorPosition)
108+
$commands = @('api', 'tools', 'completion')
109+
$shells = @('bash', 'zsh', 'fish', 'pwsh')
110+
$cmds = $commandAst.CommandElements
111+
if ($cmds.Count -eq 1) {
112+
$commands | Where-Object { $_ -like "$wordToComplete*" } | ForEach-Object {
113+
[System.Management.Automation.CompletionResult]::new($_, $_, 'ParameterValue', $_)
114+
}
115+
} elseif ($cmds.Count -ge 2 -and $cmds[1].ToString() -eq 'completion') {
116+
$shells | Where-Object { $_ -like "$wordToComplete*" } | ForEach-Object {
117+
[System.Management.Automation.CompletionResult]::new($_, $_, 'ParameterValue', $_)
118+
}
119+
}
120+
}
121+
'''
122+
123+
124+
def _get_completion_script(shell: str) -> str:
125+
scripts = {
126+
"bash": BASH_COMPLETION,
127+
"zsh": ZSH_COMPLETION,
128+
"fish": FISH_COMPLETION,
129+
"pwsh": POWERSHELL_COMPLETION,
130+
"powershell": POWERSHELL_COMPLETION,
131+
}
132+
script = scripts.get(shell.lower())
133+
if script is None:
134+
raise ValueError(f"Unsupported shell: {shell}. Supported: bash, zsh, fish, pwsh")
135+
return script.strip()
136+
137+
138+
def register_completion_commands(parser: argparse.ArgumentParser) -> None:
139+
subparsers = parser.add_subparsers()
140+
for shell in ["bash", "zsh", "fish", "pwsh"]:
141+
shell_parser = subparsers.add_parser(shell, help=f"Generate {shell} completion script")
142+
shell_parser.set_defaults(func=lambda s=shell: print(_get_completion_script(s)))

0 commit comments

Comments
 (0)