Skip to content

Commit d034aea

Browse files
committed
Merge branch 'main' of github.com:httpdss/struct
2 parents 315e448 + e3973e2 commit d034aea

13 files changed

Lines changed: 115 additions & 138 deletions

docs/cli-reference.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -117,7 +117,7 @@ Usage:
117117
struct completion install [bash|zsh|fish]
118118
```
119119

120-
- If no shell is provided, the command attempts to auto-detect your current shell and prints the exact commands to enable argcomplete-based completion for struct.
120+
- If no shell is provided, the command attempts to auto-detect your current shell and prints the exact commands to generate and install static completion files via shtab.
121121
- This does not modify your shell configuration; it only prints the commands you can copy-paste.
122122

123123
### `init`

docs/completion.md

Lines changed: 44 additions & 97 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,13 @@
11
# Command-Line Auto-Completion
22

3-
STRUCT provides intelligent auto-completion for commands, options, and **structure names** using [argcomplete](https://kislyuk.github.io/argcomplete/). This makes discovering and using available structures much faster and more user-friendly.
3+
STRUCT provides intelligent auto-completion for commands, options, and structure names using static completion scripts generated by [shtab](https://github.com/Iterative/shtab). This approach is reliable across shells and doesn’t require runtime hooks or markers.
44

5-
!!! tip "New Feature: Structure Name Completion"
6-
STRUCT now automatically completes structure names when using `struct generate`, showing all 47+ available structures from both built-in and custom paths!
5+
!!! tip "Structure Name Completion"
6+
STRUCT completes structure names when using `struct generate`, showing available structures from both built-in and custom paths.
77

88
## Quick Setup
99

10-
The easiest way is to ask struct to print the exact commands for your shell:
10+
Ask struct to print the exact commands for your shell:
1111

1212
```sh
1313
# Auto-detect current shell and print install steps
@@ -19,77 +19,48 @@ struct completion install bash
1919
struct completion install fish
2020
```
2121

22-
You can still follow the manual steps below if you prefer.
22+
You can also generate completion files manually with shtab as shown below.
2323

24-
For most users, this simple setup will enable full completion:
24+
## Manual Installation
2525

26-
```sh
27-
# Install (if not already installed)
28-
pip install argcomplete
29-
30-
# Enable completion for current session
31-
eval "$(register-python-argcomplete struct)"
32-
33-
# Make permanent - add to your ~/.zshrc or ~/.bashrc
34-
echo 'eval "$(register-python-argcomplete struct)"' >> ~/.zshrc
35-
```
36-
37-
## Detailed Installation
38-
39-
### 1. Install argcomplete
26+
### 1) Install shtab
4027

4128
```sh
42-
pip install argcomplete
29+
pip install shtab
4330
```
4431

45-
### 2. Enable Global Completion (Optional)
32+
### 2) Generate and install completion for your shell
4633

47-
This step is optional but can be done once per system:
34+
- Zsh
4835

49-
```sh
50-
activate-global-python-argcomplete
51-
```
52-
53-
This command sets up global completion for all Python scripts that use argcomplete.
36+
```sh
37+
mkdir -p ~/.zfunc
38+
struct --print-completion zsh > ~/.zfunc/_struct
39+
# ensure in ~/.zshrc
40+
fpath=(~/.zfunc $fpath)
41+
autoload -U compinit && compinit
42+
exec zsh
43+
```
5444

55-
### 3. Register the Script
45+
- Bash
5646

57-
Add the following line to your shell's configuration file:
47+
```sh
48+
mkdir -p ~/.local/share/bash-completion/completions
49+
struct --print-completion bash > ~/.local/share/bash-completion/completions/struct
50+
source ~/.bashrc
51+
```
5852

59-
**For Bash** (`.bashrc` or `.bash_profile`):
53+
- Fish
6054

61-
```sh
62-
eval "$(register-python-argcomplete struct)"
63-
```
64-
65-
**For Zsh** (`.zshrc`):
66-
67-
```sh
68-
eval "$(register-python-argcomplete struct)"
69-
```
70-
71-
**For Fish** (`.config/fish/config.fish`):
72-
73-
```fish
74-
register-python-argcomplete --shell fish struct | source
75-
```
76-
77-
### 4. Reload Your Shell
78-
79-
```sh
80-
# For Bash
81-
source ~/.bashrc
82-
83-
# For Zsh
84-
source ~/.zshrc
85-
86-
# For Fish
87-
source ~/.config/fish/config.fish
88-
```
55+
```sh
56+
mkdir -p ~/.config/fish/completions
57+
struct --print-completion fish > ~/.config/fish/completions/struct.fish
58+
fish -c 'source ~/.config/fish/completions/struct.fish'
59+
```
8960

9061
## Usage
9162

92-
After completing the setup, you can use auto-completion by typing part of a command and pressing `Tab`:
63+
After installing the completion, use Tab to complete commands/options:
9364

9465
### Command Completion
9566
```sh
@@ -132,12 +103,7 @@ struct generate --log <Tab>
132103

