cli: aliases: support multi-word alias names#9577
Conversation
Alias names containing spaces (e.g. `aliases."ws rm"`) could previously only be invoked as a single quoted argument (`jj "ws rm"`). Resolve them from the external subcommand plus its leading positional arguments instead, so they can be invoked as space-separated words (`jj ws rm`) like real subcommands. When several alias names share a prefix, the longest match wins, and the remaining arguments are forwarded to the alias definition. Recursion detection is reworked accordingly: an alias is flagged as recursive only when it resolves again without consuming any arguments, so a multi-word alias resolved repeatedly on a shrinking argument list (`a b b` -> `a b` -> `a`) still terminates. Addresses jj-vcs#6611. Change-Id: Id000000056c49bde4340301ff7de763dff332da8
josephlou5
left a comment
There was a problem hiding this comment.
Thanks for working on this! I'm pretty excited for this feature :)
|
|
||
| When alias names share a prefix, the longest match wins, so `l` and `"l all"` | ||
| can resolve to different commands. Don't start a multi-word alias with a | ||
| built-in command name: `jj log mine` is always parsed as the built-in `log` |
There was a problem hiding this comment.
Is this hard to handle? For example I personally would like a jj git sync alias that implements #/1039 until it's merged upstream, but does that mean that I'll always get a jj git: unrecognized subcommand 'sync' error?
Given that your test examples have shown that foo bar is chosen over foo, I think it makes intuitive sense that log mine should resolve an alias if present, and then fall back to log (with args) if not. But also, your example was when foo bar and foo are both defined as aliases, and maybe it's harder to check all the built-in commands?
Anyway, if this is possible, that'd be cool :) And if it's not, then I guess nothing needs to change here.
There was a problem hiding this comment.
Perhaps we'll need to set allow_external_subcommands(true) recursively to all subcommands. See hide_short_subcommand_aliases() for a recursion example.
Then, we can probably substitute arguments normally based on prefix matching. For example, ws rm would be substituted to workspace rm by "ws" = ["workspace"], and then by "workspace rm" = [...]. Aliases like "ws rm" = [...] will never match. A warning can be added if needed.
There was a problem hiding this comment.
I intentionally wanted to avoid overlap with the builtin commands, at least for the initial version -- I think this has some overlap with #1509, on letting users redefine the behaviour of builtin commands.
Basically, should users be able to define aliases like jj log mine? I'm inclined to say no. That doesn't mean we couldn't still let people define jj git sync, of course (as git is a pure "container" command).
What do you guys think?
There was a problem hiding this comment.
should users be able to define aliases like
jj log mine? I'm inclined to say no. That doesn't mean we couldn't still let people definejj git sync, of course (as git is a pure "container" command).
No and yes. The latter will allow us to move 1-char jj bookmark subcommands to predefined aliases.
[aliases]
b = ["bookmark"]
"bookmark a" = ["bookmark", "advance"]EDIT: Oh, it's unclear whether jj b --quiet a should be expanded.
There was a problem hiding this comment.
That doesn't mean we couldn't still let people define
jj git sync, of course (as git is a pure "container" command).
That makes sense to me. A follow-up question I have then is: Is it necessarily the case that if jj git has subcommands, then jj git will never have its own behavior? If clap enforces this, then allowing aliases of sub-sub-commands sounds good (e.g., jj git sync as an alias), but if not then we're left with the same problem as jj log my-alias.
I also really like being able to move the single-character built-in aliases to the default config (or being able to define your own).
There was a problem hiding this comment.
How does this feature interact with completions? I described some ideas in #9047 (closed as a duplicate of the issue that you linked). Might help to also add some tests so that the behavior is clear.
| } | ||
|
|
||
| #[test] | ||
| fn test_alias_multi_word_name() { |
There was a problem hiding this comment.
Can you also add a test with .run_jj(["ws ls"]) to ensure that the quoted versions still work for backward compatibility? I think they should but just want to make sure. (It's probably not a huge deal since I wouldn't imagine many people are depending on quoted alias names, but good to be thorough.)
#6611
Checklist
If applicable:
CHANGELOG.mdREADME.md,docs/,demos/)cli/src/config-schema.json)how it works, how it's organized), including any code drafted by an LLM.
an eye towards deleting anything that is irrelevant, clarifying anything
that is confusing, and adding details that are relevant. This includes,
for example, commit descriptions, PR descriptions, and code comments.