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

A new mechanism for showing "did you mean" help. #10872

Merged
merged 7 commits into from Sep 29, 2020

Conversation

benjyw
Copy link
Sponsor Contributor

@benjyw benjyw commented Sep 28, 2020

Makes suggestions for unknown goals and unknown flags.

The old system for suggesting similar flag names was clever
but complex, and didn't always handle or display scopes in a
user-helpful way. So for example if the user used a
global flag in goal scope, we would show a suggestion like:
"Unknown flag --foobar on scope blah, did you mean --foobar".

This new implementation handles that case, and moves
the error message computation and display out of the
options system and into the local_pants_runner.py,
which has enough context to get suggested flags without
the gymnastics that the old code had to do.

This new code uses Python's built-in difflib to find similar
strings, which is sufficient for this use-case, and so we
can drop the python-Levenshtein dependency.

[ci skip-rust]

[ci skip-build-wheels]

Makes suggestions for unknown goals and unknown flags.

The old system for suggesting similar flag names was
complex, and didn't handle or display scopes in a
user-helpful way. So for example if the user used a
global flag in goal scope, we would show a suggestion
like: "Unknown flag --foobar, did you mean --foobar".

This new implementation handles that case, and moves
the error message computation and display out of the
options system and into the local_pants_runner.py,
which has enough context to do so.

[ci skip-rust]

[ci skip-build-wheels]
Copy link
Contributor

@Eric-Arellano Eric-Arellano left a comment

Choose a reason for hiding this comment

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

Excellent improvement, including the suggestion for invalid goals.

It'd be helpful if you could please add some basic smoke unit tests that this works correctly, including the edge case of global flags in the wrong position. This is critical to our UX and I'd hate for us to regress.

3rdparty/python/requirements.txt Show resolved Hide resolved
src/python/pants/option/errors.py Outdated Show resolved Hide resolved
src/python/pants/help/maybe_color.py Show resolved Hide resolved
src/python/pants/help/flag_help_printer.py Outdated Show resolved Hide resolved
src/python/pants/help/flag_help_printer.py Outdated Show resolved Hide resolved
@Eric-Arellano
Copy link
Contributor

Also thank you @cosmicexplorer for the initial implementation! That was a huge improvement over what we had before and carried us far.

# Rust tests and lints will be skipped. Delete if not intended.
[ci skip-rust]

# Building wheels and fs_util will be skipped. Delete if not intended.
[ci skip-build-wheels]
# Rust tests and lints will be skipped. Delete if not intended.
[ci skip-rust]

# Building wheels and fs_util will be skipped. Delete if not intended.
[ci skip-build-wheels]
# Rust tests and lints will be skipped. Delete if not intended.
[ci skip-rust]

# Building wheels and fs_util will be skipped. Delete if not intended.
[ci skip-build-wheels]
# Rust tests and lints will be skipped. Delete if not intended.
[ci skip-rust]

# Building wheels and fs_util will be skipped. Delete if not intended.
[ci skip-build-wheels]
# Rust tests and lints will be skipped. Delete if not intended.
[ci skip-rust]

# Building wheels and fs_util will be skipped. Delete if not intended.
[ci skip-build-wheels]
# Rust tests and lints will be skipped. Delete if not intended.
[ci skip-rust]

# Building wheels and fs_util will be skipped. Delete if not intended.
[ci skip-build-wheels]
Copy link
Contributor

@cosmicexplorer cosmicexplorer left a comment

Choose a reason for hiding this comment

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

I really like the idea and the implementation of this change! Great work.

@@ -56,7 +57,17 @@ def print_hint() -> None:
elif isinstance(self._help_request, OptionsHelp):
self._print_options_help()
elif isinstance(self._help_request, UnknownGoalHelp):
print("Unknown goals: {}".format(", ".join(self._help_request.unknown_goals)))
# Only print help and suggestions for the first unknown goal.
# It gets confusing to try and show suggestions for multiple cases.
Copy link
Contributor

Choose a reason for hiding this comment

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

Good move. The user can recursively whittle down unknown goals until the whole command line makes sense.

src/python/pants/help/help_printer.py Show resolved Hide resolved
class MaybeColor:
"""A mixin to allow classes to optionally colorize their output."""

def __init__(self, color: bool) -> None:
Copy link
Contributor

Choose a reason for hiding this comment

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

Would we ever want to make this color configurable? Emacs registers faces (see https://www.gnu.org/software/emacs/manual/html_node/elisp/Defining-Faces.html) which allow e.g. for the user to modify colors if their terminal doesn't interact well with the default. That seems like it would mostly just require turning this into a subsystem.

Copy link
Contributor

Choose a reason for hiding this comment

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

Not a change I would expect in this PR.

Copy link
Contributor

Choose a reason for hiding this comment

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

I could maybe see wanting that. But I think it would need to be a booststrap subsystem because Rust uses this option too. Right now, bootstrap options require a ton of ceremony and must be global options, so I think we'd want to improve that first.

We'd also need to stop using ansicolors to instead use another library (or honestly just us vendoring the relevant parts; it's a tiny amount of code). We probably need to do this soon anyways, as ansicolors hasn't been updated in some time and will break once 3.10 comes out afaict.

@coveralls
Copy link

Coverage Status

Coverage remained the same at 0.0% when pulling 9379ea6 on benjyw:did_you_mean into 5f46286 on pantsbuild:master.

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.

None yet

4 participants