133104
### Per-Project Completion
134105

135-
If you only want completion for specific projects, you can add completion to your project's virtual environment activation script:
136-
137-
```sh
138-
# In your .venv/bin/activate file, add:
139-
eval "$(register-python-argcomplete struct)"
140-
```
106+
If you only want completion for a specific project/venv, generate the completion from the project’s venv and place it under your user completion directory (examples above). No runtime eval is needed.
141107

142108
### Custom Completion
143109

@@ -158,60 +124,41 @@ complete -F _struct_structures struct-generate
158124

159125
### Completion Not Working
160126

161-
1. **Check argcomplete installation**:
162-
163-
```sh
164-
python -c "import argcomplete; print('OK')"
165-
```
166-
167-
2. **Verify global activation**:
127+
1. Verify shtab is installed in the environment you’re using:
168128

169129
```sh
170-
activate-global-python-argcomplete --user
130+
python -c "import shtab; print('OK')"
171131
```
172132

173-
3. **Check shell configuration**:
174-
Make sure the eval statement is in the correct shell configuration file.
133+
2. Confirm the completion file exists in the expected location and is readable.
175134

176-
4. **Restart your shell**:
177-
Sometimes you need to completely restart your terminal.
135+
3. Ensure your shell is configured to load completions:
136+
- zsh: fpath includes ~/.zfunc and compinit is run.
137+
- bash: bash-completion is installed and sourced (on some distros).
138+
- fish: the file is in ~/.config/fish/completions/.
178139

179-
### Slow Completion
180-
181-
If completion is slow, you can enable caching:
182-
183-
```sh
184-
export ARGCOMPLETE_USE_TEMPFILES=1
185-
```
186-
187-
Add this to your shell configuration file for persistent caching.
140+
4. Restart your shell (or run `exec zsh`/`source ~/.bashrc`).
188141

189142
### Debug Completion
190143

191-
Enable debug mode to troubleshoot completion issues:
192-
193-
```sh
194-
export _ARGCOMPLETE_DEBUG=1
195-
struct <Tab>
196-
```
144+
For shell-specific debugging, check that the generated file contains the struct completion function and is in the correct directory for your shell.
197145

198146
## Platform-Specific Notes
199147

200148
### macOS
201149

202-
On macOS, you might need to install bash-completion first:
150+
On macOS, you may need to install bash-completion (for bash) or ensure zsh’s compinit is configured:
203151

204152
```sh
205153
# Using Homebrew
206154
brew install bash-completion
207-
208-
# Then add to ~/.bash_profile:
155+
# bash profile
209156
[[ -r "/usr/local/etc/profile.d/bash_completion.sh" ]] && . "/usr/local/etc/profile.d/bash_completion.sh"
210157
```
211158

212159
### Windows
213160

214-
For Windows users using Git Bash or WSL, follow the same steps as Linux. For PowerShell, argcomplete support is limited.
161+
For Windows users using Git Bash or WSL, follow the same steps as Linux. PowerShell is not covered by shtab; use bash/zsh/fish.
215162

216163
### Docker
217164

docs/installation.md

Lines changed: 1 addition & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -9,11 +9,7 @@ pip install git+https://github.com/httpdss/struct.git
99
```
1010

1111
!!! tip "Enable Auto-Completion"
12-
After installation, enable command-line auto-completion for better productivity:
13-
```sh
14-
eval "$(register-python-argcomplete struct)"
15-
```
16-
For permanent setup, see the [Command-Line Completion](completion.md) guide.
12+
After installation, enable command-line auto-completion using static scripts generated by shtab. See the [Command-Line Completion](completion.md) guide for per-shell instructions.
1713

1814
## From Source
1915

requirements.txt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ openai
44
python-dotenv
55
jinja2
66
PyGithub
7-
argcomplete
7+
shtab
88
colorlog
99
boto3
1010
google-cloud

struct_module/commands/completion.py

Lines changed: 22 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66
class CompletionCommand(Command):
77
def __init__(self, parser):
88
super().__init__(parser)
9-
parser.description = "Manage CLI shell completions for struct (argcomplete)"
9+
parser.description = "Manage CLI shell completions for struct (shtab-generated)"
1010
sub = parser.add_subparsers(dest="action")
1111

1212
install = sub.add_parser("install", help="Print the commands to enable completion for your shell")
@@ -29,32 +29,37 @@ def _install(self, args):
2929
print(f"Detected shell: {shell}")
3030

3131
if shell == "bash":
32-
print("\n# One-time dependency (if not installed):")
33-
print("python -m pip install argcomplete")
34-
print("\n# Enable completion for 'struct' in bash (append to ~/.bashrc):")
35-
print('echo "eval \"$(register-python-argcomplete struct)\"" >> ~/.bashrc')
36-
print("\n# Apply now:")
32+
print("\n# Install shtab (once, in your environment):")
33+
print("python -m pip install shtab")
34+
print("\n# Generate static bash completion for 'struct':")
35+
print("mkdir -p ~/.local/share/bash-completion/completions")
36+
print("struct --print-completion bash > ~/.local/share/bash-completion/completions/struct")
37+
print("\n# Apply now (or open a new shell):")
3738
print("source ~/.bashrc")
3839

3940
elif shell == "zsh":
40-
print("\n# One-time dependency (if not installed):")
41-
print("python -m pip install argcomplete")
42-
print("\n# Enable completion for 'struct' in zsh (append to ~/.zshrc):")
43-
print('echo "eval \"$(register-python-argcomplete --shell zsh struct)\"" >> ~/.zshrc')
44-
print("\n# Apply now:")
45-
print("source ~/.zshrc")
41+
print("\n# Install shtab (once, in your environment):")
42+
print("python -m pip install shtab")
43+
print("\n# Generate static zsh completion for 'struct':")
44+
print("mkdir -p ~/.zfunc")
45+
print("struct --print-completion zsh > ~/.zfunc/_struct")
46+
print("\n# Ensure zsh loads user functions/completions (append to ~/.zshrc if needed):")
47+
print('echo "fpath=(~/.zfunc $fpath)" >> ~/.zshrc')
48+
print('echo "autoload -U compinit && compinit" >> ~/.zshrc')
49+
print("\n# Apply now (or open a new shell):")
50+
print("exec zsh")
4651

4752
elif shell == "fish":
48-
print("\n# One-time dependency (if not installed):")
49-
print("python -m pip install argcomplete")
50-
print("\n# Install fish completion file for 'struct':")
53+
print("\n# Install shtab (once, in your environment):")
54+
print("python -m pip install shtab")
55+
print("\n# Generate static fish completion for 'struct':")
5156
print('mkdir -p ~/.config/fish/completions')
52-
print('register-python-argcomplete --shell fish struct > ~/.config/fish/completions/struct.fish')
57+
print('struct --print-completion fish > ~/.config/fish/completions/struct.fish')
5358
print("\n# Apply now:")
5459
print("fish -c 'source ~/.config/fish/completions/struct.fish'")
5560

5661
else:
5762
self.logger.error(f"Unsupported shell: {shell}. Supported: {', '.join(SUPPORTED_SHELLS)}")
5863
return
5964

60-
print("\nTip: If 'register-python-argcomplete' is not found, try:\n python -m argcomplete.shellintegration <shell>")
65+
print("\nTip: You can also print completion directly via: struct --print-completion <shell>")

struct_module/commands/generate.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212
class GenerateCommand(Command):
1313
def __init__(self, parser):
1414
super().__init__(parser)
15+
parser.description = "Generate the project structure from a YAML configuration file"
1516
structure_arg = parser.add_argument('structure_definition', type=str, help='Path to the YAML configuration file')
1617
structure_arg.completer = structures_completer
1718
parser.add_argument('base_path', type=str, help='Base path where the structure will be created')

struct_module/commands/generate_schema.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
class GenerateSchemaCommand(Command):
77
def __init__(self, parser):
88
super().__init__(parser)
9+
parser.description = "Generate JSON schema for available structures"
910
parser.add_argument('-s', '--structures-path', type=str, help='Path to structure definitions')
1011
parser.add_argument('-o', '--output', type=str, help='Output file path for the schema (default: stdout)')
1112
parser.set_defaults(func=self.execute)

struct_module/commands/info.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
class InfoCommand(Command):
99
def __init__(self, parser):
1010
super().__init__(parser)
11+
parser.description = "Show information about the package or structure definition"
1112
parser.add_argument('structure_definition', type=str, help='Name of the structure definition')
1213
parser.add_argument('-s', '--structures-path', type=str, help='Path to structure definitions')
1314
parser.add_argument('--mcp', action='store_true', help='Enable MCP (Model Context Protocol) integration')

struct_module/commands/list.py

Lines changed: 15 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,9 @@
99
class ListCommand(Command):
1010
def __init__(self, parser):
1111
super().__init__(parser)
12+
parser.description = "List available structures"
1213
parser.add_argument('-s', '--structures-path', type=str, help='Path to structure definitions')
14+
parser.add_argument('--names-only', action='store_true', help='Print only structure names, one per line (for shell completion)')
1315
parser.add_argument('--mcp', action='store_true', help='Enable MCP (Model Context Protocol) integration')
1416
parser.set_defaults(func=self.execute)
1517

@@ -30,7 +32,6 @@ def _list_structures(self, args):
3032
else:
3133
paths_to_list = [contribs_path]
3234

33-
print("📃 Listing available structures\n")
3435
all_structures = set()
3536
for path in paths_to_list:
3637
for root, _, files in os.walk(path):
@@ -39,11 +40,23 @@ def _list_structures(self, args):
3940
rel_path = os.path.relpath(file_path, path)
4041
if file.endswith(".yaml"):
4142
rel_path = rel_path[:-5]
42-
if path != contribs_path:
43+
# Mark custom path entries with '+ ' unless names-only requested
44+
if not args.names_only and path != contribs_path:
4345
rel_path = f"+ {rel_path}"
4446
all_structures.add(rel_path)
4547

4648
sorted_list = sorted(all_structures)
49+
50+
if args.names_only:
51+
# Print plain names without bullets or headers, remove '+ ' marker
52+
for structure in sorted_list:
53+
if structure.startswith('+ '):
54+
print(structure[2:])
55+
else:
56+
print(structure)
57+
return
58+
59+
print("📃 Listing available structures\n")
4760
for structure in sorted_list:
4861
print(f" - {structure}")
4962

struct_module/commands/mcp.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
class MCPCommand(Command):
99
def __init__(self, parser):
1010
super().__init__(parser)
11+
parser.description = "MCP (Model Context Protocol) support for struct tool"
1112
parser.add_argument('--server', action='store_true',
1213
help='Start the MCP server for stdio communication')
1314
parser.set_defaults(func=self.execute)

0 commit comments

Comments
 (0)