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

RFC for an argument completer base class #269

Open
wants to merge 3 commits into
base: master
Choose a base branch
from

Conversation

powercode
Copy link

No description provided.

/// </summary>
/// <param name="text">The text to complete</param>
/// <returns></returns>
protected virtual string QuoteCompletionText(string text) => text.Contains(" ") ? $@"""{text}""" : text;
Copy link
Member

Choose a reason for hiding this comment

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

What if the user is using a single quote?

Copy link
Contributor

@vexx32 vexx32 May 19, 2021

Choose a reason for hiding this comment

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

Oh gosh, had some flashbacks of working on argument completion for PSWordCloud. There's a bit more you need to handle for this kind of thing as well, depending on the colorful variety of things you may be expecting to handle as the completion results themselves. Let me find some code I wrote a while back... here:

https://github.com/vexx32/PSWordCloud/blob/main/Module/src/PSWordCloud/Completers/FontFamilyCompleter.cs

This one covers escaping things that need escaping, spaces, # characters in the completion results (I happened to end up having fonts with that character on my computer and it breaks completions terribly 😀) and probably a few other things. I haven't managed to break it yet.

The only thing I don't think it bothers to handle is whether the user used single quotes, it currently replaces them with double quotes instead I think. So it could be expanded on to detect that and act accordingly (less things need escaping there, etc).

Copy link
Author

Choose a reason for hiding this comment

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

I expect we have to turn this into a much more complete implementation. Maybe we can make use of the parser to determine what needs to be escaped?

@SteveL-MSFT
Copy link
Member

I like the idea of a base class to remove the need to have common code for every completer as I've had to write it for my own completers. One consideration is whether it makes sense to have this as an independent nuget assembly so it can be used for different versions of PS rather than the one it gets checked into.

@vexx32
Copy link
Contributor

vexx32 commented May 19, 2021

@SteveL-MSFT I like the idea of that, but I think it would open up too many possible dependency conflicts. If you have two modules that each depend on a different version of that completion assembly, you can easily end up only being able to load one of them into a session at a time.

Until there's a way to isolate dependencies like that properly I think it's best left in the core pwsh toolkit, and folks can simply declare a dependency on a minimum PS version as usual without much hassle.

@iSazonov
Copy link
Contributor

I see a point to put an end solution in separate nuget but it looks weird for base class.

@powercode
Copy link
Author

powercode commented May 20, 2021

There already is an function in CompletionCompeters

private static bool CompletionRequiresQuotes(string completion, bool escape)
{
    // If the tokenizer sees the completion as more than two tokens, or if there is some error, then
    // some form of quoting is necessary (if it's a variable, we'd need ${}, filenames would need [], etc.)

    Language.Token[] tokens;
    ParseError[] errors;
    Language.Parser.ParseInput(completion, out tokens, out errors);

    char[] charToCheck = escape ? new[] { '$', '[', ']', '`' } : new[] { '$', '`' };

    // Expect no errors and 2 tokens (1 is for our completion, the other is eof)
    // Or if the completion is a keyword, we ignore the errors
    bool requireQuote = !(errors.Length == 0 && tokens.Length == 2);
    if ((!requireQuote && tokens[0] is StringToken) ||
        (tokens.Length == 2 && (tokens[0].TokenFlags & TokenFlags.Keyword) != 0))
    {
        requireQuote = false;
        var value = tokens[0].Text;
        if (value.IndexOfAny(charToCheck) != -1)
            requireQuote = true;
    }

    return requireQuote;
}

This could be reused. The second parameter is named somewhat unfortunate: escape should probably be something like isGlobbingPath.

@powercode
Copy link
Author

I have updated the RFC with more robust quoting

Copy link
Contributor

@rjmholt rjmholt left a comment

Choose a reason for hiding this comment

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

I think making a base class available to deduplicate functionality is a good idea.

I suspect us trying to perfect the implementation in an RFC is going to miss the forest for the trees.

I wouldn't have necessarily said an RFC was needed for this, but given that we are discussing this in an RFC the parts I'd want us to agree on here are:

  • The name
  • The API and exposed members and what their contracts are
  • Possible future needs or directions for the class and how it might fit into the greater completion framework

@joeyaiello joeyaiello added WG-DevEx-SDK hosting PowerShell as a runtime, PowerShell's APIs, PowerShell Standard, or development of modules WG-Interactive-IntelliSense tab completion labels Jul 27, 2021
@bergmeister
Copy link

The DevEX working group briefly discussed this and we think that the implementation doesn't necessarily have to be a base class, which could lead to other problems like this: https://en.wikipedia.org/wiki/Fragile_base_class
Another alternative might be to expose an interface with extension methods or a mix of 'normal' methods and extension methods.
@powercode If you are still motivated to go ahead, I suggest to follow up on @rjmholt previous comment and from then on I think should be easier to get the ball rolling.

@powercode
Copy link
Author

powercode commented Sep 22, 2021

I'll tinker a bit with it and will get back with an update.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
WG-DevEx-SDK hosting PowerShell as a runtime, PowerShell's APIs, PowerShell Standard, or development of modules WG-Interactive-IntelliSense tab completion
Projects
None yet
Development

Successfully merging this pull request may close these issues.

7 participants