I’m trying to create a script that will mimic cd where I provide a path, and the script cd’s to that by appending it to an absolute existing path. The idea is that wherever I call it, it will always act as if I’m trying to cd from the root of the project.
A key feature I want to add is autocomplete as the user is typing where, like cd, it will provide the path options and the user can autocomplete as they type.
Example:
goto po
pointers/ positions/
goto pointers/
src/ lib/
This is the initial script I made so far:
#!/bin/zsh
# Find the root directory of the repository
find_repo_root() {
local repo_root
repo_root=$(git rev-parse --show-toplevel 2>/dev/null)
if [ -z "$repo_root" ]; then
return 1 # Return failure if not in a Git repository
fi
echo $repo_root
}
# Change directory relative to repository root
goto() {
local repo_root=$(find_repo_root)
if [ -z "$repo_root" ]; then
echo "Error: Not in a Git repository." >&2 # Print error message to stderr
return 1
fi
# Create an absolute path using the repo root
local target_dir="$repo_root/$1"
if [ -d "$target_dir" ]; then
cd "$target_dir"
else
echo "Directory does not exist: $target_dir" >&2
return 1
fi
}
# Autocomplete function for the goto command
_goto_autocomplete() {
local repo_root=$(find_repo_root)
if [ -z "$repo_root" ]; then
return 1 # If not in a Git repo, don't suggest any autocompletions
fi
# Dynamically generate possible matches relative to the repo root
local current_input="${(Q)PREFIX}"
# Find directories relative to the repository root, not the current directory
local possible_dirs=(${(f)"$(find $repo_root -type d -not -path '*/.*' -maxdepth 2)"})
# Filter for directories that start with the current input
local matches=()
for dir in $possible_dirs; do
# Strip the repository root from the beginning of the directory path
local rel_dir=${dir#$repo_root/}
if [[ $rel_dir == $current_input* ]]; then
matches+=$rel_dir
fi
done
# Provide autocomplete suggestions
compadd $matches
}
# Register the autocomplete function for the goto command
compdef _goto_autocomplete goto
# Ensure compinit is loaded for autocompletion to work
autoload -Uz compinit && compinit
At first I thought I had it working since it starts to autocomplete, but then I realized it was always looking at the current working directory I was in. I’m not understanding how compadd, compdef, and compinit is working. I’m reading the docs for more insight, but I can’t tell how to make the autocomplete only look at the provided filepath.