Skip to content

Move CompletionSourceList extension methods to CompletionSourceList #1910

Closed as not planned

Description

@jonsequitur
    // All should move to instance methods.
    public static class CompletionSourceExtensions 
    {
        public static void Add(this CompletionSourceList completionSources, Func<CompletionContext,IEnumerable<string>> complete);
        public static void Add(this CompletionSourceList completionSources, CompletionDelegate complete);
        public static void Add(this CompletionSourceList completionSources, string[] completions);
    }
 

Activity

  1. self-assigned this
    on Nov 3, 2022
  2. adamsitnik commented on Nov 3, 2022

    @adamsitnik
    Member

    Currently we have three different ways of adding completions:

    1. Via CompletionSourceExtensions which currently can be used only with argument (nothing else exposes a collection of completions): arument.Completions.Add(complete).
    2. Via ArgumentExtensions which delegates to CompletionSourceExtensions:

    argument.Completions.Add(values);

    but returns a reference to Argument to allow for chaining of fluent API calls:

    var argument = new Argument<string>()
        .AddCompletions(expectedSuggestions);
    1. Via OptionExtensions which also delegate to CompletionSourceExtensions:

    option.Argument.Completions.Add(values);

    and also returns the reference to Option so it can be used for chaining.

    If we wanted to give up on chaining, we could have a single instance method on Argument:

    argument.AddCompletions(x);
    option.Argument.AddCompletions(x);

    but we most likely don't want that. I think that we should just remove CompletionSourceExtensions and make Option.AddCompletions just delegate to Argument.AddCompletions.

    @jonsequitur thoughts?

  3. jonsequitur commented on Nov 3, 2022

    @jonsequitur
    ContributorAuthor

    Since completions can also be cleared, would it be clearer to have all completion-related functionality on a Completions property, e.g. Option.Completions.Add(x)?

    Note that Option.Argument is internal so we'd want a way to access completions directly via Option in any case. (See #1884).

  4. adamsitnik commented on Nov 3, 2022

    @adamsitnik
    Member

    remove CompletionSourceExtensions

    I can see that doing this would break some stuff. The following syntax:

    new Argument<string>
    {
    Completions = { _ => new[] { "vegetable", "mineral", "animal" } }
    }

    would stop working, as it maps to:

    Argument<string> argument = new Argument<string>();
    argument.Completions.Add((CompletionContext _) => new string[3] { "vegetable", "mineral", "animal" });

    to get it working we would need to specify the types in explicit way:

    new Argument<string>
        {
            Completions = { _ => new[] { new CompletionItem("vegetable"), new CompletionItem("mineral"), new CompletionItem("animal") } }
        }
  5. adamsitnik commented on Nov 3, 2022

    @adamsitnik
    Member

    have all completion-related functionality on a Completions property

    It would, but we would lose the fluent API syntax with chaining (assuming we would remove the extension methods and added a new property to Option)

  6. jonsequitur commented on Nov 3, 2022

    @jonsequitur
    ContributorAuthor

    Fluent APIs aren't the norm in the System namespace anyway (though people do ask for them often.)

  7. added this to the 2.0 GA milestone on Nov 9, 2022
  8. adamsitnik commented on Nov 14, 2022

    @adamsitnik
    Member

    We have removed CompletionSourceList in #1946 and we are now using ICollection<Func<CompletionContext, IEnumerable<CompletionItem>>>, so it's impossible to move these extensions methods anywhere. But they allow for using following C# syntax:

    new Argument<DayOfWeek>
    {
        Completions = { "mon", "tues", "wed", "thur", "fri", "sat", "sun" }
    }

    But... I am not sure if this feature is discoverable as Completions is not a collection of strings and seeing this work is honestly surprising to me. Also, AcceptOnlyFromAmong seems to be the best choice for such scenarios, since it does not only provide completion suggestions but also validates the input.

    @jonsequitur @jozkee What do you think about removing these extensions methods and promoting AcceptOnlyFromAmong instead?

  9. KalleOlaviNiemitalo commented on Nov 14, 2022

    @KalleOlaviNiemitalo

    That syntax creates a separate one-element array and completion source for each string, bloating the IL somewhat. SharpLab

    Doubling the braces like Completions = { { "mon", "tues", "wed", "thur", "fri", "sat", "sun" } } simplifies the IL quite a lot. SharpLab

    I think I'd prefer removing the params and requiring callers to explicitly create the array Completions = { new[] { "mon", "tues", "wed", "thur", "fri", "sat", "sun" } }. SharpLab

  10. jonsequitur commented on Nov 14, 2022

    @jonsequitur
    ContributorAuthor

    I think I'd prefer removing the params and requiring callers to explicitly create the array

    I agree.

  11. adamsitnik commented on Nov 16, 2022

    @adamsitnik
    Member

    I think I'd prefer removing the params and requiring callers to explicitly create the array

    This does not answer my question:

    What do you think about removing these extensions methods and promoting AcceptOnlyFromAmong instead?

    AcceptOnlyFromAmong sets the right completions but it also verifies that parsed values belong to the set of legal values.

  12. jonsequitur commented on Nov 16, 2022

    @jonsequitur
    ContributorAuthor

    Completions and validations are often orthogonal. For example, a completion source might contain a set of legal values from the file system, but these might not be the only acceptable values.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

Labels

Type

No type

Projects

No projects

    Milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions