Skip to content

feat: add default_subcommand and restart_token for naked task completions#410

Merged
jdx merged 4 commits intomainfrom
feat/default-subcommand-and-restart-token
Dec 31, 2025
Merged

feat: add default_subcommand and restart_token for naked task completions#410
jdx merged 4 commits intomainfrom
feat/default-subcommand-and-restart-token

Conversation

@jdx
Copy link
Owner

@jdx jdx commented Dec 31, 2025

Summary

Adds two new features to support mise's naked task completion needs:

  1. default_subcommand (Spec level): When the first non-flag argument isn't a known subcommand, automatically route to the specified default subcommand. This enables mise foo to work like mise run foo.

    default_subcommand "run"
  2. restart_token (SpecCommand level): A token that resets argument parsing, allowing multiple command invocations on one line. This enables mise run lint ::: test ::: check to complete task names after each :::.

    cmd run {
        restart_token ":::"
    }

Changes

  • lib/src/spec/mod.rs: Added default_subcommand field to Spec struct with parsing, serialization, and merge support
  • lib/src/spec/cmd.rs: Added restart_token field to SpecCommand struct with parsing, serialization, and merge support
  • lib/src/spec/builder.rs: Added restart_token() method to SpecCommandBuilder
  • lib/src/parse.rs: Updated parse_partial to handle both features:
    • In Phase 1: When word isn't a known subcommand, check for default_subcommand and route accordingly
    • In Phase 2: When encountering restart_token, reset argument parsing state
  • cli/src/cli/complete_word.rs: Updated completion logic for both features:
    • At root command with default_subcommand: also include completions from default subcommand's args
    • After restart_token: complete from first arg of current command

Test plan

  • Added test_default_subcommand - verifies naked command routing
  • Added test_default_subcommand_explicit_still_works - explicit subcommand takes precedence
  • Added test_restart_token - verifies argument parsing reset
  • Added test_restart_token_multiple - multiple restart tokens in sequence
  • All existing tests pass (112 tests)

Usage in mise

After this lands, mise will configure:

spec.default_subcommand = Some("run".to_string());
// ...
run.restart_token = Some(":::".to_string());

This will enable:

  • mise lint → completes task arguments
  • mise run lint ::: <TAB> → completes task names again

🤖 Generated with Claude Code


Note

Adds first-class support for naked subcommands and multi-invocation parsing.

  • Parser: Phase 1 routes to spec.default_subcommand when first non-flag token isn’t a known subcommand; Phase 2 recognizes cmd.restart_token to reset arg parsing, pending flag values, and -- state
  • Completion: complete_word now completes from the default subcommand’s first arg at root and from the first arg after a restart_token
  • Spec model: new Spec.default_subcommand and SpecCommand.restart_token fields with KDL parse/serialize and merge support
  • Builder: adds SpecCommandBuilder::restart_token()
  • Tests: new cases for default subcommand routing and restart token behavior (including multiple tokens and flag interactions)

Written by Cursor Bugbot for commit 43b9ad5. This will update automatically on new commits. Configure here.

Copilot AI review requested due to automatic review settings December 31, 2025 00:22
Copy link
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR adds two new features to support "naked" task completion in mise: default_subcommand at the spec level and restart_token at the command level. The default_subcommand allows routing commands like mise foo to mise run foo when foo isn't a known subcommand. The restart_token enables multiple task invocations in a single command line (e.g., mise run lint ::: test ::: check) by resetting argument parsing at each token.

  • Added default_subcommand field to Spec for automatic subcommand routing
  • Added restart_token field to SpecCommand for argument parsing resets
  • Updated parsing and completion logic to handle both features

Reviewed changes

Copilot reviewed 5 out of 5 changed files in this pull request and generated no comments.

Show a summary per file
File Description
lib/src/spec/mod.rs Added default_subcommand field with parsing, serialization, and merge support
lib/src/spec/cmd.rs Added restart_token field with parsing, serialization, and merge support
lib/src/spec/builder.rs Added builder method for restart_token configuration
lib/src/parse.rs Implemented parsing logic for both features and added comprehensive tests
cli/src/cli/complete_word.rs Updated completion logic to support both features

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

…ions

Adds two new features to support mise's naked task completion needs:

1. **default_subcommand** (Spec level): When the first non-flag argument
   isn't a known subcommand, automatically route to the specified default
   subcommand. This enables `mise foo` to work like `mise run foo`.

   ```kdl
   default_subcommand "run"
   ```

2. **restart_token** (SpecCommand level): A token that resets argument
   parsing, allowing multiple command invocations on one line. This
   enables `mise run lint ::: test ::: check` to complete task names
   after each `:::`.

   ```kdl
   cmd run {
       restart_token ":::"
   }
   ```

