Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add hinting of arg value types for zsh/fish completion #1793

Merged
merged 1 commit into from
Aug 7, 2020

Conversation

intgr
Copy link
Contributor

@intgr intgr commented Apr 7, 2020

Adds new method/attribute Arg::value_hint, taking a ValueHint enum
as argument. The hint can denote accepted values, for example: paths,
usernames, hostnames, commands, etc.

This initial implementation supports hints for the zsh and fish
completion generators, support for other shells can be added later.

@intgr
Copy link
Contributor Author

intgr commented Apr 7, 2020

Is still missing some functionality and needs some polish, but I wanted to open a PR to get some feedback first.

@pksunkara
Copy link
Member

Looks like a great start. Appreciate this @intgr

Btw, could you help us test if #850 has been fixed or not? I couldn't get it working on my local zsh

@pksunkara pksunkara self-requested a review April 8, 2020 06:25
@pickfire
Copy link
Contributor

pickfire commented Apr 8, 2020

Is it possible to extract the type of data to do value hinting automatically in addition to this, like making use of rust types like File will get a file? I think this should be harder but helps reduces user effort, of course the limitation here it that we can't figure out if we we want a file or a host from rust type itself.

@intgr
Copy link
Contributor Author

intgr commented Apr 8, 2020

Is it possible to extract the type of data to do value hinting automatically

Good idea, I will look into it.

/// .value_hint(ValueHint::CommandWithArguments)
/// # ;
/// ```
pub fn value_hint(mut self, value_hint: ValueHint) -> Self {
Copy link
Contributor Author

Choose a reason for hiding this comment

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

Looks like by convention, I should also use self.setb(ArgSettings::TakesValue); here?

Copy link
Contributor

Choose a reason for hiding this comment

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

Also, can there only be one value hint, can't it be a merged value hint or a list?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Hmm, can you imagine any use cases for combining multiple hints for one argument?

Seems it would be quite an edge case. For situations like that, I think it would be better to provide some "escape hatch" to manually override parts of the generated completion file, rather than trying to accommodate such weirdness.

src/build/arg/value_hint.rs Show resolved Hide resolved
/// Command name looked up from PATH or full path to executable
CommandName,
/// A command and each argument as multiple strings
CommandWithArguments,
Copy link
Contributor Author

Choose a reason for hiding this comment

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

The CommandWithArguments is a very important use case for implementing command wrappers, but also very different from all the others. For it to work correctly, it assumes that the arg is a positional argument, has multiple(true) and app has AppSettings::TrailingVarArg.

Can/should I add these checks to some place?

Copy link
Contributor

Choose a reason for hiding this comment

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

I'd go with setting multiple(true) and AppSettings::TrailingVarArg automatically and documenting this behavior.

clap_generate/src/generators/shells/zsh.rs Outdated Show resolved Hide resolved
@pksunkara
Copy link
Member

Also, can we do something about bash and fish too? I could try my hand at them later, but it would be great if we can support them in this PR.

Copy link
Contributor

@CreepySkeleton CreepySkeleton left a comment

Choose a reason for hiding this comment

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

Looks great, just a little question.

clap_generate/src/generators/shells/zsh.rs Outdated Show resolved Hide resolved
@intgr
Copy link
Contributor Author

intgr commented Apr 8, 2020

Also, can we do something about bash and fish too? I could try my hand at them later, but it would be great if we can support them in this PR.

Honestly, I'd prefer to keep the scope of this PR as small as possible. This is my first contribution to clap, I'm still learning Rust, that's already lots of new things. I haven't used bash for years, never even tried fish.

@Dylan-DPC-zz
Copy link

@intgr agree, go on don't worry. we can discuss that in a separate issue/pr

@CreepySkeleton
Copy link
Contributor

Is it possible to extract the type of data to do value hinting automatically

I doubt this is possible with raw clap since it's "stringy typed", no way to get type information. This might be possible with derive but it would be a very simple heuristic (is it path or not). This hint is not a big burden, anyway.

@CreepySkeleton
Copy link
Contributor

Also, can we do something about bash and fish too? I could try my hand at them later, but it would be great if we can support them in this PR.

I can try to improve bash later. no experience with fish, and I'm not really interested.

@pickfire
Copy link
Contributor

I use fish here but I don't seemed to see something equivalent (maybe I don't have much experience with completions), IIRC fish could use custom command to do these kind of completion hinting and there is no limit on what could be hint, this is both good news (it is very flexible since we can just inject some code) and bad news (there is just too many things we can hint) for us.

@benjumanji
Copy link

benjumanji commented Apr 11, 2020

I use fish here but I don't seemed to see something equivalent

As is the usual way with fish, rather than create lots of specialized options fish simply uses the same tools as the end user to provide useful functionality.

