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

Extend Extension API with QuickPickSeparator Support #74967

Closed
go2sh opened this issue Jun 6, 2019 · 30 comments
Closed

Extend Extension API with QuickPickSeparator Support #74967

go2sh opened this issue Jun 6, 2019 · 30 comments
Assignees
Labels
api-finalization feature-request Request for new features or functionality on-testplan quick-pick Quick-pick widget issues
Milestone

Comments

@go2sh
Copy link
Contributor

go2sh commented Jun 6, 2019

With #21244 QuickPick Controls got the support for separators. This functionality is currently not available through the extensions API. For a nice look and feel, it would be great to make the separators available for extensions.

It seams to be not to hard to implement and I'am willing to do it, but I'am not sure from an API standpoint. Would you accept such a change?

The API could be changed in to ways:

  • Add a property to the QuickPickItem to show a seperator above, add this seperator in the main thread.
  • Add a Interface QuickPickSeparator to the extension api and change all occurrences of items to (T | QuickPickSeparator)[] or ReadonlyArray<T | QuickPickSeparator>
@go2sh go2sh changed the title Extended Extension API with QuickPick Seperator Support Extend Extension API with QuickPickSeparator Support Jun 6, 2019
@jrieken jrieken assigned chrmarti and unassigned jrieken Jun 6, 2019
@chrmarti chrmarti added feature-request Request for new features or functionality quick-pick Quick-pick widget issues labels Jun 6, 2019
@chrmarti
Copy link
Contributor

chrmarti commented Jun 6, 2019

Adding an interface similar to the internal one would make sense:

interface QuickPickSeparator {
	type: 'separator';
	label?: string;
}

PR welcome. When adding QuickPickSeparator to the existing API, we will need to make sure we don't break existing clients.

/fyi @jrieken

@jrieken
Copy link
Member

jrieken commented Jun 6, 2019

PR welcome

Not sure, API via PRs are always hairy because API gets discussed a lot.

@go2sh
Copy link
Contributor Author

go2sh commented Jun 6, 2019

@jrieken @chrmarti I create a draft for the API changes: go2sh@b49406c
Feel free to have a look and discuss it.

I'am also almost done with the changes for the extension host components.

@go2sh
Copy link
Contributor Author

go2sh commented Jun 6, 2019

Okay I'am done. I found two things to consider:

There are some vscode internal extensions, which use the name type already for a different usage. So it might conflict and thus break some stuff. How do you handle this case?

The type of activeItems and selectedItems is hard. If it's just T code like in the tests:

pick.activeItems = [pick.items[0]];

will break. To avoid this, the type could be T | QuickPickSeperator and the value could be filtered on setting.

Maybe Using a flag for the separator might be less destructive.

@eamodio
Copy link
Contributor

eamodio commented Jun 7, 2019

To me, adding a new property to the existing QuickPickItem is an easier way to go

Something like

export interface QuickPickItem {
	...
	beginGroup?: boolean;
}

or

export interface QuickPickItem {
	...
	beginGroup?: boolean | string;
}

If you want to be able to put a label on the separator

@jrieken
Copy link
Member

jrieken commented Jun 7, 2019

👏 I like that much better @eamodio. Maybe with "begin" but just "group" or "groupInformation"

@chrmarti
Copy link
Contributor

chrmarti commented Jun 7, 2019

We had it as a property on the items in our internal API and it led to complicated code when using it because some otherwise random item suddenly also represents a group of items. That is why I introduced the QuickPickSeparator interface when doing the new implementation.

@eamodio
Copy link
Contributor

eamodio commented Jun 7, 2019

The separator method, seems like it would be problematic with search in the quickpick (or do you just throw away all separators in that case?)

@jrieken with this:

export interface QuickPickItem {
	...
	group?: string;
}

Would you expect it would still behave as a beginning marker, or an actual grouping construct? While a grouping construct might be nice, it feels like it makes things harder on the QuickPick side if the items in a group aren't consecutive. Although completely out of scope here -- have a true grouping construct, like QuickPickGroup that also supported items (and ideally a promise of items), could be a great way of having async groups in the quickpick. For example, in some GitLens quick pick the commands are static, but other parts could be dynamically provided. But I'm getting out of scope for this 😄

@chrmarti
Copy link
Contributor

Search rearranges the items according to how well they match, so items are no longer in the original groups. Because of that we remove the separators. (See, e.g., the theme picker.)

@Zingam
Copy link

Zingam commented Nov 9, 2019

Is this still not implemented? I work on a feature for the CMake extension, which would really benefit of having an item separator to separate the toolchain kits from an action to rescan the system for kits.

@alefragnani
Copy link

Some comments from my #11468 (closed yesterday as #duplicate in favor of this one), which I think are relevant to be present here


Original request

The idea is to show items in the pick list, just like Go to Symbol, where you have some kind of groups of items (that appears when you type '@:' in the pick list)?

653e93ac-264a-11e6-8dda-4c0af353f65c


More details added 2 days ago

I was thinking about a group/category data attached to each QuickPickItem and the QuickPick itself would deal with grouping and counting the items in each group (when properly turned on with a new QuickPickOptions option). At first sight, I thought the groups (line separator and labels/counting) would be generated automatically.

But, if the proposed API (QuickPickItem and QuickPickSeparator) could give me the same power/flexibility as we see today in Go to Symbol command, it would be great.

Kapture VSCode QuickPick with Grouping

I just wonder how/if I should deal with the ordering, visibility and counting myself when the user filters the PickList, with the QuickPickSeparator. As you see, the counter changes, so should I "recreate/update" that QuickPickSeparator too?

I didn't dig in VS Code source to see how the internal API works today, but with the right documentation and samples, I guess it wouldn't be a problem.


Thank you

@eamodio
Copy link
Contributor

eamodio commented Apr 29, 2020

How about something like this:

export interface QuickPick {
	...
	groups?: QuickPickItemGroup[];
}

export interface QuickPickItemGroup {
	id: string;
	label?: string;
	options?: { showCount?: boolean }; // probably don't need to support this in v1
}

export interface QuickPickItem {
	...
	group?: string;
}

Where you could specify an ordered array of groups, with optional labels, and then apply the group id to each item via the group property. If groups isn't used or a group doesn't exist, then it just falls back the to "default group" which would always be the last "group"

This somewhat follows our menu pattern (with the exception of the defined groups, since we want to apply labels/other visual indicators.

/cc @chrmarti @jrieken

@jrieken
Copy link
Member

jrieken commented Apr 30, 2020

That seems very complicated. Given that a group is just a label, it could be just this

export interface QuickPickItem {
	group?: string; // or groupLabel, groupName, category, etc
}

@eamodio
Copy link
Contributor

eamodio commented Apr 30, 2020

Well without specified groups there wouldn't be a controlled ordering (especially if the label is also it's identifier). Nor the ability to have label-less groups (just a separator really).

@jrieken
Copy link
Member

jrieken commented Apr 30, 2020

I believe the order is always as it is defined inside the array and when we re-order we don't show groups. For groups without labels - I am not sure that's desirable.

@connor4312
Copy link
Member

I like the groups property approach, but that doesn't allow arbitrary/unnamed separators. In theory I could have an empty string group, but that would be the only one of that group I could have.

connor4312 added a commit that referenced this issue Sep 11, 2020
This PR removes the hook in node-debug's auto attach, and uses only
js-debug auto attach. As referenced in the linked issues, this involves
removing `debug.javascript.usePreviewAutoAttach` and collapsing
`debug.node.autoAttach` into `debug.javascript.autoAttachFilter`. The
latter option gains a new state: `disabled`. Since there's no runtime
cost to having auto attach around, there is now no distinct off versus
disabled state.

The status bar item and the `Debug: Toggle Auto Attach` command now
open a quickpick, which looks like this:

