Skip to content

Commit 10d92e5

Browse files
authored
Prompt user with info about terminal config, add settings search by @id, and add sendToShell setting (#110987)
* something isn't right here * add parens and remove test z * something isn't right here * remove z * change name of setting, move promptChoices within conditional, use prefService instead of commandService and use set.has * only show prompt once and remove unnecessary conditional * don't show prompt if command is open terminal * don't alert on terminal open / close * Add another excluded command
1 parent 6f87c1c commit 10d92e5

File tree

8 files changed

+106
-22
lines changed

8 files changed

+106
-22
lines changed

src/vs/workbench/contrib/preferences/browser/settingsEditor2.ts

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -46,7 +46,7 @@ import { AbstractSettingRenderer, ISettingLinkClickEvent, ISettingOverrideClickE
4646
import { ISettingsEditorViewState, parseQuery, SearchResultIdx, SearchResultModel, SettingsTreeElement, SettingsTreeGroupChild, SettingsTreeGroupElement, SettingsTreeModel, SettingsTreeSettingElement } from 'vs/workbench/contrib/preferences/browser/settingsTreeModels';
4747
import { settingsTextInputBorder } from 'vs/workbench/contrib/preferences/browser/settingsWidgets';
4848
import { createTOCIterator, TOCTree, TOCTreeModel } from 'vs/workbench/contrib/preferences/browser/tocTree';
49-
import { CONTEXT_SETTINGS_EDITOR, CONTEXT_SETTINGS_ROW_FOCUS, CONTEXT_SETTINGS_SEARCH_FOCUS, CONTEXT_TOC_ROW_FOCUS, EXTENSION_SETTING_TAG, FEATURE_SETTING_TAG, IPreferencesSearchService, ISearchProvider, MODIFIED_SETTING_TAG, SETTINGS_EDITOR_COMMAND_CLEAR_SEARCH_RESULTS } from 'vs/workbench/contrib/preferences/common/preferences';
49+
import { CONTEXT_SETTINGS_EDITOR, CONTEXT_SETTINGS_ROW_FOCUS, CONTEXT_SETTINGS_SEARCH_FOCUS, CONTEXT_TOC_ROW_FOCUS, EXTENSION_SETTING_TAG, FEATURE_SETTING_TAG, ID_SETTING_TAG, IPreferencesSearchService, ISearchProvider, MODIFIED_SETTING_TAG, SETTINGS_EDITOR_COMMAND_CLEAR_SEARCH_RESULTS } from 'vs/workbench/contrib/preferences/common/preferences';
5050
import { IEditorGroup, IEditorGroupsService } from 'vs/workbench/services/editor/common/editorGroupsService';
5151
import { IPreferencesService, ISearchResult, ISettingsEditorModel, ISettingsEditorOptions, SettingsEditorOptions, SettingValueType } from 'vs/workbench/services/preferences/common/preferences';
5252
import { SettingsEditor2Input } from 'vs/workbench/services/preferences/common/preferencesEditorInput';
@@ -90,7 +90,7 @@ export class SettingsEditor2 extends EditorPane {
9090
private static CONFIG_SCHEMA_UPDATE_DELAYER = 500;
9191

9292
private static readonly SUGGESTIONS: string[] = [
93-
`@${MODIFIED_SETTING_TAG}`, '@tag:usesOnlineServices', '@tag:sync', `@${EXTENSION_SETTING_TAG}`, `@${FEATURE_SETTING_TAG}scm`, `@${FEATURE_SETTING_TAG}explorer`, `@${FEATURE_SETTING_TAG}search`, `@${FEATURE_SETTING_TAG}debug`, `@${FEATURE_SETTING_TAG}extensions`, `@${FEATURE_SETTING_TAG}terminal`, `@${FEATURE_SETTING_TAG}task`, `@${FEATURE_SETTING_TAG}problems`, `@${FEATURE_SETTING_TAG}output`, `@${FEATURE_SETTING_TAG}comments`, `@${FEATURE_SETTING_TAG}remote`, `@${FEATURE_SETTING_TAG}timeline`
93+
`@${MODIFIED_SETTING_TAG}`, '@tag:usesOnlineServices', '@tag:sync', `@${ID_SETTING_TAG}`, `@${EXTENSION_SETTING_TAG}`, `@${FEATURE_SETTING_TAG}scm`, `@${FEATURE_SETTING_TAG}explorer`, `@${FEATURE_SETTING_TAG}search`, `@${FEATURE_SETTING_TAG}debug`, `@${FEATURE_SETTING_TAG}extensions`, `@${FEATURE_SETTING_TAG}terminal`, `@${FEATURE_SETTING_TAG}task`, `@${FEATURE_SETTING_TAG}problems`, `@${FEATURE_SETTING_TAG}output`, `@${FEATURE_SETTING_TAG}comments`, `@${FEATURE_SETTING_TAG}remote`, `@${FEATURE_SETTING_TAG}timeline`
9494
];
9595

9696
private static shouldSettingUpdateFast(type: SettingValueType | SettingValueType[]): boolean {
@@ -1135,19 +1135,21 @@ export class SettingsEditor2 extends EditorPane {
11351135
this.viewState.tagFilters = new Set<string>();
11361136
this.viewState.extensionFilters = new Set<string>();
11371137
this.viewState.featureFilters = new Set<string>();
1138+
this.viewState.idFilters = new Set<string>();
11381139
if (query) {
11391140
const parsedQuery = parseQuery(query);
11401141
query = parsedQuery.query;
11411142
parsedQuery.tags.forEach(tag => this.viewState.tagFilters!.add(tag));
11421143
parsedQuery.extensionFilters.forEach(extensionId => this.viewState.extensionFilters!.add(extensionId));
11431144
parsedQuery.featureFilters!.forEach(feature => this.viewState.featureFilters!.add(feature));
1145+
parsedQuery.idFilters!.forEach(id => this.viewState.idFilters!.add(id));
11441146
}
11451147

11461148
if (query && query !== '@') {
11471149
query = this.parseSettingFromJSON(query) || query;
11481150
return this.triggerFilterPreferences(query);
11491151
} else {
1150-
if (this.viewState.tagFilters.size || this.viewState.extensionFilters.size || this.viewState.featureFilters.size) {
1152+
if (this.viewState.tagFilters.size || this.viewState.extensionFilters.size || this.viewState.featureFilters.size || this.viewState.idFilters.size) {
11511153
this.searchResultModel = this.createFilterModel();
11521154
} else {
11531155
this.searchResultModel = null;

src/vs/workbench/contrib/preferences/browser/settingsTreeModels.ts

Lines changed: 21 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@ export interface ISettingsEditorViewState {
2626
tagFilters?: Set<string>;
2727
extensionFilters?: Set<string>;
2828
featureFilters?: Set<string>;
29+
idFilters?: Set<string>;
2930
filterToCategory?: SettingsTreeGroupElement;
3031
}
3132

@@ -311,6 +312,13 @@ export class SettingsTreeSettingElement extends SettingsTreeElement {
311312
}
312313
});
313314
}
315+
316+
matchesAnyId(idFilters?: Set<string>): boolean {
317+
if (!idFilters || !idFilters.size) {
318+
return true;
319+
}
320+
return idFilters.has(this.setting.key);
321+
}
314322
}
315323

316324

@@ -641,7 +649,7 @@ export class SearchResultModel extends SettingsTreeModel {
641649
const isRemote = !!this.environmentService.remoteAuthority;
642650

643651
this.root.children = this.root.children
644-
.filter(child => child instanceof SettingsTreeSettingElement && child.matchesAllTags(this._viewState.tagFilters) && child.matchesScope(this._viewState.settingsTarget, isRemote) && child.matchesAnyExtension(this._viewState.extensionFilters) && this.containsValidFeature() ? child.matchesAnyFeature(this._viewState.featureFilters) : true);
652+
.filter(child => child instanceof SettingsTreeSettingElement && child.matchesAllTags(this._viewState.tagFilters) && child.matchesScope(this._viewState.settingsTarget, isRemote) && child.matchesAnyExtension(this._viewState.extensionFilters) && child.matchesAnyId(this._viewState.idFilters) && (this.containsValidFeature() ? child.matchesAnyFeature(this._viewState.featureFilters) : true));
645653

646654
if (this.newExtensionSearchResults && this.newExtensionSearchResults.filterMatches.length) {
647655
const resultExtensionIds = this.newExtensionSearchResults.filterMatches
@@ -687,16 +695,19 @@ export interface IParsedQuery {
687695
tags: string[];
688696
query: string;
689697
extensionFilters: string[];
698+
idFilters: string[];
690699
featureFilters: string[];
691700
}
692701

693702
const tagRegex = /(^|\s)@tag:("([^"]*)"|[^"]\S*)/g;
694703
const extensionRegex = /(^|\s)@ext:("([^"]*)"|[^"]\S*)?/g;
695704
const featureRegex = /(^|\s)@feature:("([^"]*)"|[^"]\S*)?/g;
705+
const idRegex = /(^|\s)@id:("([^"]*)"|[^"]\S*)?/g;
696706
export function parseQuery(query: string): IParsedQuery {
697707
const tags: string[] = [];
698708
const extensions: string[] = [];
699709
const features: string[] = [];
710+
const ids: string[] = [];
700711
query = query.replace(tagRegex, (_, __, quotedTag, tag) => {
701712
tags.push(tag || quotedTag);
702713
return '';
@@ -723,12 +734,21 @@ export function parseQuery(query: string): IParsedQuery {
723734
return '';
724735
});
725736

737+
query = query.replace(idRegex, (_, __, quotedId, id) => {
738+
const idRegex: string = id || quotedId;
739+
if (idRegex) {
740+
ids.push(...idRegex.split(',').map(s => s.trim()).filter(s => !isFalsyOrWhitespace(s)));
741+
}
742+
return '';
743+
});
744+
726745
query = query.trim();
727746

728747
return {
729748
tags,
730749
extensionFilters: extensions,
731750
featureFilters: features,
751+
idFilters: ids,
732752
query
733753
};
734754
}

src/vs/workbench/contrib/preferences/browser/tocTree.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -93,7 +93,8 @@ export class TOCTreeModel {
9393
return child.matchesScope(this._viewState.settingsTarget, isRemote) &&
9494
child.matchesAllTags(this._viewState.tagFilters) &&
9595
child.matchesAnyFeature(this._viewState.featureFilters) &&
96-
child.matchesAnyExtension(this._viewState.extensionFilters);
96+
child.matchesAnyExtension(this._viewState.extensionFilters) &&
97+
child.matchesAnyId(this._viewState.idFilters);
9798
}).length;
9899
}
99100
}

src/vs/workbench/contrib/preferences/common/preferences.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -71,4 +71,5 @@ export const KEYBINDINGS_EDITOR_SHOW_USER_KEYBINDINGS = 'keybindings.editor.show
7171
export const MODIFIED_SETTING_TAG = 'modified';
7272
export const EXTENSION_SETTING_TAG = 'ext:';
7373
export const FEATURE_SETTING_TAG = 'feature:';
74+
export const ID_SETTING_TAG = 'id:';
7475
export const KEYBOARD_LAYOUT_OPEN_PICKER = 'workbench.action.openKeyboardLayoutPicker';

src/vs/workbench/contrib/preferences/test/browser/settingsTreeModels.test.ts

Lines changed: 44 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -147,71 +147,79 @@ suite('SettingsTree', () => {
147147
<IParsedQuery>{
148148
tags: [],
149149
extensionFilters: [],
150+
query: '',
150151
featureFilters: [],
151-
query: ''
152+
idFilters: []
152153
});
153154

154155
testParseQuery(
155156
'@modified',
156157
<IParsedQuery>{
157158
tags: ['modified'],
158159
extensionFilters: [],
160+
query: '',
159161
featureFilters: [],
160-
query: ''
162+
idFilters: []
161163
});
162164

163165
testParseQuery(
164166
'@tag:foo',
165167
<IParsedQuery>{
166168
tags: ['foo'],
167169
extensionFilters: [],
170+
query: '',
168171
featureFilters: [],
169-
query: ''
172+
idFilters: []
170173
});
171174

172175
testParseQuery(
173176
'@modified foo',
174177
<IParsedQuery>{
175178
tags: ['modified'],
176179
extensionFilters: [],
180+
query: 'foo',
177181
featureFilters: [],
178-
query: 'foo'
182+
idFilters: []
179183
});
180184

181185
testParseQuery(
182186
'@tag:foo @modified',
183187
<IParsedQuery>{
184188
tags: ['foo', 'modified'],
185189
extensionFilters: [],
190+
query: '',
186191
featureFilters: [],
187-
query: ''
192+
idFilters: []
188193
});
189194

190195
testParseQuery(
191196
'@tag:foo @modified my query',
192197
<IParsedQuery>{
193198
tags: ['foo', 'modified'],
194199
extensionFilters: [],
200+
query: 'my query',
195201
featureFilters: [],
196-
query: 'my query'
202+
idFilters: []
197203
});
198204

199205
testParseQuery(
200206
'test @modified query',
201207
<IParsedQuery>{
202208
tags: ['modified'],
203209
extensionFilters: [],
210+
query: 'test query',
204211
featureFilters: [],
205-
query: 'test query'
212+
idFilters: []
206213
});
207214

208215
testParseQuery(
209216
'test @modified',
210217
<IParsedQuery>{
211218
tags: ['modified'],
212219
extensionFilters: [],
220+
query: 'test',
213221
featureFilters: [],
214-
query: 'test'
222+
idFilters: []
215223
});
216224

217225
testParseQuery(
@@ -221,32 +229,36 @@ suite('SettingsTree', () => {
221229
extensionFilters: [],
222230
query: 'query has @ for some reason',
223231
featureFilters: [],
232+
idFilters: []
224233
});
225234

226235
testParseQuery(
227236
'@ext:github.vscode-pull-request-github',
228237
<IParsedQuery>{
229238
tags: [],
230239
extensionFilters: ['github.vscode-pull-request-github'],
240+
query: '',
231241
featureFilters: [],
232-
query: ''
242+
idFilters: []
233243
});
234244

235245
testParseQuery(
236246
'@ext:github.vscode-pull-request-github,vscode.git',
237247
<IParsedQuery>{
238248
tags: [],
239249
extensionFilters: ['github.vscode-pull-request-github', 'vscode.git'],
250+
query: '',
240251
featureFilters: [],
241-
query: ''
252+
idFilters: []
242253
});
243254
testParseQuery(
244255
'@feature:scm',
245256
<IParsedQuery>{
246257
tags: [],
247258
extensionFilters: [],
248259
featureFilters: ['scm'],
249-
query: ''
260+
query: '',
261+
idFilters: []
250262
});
251263

252264
testParseQuery(
@@ -255,7 +267,27 @@ suite('SettingsTree', () => {
255267
tags: [],
256268
extensionFilters: [],
257269
featureFilters: ['scm', 'terminal'],
258-
query: ''
270+
query: '',
271+
idFilters: []
272+
});
273+
testParseQuery(
274+
'@id:files.autoSave',
275+
<IParsedQuery>{
276+
tags: [],
277+
extensionFilters: [],
278+
featureFilters: [],
279+
query: '',
280+
idFilters: ['files.autoSave']
281+
});
282+
283+
testParseQuery(
284+
'@id:files.autoSave,terminal.integrated.commandsToSkipShell',
285+
<IParsedQuery>{
286+
tags: [],
287+
extensionFilters: [],
288+
featureFilters: [],
289+
query: '',
290+
idFilters: ['files.autoSave', 'terminal.integrated.commandsToSkipShell']
259291
});
260292
});
261293
});

src/vs/workbench/contrib/terminal/browser/terminalInstance.ts

Lines changed: 26 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@ import { activeContrastBorder, scrollbarSliderActiveBackground, scrollbarSliderB
2525
import { ICssStyleCollector, IColorTheme, IThemeService, registerThemingParticipant } from 'vs/platform/theme/common/themeService';
2626
import { PANEL_BACKGROUND, SIDE_BAR_BACKGROUND } from 'vs/workbench/common/theme';
2727
import { TerminalWidgetManager } from 'vs/workbench/contrib/terminal/browser/widgets/widgetManager';
28-
import { IShellLaunchConfig, ITerminalProcessManager, KEYBINDING_CONTEXT_TERMINAL_TEXT_SELECTED, NEVER_MEASURE_RENDER_TIME_STORAGE_KEY, ProcessState, TERMINAL_VIEW_ID, IWindowsShellHelper, KEYBINDING_CONTEXT_TERMINAL_A11Y_TREE_FOCUS, INavigationMode, TitleEventSource, DEFAULT_COMMANDS_TO_SKIP_SHELL, ITerminalLaunchError, IProcessDataEvent, ITerminalDimensionsOverride } from 'vs/workbench/contrib/terminal/common/terminal';
28+
import { IShellLaunchConfig, ITerminalProcessManager, KEYBINDING_CONTEXT_TERMINAL_TEXT_SELECTED, NEVER_MEASURE_RENDER_TIME_STORAGE_KEY, ProcessState, TERMINAL_VIEW_ID, IWindowsShellHelper, KEYBINDING_CONTEXT_TERMINAL_A11Y_TREE_FOCUS, INavigationMode, TitleEventSource, DEFAULT_COMMANDS_TO_SKIP_SHELL, ITerminalLaunchError, IProcessDataEvent, ITerminalDimensionsOverride, SHOW_TERMINAL_CONFIG_PROMPT } from 'vs/workbench/contrib/terminal/common/terminal';
2929
import { ansiColorIdentifiers, TERMINAL_BACKGROUND_COLOR, TERMINAL_CURSOR_BACKGROUND_COLOR, TERMINAL_CURSOR_FOREGROUND_COLOR, TERMINAL_FOREGROUND_COLOR, TERMINAL_SELECTION_BACKGROUND_COLOR } from 'vs/workbench/contrib/terminal/common/terminalColorRegistry';
3030
import { TerminalConfigHelper } from 'vs/workbench/contrib/terminal/browser/terminalConfigHelper';
3131
import { TerminalLinkManager } from 'vs/workbench/contrib/terminal/browser/links/terminalLinkManager';
@@ -46,6 +46,7 @@ import { IEnvironmentVariableInfo } from 'vs/workbench/contrib/terminal/common/e
4646
import { TerminalLaunchHelpAction } from 'vs/workbench/contrib/terminal/browser/terminalActions';
4747
import { TypeAheadAddon } from 'vs/workbench/contrib/terminal/browser/terminalTypeAheadAddon';
4848
import { BrowserFeatures } from 'vs/base/browser/canIUse';
49+
import { IPreferencesService } from 'vs/workbench/services/preferences/common/preferences';
4950

5051
// How long in milliseconds should an average frame take to render for a notification to appear
5152
// which suggests the fallback DOM-based renderer
@@ -187,6 +188,7 @@ export class TerminalInstance extends Disposable implements ITerminalInstance {
187188
@IContextKeyService private readonly _contextKeyService: IContextKeyService,
188189
@IKeybindingService private readonly _keybindingService: IKeybindingService,
189190
@INotificationService private readonly _notificationService: INotificationService,
191+
@IPreferencesService private readonly _preferencesService: IPreferencesService,
190192
@IViewsService private readonly _viewsService: IViewsService,
191193
@IInstantiationService private readonly _instantiationService: IInstantiationService,
192194
@IClipboardService private readonly _clipboardService: IClipboardService,
@@ -542,9 +544,29 @@ export class TerminalInstance extends Disposable implements ITerminalInstance {
542544
return false;
543545
}
544546

545-
// Skip processing by xterm.js of keyboard events that resolve to commands described
546-
// within commandsToSkipShell
547-
if (resolveResult && this._skipTerminalCommands.some(k => k === resolveResult.commandId)) {
547+
// for keyboard events that resolve to commands described
548+
// within commandsToSkipShell, either alert or skip processing by xterm.js
549+
if (resolveResult && this._skipTerminalCommands.some(k => k === resolveResult.commandId) && !this._configHelper.config.sendKeybindingsToShell) {
550+
// don't alert when terminal is opened or closed
551+
if (this._storageService.getBoolean(SHOW_TERMINAL_CONFIG_PROMPT, StorageScope.GLOBAL, true) &&
552+
resolveResult.commandId !== 'workbench.action.terminal.toggleTerminal' &&
553+
resolveResult.commandId !== 'workbench.action.terminal.new' &&
554+
resolveResult.commandId !== 'workbench.action.togglePanel' &&
555+
resolveResult.commandId !== 'workbench.action.terminal.focus') {
556+
this._notificationService.prompt(
557+
Severity.Info,
558+
nls.localize('configure terminal settings', "Some keybindings are dispatched to the workbench by default."),
559+
[
560+
{
561+
label: nls.localize('configureTerminalSettings', "Configure Terminal Settings"),
562+
run: () => {
563+
this._preferencesService.openSettings(false, '@id:terminal.integrated.commandsToSkipShell,terminal.integrated.sendKeybindingsToShell,terminal.integrated.allowChords');
564+
}
565+
} as IPromptChoice
566+
]
567+
);
568+
this._storageService.store(SHOW_TERMINAL_CONFIG_PROMPT, false, StorageScope.GLOBAL, StorageTarget.USER);
569+
}
548570
event.preventDefault();
549571
return false;
550572
}

src/vs/workbench/contrib/terminal/common/terminal.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -50,7 +50,7 @@ export const KEYBINDING_CONTEXT_TERMINAL_PROCESS_SUPPORTED = new RawContextKey<b
5050

5151
export const IS_WORKSPACE_SHELL_ALLOWED_STORAGE_KEY = 'terminal.integrated.isWorkspaceShellAllowed';
5252
export const NEVER_MEASURE_RENDER_TIME_STORAGE_KEY = 'terminal.integrated.neverMeasureRenderTime';
53-
53+
export const SHOW_TERMINAL_CONFIG_PROMPT = 'terminal.integrated.showTerminalConfigPrompt';
5454
// The creation of extension host terminals is delayed by this value (milliseconds). The purpose of
5555
// this delay is to allow the terminal instance to initialize correctly and have its ID set before
5656
// trying to create the corressponding object on the ext host.
@@ -108,6 +108,7 @@ export interface ITerminalConfiguration {
108108
fontWeightBold: FontWeight;
109109
minimumContrastRatio: number;
110110
mouseWheelScrollSensitivity: number;
111+
sendKeybindingsToShell: boolean;
111112
// fontLigatures: boolean;
112113
fontSize: number;
113114
letterSpacing: number;

src/vs/workbench/contrib/terminal/common/terminalConfiguration.ts

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,11 @@ export const terminalConfiguration: IConfigurationNode = {
1515
title: localize('terminalIntegratedConfigurationTitle', "Integrated Terminal"),
1616
type: 'object',
1717
properties: {
18+
'terminal.integrated.sendKeybindingsToShell': {
19+
markdownDescription: localize('terminal.integrated.sendKeybindingsToShell', "Dispatches most keybindings to the terminal instead of the workbench, overriding `#terminal.integrated.commandsToSkipShell#`, which can be used alternatively for fine tuning."),
20+
type: 'boolean',
21+
default: false
22+
},
1823
'terminal.integrated.automationShell.linux': {
1924
markdownDescription: localize({
2025
key: 'terminal.integrated.automationShell.linux',

0 commit comments

Comments
 (0)