I previously used shell aliases to quickly access the config files I was modifying often. This become a bit cumbersome when the number of configs grew.
Instead, I created a zsh script (easily modifiable for bash) using fzf
to quickly select which config to edit or navigate to.
Since configs often contain multiple files, also changing the directory to your selected config allows you to easily navigate your config directories.
Usage
Typically, I want to edit the config I want to navigate to, so by default the scripts opens the selected config in your selected $EDITOR
. To instead only cd to the config directory, you can add -d
or dir
flags. Example: config -d
or config dir nvim
.
config # Config selection in fzf, opening in $EDITOR
config config-name # Opens config-name in $EDITOR
config -d config-name # Navigates to config directory ('dir' also works)
Make sure to set your EDITOR
environment variable to open the configs in your preferred editor.
export EDITOR=nvim
You can also provide appropriate permissions for your scripts and directory:
chmod 700 .dotfiles
chmod 700 .dotfiles/path-to-scripts/*.sh
Script
#!/usr/bin/env zsh
typeset -A config_map=(
"alacritty" "$HOME/.dotfiles/.config/alacritty"
"ghostty" "$HOME/.dotfiles/.config/ghostty/config"
"kitty" "$HOME/.dotfiles/.config/kitty"
"nvim" "$HOME/.dotfiles/.config/nvim"
"tmux" "$HOME/.dotfiles/.config/tmux/.tmux.conf"
"bash" "$HOME/.dotfiles/.bashrc"
"zsh" "$HOME/.dotfiles/.zshrc"
)
config() {
# Declare all variables as local
local OPEN_EDITOR=true selection config_path config_dir
if [[ "$1" == "dir" || "$1" == "-d" ]]; then
OPEN_EDITOR=false
shift
fi
# Selection process
if [ -z "$1" ]; then
if command -v fzf &>/dev/null; then
selection=$(printf "%s\n" "${(@k)config_map}" | fzf --prompt="Select config: ")
else
echo "Select a config:"
select selection in "${(@k)config_map}"; do
[ -n "$selection" ] && break
done
fi
else
# Sanitize user-provided input
selection="${1//[^a-zA-Z0-9_-]/}" # Strip invalid characters
[ -z "$selection" ] && { echo "Invalid config name" >&2; return 1 }
fi
# Validate selection exists
if [ -z "$selection" ] || ! (( ${+config_map[$selection]} )); then
echo "Error: Invalid config '$selection'" >&2
return 1
fi
# Resolve path
config_path=${config_map[$selection]}
[ -z "$config_path" ] && { echo "Path not found for '$selection'" >&2; return 1 }
# Handle navigation
if [ -d "$config_path" ]; then
cd "$config_path" || { echo "Failed to navigate to directory" >&2; return 1 }
echo "Navigated to $config_path"
else
config_dir=$(dirname "$config_path")
cd "$config_dir" || { echo "Failed to navigate to parent directory" >&2; return 1 }
echo "Navigated to $config_dir"
fi
# Open editor if requested
if $OPEN_EDITOR; then
if [ -d "$config_path" ]; then
${EDITOR:-nvim} . || echo "Failed to open editor" >&2
else
${EDITOR:-nvim} "$config_path" || echo "Failed to open file" >&2
fi
fi
}
# Zsh completion
_config-autocomplete() {
local -a config_names
config_names=("${(@k)config_map}")
_arguments "1: :(${config_names[*]})"
}
compdef _config-autocomplete config