Both features include:
- KDL parsing and serialization
- Integration with parse_partial for correct argument routing
- Integration with complete_word for shell completions
- Builder API support
- Comprehensive tests

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
@jdx jdx force-pushed the feat/default-subcommand-and-restart-token branch from 675ee7b to abb913b Compare December 31, 2025 00:23
@codecov
Copy link

codecov bot commented Dec 31, 2025

Codecov Report

❌ Patch coverage is 66.40927% with 87 lines in your changes missing coverage. Please review.
✅ Project coverage is 52.08%. Comparing base (8723415) to head (43b9ad5).
⚠️ Report is 1 commits behind head on main.

Files with missing lines Patch % Lines
cli/src/cli/complete_word.rs 2.63% 26 Missing and 11 partials ⚠️
lib/src/parse.rs 89.00% 6 Missing and 15 partials ⚠️
lib/src/spec/mod.rs 0.00% 10 Missing and 3 partials ⚠️
lib/src/spec/cmd.rs 0.00% 7 Missing and 5 partials ⚠️
lib/src/spec/builder.rs 20.00% 1 Missing and 3 partials ⚠️
Additional details and impacted files
@@            Coverage Diff             @@
##             main     #410      +/-   ##
==========================================
- Coverage   57.32%   52.08%   -5.25%     
==========================================
  Files          47       47              
  Lines        5561     5894     +333     
  Branches     5561     5894     +333     
==========================================
- Hits         3188     3070     -118     
- Misses       1316     1438     +122     
- Partials     1057     1386     +329     

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

next_arg = out.cmd.args.first();
// Keep flags and continue parsing
continue;
}
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

restart_token doesn't reset enable_flags after -- separator

When encountering a restart_token, the enable_flags variable is not reset to true. If the user previously used -- to disable flag parsing (e.g., mise run task1 -- extra ::: --verbose task2), flags after the restart token will still be treated as positional arguments instead of flags. Since the restart token represents a new independent command invocation, enable_flags needs to be reset to true alongside the other state resets to allow proper flag parsing in subsequent invocations.

Fix in Cursor Fix in Web

jdx and others added 2 commits December 30, 2025 16:37
Fixed two bugs in restart_token handling:

1. Clear flag_awaiting_value when encountering restart_token
   - Previously, if a flag expecting a value appeared before :::
     (e.g., `mise run lint --jobs ::: test`), the word after :::
     would be consumed as the flag's value instead of being parsed
     as a new positional argument.

2. Reset enable_flags to true when encountering restart_token
   - Previously, if -- was used before ::: to disable flag parsing
     (e.g., `mise run task1 -- extra ::: --verbose task2`), flags
     after ::: would still be treated as positional arguments.

Also fixed completion logic to check after_restart_token before
flag_awaiting_value, ensuring completions after ::: offer the
correct first argument completions.

Added tests for both edge cases.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
@jdx
Copy link
Owner Author

jdx commented Dec 31, 2025

bugbot run

Move after_restart_token check after flag completion checks so that
typing `mise run lint ::: --<TAB>` correctly offers flag completions
instead of trying to complete as a positional argument.

The check order is now:
1. Flag completions (-, --, -x)
2. after_restart_token (first positional arg)
3. flag_awaiting_value
4. Normal arg/subcommand completion

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
@jdx jdx merged commit beffc0b into main Dec 31, 2025
8 of 9 checks passed
@jdx jdx deleted the feat/default-subcommand-and-restart-token branch December 31, 2025 01:09
jdx pushed a commit that referenced this pull request Dec 31, 2025
## [2.11.0](https://github.com/jdx/usage/compare/v2.10.0..v2.11.0) -
2025-12-31

### 🚀 Features