https://fishshell.com/docs/current/index.html#useful-functions-for-writing-completions

@pksunkara
Copy link
Member

Hey, sorry about this, but you should probably rebase on master since we touched clap_generate this week.

@intgr
Copy link
Contributor Author

intgr commented Apr 12, 2020

@benjumanji Actually yeah, I looked into fish already on Thursday and whipped up some rudimentary support. It's surprisingly sane compared to bash and zsh completion definitions.

@intgr intgr force-pushed the value-hints-for-zsh-completion branch from 288891b to 278ba99 Compare April 12, 2020 17:49
Copy link
Member

@pksunkara pksunkara left a comment

Choose a reason for hiding this comment

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

Yeah, that is why I use fish. I would have added support later on anyway, but it's not priority clap wise. Glad you could finish it.

Please write here once you consider the PR complete so that we can review. Thanks.

src/build/arg/mod.rs Outdated Show resolved Hide resolved
@intgr
Copy link
Contributor Author

intgr commented Apr 12, 2020

Yeah this is still WIP and not entirely ready for a review yet. Meanwhile, some points for bikeshedding:

  1. CreepySkeleton suggested that ValueHint::CommandWithArguments should automatically set AppSettings::TrailingVarArg and multiple(), which would make hints directly affect command parsing as well. So it seems it's not just a "hint" any more.

    Any suggestions what to rename ValueHint to? CompletionType seems bad for the same reason, it doesn't just affect completion. ValueKind? ...

  2. I'm not happy with the naming of ValueHint::CommandString (one string containing a whole shell command) and ValueHint::CommandWithArguments (command and arguments as separate arguments), suggestions welcome.

@CreepySkeleton
Copy link
Contributor

  1. Right, but allowing completions to disagree with actual implementation is also not very good. Well, this is not necessarily bad, we may try to sell it as "Help the generator but remember: enforcing correctness is up to you".

@intgr
Copy link
Contributor Author

intgr commented Apr 12, 2020

Yeah it makes sense, I'm just thinking if I should stop calling it a "hint" now.

@pksunkara
Copy link
Member

pksunkara commented Apr 12, 2020

Or, we could keep it as a hint, but add an assert that any arg hinted as ValueHint::CommandWithArguments is inside an app with setting TrailingVarArg. I recently made asserts easier to implement with #1797

@CreepySkeleton
Copy link
Contributor

I'd go for ValueKind and extensive documentation.

@benjumanji
Copy link

benjumanji commented Apr 13, 2020

I know my opinion means nothing here, but @intgr I'm am so excited for this to land! I have a new cli project that I kicked off last night and was going to pause it to work on this but you have basically already implemented everything I need.

EDIT: I also think ValueKind is a better name, and I am really for the embedding of a bit of shell to do fully dynamic completions. I don't think it will be reasonably possible to avoid this, and it isn't untrusted input or anything insane like that. At least I don't think it will be possible to avoid without clap itself basically reimplementing a ton of stuff, which seems like a really bad trade off.

@intgr
Copy link
Contributor Author

intgr commented Apr 15, 2020

@benjumanji I definitely see the value in custom completion functions or some other "escape hatch" mechanism, but it seems more complicated, less portable between shells and not something I need myself right now.

However, it's worth thinking ahead to what that API would look like, to make sure I'm not painting clap into a corner somehow with my current work. Personally I can't imagine any way they would interact, apart from completion generators which would prefer the custom completion over ValueHint if there is one.

@intgr intgr force-pushed the value-hints-for-zsh-completion branch from 278ba99 to 5d2a6dc Compare April 16, 2020 00:01
@intgr
Copy link
Contributor Author

intgr commented Jun 5, 2020

By the way, do completion test snapshots (e.g. static ZSH_SPECIAL_CMDS: &str in clap_generate/tests/completions.rs) have to be updated by hand or is there an easier way?

@pksunkara
Copy link
Member

