Skip to content

Commit d7a79b9

Browse files
committed
feat: added zsh completion
1 parent 7f2da26 commit d7a79b9

File tree

7 files changed

+545
-1
lines changed

7 files changed

+545
-1
lines changed

.markdownlint.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
{ "MD013": false, "MD029": false, "MD014": false }

README.md

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,10 +35,24 @@ Access deeply **nested values** using intuitive dot-separated paths (e.g., **`pe
3535

3636
Dotcat is a good **unix citizen** with well structured **exit codes** so it can take part of your command pipeline like cat or grep would.
3737

38+
Includes **ZSH autocompletion** for both file paths and dotted paths, making it even easier to navigate complex data structures.
39+
3840
## Installation
3941

4042
If you have a global pip install, this will install dotcat globally:
4143

4244
```bash
4345
pip install dotcat
4446
```
47+
48+
## ZSH Completion
49+
50+
Dotcat comes with ZSH completion support. After installing the package, you can set up the completion by:
51+
52+
```bash
53+
# Copy the completion script to your ZSH completions directory
54+
mkdir -p ~/.zsh/completions
55+
cp /path/to/installed/package/zsh/_dotcat ~/.zsh/completions/
56+
```
57+
58+
See the [ZSH completion README](zsh/README.md) for detailed instructions.

pyproject.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ build-backend = "poetry.core.masonry.api"
44

55
[tool.poetry]
66
packages = [{ include = "dotcat", from = "src" }]
7-
include = ["templates", "template/**", "LICENSE", "README.md"]
7+
include = ["templates", "template/**", "LICENSE", "README.md", "zsh/**"]
88
exclude = ["tests"]
99

1010
[project]

zsh/README.md

Lines changed: 185 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,185 @@
1+
# Dotcat ZSH Completion
2+
3+
This directory contains ZSH completion scripts for the `dotcat` command.
4+
5+
These completion files are included when you install the dotcat package.
6+
7+
## Files
8+
9+
- `_dotcat` - ZSH completion script (uses the Python helper)
10+
- `dotcat-completion.py` - Python helper script for extracting dotted paths
11+
- `test-completion.zsh` - Script for testing the completion locally
12+
13+
## Quick Installation
14+
15+
1. Copy the completion script to a directory in your $fpath:
16+
17+
```bash
18+
# Create completion directory if it doesn't exist
19+
mkdir -p ~/.zsh/completions
20+
21+
# Copy the completion script
22+
cp zsh/_dotcat ~/.zsh/completions/_dotcat
23+
24+
# Make sure the directory is in your fpath
25+
echo 'fpath=(~/.zsh/completions $fpath)' >> ~/.zshrc
26+
```
27+
28+
2. Install the Python helper script:
29+
30+
```bash
31+
# Copy to a directory in your PATH
32+
mkdir -p ~/bin
33+
cp zsh/dotcat-completion.py ~/bin/
34+
chmod +x ~/bin/dotcat-completion.py
35+
36+
# Make sure the directory is in your PATH
37+
echo 'export PATH="$HOME/bin:$PATH"' >> ~/.zshrc
38+
```
39+
40+
3. Reload your ZSH configuration:
41+
42+
```bash
43+
source ~/.zshrc
44+
```
45+
46+
## Testing
47+
48+
You can test the completion by typing:
49+
50+
```bash
51+
# Test file completion
52+
dotcat [TAB]
53+
54+
# Test dotted path completion
55+
dotcat path/to/file.json [TAB]
56+
57+
# Test nested path completion
58+
dotcat path/to/file.json python[TAB]
59+
```
60+
61+
For local testing without installation, use the test script:
62+
63+
```bash
64+
./zsh/test-completion.zsh
65+
```
66+
67+
## Detailed Installation Guide
68+
69+
### Step 1: Choose a directory in your $fpath
70+
71+
First, check your current $fpath directories:
72+
73+
```bash
74+
echo $fpath
75+
```
76+
77+
Choose one of the directories from the output (e.g.,
78+
`/usr/local/share/zsh/site-functions/` or `~/.zsh/completions/`).
79+
80+
If you want to use `~/.zsh/completions/`, make sure it exists:
81+
82+
```bash
83+
mkdir -p ~/.zsh/completions
84+
```
85+
86+
And add it to your $fpath in your `~/.zshrc`:
87+
88+
```bash
89+
fpath=(~/.zsh/completions $fpath)
90+
```
91+
92+
### Step 2: Install the completion files
93+
94+
Copy the completion script to your chosen directory:
95+
96+
```bash
97+
cp zsh/_dotcat /path/to/your/chosen/directory/_dotcat
98+
```
99+
100+
Install the Python helper script to a directory in your PATH:
101+
102+
```bash
103+
# System-wide installation
104+
cp zsh/dotcat-completion.py /usr/local/bin/
105+
chmod +x /usr/local/bin/dotcat-completion.py
106+
107+
# Or to a local bin directory
108+
mkdir -p $HOME/bin
109+
cp zsh/dotcat-completion.py $HOME/bin/
110+
chmod +x $HOME/bin/dotcat-completion.py
111+
```
112+
113+
Make sure the directory is in your PATH:
114+
115+
```bash
116+
echo 'export PATH="$HOME/bin:$PATH"' >> $HOME/.zshrc
117+
```
118+
119+
### Step 3: Reload your ZSH configuration
120+
121+
```bash
122+
source ~/.zshrc
123+
```
124+
125+
Or restart your terminal.
126+
127+
## Troubleshooting
128+
129+
If completion doesn't work:
130+
131+
1. Make sure the file is in a directory in your $fpath
132+
2. Check that the file has the correct permissions:
133+
134+
```bash
135+
chmod 755 /path/to/_dotcat
136+
```
137+
138+
3. If using the Python helper, make sure it's in your PATH and executable:
139+
140+
```bash
141+
which dotcat-completion.py
142+
chmod +x /path/to/dotcat-completion.py
143+
```
144+
145+
4. Run `compinit` to rebuild the completion system:
146+
147+
```bash
148+
autoload -Uz compinit && compinit
149+
```
150+
151+
5. Check for any error messages when sourcing your `.zshrc`
152+
153+
## Manual Testing
154+
155+
If you want to test the Python helper script directly:
156+
157+
```bash
158+
# Get top-level paths from a file
159+
dotcat-completion.py path/to/file.json
160+
161+
# Get nested paths
162+
dotcat-completion.py path/to/file.json python
163+
dotcat-completion.py path/to/file.json python.editor
164+
```
165+
166+
You can also use the included test script to try the completion in a temporary
167+
environment:
168+
169+
```bash
170+
# Run the test script
171+
./zsh/test-completion.zsh
172+
```
173+
174+
## How It Works
175+
176+
The completion system works in two parts:
177+
178+
1. The ZSH completion script (`_dotcat`) handles the command-line argument
179+
completion.
180+
2. The Python helper script (`dotcat-completion.py`) parses the structured data
181+
files and extracts the dotted paths.
182+
183+
When you type `dotcat file.json` and press TAB, the completion script calls the
184+
Python helper to extract the possible paths from the file and presents them as
185+
completion options.

zsh/_dotcat

Lines changed: 91 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,91 @@
1+
#!/usr/bin/env zsh
2+
# shellcheck disable=SC1071 # ShellCheck only supports sh/bash/dash/ksh scripts, not zsh
3+
#compdef dotcat
4+
5+
# zsh completion for dotcat command
6+
# Uses the dotcat-completion.py helper script for dotted path suggestions
7+
8+
_dotcat() {
9+
local curcontext="$curcontext" state line
10+
typeset -A opt_args
11+
12+
_arguments -C \
13+
'1:file:_files' \
14+
'2:dotted path:_dotcat_dotted_path' \
15+
'--output=[Output format]:format:(raw formatted json yaml toml ini)' \
16+
'--check-install[Check if required packages are installed]' \
17+
'--version[Show version information]' \
18+
'--help[Show help message]'
19+
}
20+
21+
# Function to suggest dotted paths based on file content using the Python helper
22+
_dotcat_dotted_path() {
23+
local file=${words[2]}
24+
local current=${words[3]}
25+
local prefix="" suggestions=()
26+
27+
# If we already have part of a dotted path, extract the prefix
28+
if [[ "$current" == *.* ]]; then
29+
prefix=$(echo "$current" | sed 's/\.[^.]*$//')
30+
fi
31+
32+
# Check if we have a file argument and it exists
33+
if [[ -n "$file" && -f "$file" ]]; then
34+
# Get the path to the helper script
35+
local script_dir=${0:A:h} # Directory containing this completion script
36+
local helper_script="${script_dir}/dotcat-completion.py"
37+
38+
# If the helper script doesn't exist in the same directory, try to find it
39+
if [[ ! -f "$helper_script" ]]; then
40+
# Try common locations
41+
for dir in "/usr/local/bin" "/usr/bin" "$HOME/.local/bin" "$HOME/bin"; do
42+
if [[ -f "${dir}/dotcat-completion.py" ]]; then
43+
helper_script="${dir}/dotcat-completion.py"
44+
break
45+
fi
46+
done
47+
fi
48+
49+
# If we found the helper script, use it to get suggestions
50+
if [[ -f "$helper_script" ]]; then
51+
# Make sure the script is executable
52+
[[ -x "$helper_script" ]] || chmod +x "$helper_script"
53+
54+
# Call the helper script with the file and prefix (if any)
55+
if [[ -n "$prefix" ]]; then
56+
# Get suggestions for the given prefix
57+
while IFS= read -r line; do
58+
[[ -n "$line" ]] && suggestions+=("$line")
59+
done < <(python3 "$helper_script" "$file" "$prefix" 2>/dev/null)
60+
else
61+
# Get top-level suggestions
62+
while IFS= read -r line; do
63+
[[ -n "$line" ]] && suggestions+=("$line")
64+
done < <(python3 "$helper_script" "$file" 2>/dev/null)
65+
fi
66+
67+
# If we have suggestions, offer them as completions
68+
if (( ${#suggestions} > 0 )); then
69+
_describe -t dotted-paths 'dotted path' suggestions
70+
return 0
71+
fi
72+
else
73+
# If we couldn't find the helper script, show a message
74+
_message "dotted path (helper script not found)"
75+
return 1
76+
fi
77+
fi
78+
79+
# If we couldn't parse the file or there are no suggestions,
80+
# just complete without suggestions
81+
_message 'dotted path'
82+
return 1
83+
}
84+
85+
_dotcat "$@"
86+
87+
# Installation instructions:
88+
# 1. Place this file in a directory in your $fpath (e.g., /usr/local/share/zsh/site-functions/)
89+
# 2. Rename it to _dotcat
90+
# 3. Make sure dotcat-completion.py is in your PATH or in the same directory
91+
# 4. Run `compinit` or restart your shell

0 commit comments

Comments
 (0)