Skip to content

Commit 2715fc5

Browse files
committed
feat: shell completions
1 parent 37cbdf8 commit 2715fc5

17 files changed

+2678
-16
lines changed

README.md

Lines changed: 93 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ The slic (**S**tellarWP **L**ocal **I**nteractive **C**ontainers) CLI command pr
2020
* [Advanced topics](#advanced-topics)
2121
* [Defaults for your project with `slic.json`](/docs/slicjson.md)
2222
* [Managing PHP Versions](#managing-php-versions)
23+
* [Shell Completion](#shell-completion)
2324
* [Making composer installs faster](#making-composer-installs-faster)
2425
* [Changing your composer version](#changing-your-composer-version)
2526
* [Customizing `slic`'s `.env` file](#customizing-slics-env-file)
@@ -844,6 +845,98 @@ To reset slic to the default PHP version (7.4):
844845
slic php-version reset
845846
```
846847

848+
### Shell Completion
849+
850+
`slic` provides tab completion for bash, zsh, and fish shells. This makes it faster to use `slic` by allowing you to press Tab to autocomplete commands, targets, branches, and options.
851+
852+
#### Quick Installation
853+
854+
The easiest way to set up completions is:
855+
856+
```bash
857+
slic completion install
858+
```
859+
860+
This auto-detects your shell and installs the appropriate completion script. You'll be prompted to confirm before any files are modified.
861+
862+
#### What Gets Completed
863+
864+
Once installed, you can tab-complete:
865+
866+
- **Commands**: `slic <TAB>` shows all available commands
867+
- **Targets**: `slic use <TAB>` shows all valid plugins/themes
868+
- **Subcommands**: `slic stack <TAB>` shows `list`, `stop`, `info`
869+
- **Git branches**: `slic worktree add <TAB>` shows available branches
870+
- **Stack paths**: `slic --stack=<TAB>` shows registered stack paths
871+
- **Toggle options**: `slic xdebug <TAB>` shows `on`, `off`, `status`, etc.
872+
- **PHP versions**: `slic php-version set <TAB>` shows `7.4`, `8.0`, `8.1`, `8.2`, `8.3`
873+
874+
#### Manual Installation
875+
876+
If you prefer manual installation or the automatic installation doesn't work:
877+
878+
**Bash** - Add to `~/.bashrc` or `~/.bash_profile`:
879+
880+
```bash
881+
# slic completions
882+
if command -v slic &> /dev/null; then
883+
_slic_path=$(command -v slic)
884+
if [[ -L "$_slic_path" ]]; then
885+
_slic_path=$(realpath "$_slic_path" 2>/dev/null || readlink -f "$_slic_path" 2>/dev/null || readlink "$_slic_path")
886+
fi
887+
source "$(dirname "$_slic_path")/completions/bash/slic.bash"
888+
unset _slic_path
889+
fi
890+
```
891+
892+
**Zsh** - Add to `~/.zshrc`:
893+
894+
```zsh
895+
# slic completions
896+
if command -v slic &> /dev/null; then
897+
_slic_path=$(command -v slic)
898+
if [[ -L "$_slic_path" ]]; then
899+
_slic_path=$(realpath "$_slic_path" 2>/dev/null || readlink -f "$_slic_path" 2>/dev/null || readlink "$_slic_path")
900+
fi
901+
fpath=("$(dirname "$_slic_path")/completions/zsh" $fpath)
902+
autoload -Uz compinit && compinit
903+
unset _slic_path
904+
fi
905+
```
906+
907+
**Fish** - Create a symlink:
908+
909+
```fish
910+
mkdir -p ~/.config/fish/completions
911+
ln -sf /path/to/slic/completions/fish/slic.fish ~/.config/fish/completions/slic.fish
912+
```
913+
914+
#### Other Completion Commands
915+
916+
```bash
917+
# Show installation instructions for your shell
918+
slic completion
919+
920+
# Display the completion script content (for inspection or manual setup)
921+
slic completion show [bash|zsh|fish]
922+
923+
# Clear the completion cache (useful if completions seem stale)
924+
slic completion cache-clear
925+
```
926+
927+
#### How It Works
928+
929+
The completion system uses a two-layer architecture:
930+
931+
1. **Shell scripts** (bash/zsh/fish) - Thin wrappers that capture the command line context
932+
2. **PHP backend** - Generates completions dynamically based on your slic configuration
933+
934+
Completions are cached for performance:
935+
- Commands list: 24 hours
936+
- Targets: 5 minutes
937+
- Git branches: 2 minutes
938+
- Stack paths: 1 minute
939+
847940
### Making composer installs faster
848941

849942
By default, `slic` caches composer dependencies within the container

changelog.md

Lines changed: 6 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -9,25 +9,15 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
99
### Changed
1010
- Breaking Change - The `slic here` command will now create a new stack for the current path instead of changing the context of the previously only stack to the path.
1111
- Breaking Change - The `XDK` configuration variable (`slic` by default) is now used as **root** for each stack IDE key. An `XDK` of `slic` will create stack IDE keys like `slic_<stack_hash>` and not just `slic` as it was before.
12+
- Extend `-y, --yes` flag support for all commands that might require confirmation
1213

1314
### Added
14-
- Multi-path support with a 1:1 mapping between stacks and paths.
15-
- Interactive Terminal User Interface (TUI) for the `slic use` command. Running `slic use` without arguments now opens an interactive selection menu with fuzzy search and current selection indicator.
15+
- Multiple, isolated Docker Compose projects per path
1616
- Git worktree multi-stack support for concurrent development workflows
17-
- New `slic worktree` command with subcommands:
18-
- `slic worktree add <branch>` - Create a new git worktree with dedicated stack
19-
- `slic worktree list` - List all worktrees and their stacks
20-
- `slic worktree remove <branch>` - Remove a worktree and its stack
21-
- `slic worktree sync` - Synchronize git worktrees with slic registry
22-
- Automatic worktree detection and registration prompts
23-
- Isolated Docker Compose projects per worktree with unique XDebug ports
24-
- Worktree-specific environment variables (SLIC_IS_WORKTREE, SLIC_WORKTREE_FULL_PATH, SLIC_WORKTREE_CONTAINER_PATH)
25-
- `slic stack list` command to display all registered stacks with their status, target paths, and ports
26-
- `slic stack stop [<stack>]` command to stop a specific stack. If no stack is provided and multiple exist, prompts user to choose one
27-
- `slic stack stop all` command to stop all registered stacks at once. Always prompts for confirmation, shows list of stacks being stopped, continues even if one stack fails, and displays comprehensive summary with success/failure counts. Works from any directory
28-
- `slic stack info [<stack>]` command to display detailed information about a specific stack including container status, ports, and configuration
29-
- Global `--stack=<path>` flag to target specific stacks. This allows running commands against any registered stack without changing the current working directory
30-
- `-y, --yes` flag support for `slic stack stop all` command to skip confirmation prompt, enabling use in non-interactive environments like CI pipelines and automation scripts
17+
- New `slic worktree` command leveraging dedicated stacks for each worktree
18+
- Interactive Terminal User Interface (TUI) for the `slic use` command. Running `slic use` without arguments now opens an interactive selection menu with fuzzy search and current selection indicator.
19+
- New `slic completion` command with subcommands to install bash/zsh/fish completions
20+
- Shell completion support for bash, zsh, and fish shells with dynamic completions for commands, targets, git branches, stack paths, and options
3121

3222
# [2.1.2] - 2025-11-13
3323
- Change - GitHub Actions workflows now use native ARM64 runners (`ubuntu-24.04-arm`) instead of QEMU emulation for multi-platform builds, to reduce build times.

completions/bash/slic.bash

Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
#!/usr/bin/env bash
2+
# Bash completion script for slic
3+
#
4+
# This script provides tab completion for the slic CLI tool.
5+
# It delegates completion generation to a PHP script.
6+
#
7+
# Installation:
8+
# Add this to ~/.bashrc or ~/.bash_profile:
9+
# source /path/to/slic/completions/bash/slic.bash
10+
#
11+
# Or use: slic completion install bash
12+
13+
_slic_completions() {
14+
local cur prev words cword
15+
_init_completion || return
16+
17+
# Get the directory where slic is installed
18+
local slic_cmd
19+
slic_cmd=$(command -v slic 2>/dev/null)
20+
21+
if [[ -z "$slic_cmd" ]]; then
22+
return 0
23+
fi
24+
25+
# Resolve symlinks to get the actual slic directory
26+
if [[ -L "$slic_cmd" ]]; then
27+
# Try realpath first (more portable), then readlink -f (GNU), then readlink (basic)
28+
slic_cmd=$(realpath "$slic_cmd" 2>/dev/null || readlink -f "$slic_cmd" 2>/dev/null || readlink "$slic_cmd" 2>/dev/null)
29+
fi
30+
31+
local slic_dir
32+
slic_dir=$(dirname "$slic_cmd")
33+
34+
# Call the PHP completion script
35+
local completions
36+
completions=$(php "${slic_dir}/src/completions/complete.php" \
37+
--line="${COMP_LINE}" \
38+
--point="${COMP_POINT}" \
39+
--words="${COMP_WORDS[*]}" \
40+
--cword="${COMP_CWORD}" 2>/dev/null)
41+
42+
# Convert space-separated completions to array
43+
if [[ -n "$completions" ]]; then
44+
COMPREPLY=($(compgen -W "$completions" -- "$cur"))
45+
fi
46+
}
47+
48+
# Register the completion function for slic
49+
complete -F _slic_completions slic

completions/fish/slic.fish

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
# Fish completion script for slic
2+
#
3+
# This script provides tab completion for the slic CLI tool.
4+
# It delegates completion generation to a PHP script.
5+
#
6+
# Installation:
7+
# Copy or symlink this file to ~/.config/fish/completions/slic.fish
8+
# Or use: slic completion install fish
9+
10+
function __slic_completions
11+
# Find the slic command
12+
set -l slic_cmd (command -v slic 2>/dev/null)
13+
14+
if test -z "$slic_cmd"
15+
return 0
16+
end
17+
18+
# Resolve symlinks to get the actual slic directory
19+
if test -L "$slic_cmd"
20+
set slic_cmd (realpath "$slic_cmd" 2>/dev/null; or readlink -f "$slic_cmd" 2>/dev/null; or readlink "$slic_cmd" 2>/dev/null)
21+
end
22+
23+
set -l slic_dir (dirname "$slic_cmd")
24+
25+
# Get the current command line tokens (already completed)
26+
set -l tokens (commandline -opc)
27+
28+
# Get the current token being typed
29+
set -l current (commandline -ct)
30+
31+
# Call the PHP completion script
32+
php "$slic_dir/src/completions/complete.php" \
33+
--shell=fish \
34+
--words="$tokens" \
35+
--current="$current" 2>/dev/null
36+
end
37+
38+
# Register completions for slic command
39+
# -f: don't complete files
40+
# -a: provide completions from the function
41+
complete -c slic -f -a "(__slic_completions)"

completions/zsh/_slic

Lines changed: 65 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,65 @@
1+
#compdef slic
2+
# Zsh completion script for slic
3+
#
4+
# This script provides tab completion for the slic CLI tool.
5+
# It delegates completion generation to a PHP script.
6+
#
7+
# Installation:
8+
# Add this to ~/.zshrc:
9+
# fpath=(/path/to/slic/completions/zsh $fpath)
10+
# autoload -Uz compinit && compinit
11+
#
12+
# Or use: slic completion install zsh
13+
14+
_slic() {
15+
local slic_cmd slic_dir completions
16+
17+
# Find the slic command
18+
slic_cmd=$(command -v slic 2>/dev/null)
19+
20+
if [[ -z "$slic_cmd" ]]; then
21+
return 0
22+
fi
23+
24+
# Resolve symlinks to get the actual slic directory
25+
if [[ -L "$slic_cmd" ]]; then
26+
# macOS uses readlink differently than GNU
27+
if [[ "$OSTYPE" == "darwin"* ]]; then
28+
# On macOS, try to use greadlink if available, otherwise use a while loop
29+
if command -v greadlink >/dev/null 2>&1; then
30+
slic_cmd=$(greadlink -f "$slic_cmd")
31+
else
32+
# Follow symlinks manually with protection against circular links
33+
local iterations=0
34+
local max_iterations=10
35+
while [[ -L "$slic_cmd" ]] && (( iterations < max_iterations )); do
36+
local link_target
37+
link_target=$(readlink "$slic_cmd")
38+
if [[ "$link_target" == /* ]]; then
39+
slic_cmd="$link_target"
40+
else
41+
slic_cmd="$(dirname "$slic_cmd")/$link_target"
42+
fi
43+
(( iterations++ ))
44+
done
45+
fi
46+
else
47+
slic_cmd=$(readlink -f "$slic_cmd" 2>/dev/null)
48+
fi
49+
fi
50+
51+
slic_dir=$(dirname "$slic_cmd")
52+
53+
# Call the PHP completion script
54+
completions=($(php "${slic_dir}/src/completions/complete.php" \
55+
--line="${BUFFER}" \
56+
--point="${CURSOR}" \
57+
--words="${words[*]}" \
58+
--cword="${CURRENT}" 2>/dev/null))
59+
60+
if [[ ${#completions[@]} -gt 0 ]]; then
61+
_describe 'slic commands' completions
62+
fi
63+
}
64+
65+
_slic "$@"

0 commit comments

Comments
 (0)