dotcli: fix help falling through to git.
This commit is contained in:
@@ -3,14 +3,24 @@
|
|||||||
## Architecture
|
## Architecture
|
||||||
|
|
||||||
`dot` is defined in one file: `~/.config/fish/functions/dot.fish`. It holds
|
`dot` is defined in one file: `~/.config/fish/functions/dot.fish`. It holds
|
||||||
two functions:
|
three functions:
|
||||||
|
|
||||||
- `dot` (`--wraps=git`) — dispatches `init` and any file found under
|
- `dot` (`--wraps=git`) — dispatches `init`, `help`, and any file found under
|
||||||
`~/.config/dot/commands/`, otherwise forwards everything to
|
`~/.config/dot/commands/`, otherwise forwards everything to
|
||||||
`git --git-dir=~/.dotfiles --work-tree=$HOME $argv` (full passthrough).
|
`git --git-dir=~/.dotfiles --work-tree=$HOME $argv` (full passthrough).
|
||||||
- `__dot_init` — the bootstrap logic, inlined in the same file rather than
|
- `__dot_init` — the bootstrap logic, inlined in the same file rather than
|
||||||
autoloaded separately, because it's the one subcommand that must work
|
autoloaded separately, because it's the one subcommand that must work
|
||||||
before the dotfiles repo has ever been cloned onto a machine.
|
before the dotfiles repo has ever been cloned onto a machine.
|
||||||
|
- `__dot_help` — prints usage: the built-in commands plus whatever is
|
||||||
|
currently found under `~/.config/dot/commands/`, generated by globbing that
|
||||||
|
directory rather than a hardcoded list, so it can't drift from reality.
|
||||||
|
|
||||||
|
`__dot_help`'s glob over `~/.config/dot/commands/*.fish` is duplicated in
|
||||||
|
`~/.config/fish/completions/dot.fish`'s `__dot_custom_subcommands` rather than
|
||||||
|
shared: fish only autoloads a function from a file named after that function,
|
||||||
|
so a helper defined inside `dot.fish` would be undefined if tab-completion
|
||||||
|
ran before `dot` had ever been sourced in the session. Keep both copies in
|
||||||
|
sync when the listing logic changes.
|
||||||
|
|
||||||
`dot init`:
|
`dot init`:
|
||||||
|
|
||||||
@@ -33,9 +43,9 @@ of `dot` itself.
|
|||||||
1. Create `~/.config/dot/commands/<name>.fish` defining a `_dot_<name>`
|
1. Create `~/.config/dot/commands/<name>.fish` defining a `_dot_<name>`
|
||||||
function.
|
function.
|
||||||
2. Confirm `dot <name>` dispatches to it. No other wiring is needed —
|
2. Confirm `dot <name>` dispatches to it. No other wiring is needed —
|
||||||
`~/.config/fish/completions/dot.fish` discovers new command files by
|
`~/.config/fish/completions/dot.fish` and `__dot_help` both discover new
|
||||||
globbing that directory, and `--wraps=git` still covers raw git
|
command files by globbing that directory, and `--wraps=git` still covers
|
||||||
subcommands.
|
raw git subcommands.
|
||||||
3. Add a case to `~/.config/dot/tests/dot.fish` covering it and run
|
3. Add a case to `~/.config/dot/tests/dot.fish` covering it and run
|
||||||
`fishtape ~/.config/dot/tests/dot.fish` until it passes.
|
`fishtape ~/.config/dot/tests/dot.fish` until it passes.
|
||||||
|
|
||||||
|
|||||||
@@ -70,3 +70,22 @@ end" >$HOME/.config/dot/commands/mark.fish
|
|||||||
|
|
||||||
dot mark >/dev/null 2>&1
|
dot mark >/dev/null 2>&1
|
||||||
@test "dispatches to a command file under ~/.config/dot/commands/" (cat $marker) = marked
|
@test "dispatches to a command file under ~/.config/dot/commands/" (cat $marker) = marked
|
||||||
|
|
||||||
|
# --- dot help ---
|
||||||
|
set -gx HOME (mktemp -d)
|
||||||
|
dot init --url $remote >/dev/null 2>&1
|
||||||
|
|
||||||
|
set -l help_output (dot help)
|
||||||
|
set -l help_status $status
|
||||||
|
|
||||||
|
@test "dot help succeeds" $help_status -eq 0
|
||||||
|
@test "dot help lists init" (string match -q '*init*' -- $help_output; echo $status) -eq 0
|
||||||
|
@test "dot help mentions git passthrough" (string match -q '*git*' -- $help_output; echo $status) -eq 0
|
||||||
|
|
||||||
|
mkdir -p $HOME/.config/dot/commands
|
||||||
|
echo "function _dot_mark
|
||||||
|
echo marked
|
||||||
|
end" >$HOME/.config/dot/commands/mark.fish
|
||||||
|
|
||||||
|
set -l help_with_custom (dot help)
|
||||||
|
@test "dot help lists custom commands found under ~/.config/dot/commands/" (string match -q '*mark*' -- $help_with_custom; echo $status) -eq 0
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
function __dot_custom_subcommands
|
function __dot_custom_subcommands
|
||||||
echo init
|
echo init
|
||||||
|
echo help
|
||||||
path basename $HOME/.config/dot/commands/*.fish 2>/dev/null | path change-extension ''
|
path basename $HOME/.config/dot/commands/*.fish 2>/dev/null | path change-extension ''
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|||||||
80
.config/fish/fish_variables
Normal file
80
.config/fish/fish_variables
Normal file
@@ -0,0 +1,80 @@
|
|||||||
|
# This file contains fish universal variable definitions.
|
||||||
|
# VERSION: 3.0
|
||||||
|
SETUVAR __done_min_cmd_duration:10000
|
||||||
|
SETUVAR __done_notification_urgency_level:low
|
||||||
|
SETUVAR _fisher_jorgebucaran_2F_fishtape_files:\x7e/\x2econfig/fish/functions/fishtape\x2efish\x1e\x7e/\x2econfig/fish/completions/fishtape\x2efish
|
||||||
|
SETUVAR _fisher_plugins:jorgebucaran/fishtape
|
||||||
|
SETUVAR _fisher_upgraded_to_4_4:\x1d
|
||||||
|
SETUVAR pure_begin_prompt_with_current_directory:true
|
||||||
|
SETUVAR pure_check_for_new_release:false
|
||||||
|
SETUVAR pure_color_at_sign:pure_color_mute
|
||||||
|
SETUVAR pure_color_aws_profile:pure_color_warning
|
||||||
|
SETUVAR pure_color_command_duration:pure_color_warning
|
||||||
|
SETUVAR pure_color_current_directory:pure_color_primary
|
||||||
|
SETUVAR pure_color_danger:red
|
||||||
|
SETUVAR pure_color_dark:black
|
||||||
|
SETUVAR pure_color_exit_status:pure_color_danger
|
||||||
|
SETUVAR pure_color_git_branch:pure_color_mute
|
||||||
|
SETUVAR pure_color_git_dirty:pure_color_mute
|
||||||
|
SETUVAR pure_color_git_stash:pure_color_info
|
||||||
|
SETUVAR pure_color_git_unpulled_commits:pure_color_info
|
||||||
|
SETUVAR pure_color_git_unpushed_commits:pure_color_info
|
||||||
|
SETUVAR pure_color_hostname:pure_color_mute
|
||||||
|
SETUVAR pure_color_info:cyan
|
||||||
|
SETUVAR pure_color_jobs:pure_color_normal
|
||||||
|
SETUVAR pure_color_k8s_context:pure_color_success
|
||||||
|
SETUVAR pure_color_k8s_namespace:pure_color_primary
|
||||||
|
SETUVAR pure_color_k8s_prefix:pure_color_info
|
||||||
|
SETUVAR pure_color_light:white
|
||||||
|
SETUVAR pure_color_mute:brblack
|
||||||
|
SETUVAR pure_color_nixdevshell_prefix:pure_color_info
|
||||||
|
SETUVAR pure_color_nixdevshell_symbol:pure_color_mute
|
||||||
|
SETUVAR pure_color_normal:normal
|
||||||
|
SETUVAR pure_color_prefix_root_prompt:pure_color_danger
|
||||||
|
SETUVAR pure_color_primary:blue
|
||||||
|
SETUVAR pure_color_prompt_on_error:pure_color_danger
|
||||||
|
SETUVAR pure_color_prompt_on_success:pure_color_success
|
||||||
|
SETUVAR pure_color_success:magenta
|
||||||
|
SETUVAR pure_color_system_time:pure_color_mute
|
||||||
|
SETUVAR pure_color_username_normal:pure_color_mute
|
||||||
|
SETUVAR pure_color_username_root:pure_color_light
|
||||||
|
SETUVAR pure_color_virtualenv:pure_color_mute
|
||||||
|
SETUVAR pure_color_warning:yellow
|
||||||
|
SETUVAR pure_convert_exit_status_to_signal:false
|
||||||
|
SETUVAR pure_enable_aws_profile:true
|
||||||
|
SETUVAR pure_enable_container_detection:true
|
||||||
|
SETUVAR pure_enable_git:true
|
||||||
|
SETUVAR pure_enable_k8s:false
|
||||||
|
SETUVAR pure_enable_nixdevshell:false
|
||||||
|
SETUVAR pure_enable_single_line_prompt:false
|
||||||
|
SETUVAR pure_enable_virtualenv:true
|
||||||
|
SETUVAR pure_reverse_prompt_symbol_in_vimode:true
|
||||||
|
SETUVAR pure_separate_prompt_on_error:false
|
||||||
|
SETUVAR pure_shorten_prompt_current_directory_length:0
|
||||||
|
SETUVAR pure_shorten_window_title_current_directory_length:0
|
||||||
|
SETUVAR pure_show_exit_status:false
|
||||||
|
SETUVAR pure_show_jobs:false
|
||||||
|
SETUVAR pure_show_numbered_git_indicator:false
|
||||||
|
SETUVAR pure_show_prefix_root_prompt:false
|
||||||
|
SETUVAR pure_show_subsecond_command_duration:false
|
||||||
|
SETUVAR pure_show_system_time:false
|
||||||
|
SETUVAR pure_symbol_aws_profile_prefix:
|
||||||
|
SETUVAR pure_symbol_container_prefix:
|
||||||
|
SETUVAR pure_symbol_exit_status_prefix:\x7c
|
||||||
|
SETUVAR pure_symbol_exit_status_separator:\x7c
|
||||||
|
SETUVAR pure_symbol_git_dirty:\x2a
|
||||||
|
SETUVAR pure_symbol_git_stash:\u2261
|
||||||
|
SETUVAR pure_symbol_git_unpulled_commits:\u21e3
|
||||||
|
SETUVAR pure_symbol_git_unpushed_commits:\u21e1
|
||||||
|
SETUVAR pure_symbol_k8s_prefix:\u2638
|
||||||
|
SETUVAR pure_symbol_nixdevshell_prefix:\u2744\ufe0f
|
||||||
|
SETUVAR pure_symbol_prefix_root_prompt:\x23
|
||||||
|
SETUVAR pure_symbol_prompt:\u276f
|
||||||
|
SETUVAR pure_symbol_reverse_prompt:\u276e
|
||||||
|
SETUVAR pure_symbol_ssh_prefix:
|
||||||
|
SETUVAR pure_symbol_title_bar_separator:\x2d
|
||||||
|
SETUVAR pure_symbol_virtualenv_prefix:
|
||||||
|
SETUVAR pure_system_time_format:\x2b\x25T
|
||||||
|
SETUVAR pure_threshold_command_duration:5
|
||||||
|
SETUVAR pure_truncate_prompt_current_directory_keeps:\x2d1
|
||||||
|
SETUVAR pure_truncate_window_title_current_directory_keeps:\x2d1
|
||||||
@@ -7,6 +7,11 @@ function dot --wraps=git --description 'Manage dotfiles via a bare repo checked
|
|||||||
return $status
|
return $status
|
||||||
end
|
end
|
||||||
|
|
||||||
|
if test "$argv[1]" = help
|
||||||
|
__dot_help
|
||||||
|
return $status
|
||||||
|
end
|
||||||
|
|
||||||
set -l commands_dir $HOME/.config/dot/commands
|
set -l commands_dir $HOME/.config/dot/commands
|
||||||
set -l command_file $commands_dir/$argv[1].fish
|
set -l command_file $commands_dir/$argv[1].fish
|
||||||
|
|
||||||
@@ -87,3 +92,23 @@ function __dot_init
|
|||||||
|
|
||||||
echo "dot init: bootstrapped $dotfiles_dir from $url"
|
echo "dot init: bootstrapped $dotfiles_dir from $url"
|
||||||
end
|
end
|
||||||
|
|
||||||
|
# The custom-subcommand glob is duplicated (not shared with
|
||||||
|
# completions/dot.fish) because fish only autoloads a function from a file
|
||||||
|
# named after that function; a shared helper would go undefined if `dot help`
|
||||||
|
# ran in a completion context before `dot` itself had ever been sourced.
|
||||||
|
function __dot_help
|
||||||
|
echo "dot: manage dotfiles via a bare repo checked out over \$HOME"
|
||||||
|
echo
|
||||||
|
echo "Commands:"
|
||||||
|
echo " init bootstrap the dotfiles repo on a new machine"
|
||||||
|
echo " help show this message"
|
||||||
|
|
||||||
|
for f in $HOME/.config/dot/commands/*.fish
|
||||||
|
test -e $f; or continue
|
||||||
|
echo " "(path basename $f | path change-extension '')
|
||||||
|
end
|
||||||
|
|
||||||
|
echo
|
||||||
|
echo "Any other command is passed through to git (dot status, dot add, dot commit, dot push, ...)."
|
||||||
|
end
|
||||||
|
|||||||
@@ -1,27 +1,10 @@
|
|||||||
# dotfiles
|
# dotfiles
|
||||||
|
|
||||||
Managed as a bare git repo checked out over `$HOME`. Not cloned in the usual
|
Dotfiles managed as a bare git repo checked out over `$HOME`, for machines
|
||||||
sense — `git --git-dir=~/.dotfiles --work-tree=$HOME` treats `$HOME` itself as
|
running CachyOS with KDE Plasma.
|
||||||
the working tree.
|
|
||||||
|
|
||||||
## Everyday use
|
|
||||||
|
|
||||||
A fish function named `dot` wraps that invocation:
|
|
||||||
|
|
||||||
```fish
|
|
||||||
dot status
|
|
||||||
dot add .bashrc
|
|
||||||
dot commit -m 'update bashrc'
|
|
||||||
dot push
|
|
||||||
```
|
|
||||||
|
|
||||||
Any git subcommand works — `dot` forwards whatever you type straight to git.
|
|
||||||
|
|
||||||
## Bootstrapping a new machine
|
## Bootstrapping a new machine
|
||||||
|
|
||||||
Before `dot` exists there's nothing to autoload it from, so the very first
|
|
||||||
step is fetching that one file by hand:
|
|
||||||
|
|
||||||
```sh
|
```sh
|
||||||
mkdir -p ~/.config/fish/functions
|
mkdir -p ~/.config/fish/functions
|
||||||
curl -fsSL https://git.alexion.dev/alexion/dotfiles/raw/branch/main/.config/fish/functions/dot.fish \
|
curl -fsSL https://git.alexion.dev/alexion/dotfiles/raw/branch/main/.config/fish/functions/dot.fish \
|
||||||
@@ -29,25 +12,13 @@ curl -fsSL https://git.alexion.dev/alexion/dotfiles/raw/branch/main/.config/fish
|
|||||||
fish -c 'dot init'
|
fish -c 'dot init'
|
||||||
```
|
```
|
||||||
|
|
||||||
`dot init`:
|
## Commands
|
||||||
|
|
||||||
- clones the bare repo to `~/.dotfiles`
|
| Command | Description |
|
||||||
- backs up any pre-existing files that would be overwritten by checkout into
|
| ----------- | ----------------------------------------------- |
|
||||||
`~/.dotfiles-backup/<timestamp>/`
|
| `dot help` | Lists available commands. |
|
||||||
- checks out the tracked files onto `$HOME`
|
| `dot init` | Bootstraps the dotfiles repo on a new machine. |
|
||||||
- sets `status.showUntrackedFiles=no` so `dot status` doesn't list all of
|
| `dot <git>` | Everything else is passed to `git`. |
|
||||||
`$HOME`
|
|
||||||
|
|
||||||
It refuses to run if `~/.dotfiles` already exists, and it never falls back to
|
See [DOT-CLI.md](../.claude/skills/dotfiles/DOT-CLI.md) for the `dot` tool's
|
||||||
creating a fresh empty repo if the clone fails.
|
internal architecture, bootstrap logic, subcommand dispatch, and test suite.
|
||||||
|
|
||||||
## Adding new subcommands
|
|
||||||
|
|
||||||
Beyond `init`, `dot` looks for `~/.config/dot/commands/<name>.fish`. Each file
|
|
||||||
should define a `_dot_<name>` function; `dot <name> args...` sources the file
|
|
||||||
and calls it. These files are deliberately *not* under
|
|
||||||
`~/.config/fish/functions/`, so they never become independently invokable
|
|
||||||
commands or clutter tab-completion outside of `dot` itself.
|
|
||||||
|
|
||||||
`~/.config/fish/completions/dot.fish` discovers them automatically by
|
|
||||||
scanning that directory, so a new command file gets tab-completion for free.
|
|
||||||
|
|||||||
Reference in New Issue
Block a user