![](https://memes.peet.io/img/20-09-9d2b6c0a-8b3f-4481-b2df-0753c54ee02b.png)

The current setting value is selected in the quickpick. If there is a
workspace setting for auto attach, the quickpick toggle the setting
there by default. Otherwise (as in the image) it will target the user
settings. The targeting is more explicit and defaults to the user
instead of the workspace, which should help reduce confusion (#97087).
Selecting the "scope change" item will reopen the quickpick in that
location.

Aside from the extra options for the `disabled` state in js-debug's
contributions, there's no changes required to it or its interaction
with debug-auto-launch.

Side note: I really wanted a separator between the states and the
scope change item, but this is not possible from an extension #74967.

Fixes #105883
Fixes microsoft/vscode-js-debug#732 (the rest of it)
Fixes #105963
Fixes #97087
connor4312 added a commit that referenced this issue Sep 11, 2020
This PR removes the hook in node-debug's auto attach, and uses only
js-debug auto attach. As referenced in the linked issues, this involves
removing `debug.javascript.usePreviewAutoAttach` and collapsing
`debug.node.autoAttach` into `debug.javascript.autoAttachFilter`. The
latter option gains a new state: `disabled`. Since there's no runtime
cost to having auto attach around, there is now no distinct off versus
disabled state.

The status bar item and the `Debug: Toggle Auto Attach` command now
open a quickpick, which looks like this:

![](https://memes.peet.io/img/20-09-9d2b6c0a-8b3f-4481-b2df-0753c54ee02b.png)

The current setting value is selected in the quickpick. If there is a
workspace setting for auto attach, the quickpick toggle the setting
there by default. Otherwise (as in the image) it will target the user
settings. The targeting is more explicit and defaults to the user
instead of the workspace, which should help reduce confusion (#97087).
Selecting the "scope change" item will reopen the quickpick in that
location.

Aside from the extra options for the `disabled` state in js-debug's
contributions, there's no changes required to it or its interaction
with debug-auto-launch.

Side note: I really wanted a separator between the states and the
scope change item, but this is not possible from an extension #74967.

Fixes #105883
Fixes microsoft/vscode-js-debug#732 (the rest of it)
Fixes #105963
Fixes #97087
@TylerLeonhardt
Copy link
Member

TylerLeonhardt commented Nov 10, 2021

So with the discussion in API sync, I'm proposing:

	export interface QuickPickItem {
		kind?: string | { label: string; };
	}
  • The kind aligns nicely with our other APIs.
  • (not sure if needed right now...) The extra { label: string; } allows for future proofing of separators if we ever introduce like (color, a click listener, etc)
  • No breaking changes needed whatsoever

an example:

const a = await window.showQuickPick([
		{
			label: 'asdf',
			kind: 'asdf',

		},
		{
			label: 'asdf',
			kind: 'asdf'
		},
		{
			label: 'asdf',
			kind: 'asdf'
		},
		{
			label: 'asdf',
			kind: 'asdf'
		},
		{
			label: 'zxcv',
			kind: 'zxcv'
		},
		{
			label: 'zxcv',
			kind: 'zxcv'
		},
		{
			label: 'zxcv',
			kind: 'zxcv'
		},
		{
			label: 'star',
			kind: 'star'
		},
		{
			label: 'idk',
		},
	]);

image

@TylerLeonhardt
Copy link
Member

My conclusion is that this is very easy to use for the extension author and I was able to add these separators to existing quick picks with little effort.

I like the groups property approach, but that doesn't allow arbitrary/unnamed separators. In theory I could have an empty string group, but that would be the only one of that group I could have.

I missed this comment before and it brings up a good point... how would we add an arbitrary separator between two groups?

If we still encapsulate this in within kind I wonder if we could leverage the extra { label?: string } bag somehow to say "hey this is the start"

@TylerLeonhardt
Copy link
Member

So in standup @connor4312 and @Tyriar convinced me that kind is harder to use than a separator...

@connor4312 pointed out that the kind proposal for quickpick separators isn’t ideal because it would not be possible to have a single blank line separating two groups.

and @Tyriar pointed out that kind is ambiguous if you have a situation like this:

kind: ‘a’
kind: ‘b’
kind: ‘a’

we discussed this in the API sync as ‘doc-able’ but I do share the same feeling as he.

Further discussion with @jrieken left us with:

enum QuickPickItemKind {
  Default, 
  Separator
}

interface QuickPickItem {
  // when set to Separator the following properties are ignored....
  kind?: QuickPickItemKind
}

So that we didn't need a separate type just for separators and so we didn't use string enums or literal or types.

However, we can't go down that route because QuickPickItem#label can't be undefined... where in separators in can...

I also wanted to call out that @chrmarti mentioned a tree-like structure... which might have looked similar to what @connor4312 was suggesting here:
#74967 (comment)

@TylerLeonhardt
Copy link
Member

However, we can't go down that route because QuickPickItem#label can't be undefined... where in separators in can...

Going down this route... where QuickPickItem#label can just be empty string

@TylerLeonhardt
Copy link
Member

TylerLeonhardt commented Nov 16, 2021

Folks were happy in the API call so let's see how people feel about the API.

@TylerLeonhardt
Copy link
Member

Please take a look at the example in #137745 and don't be afraid to provide feedback here. Moving this to December to track finalization.

@TylerLeonhardt
Copy link
Member

Finalized in e15397d and eb416b4

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
api-finalization feature-request Request for new features or functionality on-testplan quick-pick Quick-pick widget issues
Projects
None yet
Development

No branches or pull requests

8 participants