No easier way for now :(

@CreepySkeleton
Copy link
Contributor

@intgr knock knock

@intgr intgr force-pushed the value-hints-for-zsh-completion branch from 553292a to 0df6c30 Compare July 18, 2020 11:24
@intgr
Copy link
Contributor Author

intgr commented Jul 18, 2020

Hey people. I'm on vacation now and hopefully with enough motivation to move this forward. Sorry for the wait. :)

One part of this MR that I have postponed is the YAML (de)serialization part, if anyone can give me some quick pointers -- where to start -- that would be great.

@CreepySkeleton
Copy link
Contributor

One part of this MR that I have postponed is the YAML (de)serialization part, if anyone can give me some quick pointers -- where to start -- that would be great.

Just implement FromStr for it (case insensitive) and then use yaml_str! as it's used in thereabouts.

@intgr intgr force-pushed the value-hints-for-zsh-completion branch from ae206b7 to e3b45ad Compare July 18, 2020 16:01
@intgr
Copy link
Contributor Author

intgr commented Jul 18, 2020

I ended up creating a new yaml_str_parse!() macro because the yaml_str! does not call parse() on the value. Or should I just inline the code instead of creating a new macro?

btw I also found it confusing that there are 2 different macros with the name yaml_str!

@intgr
Copy link
Contributor Author

intgr commented Jul 18, 2020

I think the initial feature set is now complete, feel free to start reviewing.

There are issues with the fish generator, which already existed before my changes:

  • It does not handle positional arguments at all -- only named arguments.
  • There are some odd completion issues with examples/value_hints.rs, which disappear if I remove the -n __fish_use_subcommand. It seems the generator shouldn't add it if the App doesn't use subcommands at all?

I'm not very interested in fixing these issues in the fish generator. Does that seem OK? Should I keep my fish changes in or back them out from this PR? I believe my changes don't make anything worse, but it's easier to notice these problems now.

@pksunkara pksunkara self-requested a review July 19, 2020 10:49
@intgr intgr force-pushed the value-hints-for-zsh-completion branch from d49374f to 3827ac0 Compare July 20, 2020 12:17
@intgr
Copy link
Contributor Author

intgr commented Jul 20, 2020

I also added a support matrix table to ValueHint documentation:

Hint zsh fish1
AnyPath Yes Yes
FilePath Yes Yes
DirPath Yes Yes
ExecutablePath Yes Partial
CommandName Yes Yes
CommandString Yes Partial
CommandWithArguments Yes
Username Yes Yes
Hostname Yes Yes
Url Yes
EmailAddress Yes

Footnotes

  1. fish completions currently only support named arguments (e.g. -o or --opt), not
    positional arguments.

@intgr
Copy link
Contributor Author

intgr commented Jul 31, 2020

Ping? Rebased to latest master.

Copy link
Contributor

@CreepySkeleton CreepySkeleton left a comment

Choose a reason for hiding this comment

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

Sorry for the delay. I'm not the best person to review this kind of PR because I have very shallow experience with completions and stuff, but others doesn't seem to be very interested, so here we go.

I say the PR is ready. Everything that's supposed to work does work (except for that wasn't working before), documentation is in place, and I think the code is good. Great job!

Could you please fix the test (we changed extensions) and ensure cargo fmt & clippy is applied? And the squash the commits.

There are some odd completion issues with examples/value_hints.rs, which disappear if I remove the -n __fish_use_subcommand. It seems the generator shouldn't add it if the App doesn't use subcommands at all?

That's right. It's not your problem until you say so.

tests/yaml.rs Outdated Show resolved Hide resolved
@intgr intgr force-pushed the value-hints-for-zsh-completion branch from dae4900 to c5b4e89 Compare August 6, 2020 19:16
Adds new method/attribute `Arg::value_hint`, taking a `ValueHint` enum
as argument. The hint can denote accepted values, for example: paths,
usernames, hostnames, commands, etc.

This initial implementation supports hints for the zsh and fish
completion generators, support for other shells can be added later.
@intgr
Copy link
Contributor Author

intgr commented Aug 6, 2020

Thanks for the feedback!

Doh, I did not notice that the tests broke with my last rebase. Fixed!

Are you happy with the naming of ValueHint as well? Earlier you preferred ValueKind.

@intgr intgr force-pushed the value-hints-for-zsh-completion branch from c5b4e89 to 64ee0f8 Compare August 6, 2020 19:21
@intgr intgr changed the title Add hinting of allowed value types for zsh completion Add hinting of arg value types for zsh/fish completion Aug 6, 2020
@pickfire
Copy link
Contributor

pickfire commented Aug 7, 2020

Can we add conflicts for fish shell? Is that not possible?

@CreepySkeleton
Copy link
Contributor

Are you happy with the naming of ValueHint as well? Earlier you preferred ValueKind.

That was then, this is now.

I now think that using "right" words in public API is more important than being 100% technically correct. What you did here, it was to allow hinting about the type first and foremost; stuff like assets and implications was brought after. It was a convince, not the intention. And the intention was to hint.

I'm pretty happy with how this went along.

bors r+

@bors
Copy link
Contributor

bors bot commented Aug 7, 2020

Build succeeded:

@bors bors bot merged commit 6492ae2 into clap-rs:master Aug 7, 2020
@intgr
Copy link
Contributor Author

intgr commented Aug 7, 2020

Great, will be looking forward to the next (beta) release :)

Copy link
Member

@pksunkara pksunkara left a comment

Choose a reason for hiding this comment

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

Great work! I was unfortunately busy to review this immediately. But I don't see any issues at all.

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.

6 participants