- add default_subcommand and restart_token for naked task completions by
[@jdx](https://github.com/jdx) in
[#410](#410)

### 🐛 Bug Fixes

- handle --help flag in exec command for non-shell scripts by
[@jdx](https://github.com/jdx) in
[#409](#409)

### 🧪 Testing

- add non-shell script tests by
[@muzimuzhi](https://github.com/muzimuzhi) in
[#406](#406)

### 📦️ Dependency Updates

- lock file maintenance by
[@renovate[bot]](https://github.com/renovate[bot]) in
[#403](#403)
- lock file maintenance by
[@renovate[bot]](https://github.com/renovate[bot]) in
[#407](#407)
- lock file maintenance by
[@renovate[bot]](https://github.com/renovate[bot]) in
[#408](#408)
jdx added a commit to jdx/mise that referenced this pull request Dec 31, 2025
## Summary

Enables shell completions for:
- **Naked task commands**: `mise foo <TAB>` now completes like `mise run
foo <TAB>`
- **Multi-task separators**: `mise run lint ::: <TAB>` now completes
task names again after `:::`

## Changes

- Add `default_subcommand = "run"` to the usage spec so unknown first
args route to `run`
- Add `restart_token = ":::"` to `run` and `tasks run` commands for
multi-task completion
- Bump `min_usage_version` from "1.3" to "2.11"
- Update `task_script_parser.rs` with new `var_min`/`var_max` fields for
usage-lib 2.11 compatibility

## Dependencies

Requires usage-lib v2.11.0 (jdx/usage#410)

## Test plan

- [ ] `mise fo<TAB>` completes task name "foo" (naked completion)
- [ ] `mise run lint ::: te<TAB>` completes task name "test" (restart
token)
- [ ] `mise --verbose fo<TAB>` still works with global flags before
naked arg

🤖 Generated with [Claude Code](https://claude.com/claude-code)

<!-- CURSOR_SUMMARY -->
---

> [!NOTE]
> Adds enhanced shell completions and updates the usage spec for
compatibility.
> 
> - Set `spec.default_subcommand = "run"` to enable naked task
completions (`mise foo <TAB>` behaves like `mise run foo <TAB>`)
> - Add `restart_token = ":::"` to `run` and `tasks run` for multi-task
completions after `:::`
> - Bump `min_usage_version` to `2.11` and update dependency to
`usage-lib 2.11.0`
> - Align parser with new spec by initializing `usage::SpecFlag` with
`var_min`/`var_max` fields
> 
> <sup>Written by [Cursor
Bugbot](https://cursor.com/dashboard?tab=bugbot) for commit
536a529. This will update automatically
on new commits. Configure
[here](https://cursor.com/dashboard?tab=bugbot).</sup>
<!-- /CURSOR_SUMMARY -->

Co-authored-by: Claude Opus 4.5 <noreply@anthropic.com>
tmeijn pushed a commit to tmeijn/dotfiles that referenced this pull request Jan 9, 2026
This MR contains the following updates:

| Package | Update | Change |
|---|---|---|
| [usage](https://github.com/jdx/usage) | minor | `2.10.0` → `2.11.0` |

MR created with the help of [el-capitano/tools/renovate-bot](https://gitlab.com/el-capitano/tools/renovate-bot).

**Proposed changes to behavior should be submitted there as MRs.**

---

### Release Notes

<details>
<summary>jdx/usage (usage)</summary>

### [`v2.11.0`](https://github.com/jdx/usage/blob/HEAD/CHANGELOG.md#2110---2025-12-31)

[Compare Source](jdx/usage@v2.10.0...v2.11.0)

##### 🚀 Features

- add default\_subcommand and restart\_token for naked task completions by [@&#8203;jdx](https://github.com/jdx) in [#&#8203;410](jdx/usage#410)

##### 🐛 Bug Fixes

- handle --help flag in exec command for non-shell scripts by [@&#8203;jdx](https://github.com/jdx) in [#&#8203;409](jdx/usage#409)

##### 🧪 Testing

- add non-shell script tests by [@&#8203;muzimuzhi](https://github.com/muzimuzhi) in [#&#8203;406](jdx/usage#406)

##### 📦️ Dependency Updates

- lock file maintenance by [@&#8203;renovate\[bot\]](https://github.com/renovate\[bot]) in [#&#8203;403](jdx/usage#403)
- lock file maintenance by [@&#8203;renovate\[bot\]](https://github.com/renovate\[bot]) in [#&#8203;407](jdx/usage#407)
- lock file maintenance by [@&#8203;renovate\[bot\]](https://github.com/renovate\[bot]) in [#&#8203;408](jdx/usage#408)

</details>

---

### Configuration

📅 **Schedule**: Branch creation - At any time (no schedule defined), Automerge - At any time (no schedule defined).

🚦 **Automerge**: Disabled by config. Please merge this manually once you are satisfied.

♻ **Rebasing**: Whenever MR becomes conflicted, or you tick the rebase/retry checkbox.

🔕 **Ignore**: Close this MR and you won't be reminded about this update again.

---

 - [ ] <!-- rebase-check -->If you want to rebase/retry this MR, check this box

---

This MR has been generated by [Renovate Bot](https://github.com/renovatebot/renovate).
<!--renovate-debug:eyJjcmVhdGVkSW5WZXIiOiI0Mi42OS4yIiwidXBkYXRlZEluVmVyIjoiNDIuNjkuMiIsInRhcmdldEJyYW5jaCI6Im1haW4iLCJsYWJlbHMiOlsiUmVub3ZhdGUgQm90IiwiYXV0b21hdGlvbjpib3QtYXV0aG9yZWQiLCJkZXBlbmRlbmN5LXR5cGU6Om1pbm9yIl19-->
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants