mirror of
https://github.com/ckaczor/azuredatastudio.git
synced 2026-03-31 17:20:28 -04:00
Refresh master with initial release/0.24 snapshot (#332)
* Initial port of release/0.24 source code * Fix additional headers * Fix a typo in launch.json
This commit is contained in:
@@ -251,6 +251,10 @@ export class KeybindingsEditor extends BaseEditor implements IKeybindingsEditor
|
||||
this.searchWidget.focus();
|
||||
}
|
||||
|
||||
clearSearchResults(): void {
|
||||
this.searchWidget.clear();
|
||||
}
|
||||
|
||||
showConflicts(keybindingEntry: IKeybindingItemEntry): TPromise<any> {
|
||||
const value = `"${keybindingEntry.keybindingItem.keybinding.getAriaLabel()}"`;
|
||||
if (value !== this.searchWidget.getValue()) {
|
||||
@@ -517,6 +521,12 @@ export class KeybindingsEditor extends BaseEditor implements IKeybindingsEditor
|
||||
emptyFilters: this.getLatestEmptyFiltersForTelemetry()
|
||||
};
|
||||
this.latestEmptyFilters = [];
|
||||
/* __GDPR__
|
||||
"keybindings.filter" : {
|
||||
"filter": { "classification": "CustomerContent", "purpose": "FeatureInsight" },
|
||||
"emptyFilters" : { "classification": "SystemMetaData", "purpose": "FeatureInsight" }
|
||||
}
|
||||
*/
|
||||
this.telemetryService.publicLog('keybindings.filter', data);
|
||||
}
|
||||
}
|
||||
@@ -531,6 +541,7 @@ export class KeybindingsEditor extends BaseEditor implements IKeybindingsEditor
|
||||
}
|
||||
|
||||
private reportKeybindingAction(action: string, command: string, keybinding: ResolvedKeybinding | string): void {
|
||||
// __GDPR__TODO__ Need to move off dynamic event names and properties as they cannot be registered statically
|
||||
this.telemetryService.publicLog(action, { command, keybinding: keybinding ? (typeof keybinding === 'string' ? keybinding : keybinding.getUserSettingsLabel()) : '' });
|
||||
}
|
||||
|
||||
@@ -712,16 +723,21 @@ class CommandColumn extends Column {
|
||||
const commandDefaultLabelMatched = !!keybindingItemEntry.commandDefaultLabelMatches;
|
||||
DOM.toggleClass(this.commandColumn, 'vertical-align-column', commandIdMatched || commandDefaultLabelMatched);
|
||||
this.commandColumn.setAttribute('aria-label', this.getAriaLabel(keybindingItemEntry));
|
||||
let commandLabel: HighlightedLabel;
|
||||
if (keybindingItem.commandLabel) {
|
||||
const commandLabel = new HighlightedLabel(this.commandColumn);
|
||||
commandLabel = new HighlightedLabel(this.commandColumn);
|
||||
commandLabel.set(keybindingItem.commandLabel, keybindingItemEntry.commandLabelMatches);
|
||||
commandLabel.element.title = keybindingItem.command;
|
||||
}
|
||||
if (keybindingItemEntry.commandDefaultLabelMatches) {
|
||||
new HighlightedLabel(DOM.append(this.commandColumn, $('.command-default-label'))).set(keybindingItem.commandDefaultLabel, keybindingItemEntry.commandDefaultLabelMatches);
|
||||
commandLabel = new HighlightedLabel(DOM.append(this.commandColumn, $('.command-default-label')));
|
||||
commandLabel.set(keybindingItem.commandDefaultLabel, keybindingItemEntry.commandDefaultLabelMatches);
|
||||
}
|
||||
if (keybindingItemEntry.commandIdMatches || !keybindingItem.commandLabel) {
|
||||
new HighlightedLabel(DOM.append(this.commandColumn, $('.code'))).set(keybindingItem.command, keybindingItemEntry.commandIdMatches);
|
||||
commandLabel = new HighlightedLabel(DOM.append(this.commandColumn, $('.code')));
|
||||
commandLabel.set(keybindingItem.command, keybindingItemEntry.commandIdMatches);
|
||||
}
|
||||
if (commandLabel) {
|
||||
commandLabel.element.title = keybindingItem.command;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -73,18 +73,38 @@
|
||||
padding-right: 32px;
|
||||
}
|
||||
|
||||
.settings-header-widget > .settings-count-widget {
|
||||
.settings-header-widget > .settings-search-controls > .settings-count-widget {
|
||||
margin: 6px 0px;
|
||||
padding: 0px 8px;
|
||||
position: absolute;
|
||||
right: 10px;
|
||||
border-radius: 2px;
|
||||
float: left;
|
||||
}
|
||||
|
||||
.settings-header-widget > .settings-count-widget.hide {
|
||||
.settings-header-widget > .settings-search-controls {
|
||||
position: absolute;
|
||||
right: 10px;
|
||||
}
|
||||
|
||||
.settings-header-widget > .settings-search-controls > .settings-count-widget.hide {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.settings-header-widget > .settings-search-controls > .prefs-fuzzy-search-toggle {
|
||||
margin: 5px 3px 5px 0px;
|
||||
}
|
||||
|
||||
.settings-header-widget > .settings-search-controls > .prefs-fuzzy-search-toggle.hidden {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.vs .settings-header-widget > .settings-search-controls > .prefs-fuzzy-search-toggle {
|
||||
background: url('regex.svg') center center no-repeat;
|
||||
}
|
||||
|
||||
.vs-dark .settings-header-widget > .settings-search-controls > .prefs-fuzzy-search-toggle {
|
||||
background: url('regex-dark.svg') center center no-repeat;
|
||||
}
|
||||
|
||||
.settings-header-widget > .settings-search-container {
|
||||
flex: 1;
|
||||
}
|
||||
@@ -106,8 +126,13 @@
|
||||
padding-left:10px;
|
||||
}
|
||||
|
||||
.monaco-editor .view-zones > .settings-header-widget {
|
||||
z-index: 1;
|
||||
}
|
||||
|
||||
.monaco-editor .settings-header-widget .title-container {
|
||||
display: flex;
|
||||
user-select: none;
|
||||
}
|
||||
|
||||
.vs .monaco-editor .settings-header-widget .title-container {
|
||||
@@ -130,6 +155,16 @@
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
.monaco-editor .settings-header-widget .title-container .settings-header-fuzzy-link {
|
||||
margin-left: 4px;
|
||||
text-decoration: underline;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.monaco-editor .settings-header-widget .title-container .settings-header-fuzzy-link.hidden {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.monaco-editor .settings-group-title-widget {
|
||||
z-index: 1;
|
||||
}
|
||||
|
||||
@@ -0,0 +1 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16"><polygon fill="#2d2d30" points="13.64,7.396 12.169,2.898 10.706,3.761 11.087,2 6.557,2 6.936,3.762 5.473,2.898 4,7.396 5.682,7.554 4.513,8.561 5.013,9 2,9 2,14 7,14 7,10.747 7.978,11.606 8.82,9.725 9.661,11.602 13.144,8.562 11.968,7.554"/><g fill="#C5C5C5"><path d="M12.301 6.518l-2.772.262 2.086 1.788-1.594 1.392-1.201-2.682-1.201 2.682-1.583-1.392 2.075-1.788-2.771-.262.696-2.126 2.358 1.392-.599-2.784h2.053l-.602 2.783 2.359-1.392.696 2.127z"/><rect x="3" y="10" width="3" height="3"/></g></svg>
|
||||
|
After Width: | Height: | Size: 564 B |
@@ -0,0 +1 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16"><polygon fill="#F6F6F6" points="13.64,7.396 12.169,2.898 10.706,3.761 11.087,2 6.557,2 6.936,3.762 5.473,2.898 4,7.396 5.682,7.554 4.513,8.561 5.013,9 2,9 2,14 7,14 7,10.747 7.978,11.606 8.82,9.725 9.661,11.602 13.144,8.562 11.968,7.554"/><g fill="#424242"><path d="M12.301 6.518l-2.772.262 2.086 1.788-1.594 1.392-1.201-2.682-1.201 2.682-1.583-1.392 2.075-1.788-2.771-.262.696-2.126 2.358 1.392-.599-2.784h2.053l-.602 2.783 2.359-1.392.696 2.127z"/><rect x="3" y="10" width="3" height="3"/></g></svg>
|
||||
|
After Width: | Height: | Size: 564 B |
@@ -8,35 +8,36 @@ import * as nls from 'vs/nls';
|
||||
import URI from 'vs/base/common/uri';
|
||||
import { Registry } from 'vs/platform/registry/common/platform';
|
||||
import { KeybindingsRegistry } from 'vs/platform/keybinding/common/keybindingsRegistry';
|
||||
import { IWorkbenchActionRegistry, Extensions } from 'vs/workbench/common/actionRegistry';
|
||||
import { EditorInput, IEditorRegistry, Extensions as EditorExtensions, IEditorInputFactory } from 'vs/workbench/common/editor';
|
||||
import { EditorDescriptor } from 'vs/workbench/browser/parts/editor/baseEditor';
|
||||
import { IWorkbenchActionRegistry, Extensions } from 'vs/workbench/common/actions';
|
||||
import { EditorInput, IEditorInputFactory, IEditorInputFactoryRegistry, Extensions as EditorInputExtensions } from 'vs/workbench/common/editor';
|
||||
import { SyncActionDescriptor } from 'vs/platform/actions/common/actions';
|
||||
import { registerSingleton } from 'vs/platform/instantiation/common/extensions';
|
||||
import { KeyMod, KeyChord, KeyCode } from 'vs/base/common/keyCodes';
|
||||
import { SyncDescriptor } from 'vs/platform/instantiation/common/descriptors';
|
||||
import { DefaultPreferencesEditorInput, PreferencesEditor, PreferencesEditorInput } from 'vs/workbench/parts/preferences/browser/preferencesEditor';
|
||||
import { KeybindingsEditor, KeybindingsEditorInput } from 'vs/workbench/parts/preferences/browser/keybindingsEditor';
|
||||
import { OpenGlobalSettingsAction, OpenGlobalKeybindingsAction, OpenGlobalKeybindingsFileAction, OpenWorkspaceSettingsAction, OpenFolderSettingsAction, ConfigureLanguageBasedSettingsAction } from 'vs/workbench/parts/preferences/browser/preferencesActions';
|
||||
import { OpenGlobalSettingsAction, OpenGlobalKeybindingsAction, OpenGlobalKeybindingsFileAction, OpenWorkspaceSettingsAction, OpenFolderSettingsAction, ConfigureLanguageBasedSettingsAction, OPEN_FOLDER_SETTINGS_COMMAND } from 'vs/workbench/parts/preferences/browser/preferencesActions';
|
||||
import {
|
||||
IPreferencesService, IKeybindingsEditor, CONTEXT_KEYBINDING_FOCUS, CONTEXT_KEYBINDINGS_EDITOR, CONTEXT_KEYBINDINGS_SEARCH_FOCUS, KEYBINDINGS_EDITOR_COMMAND_DEFINE, KEYBINDINGS_EDITOR_COMMAND_REMOVE, KEYBINDINGS_EDITOR_COMMAND_SEARCH,
|
||||
KEYBINDINGS_EDITOR_COMMAND_COPY, KEYBINDINGS_EDITOR_COMMAND_RESET, KEYBINDINGS_EDITOR_COMMAND_SHOW_CONFLICTS, KEYBINDINGS_EDITOR_COMMAND_FOCUS_KEYBINDINGS
|
||||
KEYBINDINGS_EDITOR_COMMAND_COPY, KEYBINDINGS_EDITOR_COMMAND_RESET, KEYBINDINGS_EDITOR_COMMAND_SHOW_CONFLICTS, KEYBINDINGS_EDITOR_COMMAND_FOCUS_KEYBINDINGS, KEYBINDINGS_EDITOR_COMMAND_CLEAR_SEARCH_RESULTS
|
||||
} from 'vs/workbench/parts/preferences/common/preferences';
|
||||
import { PreferencesService } from 'vs/workbench/parts/preferences/browser/preferencesService';
|
||||
import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation';
|
||||
import { IInstantiationService, ServicesAccessor } from 'vs/platform/instantiation/common/instantiation';
|
||||
import { IWorkbenchContributionsRegistry, Extensions as WorkbenchExtensions } from 'vs/workbench/common/contributions';
|
||||
import { PreferencesContentProvider } from 'vs/workbench/parts/preferences/common/preferencesContentProvider';
|
||||
import { PreferencesContribution } from 'vs/workbench/parts/preferences/common/preferencesContribution';
|
||||
import { ContextKeyExpr } from 'vs/platform/contextkey/common/contextkey';
|
||||
import { IWorkbenchEditorService } from 'vs/workbench/services/editor/common/editorService';
|
||||
import { CommandsRegistry } from 'vs/platform/commands/common/commands';
|
||||
import { IWorkspaceFolder } from 'vs/platform/workspace/common/workspace';
|
||||
import { IEditorRegistry, EditorDescriptor, Extensions as EditorExtensions } from 'vs/workbench/browser/editor';
|
||||
|
||||
registerSingleton(IPreferencesService, PreferencesService);
|
||||
|
||||
Registry.as<IEditorRegistry>(EditorExtensions.Editors).registerEditor(
|
||||
new EditorDescriptor(
|
||||
PreferencesEditor,
|
||||
PreferencesEditor.ID,
|
||||
nls.localize('defaultPreferencesEditor', "Default Preferences Editor"),
|
||||
'vs/workbench/parts/preferences/browser/preferencesEditor',
|
||||
'PreferencesEditor'
|
||||
nls.localize('defaultPreferencesEditor', "Default Preferences Editor")
|
||||
),
|
||||
[
|
||||
new SyncDescriptor(PreferencesEditorInput)
|
||||
@@ -45,10 +46,9 @@ Registry.as<IEditorRegistry>(EditorExtensions.Editors).registerEditor(
|
||||
|
||||
Registry.as<IEditorRegistry>(EditorExtensions.Editors).registerEditor(
|
||||
new EditorDescriptor(
|
||||
KeybindingsEditor,
|
||||
KeybindingsEditor.ID,
|
||||
nls.localize('keybindingsEditor', "Keybindings Editor"),
|
||||
'vs/workbench/parts/preferences/browser/keybindingsEditor',
|
||||
'KeybindingsEditor'
|
||||
nls.localize('keybindingsEditor', "Keybindings Editor")
|
||||
),
|
||||
[
|
||||
new SyncDescriptor(KeybindingsEditorInput)
|
||||
@@ -73,7 +73,7 @@ class PreferencesEditorInputFactory implements IEditorInputFactory {
|
||||
const input = <PreferencesEditorInput>editorInput;
|
||||
|
||||
if (input.details && input.master) {
|
||||
const registry = Registry.as<IEditorRegistry>(EditorExtensions.Editors);
|
||||
const registry = Registry.as<IEditorInputFactoryRegistry>(EditorInputExtensions.EditorInputFactories);
|
||||
const detailsInputFactory = registry.getEditorInputFactory(input.details.getTypeId());
|
||||
const masterInputFactory = registry.getEditorInputFactory(input.master.getTypeId());
|
||||
|
||||
@@ -100,7 +100,7 @@ class PreferencesEditorInputFactory implements IEditorInputFactory {
|
||||
public deserialize(instantiationService: IInstantiationService, serializedEditorInput: string): EditorInput {
|
||||
const deserialized: ISerializedPreferencesEditorInput = JSON.parse(serializedEditorInput);
|
||||
|
||||
const registry = Registry.as<IEditorRegistry>(EditorExtensions.Editors);
|
||||
const registry = Registry.as<IEditorInputFactoryRegistry>(EditorInputExtensions.EditorInputFactories);
|
||||
const detailsInputFactory = registry.getEditorInputFactory(deserialized.detailsTypeId);
|
||||
const masterInputFactory = registry.getEditorInputFactory(deserialized.masterTypeId);
|
||||
|
||||
@@ -155,9 +155,9 @@ class DefaultPreferencesEditorInputFactory implements IEditorInputFactory {
|
||||
}
|
||||
}
|
||||
|
||||
Registry.as<IEditorRegistry>(EditorExtensions.Editors).registerEditorInputFactory(PreferencesEditorInput.ID, PreferencesEditorInputFactory);
|
||||
Registry.as<IEditorRegistry>(EditorExtensions.Editors).registerEditorInputFactory(DefaultPreferencesEditorInput.ID, DefaultPreferencesEditorInputFactory);
|
||||
Registry.as<IEditorRegistry>(EditorExtensions.Editors).registerEditorInputFactory(KeybindingsEditorInput.ID, KeybindingsEditorInputFactory);
|
||||
Registry.as<IEditorInputFactoryRegistry>(EditorInputExtensions.EditorInputFactories).registerEditorInputFactory(PreferencesEditorInput.ID, PreferencesEditorInputFactory);
|
||||
Registry.as<IEditorInputFactoryRegistry>(EditorInputExtensions.EditorInputFactories).registerEditorInputFactory(DefaultPreferencesEditorInput.ID, DefaultPreferencesEditorInputFactory);
|
||||
Registry.as<IEditorInputFactoryRegistry>(EditorInputExtensions.EditorInputFactories).registerEditorInputFactory(KeybindingsEditorInput.ID, KeybindingsEditorInputFactory);
|
||||
|
||||
// Contribute Global Actions
|
||||
const category = nls.localize('preferences', "Preferences");
|
||||
@@ -246,4 +246,20 @@ KeybindingsRegistry.registerCommandAndKeybindingRule({
|
||||
}
|
||||
});
|
||||
|
||||
Registry.as<IWorkbenchContributionsRegistry>(WorkbenchExtensions.Workbench).registerWorkbenchContribution(PreferencesContentProvider);
|
||||
KeybindingsRegistry.registerCommandAndKeybindingRule({
|
||||
id: KEYBINDINGS_EDITOR_COMMAND_CLEAR_SEARCH_RESULTS,
|
||||
weight: KeybindingsRegistry.WEIGHT.workbenchContrib(),
|
||||
when: ContextKeyExpr.and(CONTEXT_KEYBINDINGS_EDITOR, CONTEXT_KEYBINDINGS_SEARCH_FOCUS),
|
||||
primary: KeyCode.Escape,
|
||||
handler: (accessor, args: any) => {
|
||||
const editor = accessor.get(IWorkbenchEditorService).getActiveEditor() as IKeybindingsEditor;
|
||||
editor.clearSearchResults();
|
||||
}
|
||||
});
|
||||
|
||||
Registry.as<IWorkbenchContributionsRegistry>(WorkbenchExtensions.Workbench).registerWorkbenchContribution(PreferencesContribution);
|
||||
|
||||
CommandsRegistry.registerCommand(OPEN_FOLDER_SETTINGS_COMMAND, function (accessor: ServicesAccessor, args?: IWorkspaceFolder) {
|
||||
const preferencesService = accessor.get(IPreferencesService);
|
||||
return preferencesService.openFolderSettings(args.uri);
|
||||
});
|
||||
@@ -8,11 +8,13 @@ import { TPromise } from 'vs/base/common/winjs.base';
|
||||
import * as nls from 'vs/nls';
|
||||
import URI from 'vs/base/common/uri';
|
||||
import { Action } from 'vs/base/common/actions';
|
||||
import { IDisposable, dispose } from 'vs/base/common/lifecycle';
|
||||
import { IModeService } from 'vs/editor/common/services/modeService';
|
||||
import { IQuickOpenService, IPickOpenEntry, IFilePickOpenEntry } from 'vs/platform/quickOpen/common/quickOpen';
|
||||
import { IPreferencesService, getSettingsTargetName } from 'vs/workbench/parts/preferences/common/preferences';
|
||||
import { IWorkspaceContextService } from 'vs/platform/workspace/common/workspace';
|
||||
import { ConfigurationTarget } from 'vs/workbench/services/configuration/common/configurationEditing';
|
||||
import { IPreferencesService } from 'vs/workbench/parts/preferences/common/preferences';
|
||||
import { IWorkspaceContextService, WorkbenchState, IWorkspaceFolder } from 'vs/platform/workspace/common/workspace';
|
||||
import { ICommandService } from 'vs/platform/commands/common/commands';
|
||||
import { PICK_WORKSPACE_FOLDER_COMMAND } from 'vs/workbench/browser/actions/workspaceActions';
|
||||
|
||||
export class OpenGlobalSettingsAction extends Action {
|
||||
|
||||
@@ -73,6 +75,8 @@ export class OpenWorkspaceSettingsAction extends Action {
|
||||
public static ID = 'workbench.action.openWorkspaceSettings';
|
||||
public static LABEL = nls.localize('openWorkspaceSettings', "Open Workspace Settings");
|
||||
|
||||
private disposables: IDisposable[] = [];
|
||||
|
||||
constructor(
|
||||
id: string,
|
||||
label: string,
|
||||
@@ -80,46 +84,63 @@ export class OpenWorkspaceSettingsAction extends Action {
|
||||
@IWorkspaceContextService private workspaceContextService: IWorkspaceContextService
|
||||
) {
|
||||
super(id, label);
|
||||
this.enabled = this.workspaceContextService.hasWorkspace();
|
||||
this.update();
|
||||
this.workspaceContextService.onDidChangeWorkbenchState(() => this.update(), this, this.disposables);
|
||||
}
|
||||
|
||||
private update(): void {
|
||||
this.enabled = this.workspaceContextService.getWorkbenchState() !== WorkbenchState.EMPTY;
|
||||
}
|
||||
|
||||
public run(event?: any): TPromise<any> {
|
||||
return this.preferencesService.openWorkspaceSettings();
|
||||
}
|
||||
|
||||
public dispose(): void {
|
||||
this.disposables = dispose(this.disposables);
|
||||
super.dispose();
|
||||
}
|
||||
}
|
||||
|
||||
export const OPEN_FOLDER_SETTINGS_COMMAND = '_workbench.action.openFolderSettings';
|
||||
export class OpenFolderSettingsAction extends Action {
|
||||
|
||||
public static ID = 'workbench.action.openFolderSettings';
|
||||
public static LABEL = nls.localize('openFolderSettings', "Open Folder Settings");
|
||||
|
||||
private disposables: IDisposable[] = [];
|
||||
|
||||
|
||||
constructor(
|
||||
id: string,
|
||||
label: string,
|
||||
@IPreferencesService private preferencesService: IPreferencesService,
|
||||
@IWorkspaceContextService private workspaceContextService: IWorkspaceContextService,
|
||||
@IQuickOpenService private quickOpenService: IQuickOpenService
|
||||
@ICommandService private commandService: ICommandService
|
||||
) {
|
||||
super(id, label);
|
||||
this.enabled = this.workspaceContextService.hasMultiFolderWorkspace();
|
||||
this.update();
|
||||
this.workspaceContextService.onDidChangeWorkbenchState(() => this.update(), this, this.disposables);
|
||||
this.workspaceContextService.onDidChangeWorkspaceFolders(() => this.update(), this, this.disposables);
|
||||
}
|
||||
|
||||
private update(): void {
|
||||
this.enabled = this.workspaceContextService.getWorkbenchState() === WorkbenchState.WORKSPACE && this.workspaceContextService.getWorkspace().folders.length > 0;
|
||||
}
|
||||
|
||||
public run(): TPromise<any> {
|
||||
const picks: IPickOpenEntry[] = this.workspaceContextService.getWorkspace().roots.map((root, index) => {
|
||||
return <IPickOpenEntry>{
|
||||
label: getSettingsTargetName(ConfigurationTarget.FOLDER, root, this.workspaceContextService),
|
||||
id: `${index}`
|
||||
};
|
||||
});
|
||||
|
||||
return this.quickOpenService.pick(picks, { placeHolder: nls.localize('pickFolder', "Select Folder") })
|
||||
.then(pick => {
|
||||
if (pick) {
|
||||
return this.preferencesService.openFolderSettings(this.workspaceContextService.getWorkspace().roots[parseInt(pick.id)]);
|
||||
return this.commandService.executeCommand<IWorkspaceFolder>(PICK_WORKSPACE_FOLDER_COMMAND)
|
||||
.then(workspaceFolder => {
|
||||
if (workspaceFolder) {
|
||||
return this.commandService.executeCommand(OPEN_FOLDER_SETTINGS_COMMAND, workspaceFolder);
|
||||
}
|
||||
return undefined;
|
||||
return null;
|
||||
});
|
||||
}
|
||||
|
||||
public dispose(): void {
|
||||
this.disposables = dispose(this.disposables);
|
||||
super.dispose();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -6,14 +6,15 @@
|
||||
import { TPromise } from 'vs/base/common/winjs.base';
|
||||
import * as nls from 'vs/nls';
|
||||
import URI from 'vs/base/common/uri';
|
||||
import { onUnexpectedError } from 'vs/base/common/errors';
|
||||
import * as DOM from 'vs/base/browser/dom';
|
||||
import { Delayer } from 'vs/base/common/async';
|
||||
import { Delayer, ThrottledDelayer } from 'vs/base/common/async';
|
||||
import { Dimension, Builder } from 'vs/base/browser/builder';
|
||||
import { ArrayNavigator, INavigator } from 'vs/base/common/iterator';
|
||||
import { Disposable, IDisposable, dispose } from 'vs/base/common/lifecycle';
|
||||
import { KeyMod, KeyCode } from 'vs/base/common/keyCodes';
|
||||
import { toResource, SideBySideEditorInput, EditorOptions, EditorInput, IEditorRegistry, Extensions as EditorExtensions } from 'vs/workbench/common/editor';
|
||||
import { BaseEditor, EditorDescriptor } from 'vs/workbench/browser/parts/editor/baseEditor';
|
||||
import { SideBySideEditorInput, EditorOptions, EditorInput } from 'vs/workbench/common/editor';
|
||||
import { BaseEditor } from 'vs/workbench/browser/parts/editor/baseEditor';
|
||||
import { ResourceEditorModel } from 'vs/workbench/common/editor/resourceEditorModel';
|
||||
import { IEditorControl, Position, Verbosity } from 'vs/platform/editor/common/editor';
|
||||
import { ResourceEditorInput } from 'vs/workbench/common/editor/resourceEditorInput';
|
||||
@@ -23,12 +24,13 @@ import { CodeEditor } from 'vs/editor/browser/codeEditor';
|
||||
import { IInstantiationService, ServicesAccessor } from 'vs/platform/instantiation/common/instantiation';
|
||||
import {
|
||||
IPreferencesService, ISettingsGroup, ISetting, IFilterResult,
|
||||
CONTEXT_SETTINGS_EDITOR, CONTEXT_SETTINGS_SEARCH_FOCUS, SETTINGS_EDITOR_COMMAND_SEARCH, SETTINGS_EDITOR_COMMAND_FOCUS_FILE, ISettingsEditorModel
|
||||
CONTEXT_SETTINGS_EDITOR, CONTEXT_SETTINGS_SEARCH_FOCUS, SETTINGS_EDITOR_COMMAND_SEARCH, SETTINGS_EDITOR_COMMAND_FOCUS_FILE, ISettingsEditorModel, SETTINGS_EDITOR_COMMAND_CLEAR_SEARCH_RESULTS, SETTINGS_EDITOR_COMMAND_FOCUS_NEXT_SETTING, SETTINGS_EDITOR_COMMAND_FOCUS_PREVIOUS_SETTING
|
||||
} from 'vs/workbench/parts/preferences/common/preferences';
|
||||
import { SettingsEditorModel, DefaultSettingsEditorModel } from 'vs/workbench/parts/preferences/common/preferencesModels';
|
||||
import { editorContribution } from 'vs/editor/browser/editorBrowserExtensions';
|
||||
import { ICodeEditor, IEditorContributionCtor } from 'vs/editor/browser/editorBrowser';
|
||||
import { SearchWidget, SettingsTargetsWidget } from 'vs/workbench/parts/preferences/browser/preferencesWidgets';
|
||||
import { PreferencesSearchProvider, PreferencesSearchModel } from 'vs/workbench/parts/preferences/browser/preferencesSearch';
|
||||
import { ContextKeyExpr, IContextKeyService, IContextKey } from 'vs/platform/contextkey/common/contextkey';
|
||||
import { Command } from 'vs/editor/common/editorCommonExtensions';
|
||||
import { ITelemetryService } from 'vs/platform/telemetry/common/telemetry';
|
||||
@@ -39,7 +41,6 @@ import { IStorageService } from 'vs/platform/storage/common/storage';
|
||||
import { ITextResourceConfigurationService } from 'vs/editor/common/services/resourceConfiguration';
|
||||
import { IWorkbenchEditorService } from 'vs/workbench/services/editor/common/editorService';
|
||||
import { ITextModelService } from 'vs/editor/common/services/resolverService';
|
||||
import { ConfigurationTarget } from 'vs/workbench/services/configuration/common/configurationEditing';
|
||||
import { IEnvironmentService } from 'vs/platform/environment/common/environment';
|
||||
import { VSash } from 'vs/base/browser/ui/sash/sash';
|
||||
import { Widget } from 'vs/base/browser/ui/widget';
|
||||
@@ -47,11 +48,10 @@ import { IPreferencesRenderer, DefaultSettingsRenderer, UserSettingsRenderer, Wo
|
||||
import { ITextFileService } from 'vs/workbench/services/textfile/common/textfiles';
|
||||
import { IEditorGroupService } from 'vs/workbench/services/group/common/groupService';
|
||||
import { getCodeEditor } from 'vs/editor/common/services/codeEditorService';
|
||||
|
||||
// Ignore following contributions
|
||||
import { IEditorRegistry, Extensions as EditorExtensions } from 'vs/workbench/browser/editor';
|
||||
import { FoldingController } from 'vs/editor/contrib/folding/browser/folding';
|
||||
import { FindController } from 'vs/editor/contrib/find/browser/find';
|
||||
import { SelectionHighlighter } from 'vs/editor/contrib/find/common/findController';
|
||||
import { SelectionHighlighter } from 'vs/editor/contrib/multicursor/common/multicursor';
|
||||
import { IEditorOptions } from 'vs/editor/common/config/editorOptions';
|
||||
import { KeybindingsRegistry } from 'vs/platform/keybinding/common/keybindingsRegistry';
|
||||
import { attachStylerCallback } from 'vs/platform/theme/common/styler';
|
||||
@@ -59,6 +59,9 @@ import { scrollbarShadow } from 'vs/platform/theme/common/colorRegistry';
|
||||
import { IWorkspaceContextService } from 'vs/platform/workspace/common/workspace';
|
||||
import Event, { Emitter } from 'vs/base/common/event';
|
||||
import { Registry } from 'vs/platform/registry/common/platform';
|
||||
import { MessageController } from 'vs/editor/contrib/message/messageController';
|
||||
import { ConfigurationTarget } from 'vs/platform/configuration/common/configuration';
|
||||
import { IHashService } from 'vs/workbench/services/hash/common/hashService';
|
||||
|
||||
export class PreferencesEditorInput extends SideBySideEditorInput {
|
||||
public static ID: string = 'workbench.editorinputs.preferencesEditorInput';
|
||||
@@ -75,9 +78,10 @@ export class PreferencesEditorInput extends SideBySideEditorInput {
|
||||
export class DefaultPreferencesEditorInput extends ResourceEditorInput {
|
||||
public static ID = 'workbench.editorinputs.defaultpreferences';
|
||||
constructor(defaultSettingsResource: URI,
|
||||
@ITextModelService textModelResolverService: ITextModelService
|
||||
@ITextModelService textModelResolverService: ITextModelService,
|
||||
@IHashService hashService: IHashService
|
||||
) {
|
||||
super(nls.localize('settingsEditorName', "Default Settings"), '', defaultSettingsResource, textModelResolverService);
|
||||
super(nls.localize('settingsEditorName', "Default Settings"), '', defaultSettingsResource, textModelResolverService, hashService);
|
||||
}
|
||||
|
||||
getTypeId(): string {
|
||||
@@ -85,10 +89,10 @@ export class DefaultPreferencesEditorInput extends ResourceEditorInput {
|
||||
}
|
||||
|
||||
matches(other: any): boolean {
|
||||
if (!super.matches(other)) {
|
||||
return false;
|
||||
if (other instanceof DefaultPreferencesEditorInput) {
|
||||
return true;
|
||||
}
|
||||
if (!(other instanceof DefaultPreferencesEditorInput)) {
|
||||
if (!super.matches(other)) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
@@ -106,8 +110,10 @@ export class PreferencesEditor extends BaseEditor {
|
||||
private settingsTargetsWidget: SettingsTargetsWidget;
|
||||
private sideBySidePreferencesWidget: SideBySidePreferencesWidget;
|
||||
private preferencesRenderers: PreferencesRenderers;
|
||||
private searchProvider: PreferencesSearchProvider;
|
||||
|
||||
private delayedFilterLogging: Delayer<void>;
|
||||
private filterThrottle: ThrottledDelayer<void>;
|
||||
|
||||
private latestEmptyFilters: string[] = [];
|
||||
private lastFocusedWidget: SearchWidget | SideBySidePreferencesWidget = null;
|
||||
@@ -126,6 +132,8 @@ export class PreferencesEditor extends BaseEditor {
|
||||
this.defaultSettingsEditorContextKey = CONTEXT_SETTINGS_EDITOR.bindTo(this.contextKeyService);
|
||||
this.focusSettingsContextKey = CONTEXT_SETTINGS_SEARCH_FOCUS.bindTo(this.contextKeyService);
|
||||
this.delayedFilterLogging = new Delayer<void>(1000);
|
||||
this.searchProvider = this.instantiationService.createInstance(PreferencesSearchProvider);
|
||||
this.filterThrottle = new ThrottledDelayer(200);
|
||||
}
|
||||
|
||||
public createEditor(parent: Builder): void {
|
||||
@@ -139,8 +147,9 @@ export class PreferencesEditor extends BaseEditor {
|
||||
placeholder: nls.localize('SearchSettingsWidget.Placeholder', "Search Settings"),
|
||||
focusKey: this.focusSettingsContextKey
|
||||
}));
|
||||
this._register(this.searchWidget.onDidChange(value => this.filterPreferences(value.trim())));
|
||||
this._register(this.searchWidget.onNavigate(shift => this.preferencesRenderers.focusNextPreference(!shift)));
|
||||
this.searchWidget.setFuzzyToggleVisible(this.searchProvider.remoteSearchEnabled);
|
||||
this._register(this.searchProvider.onRemoteSearchEnablementChanged(enabled => this.searchWidget.setFuzzyToggleVisible(enabled)));
|
||||
this._register(this.searchWidget.onDidChange(value => this.onInputChanged()));
|
||||
this._register(this.searchWidget.onFocus(() => this.lastFocusedWidget = this.searchWidget));
|
||||
this.lastFocusedWidget = this.searchWidget;
|
||||
|
||||
@@ -152,7 +161,31 @@ export class PreferencesEditor extends BaseEditor {
|
||||
this._register(this.sideBySidePreferencesWidget.onFocus(() => this.lastFocusedWidget = this.sideBySidePreferencesWidget));
|
||||
|
||||
this.preferencesRenderers = this._register(new PreferencesRenderers());
|
||||
this._register(this.workspaceContextService.onDidChangeWorkspaceRoots(() => this.onWorkspaceRootsChanged()));
|
||||
this._register(this.workspaceContextService.onDidChangeWorkspaceFolders(() => this.onWorkspaceFoldersChanged()));
|
||||
this._register(this.workspaceContextService.onDidChangeWorkbenchState(() => this.onWorkbenchStateChanged()));
|
||||
|
||||
this._register(this.preferencesRenderers.onTriggeredFuzzy(() => {
|
||||
this.searchWidget.fuzzyEnabled = true;
|
||||
this.filterPreferences();
|
||||
}));
|
||||
}
|
||||
|
||||
public clearSearchResults(): void {
|
||||
if (this.searchWidget) {
|
||||
this.searchWidget.clear();
|
||||
}
|
||||
}
|
||||
|
||||
public focusNextResult(): void {
|
||||
if (this.preferencesRenderers) {
|
||||
this.preferencesRenderers.focusNextPreference(true);
|
||||
}
|
||||
}
|
||||
|
||||
public focusPreviousResult(): void {
|
||||
if (this.preferencesRenderers) {
|
||||
this.preferencesRenderers.focusNextPreference(false);
|
||||
}
|
||||
}
|
||||
|
||||
public setInput(newInput: PreferencesEditorInput, options?: EditorOptions): TPromise<void> {
|
||||
@@ -209,43 +242,60 @@ export class PreferencesEditor extends BaseEditor {
|
||||
}
|
||||
|
||||
private updateInput(oldInput: PreferencesEditorInput, newInput: PreferencesEditorInput, options?: EditorOptions): TPromise<void> {
|
||||
const resource = toResource(newInput.master);
|
||||
this.settingsTargetsWidget.setTarget(this.getSettingsConfigurationTargetUri(resource), this.getSettingsConfigurationTarget(resource));
|
||||
const resource = newInput.master.getResource();
|
||||
this.settingsTargetsWidget.updateTargets(this.getSettingsConfigurationTargetUri(resource), this.getSettingsConfigurationTarget(resource));
|
||||
|
||||
return this.sideBySidePreferencesWidget.setInput(<DefaultPreferencesEditorInput>newInput.details, <EditorInput>newInput.master, options).then(({ defaultPreferencesRenderer, editablePreferencesRenderer }) => {
|
||||
this.preferencesRenderers.defaultPreferencesRenderer = defaultPreferencesRenderer;
|
||||
this.preferencesRenderers.editablePreferencesRenderer = editablePreferencesRenderer;
|
||||
this.filterPreferences(this.searchWidget.getValue());
|
||||
this.onInputChanged();
|
||||
});
|
||||
}
|
||||
|
||||
private onInputChanged(): void {
|
||||
if (this.searchWidget.fuzzyEnabled) {
|
||||
this.triggerThrottledFilter();
|
||||
} else {
|
||||
this.filterPreferences();
|
||||
}
|
||||
}
|
||||
|
||||
private triggerThrottledFilter(): void {
|
||||
this.filterThrottle.trigger(() => this.filterPreferences());
|
||||
}
|
||||
|
||||
private getSettingsConfigurationTarget(resource: URI): ConfigurationTarget {
|
||||
if (this.preferencesService.userSettingsResource.fsPath === resource.fsPath) {
|
||||
if (this.preferencesService.userSettingsResource.toString() === resource.toString()) {
|
||||
return ConfigurationTarget.USER;
|
||||
}
|
||||
if (this.preferencesService.workspaceSettingsResource.fsPath === resource.fsPath) {
|
||||
|
||||
const workspaceSettingsResource = this.preferencesService.workspaceSettingsResource;
|
||||
if (workspaceSettingsResource && workspaceSettingsResource.toString() === resource.toString()) {
|
||||
return ConfigurationTarget.WORKSPACE;
|
||||
}
|
||||
if (this.workspaceContextService.getRoot(resource)) {
|
||||
return ConfigurationTarget.FOLDER;
|
||||
|
||||
if (this.workspaceContextService.getWorkspaceFolder(resource)) {
|
||||
return ConfigurationTarget.WORKSPACE_FOLDER;
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
private getSettingsConfigurationTargetUri(resource: URI): URI {
|
||||
if (this.preferencesService.userSettingsResource.fsPath === resource.fsPath) {
|
||||
if (this.preferencesService.userSettingsResource.toString() === resource.toString()) {
|
||||
return resource;
|
||||
}
|
||||
if (this.preferencesService.workspaceSettingsResource.fsPath === resource.fsPath) {
|
||||
if (this.preferencesService.workspaceSettingsResource.toString() === resource.toString()) {
|
||||
return resource;
|
||||
}
|
||||
|
||||
return this.workspaceContextService.getRoot(resource);
|
||||
const workspaceFolder = this.workspaceContextService.getWorkspaceFolder(resource);
|
||||
return workspaceFolder ? workspaceFolder.uri : null;
|
||||
}
|
||||
|
||||
private onWorkspaceRootsChanged(): void {
|
||||
private onWorkspaceFoldersChanged(): void {
|
||||
if (this.input) {
|
||||
const settingsResource = toResource((<PreferencesEditorInput>this.input).master);
|
||||
const settingsResource = (<PreferencesEditorInput>this.input).master.getResource();
|
||||
const targetResource = this.getSettingsConfigurationTargetUri(settingsResource);
|
||||
if (!targetResource) {
|
||||
this.switchSettings(this.preferencesService.userSettingsResource);
|
||||
@@ -253,6 +303,21 @@ export class PreferencesEditor extends BaseEditor {
|
||||
}
|
||||
}
|
||||
|
||||
private onWorkbenchStateChanged(): void {
|
||||
if (this.input) {
|
||||
const editableSettingsResource = (<PreferencesEditorInput>this.input).master.getResource();
|
||||
const newConfigurationTarget = this.getSettingsConfigurationTarget(editableSettingsResource);
|
||||
if (newConfigurationTarget) {
|
||||
if (newConfigurationTarget !== this.settingsTargetsWidget.configurationTarget) {
|
||||
// Update the editor if the configuration target of the settings resource changed
|
||||
this.switchSettings(editableSettingsResource);
|
||||
}
|
||||
} else {
|
||||
this.switchSettings(this.preferencesService.userSettingsResource);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private switchSettings(resource: URI): void {
|
||||
// Focus the editor if this editor is not active editor
|
||||
if (this.editorService.getActiveEditor() !== this) {
|
||||
@@ -262,14 +327,16 @@ export class PreferencesEditor extends BaseEditor {
|
||||
promise.done(value => this.preferencesService.switchSettings(this.getSettingsConfigurationTarget(resource), resource));
|
||||
}
|
||||
|
||||
private filterPreferences(filter: string) {
|
||||
const count = this.preferencesRenderers.filterPreferences(filter);
|
||||
const message = filter ? this.showSearchResultsMessage(count) : nls.localize('totalSettingsMessage', "Total {0} Settings", count);
|
||||
this.searchWidget.showMessage(message, count);
|
||||
if (count === 0) {
|
||||
this.latestEmptyFilters.push(filter);
|
||||
}
|
||||
this.delayedFilterLogging.trigger(() => this.reportFilteringUsed(filter));
|
||||
private filterPreferences(): TPromise<void> {
|
||||
const filter = this.searchWidget.getValue().trim();
|
||||
return this.preferencesRenderers.filterPreferences(filter, this.searchProvider, this.searchWidget.fuzzyEnabled).then(count => {
|
||||
const message = filter ? this.showSearchResultsMessage(count) : nls.localize('totalSettingsMessage', "Total {0} Settings", count);
|
||||
this.searchWidget.showMessage(message, count);
|
||||
if (count === 0) {
|
||||
this.latestEmptyFilters.push(filter);
|
||||
}
|
||||
this.delayedFilterLogging.trigger(() => this.reportFilteringUsed(filter));
|
||||
}, onUnexpectedError);
|
||||
}
|
||||
|
||||
private showSearchResultsMessage(count: number): string {
|
||||
@@ -285,6 +352,12 @@ export class PreferencesEditor extends BaseEditor {
|
||||
emptyFilters: this.getLatestEmptyFiltersForTelemetry()
|
||||
};
|
||||
this.latestEmptyFilters = [];
|
||||
/* __GDPR__
|
||||
"defaultSettings.filter" : {
|
||||
"filter": { "classification": "SystemMetaData", "purpose": "FeatureInsight" },
|
||||
"emptyFilters" : { "classification": "SystemMetaData", "purpose": "FeatureInsight" }
|
||||
}
|
||||
*/
|
||||
this.telemetryService.publicLog('defaultSettings.filter', data);
|
||||
}
|
||||
}
|
||||
@@ -337,9 +410,13 @@ class PreferencesRenderers extends Disposable {
|
||||
private _defaultPreferencesRenderer: IPreferencesRenderer<ISetting>;
|
||||
private _editablePreferencesRenderer: IPreferencesRenderer<ISetting>;
|
||||
private _settingsNavigator: SettingsNavigator;
|
||||
private _filtersInProgress: TPromise<any>[];
|
||||
|
||||
private _disposables: IDisposable[] = [];
|
||||
|
||||
private _onTriggeredFuzzy: Emitter<void> = new Emitter<void>();
|
||||
public onTriggeredFuzzy: Event<void> = this._onTriggeredFuzzy.event;
|
||||
|
||||
public get defaultPreferencesRenderer(): IPreferencesRenderer<ISetting> {
|
||||
return this._defaultPreferencesRenderer;
|
||||
}
|
||||
@@ -354,6 +431,9 @@ class PreferencesRenderers extends Disposable {
|
||||
this._defaultPreferencesRenderer.onUpdatePreference(({ key, value, source }) => this._updatePreference(key, value, source, this._editablePreferencesRenderer), this, this._disposables);
|
||||
this._defaultPreferencesRenderer.onFocusPreference(preference => this._focusPreference(preference, this._editablePreferencesRenderer), this, this._disposables);
|
||||
this._defaultPreferencesRenderer.onClearFocusPreference(preference => this._clearFocus(preference, this._editablePreferencesRenderer), this, this._disposables);
|
||||
if (this._defaultPreferencesRenderer.onTriggeredFuzzy) {
|
||||
this._register(this._defaultPreferencesRenderer.onTriggeredFuzzy(() => this._onTriggeredFuzzy.fire()));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -362,19 +442,37 @@ class PreferencesRenderers extends Disposable {
|
||||
this._editablePreferencesRenderer = editableSettingsRenderer;
|
||||
}
|
||||
|
||||
public filterPreferences(filter: string): number {
|
||||
const defaultPreferencesFilterResult = this._filterPreferences(filter, this._defaultPreferencesRenderer);
|
||||
const editablePreferencesFilterResult = this._filterPreferences(filter, this._editablePreferencesRenderer);
|
||||
public filterPreferences(filter: string, searchProvider: PreferencesSearchProvider, fuzzy: boolean): TPromise<number> {
|
||||
if (this._filtersInProgress) {
|
||||
// Resolved/rejected promises have no .cancel()
|
||||
this._filtersInProgress.forEach(p => p.cancel && p.cancel());
|
||||
}
|
||||
|
||||
const defaultPreferencesFilteredGroups = defaultPreferencesFilterResult ? defaultPreferencesFilterResult.filteredGroups : this._getAllPreferences(this._defaultPreferencesRenderer);
|
||||
const editablePreferencesFilteredGroups = editablePreferencesFilterResult ? editablePreferencesFilterResult.filteredGroups : this._getAllPreferences(this._editablePreferencesRenderer);
|
||||
const consolidatedSettings = this._consolidateSettings(editablePreferencesFilteredGroups, defaultPreferencesFilteredGroups);
|
||||
this._settingsNavigator = new SettingsNavigator(filter ? consolidatedSettings : []);
|
||||
const searchModel = searchProvider.startSearch(filter, fuzzy);
|
||||
this._filtersInProgress = [
|
||||
this._filterPreferences(searchModel, searchProvider, this._defaultPreferencesRenderer),
|
||||
this._filterPreferences(searchModel, searchProvider, this._editablePreferencesRenderer)];
|
||||
|
||||
return consolidatedSettings.length;
|
||||
return TPromise.join<IFilterResult>(this._filtersInProgress).then(filterResults => {
|
||||
this._filtersInProgress = null;
|
||||
const defaultPreferencesFilterResult = filterResults[0];
|
||||
const editablePreferencesFilterResult = filterResults[1];
|
||||
|
||||
const defaultPreferencesFilteredGroups = defaultPreferencesFilterResult ? defaultPreferencesFilterResult.filteredGroups : this._getAllPreferences(this._defaultPreferencesRenderer);
|
||||
const editablePreferencesFilteredGroups = editablePreferencesFilterResult ? editablePreferencesFilterResult.filteredGroups : this._getAllPreferences(this._editablePreferencesRenderer);
|
||||
const consolidatedSettings = this._consolidateSettings(editablePreferencesFilteredGroups, defaultPreferencesFilteredGroups);
|
||||
|
||||
this._settingsNavigator = new SettingsNavigator(filter ? consolidatedSettings : []);
|
||||
|
||||
return consolidatedSettings.length;
|
||||
});
|
||||
}
|
||||
|
||||
public focusNextPreference(forward: boolean = true) {
|
||||
if (!this._settingsNavigator) {
|
||||
return;
|
||||
}
|
||||
|
||||
const setting = forward ? this._settingsNavigator.next() : this._settingsNavigator.previous();
|
||||
this._focusPreference(setting, this._defaultPreferencesRenderer);
|
||||
this._focusPreference(setting, this._editablePreferencesRenderer);
|
||||
@@ -384,13 +482,17 @@ class PreferencesRenderers extends Disposable {
|
||||
return preferencesRenderer ? (<ISettingsEditorModel>preferencesRenderer.preferencesModel).settingsGroups : [];
|
||||
}
|
||||
|
||||
private _filterPreferences(filter: string, preferencesRenderer: IPreferencesRenderer<ISetting>): IFilterResult {
|
||||
let filterResult = null;
|
||||
private _filterPreferences(searchModel: PreferencesSearchModel, searchProvider: PreferencesSearchProvider, preferencesRenderer: IPreferencesRenderer<ISetting>): TPromise<IFilterResult> {
|
||||
if (preferencesRenderer) {
|
||||
filterResult = filter ? (<ISettingsEditorModel>preferencesRenderer.preferencesModel).filterSettings(filter) : null;
|
||||
preferencesRenderer.filterPreferences(filterResult);
|
||||
const prefSearchP = searchModel.filterPreferences(<ISettingsEditorModel>preferencesRenderer.preferencesModel);
|
||||
|
||||
return prefSearchP.then(filterResult => {
|
||||
preferencesRenderer.filterPreferences(filterResult, searchProvider.remoteSearchEnabled);
|
||||
return filterResult;
|
||||
});
|
||||
}
|
||||
return filterResult;
|
||||
|
||||
return TPromise.wrap(null);
|
||||
}
|
||||
|
||||
private _focusPreference(preference: ISetting, preferencesRenderer: IPreferencesRenderer<ISetting>): void {
|
||||
@@ -483,13 +585,11 @@ class SideBySidePreferencesWidget extends Widget {
|
||||
}
|
||||
|
||||
public setInput(defaultPreferencesEditorInput: DefaultPreferencesEditorInput, editablePreferencesEditorInput: EditorInput, options?: EditorOptions): TPromise<{ defaultPreferencesRenderer: IPreferencesRenderer<ISetting>, editablePreferencesRenderer: IPreferencesRenderer<ISetting> }> {
|
||||
return this.getOrCreateEditablePreferencesEditor(editablePreferencesEditorInput)
|
||||
.then(() => {
|
||||
this.dolayout(this.sash.getVerticalSashLeft());
|
||||
return TPromise.join([this.updateInput(this.defaultPreferencesEditor, defaultPreferencesEditorInput, DefaultSettingsEditorContribution.ID, toResource(editablePreferencesEditorInput), options),
|
||||
this.updateInput(this.editablePreferencesEditor, editablePreferencesEditorInput, SettingsEditorContribution.ID, defaultPreferencesEditorInput.getResource(), options)])
|
||||
.then(([defaultPreferencesRenderer, editablePreferencesRenderer]) => ({ defaultPreferencesRenderer, editablePreferencesRenderer }));
|
||||
});
|
||||
this.getOrCreateEditablePreferencesEditor(editablePreferencesEditorInput);
|
||||
this.dolayout(this.sash.getVerticalSashLeft());
|
||||
return TPromise.join([this.updateInput(this.defaultPreferencesEditor, defaultPreferencesEditorInput, DefaultSettingsEditorContribution.ID, editablePreferencesEditorInput.getResource(), options),
|
||||
this.updateInput(this.editablePreferencesEditor, editablePreferencesEditorInput, SettingsEditorContribution.ID, defaultPreferencesEditorInput.getResource(), options)])
|
||||
.then(([defaultPreferencesRenderer, editablePreferencesRenderer]) => ({ defaultPreferencesRenderer, editablePreferencesRenderer }));
|
||||
}
|
||||
|
||||
public layout(dimension: Dimension): void {
|
||||
@@ -508,6 +608,9 @@ class SideBySidePreferencesWidget extends Widget {
|
||||
}
|
||||
|
||||
public clearInput(): void {
|
||||
if (this.defaultPreferencesEditor) {
|
||||
this.defaultPreferencesEditor.clearInput();
|
||||
}
|
||||
if (this.editablePreferencesEditor) {
|
||||
this.editablePreferencesEditor.clearInput();
|
||||
}
|
||||
@@ -525,20 +628,19 @@ class SideBySidePreferencesWidget extends Widget {
|
||||
}
|
||||
}
|
||||
|
||||
private getOrCreateEditablePreferencesEditor(editorInput: EditorInput): TPromise<BaseEditor> {
|
||||
private getOrCreateEditablePreferencesEditor(editorInput: EditorInput): BaseEditor {
|
||||
if (this.editablePreferencesEditor) {
|
||||
return TPromise.as(this.editablePreferencesEditor);
|
||||
return this.editablePreferencesEditor;
|
||||
}
|
||||
const descriptor = Registry.as<IEditorRegistry>(EditorExtensions.Editors).getEditor(editorInput);
|
||||
return this.instantiationService.createInstance(<EditorDescriptor>descriptor)
|
||||
.then((editor: BaseEditor) => {
|
||||
this.editablePreferencesEditor = editor;
|
||||
this.editablePreferencesEditor.create(new Builder(this.editablePreferencesEditorContainer));
|
||||
this.editablePreferencesEditor.setVisible(true);
|
||||
(<CodeEditor>this.editablePreferencesEditor.getControl()).onDidFocusEditor(() => this.lastFocusedEditor = this.editablePreferencesEditor);
|
||||
this.lastFocusedEditor = this.editablePreferencesEditor;
|
||||
return editor;
|
||||
});
|
||||
const editor = descriptor.instantiate(this.instantiationService);
|
||||
this.editablePreferencesEditor = editor;
|
||||
this.editablePreferencesEditor.create(new Builder(this.editablePreferencesEditorContainer));
|
||||
this.editablePreferencesEditor.setVisible(true);
|
||||
(<CodeEditor>this.editablePreferencesEditor.getControl()).onDidFocusEditor(() => this.lastFocusedEditor = this.editablePreferencesEditor);
|
||||
this.lastFocusedEditor = this.editablePreferencesEditor;
|
||||
|
||||
return editor;
|
||||
}
|
||||
|
||||
private updateInput(editor: BaseEditor, input: EditorInput, editorContributionId: string, associatedPreferencesModelUri: URI, options: EditorOptions): TPromise<IPreferencesRenderer<ISetting>> {
|
||||
@@ -682,7 +784,20 @@ export class DefaultPreferencesEditor extends BaseTextEditor {
|
||||
}
|
||||
|
||||
public createEditorControl(parent: Builder, configuration: IEditorOptions): editorCommon.IEditor {
|
||||
return this.instantiationService.createInstance(DefaultPreferencesCodeEditor, parent.getHTMLElement(), configuration);
|
||||
const editor = this.instantiationService.createInstance(DefaultPreferencesCodeEditor, parent.getHTMLElement(), configuration);
|
||||
|
||||
// Inform user about editor being readonly if user starts type
|
||||
this.toUnbind.push(editor.onDidType(() => this.showReadonlyHint(editor)));
|
||||
this.toUnbind.push(editor.onDidPaste(() => this.showReadonlyHint(editor)));
|
||||
|
||||
return editor;
|
||||
}
|
||||
|
||||
private showReadonlyHint(editor: editorCommon.ICommonCodeEditor): void {
|
||||
const messageController = MessageController.get(editor);
|
||||
if (!messageController.isVisible()) {
|
||||
messageController.showMessage(nls.localize('defaultEditorReadonly', "Edit in the right hand side editor to override defaults."), editor.getSelection().getPosition());
|
||||
}
|
||||
}
|
||||
|
||||
protected getConfigurationOverrides(): IEditorOptions {
|
||||
@@ -712,6 +827,14 @@ export class DefaultPreferencesEditor extends BaseTextEditor {
|
||||
.then(editorModel => this.getControl().setModel((<ResourceEditorModel>editorModel).textEditorModel)));
|
||||
}
|
||||
|
||||
public clearInput(): void {
|
||||
// Clear Model
|
||||
this.getControl().setModel(null);
|
||||
|
||||
// Pass to super
|
||||
super.clearInput();
|
||||
}
|
||||
|
||||
public layout(dimension: Dimension) {
|
||||
this.getControl().layout(dimension);
|
||||
}
|
||||
@@ -765,7 +888,7 @@ abstract class AbstractSettingsEditorContribution extends Disposable {
|
||||
return TPromise.as(null);
|
||||
}
|
||||
|
||||
private _onModelChanged(): void {
|
||||
protected _onModelChanged(): void {
|
||||
const model = this.editor.getModel();
|
||||
this.disposePreferencesRenderer();
|
||||
if (model) {
|
||||
@@ -775,7 +898,7 @@ abstract class AbstractSettingsEditorContribution extends Disposable {
|
||||
|
||||
private _hasAssociatedPreferencesModelChanged(associatedPreferencesModelUri: URI): TPromise<boolean> {
|
||||
return this.preferencesRendererCreationPromise.then(preferencesRenderer => {
|
||||
return !(preferencesRenderer && preferencesRenderer.associatedPreferencesModel && preferencesRenderer.associatedPreferencesModel.uri.fsPath === associatedPreferencesModelUri.fsPath);
|
||||
return !(preferencesRenderer && preferencesRenderer.associatedPreferencesModel && preferencesRenderer.associatedPreferencesModel.uri.toString() === associatedPreferencesModelUri.toString());
|
||||
});
|
||||
}
|
||||
|
||||
@@ -801,6 +924,7 @@ abstract class AbstractSettingsEditorContribution extends Disposable {
|
||||
if (preferencesRenderer.associatedPreferencesModel) {
|
||||
preferencesRenderer.associatedPreferencesModel.dispose();
|
||||
}
|
||||
preferencesRenderer.preferencesModel.dispose();
|
||||
preferencesRenderer.dispose();
|
||||
}
|
||||
});
|
||||
@@ -842,22 +966,31 @@ class SettingsEditorContribution extends AbstractSettingsEditorContribution impl
|
||||
|
||||
static ID: string = 'editor.contrib.settings';
|
||||
|
||||
constructor(editor: ICodeEditor,
|
||||
@IInstantiationService instantiationService: IInstantiationService,
|
||||
@IPreferencesService preferencesService: IPreferencesService,
|
||||
@IWorkspaceContextService workspaceContextService: IWorkspaceContextService
|
||||
) {
|
||||
super(editor, instantiationService, preferencesService, workspaceContextService);
|
||||
this._register(this.workspaceContextService.onDidChangeWorkbenchState(() => this._onModelChanged()));
|
||||
}
|
||||
|
||||
getId(): string {
|
||||
return SettingsEditorContribution.ID;
|
||||
}
|
||||
|
||||
protected _createPreferencesRenderer(): TPromise<IPreferencesRenderer<ISetting>> {
|
||||
if (this.isSettingsModel()) {
|
||||
return TPromise.join<any>([this.preferencesService.createPreferencesEditorModel(this.preferencesService.defaultSettingsResource), this.preferencesService.createPreferencesEditorModel(this.editor.getModel().uri)])
|
||||
.then(([defaultSettingsModel, settingsModel]) => {
|
||||
return this.preferencesService.createPreferencesEditorModel(this.editor.getModel().uri)
|
||||
.then(settingsModel => {
|
||||
if (settingsModel instanceof SettingsEditorModel && this.editor.getModel()) {
|
||||
switch (settingsModel.configurationTarget) {
|
||||
case ConfigurationTarget.USER:
|
||||
return this.instantiationService.createInstance(UserSettingsRenderer, this.editor, settingsModel, defaultSettingsModel);
|
||||
return this.instantiationService.createInstance(UserSettingsRenderer, this.editor, settingsModel);
|
||||
case ConfigurationTarget.WORKSPACE:
|
||||
return this.instantiationService.createInstance(WorkspaceSettingsRenderer, this.editor, settingsModel, defaultSettingsModel);
|
||||
case ConfigurationTarget.FOLDER:
|
||||
return this.instantiationService.createInstance(FolderSettingsRenderer, this.editor, settingsModel, defaultSettingsModel);
|
||||
return this.instantiationService.createInstance(WorkspaceSettingsRenderer, this.editor, settingsModel);
|
||||
case ConfigurationTarget.WORKSPACE_FOLDER:
|
||||
return this.instantiationService.createInstance(FolderSettingsRenderer, this.editor, settingsModel);
|
||||
}
|
||||
}
|
||||
return null;
|
||||
@@ -878,21 +1011,18 @@ class SettingsEditorContribution extends AbstractSettingsEditorContribution impl
|
||||
return false;
|
||||
}
|
||||
|
||||
if (this.preferencesService.userSettingsResource && this.preferencesService.userSettingsResource.fsPath === model.uri.fsPath) {
|
||||
if (this.preferencesService.userSettingsResource && this.preferencesService.userSettingsResource.toString() === model.uri.toString()) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if (this.preferencesService.workspaceSettingsResource && this.preferencesService.workspaceSettingsResource.fsPath === model.uri.fsPath) {
|
||||
if (this.preferencesService.workspaceSettingsResource && this.preferencesService.workspaceSettingsResource.toString() === model.uri.toString()) {
|
||||
return true;
|
||||
}
|
||||
|
||||
const workspace = this.workspaceContextService.getWorkspace();
|
||||
if (workspace) {
|
||||
for (const root of workspace.roots) {
|
||||
const folderSettingsResource = this.preferencesService.getFolderSettingsResource(root);
|
||||
if (folderSettingsResource && folderSettingsResource.fsPath === model.uri.fsPath) {
|
||||
return true;
|
||||
}
|
||||
for (const folder of this.workspaceContextService.getWorkspace().folders) {
|
||||
const folderSettingsResource = this.preferencesService.getFolderSettingsResource(folder.uri);
|
||||
if (folderSettingsResource && folderSettingsResource.toString() === model.uri.toString()) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -946,3 +1076,54 @@ const focusSettingsFileEditorCommand = new FocusSettingsFileEditorCommand({
|
||||
kbOpts: { primary: KeyCode.DownArrow }
|
||||
});
|
||||
KeybindingsRegistry.registerCommandAndKeybindingRule(focusSettingsFileEditorCommand.toCommandAndKeybindingRule(KeybindingsRegistry.WEIGHT.editorContrib()));
|
||||
|
||||
class ClearSearchResultsCommand extends SettingsCommand {
|
||||
|
||||
public runCommand(accessor: ServicesAccessor, args: any): void {
|
||||
const preferencesEditor = this.getPreferencesEditor(accessor);
|
||||
if (preferencesEditor) {
|
||||
preferencesEditor.clearSearchResults();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
const clearSearchResultsCommand = new ClearSearchResultsCommand({
|
||||
id: SETTINGS_EDITOR_COMMAND_CLEAR_SEARCH_RESULTS,
|
||||
precondition: CONTEXT_SETTINGS_SEARCH_FOCUS,
|
||||
kbOpts: { primary: KeyCode.Escape }
|
||||
});
|
||||
KeybindingsRegistry.registerCommandAndKeybindingRule(clearSearchResultsCommand.toCommandAndKeybindingRule(KeybindingsRegistry.WEIGHT.editorContrib()));
|
||||
|
||||
class FocusNextSearchResultCommand extends SettingsCommand {
|
||||
|
||||
public runCommand(accessor: ServicesAccessor, args: any): void {
|
||||
const preferencesEditor = this.getPreferencesEditor(accessor);
|
||||
if (preferencesEditor) {
|
||||
preferencesEditor.focusNextResult();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
const focusNextSearchResultCommand = new FocusNextSearchResultCommand({
|
||||
id: SETTINGS_EDITOR_COMMAND_FOCUS_NEXT_SETTING,
|
||||
precondition: CONTEXT_SETTINGS_SEARCH_FOCUS,
|
||||
kbOpts: { primary: KeyCode.Enter }
|
||||
});
|
||||
KeybindingsRegistry.registerCommandAndKeybindingRule(focusNextSearchResultCommand.toCommandAndKeybindingRule(KeybindingsRegistry.WEIGHT.editorContrib()));
|
||||
|
||||
class FocusPreviousSearchResultCommand extends SettingsCommand {
|
||||
|
||||
public runCommand(accessor: ServicesAccessor, args: any): void {
|
||||
const preferencesEditor = this.getPreferencesEditor(accessor);
|
||||
if (preferencesEditor) {
|
||||
preferencesEditor.focusPreviousResult();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
const focusPreviousSearchResultCommand = new FocusPreviousSearchResultCommand({
|
||||
id: SETTINGS_EDITOR_COMMAND_FOCUS_PREVIOUS_SETTING,
|
||||
precondition: CONTEXT_SETTINGS_SEARCH_FOCUS,
|
||||
kbOpts: { primary: KeyMod.Shift | KeyCode.Enter }
|
||||
});
|
||||
KeybindingsRegistry.registerCommandAndKeybindingRule(focusPreviousSearchResultCommand.toCommandAndKeybindingRule(KeybindingsRegistry.WEIGHT.editorContrib()));
|
||||
|
||||
@@ -6,6 +6,7 @@
|
||||
import { TPromise } from 'vs/base/common/winjs.base';
|
||||
import * as nls from 'vs/nls';
|
||||
import { Delayer } from 'vs/base/common/async';
|
||||
import { tail } from 'vs/base/common/arrays';
|
||||
import { Disposable, IDisposable, dispose } from 'vs/base/common/lifecycle';
|
||||
import { IAction } from 'vs/base/common/actions';
|
||||
import { IJSONSchema } from 'vs/base/common/jsonSchema';
|
||||
@@ -15,24 +16,24 @@ import * as editorCommon from 'vs/editor/common/editorCommon';
|
||||
import { Range, IRange } from 'vs/editor/common/core/range';
|
||||
import { IConfigurationRegistry, Extensions as ConfigurationExtensions, ConfigurationScope, IConfigurationPropertySchema } from 'vs/platform/configuration/common/configurationRegistry';
|
||||
import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation';
|
||||
import { IPreferencesService, ISettingsGroup, ISetting, IPreferencesEditorModel, IFilterResult, ISettingsEditorModel } from 'vs/workbench/parts/preferences/common/preferences';
|
||||
import { SettingsEditorModel, DefaultSettingsEditorModel } from 'vs/workbench/parts/preferences/common/preferencesModels';
|
||||
import { IPreferencesService, ISettingsGroup, ISetting, IPreferencesEditorModel, IFilterResult, ISettingsEditorModel, IScoredResults } from 'vs/workbench/parts/preferences/common/preferences';
|
||||
import { SettingsEditorModel, DefaultSettingsEditorModel, WorkspaceConfigurationEditorModel } from 'vs/workbench/parts/preferences/common/preferencesModels';
|
||||
import { ICodeEditor, IEditorMouseEvent, MouseTargetType } from 'vs/editor/browser/editorBrowser';
|
||||
import { IContextMenuService, ContextSubMenu } from 'vs/platform/contextview/browser/contextView';
|
||||
import { SettingsGroupTitleWidget, EditPreferenceWidget, SettingsHeaderWidget } from 'vs/workbench/parts/preferences/browser/preferencesWidgets';
|
||||
import { SettingsGroupTitleWidget, EditPreferenceWidget, SettingsHeaderWidget, DefaultSettingsHeaderWidget, FloatingClickWidget } from 'vs/workbench/parts/preferences/browser/preferencesWidgets';
|
||||
import { ITelemetryService } from 'vs/platform/telemetry/common/telemetry';
|
||||
import { RangeHighlightDecorations } from 'vs/workbench/common/editor/rangeDecorations';
|
||||
import { IConfigurationEditingService, ConfigurationEditingError, ConfigurationEditingErrorCode, ConfigurationTarget } from 'vs/workbench/services/configuration/common/configurationEditing';
|
||||
import { ITextFileService } from 'vs/workbench/services/textfile/common/textfiles';
|
||||
import { overrideIdentifierFromKey } from 'vs/platform/configuration/common/model';
|
||||
import { IMarkerService, IMarkerData } from 'vs/platform/markers/common/markers';
|
||||
import { IWorkspaceConfigurationService } from 'vs/workbench/services/configuration/common/configuration';
|
||||
import { IMessageService, Severity } from 'vs/platform/message/common/message';
|
||||
import { IWorkbenchEditorService } from 'vs/workbench/services/editor/common/editorService';
|
||||
import { ICursorPositionChangedEvent } from 'vs/editor/common/controller/cursorEvents';
|
||||
import { ModelDecorationOptions } from 'vs/editor/common/model/textModelWithDecorations';
|
||||
import { IWorkspaceContextService } from 'vs/platform/workspace/common/workspace';
|
||||
import { IWorkspaceContextService, WorkbenchState } from 'vs/platform/workspace/common/workspace';
|
||||
import { MarkdownString } from 'vs/base/common/htmlContent';
|
||||
import { overrideIdentifierFromKey, IConfigurationService, ConfigurationTarget } from 'vs/platform/configuration/common/configuration';
|
||||
import { IEnvironmentService } from 'vs/platform/environment/common/environment';
|
||||
|
||||
export interface IPreferencesRenderer<T> extends IDisposable {
|
||||
preferencesModel: IPreferencesEditorModel<T>;
|
||||
@@ -41,21 +42,22 @@ export interface IPreferencesRenderer<T> extends IDisposable {
|
||||
onFocusPreference: Event<T>;
|
||||
onClearFocusPreference: Event<T>;
|
||||
onUpdatePreference: Event<{ key: string, value: any, source: T }>;
|
||||
onTriggeredFuzzy?: Event<void>;
|
||||
|
||||
render(): void;
|
||||
updatePreference(key: string, value: any, source: T): void;
|
||||
filterPreferences(filterResult: IFilterResult): void;
|
||||
filterPreferences(filterResult: IFilterResult, fuzzySearchAvailable: boolean): void;
|
||||
focusPreference(setting: T): void;
|
||||
clearFocus(setting: T): void;
|
||||
}
|
||||
|
||||
|
||||
export class UserSettingsRenderer extends Disposable implements IPreferencesRenderer<ISetting> {
|
||||
|
||||
private settingHighlighter: SettingHighlighter;
|
||||
private editSettingActionRenderer: EditSettingRenderer;
|
||||
private highlightMatchesRenderer: HighlightMatchesRenderer;
|
||||
private modelChangeDelayer: Delayer<void> = new Delayer<void>(200);
|
||||
private _associatedPreferencesModel: IPreferencesEditorModel<ISetting>;
|
||||
|
||||
private _onFocusPreference: Emitter<ISetting> = new Emitter<ISetting>();
|
||||
public readonly onFocusPreference: Event<ISetting> = this._onFocusPreference.event;
|
||||
@@ -68,16 +70,14 @@ export class UserSettingsRenderer extends Disposable implements IPreferencesRend
|
||||
|
||||
private filterResult: IFilterResult;
|
||||
|
||||
constructor(protected editor: ICodeEditor, public readonly preferencesModel: SettingsEditorModel, private _associatedPreferencesModel: IPreferencesEditorModel<ISetting>,
|
||||
constructor(protected editor: ICodeEditor, public readonly preferencesModel: SettingsEditorModel,
|
||||
@IPreferencesService protected preferencesService: IPreferencesService,
|
||||
@ITelemetryService private telemetryService: ITelemetryService,
|
||||
@ITextFileService private textFileService: ITextFileService,
|
||||
@IConfigurationEditingService private configurationEditingService: IConfigurationEditingService,
|
||||
@IMessageService private messageService: IMessageService,
|
||||
@IConfigurationService private configurationService: IConfigurationService,
|
||||
@IInstantiationService protected instantiationService: IInstantiationService
|
||||
) {
|
||||
super();
|
||||
this._register(preferencesModel);
|
||||
this.settingHighlighter = this._register(instantiationService.createInstance(SettingHighlighter, editor, this._onFocusPreference, this._onClearFocusPreference));
|
||||
this.highlightMatchesRenderer = this._register(instantiationService.createInstance(HighlightMatchesRenderer, editor));
|
||||
this.editSettingActionRenderer = this._register(this.instantiationService.createInstance(EditSettingRenderer, this.editor, this.preferencesModel, this.settingHighlighter));
|
||||
@@ -108,22 +108,16 @@ export class UserSettingsRenderer extends Disposable implements IPreferencesRend
|
||||
}
|
||||
|
||||
public updatePreference(key: string, value: any, source: ISetting): void {
|
||||
/* __GDPR__
|
||||
"defaultSettingsActions.copySetting" : {
|
||||
"userConfigurationKeys" : { "classification": "SystemMetaData", "purpose": "FeatureInsight" }
|
||||
}
|
||||
*/
|
||||
this.telemetryService.publicLog('defaultSettingsActions.copySetting', { userConfigurationKeys: [key] });
|
||||
const overrideIdentifier = source.overrideOf ? overrideIdentifierFromKey(source.overrideOf.key) : null;
|
||||
const resource = this.preferencesModel.uri;
|
||||
this.configurationEditingService.writeConfiguration(this.preferencesModel.configurationTarget, { key, value }, { donotSave: this.textFileService.isDirty(resource), donotNotifyError: true, scopes: { overrideIdentifier, resource } })
|
||||
.then(() => this.onSettingUpdated(source), error => {
|
||||
this.messageService.show(Severity.Error, this.toErrorMessage(error, this.preferencesModel.configurationTarget));
|
||||
});
|
||||
}
|
||||
|
||||
private toErrorMessage(error: ConfigurationEditingError, target: ConfigurationTarget): string {
|
||||
switch (error.code) {
|
||||
case ConfigurationEditingErrorCode.ERROR_INVALID_CONFIGURATION: {
|
||||
return nls.localize('errorInvalidConfiguration', "Unable to write into settings. Correct errors/warnings in the file and try again.");
|
||||
};
|
||||
}
|
||||
return error.message;
|
||||
this.configurationService.updateValue(key, value, { overrideIdentifier, resource }, this.preferencesModel.configurationTarget)
|
||||
.then(() => this.onSettingUpdated(source));
|
||||
}
|
||||
|
||||
private onModelChanged(): void {
|
||||
@@ -180,19 +174,18 @@ export class UserSettingsRenderer extends Disposable implements IPreferencesRend
|
||||
|
||||
export class WorkspaceSettingsRenderer extends UserSettingsRenderer implements IPreferencesRenderer<ISetting> {
|
||||
|
||||
private untrustedSettingRenderer: UnsupportedWorkspaceSettingsRenderer;
|
||||
private unsupportedSettingsRenderer: UnsupportedSettingsRenderer;
|
||||
private workspaceConfigurationRenderer: WorkspaceConfigurationRenderer;
|
||||
|
||||
constructor(editor: ICodeEditor, preferencesModel: SettingsEditorModel, associatedPreferencesModel: IPreferencesEditorModel<ISetting>,
|
||||
constructor(editor: ICodeEditor, preferencesModel: SettingsEditorModel,
|
||||
@IPreferencesService preferencesService: IPreferencesService,
|
||||
@ITelemetryService telemetryService: ITelemetryService,
|
||||
@ITextFileService textFileService: ITextFileService,
|
||||
@IConfigurationEditingService configurationEditingService: IConfigurationEditingService,
|
||||
@IMessageService messageService: IMessageService,
|
||||
@IConfigurationService configurationService: IConfigurationService,
|
||||
@IInstantiationService instantiationService: IInstantiationService
|
||||
) {
|
||||
super(editor, preferencesModel, associatedPreferencesModel, preferencesService, telemetryService, textFileService, configurationEditingService, messageService, instantiationService);
|
||||
this.untrustedSettingRenderer = this._register(instantiationService.createInstance(UnsupportedWorkspaceSettingsRenderer, editor, preferencesModel));
|
||||
super(editor, preferencesModel, preferencesService, telemetryService, textFileService, configurationService, instantiationService);
|
||||
this.unsupportedSettingsRenderer = this._register(instantiationService.createInstance(UnsupportedSettingsRenderer, editor, preferencesModel));
|
||||
this.workspaceConfigurationRenderer = this._register(instantiationService.createInstance(WorkspaceConfigurationRenderer, editor, preferencesModel));
|
||||
}
|
||||
|
||||
@@ -202,25 +195,24 @@ export class WorkspaceSettingsRenderer extends UserSettingsRenderer implements I
|
||||
|
||||
public render(): void {
|
||||
super.render();
|
||||
this.untrustedSettingRenderer.render();
|
||||
this.unsupportedSettingsRenderer.render();
|
||||
this.workspaceConfigurationRenderer.render();
|
||||
}
|
||||
}
|
||||
|
||||
export class FolderSettingsRenderer extends UserSettingsRenderer implements IPreferencesRenderer<ISetting> {
|
||||
|
||||
private unsupportedWorkbenchSettingsRenderer: UnsupportedWorkbenchSettingsRenderer;
|
||||
private unsupportedSettingsRenderer: UnsupportedSettingsRenderer;
|
||||
|
||||
constructor(editor: ICodeEditor, preferencesModel: SettingsEditorModel, associatedPreferencesModel: IPreferencesEditorModel<ISetting>,
|
||||
constructor(editor: ICodeEditor, preferencesModel: SettingsEditorModel,
|
||||
@IPreferencesService preferencesService: IPreferencesService,
|
||||
@ITelemetryService telemetryService: ITelemetryService,
|
||||
@ITextFileService textFileService: ITextFileService,
|
||||
@IConfigurationEditingService configurationEditingService: IConfigurationEditingService,
|
||||
@IMessageService messageService: IMessageService,
|
||||
@IConfigurationService configurationService: IConfigurationService,
|
||||
@IInstantiationService instantiationService: IInstantiationService
|
||||
) {
|
||||
super(editor, preferencesModel, associatedPreferencesModel, preferencesService, telemetryService, textFileService, configurationEditingService, messageService, instantiationService);
|
||||
this.unsupportedWorkbenchSettingsRenderer = this._register(instantiationService.createInstance(UnsupportedWorkbenchSettingsRenderer, editor, preferencesModel));
|
||||
super(editor, preferencesModel, preferencesService, telemetryService, textFileService, configurationService, instantiationService);
|
||||
this.unsupportedSettingsRenderer = this._register(instantiationService.createInstance(UnsupportedSettingsRenderer, editor, preferencesModel));
|
||||
}
|
||||
|
||||
protected createHeader(): void {
|
||||
@@ -229,7 +221,7 @@ export class FolderSettingsRenderer extends UserSettingsRenderer implements IPre
|
||||
|
||||
public render(): void {
|
||||
super.render();
|
||||
this.unsupportedWorkbenchSettingsRenderer.render();
|
||||
this.unsupportedSettingsRenderer.render();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -242,6 +234,7 @@ export class DefaultSettingsRenderer extends Disposable implements IPreferencesR
|
||||
private filteredMatchesRenderer: FilteredMatchesRenderer;
|
||||
private hiddenAreasRenderer: HiddenAreasRenderer;
|
||||
private editSettingActionRenderer: EditSettingRenderer;
|
||||
private feedbackWidgetRenderer: FeedbackWidgetRenderer;
|
||||
|
||||
private _onUpdatePreference: Emitter<{ key: string, value: any, source: ISetting }> = new Emitter<{ key: string, value: any, source: ISetting }>();
|
||||
public readonly onUpdatePreference: Event<{ key: string, value: any, source: ISetting }> = this._onUpdatePreference.event;
|
||||
@@ -252,6 +245,8 @@ export class DefaultSettingsRenderer extends Disposable implements IPreferencesR
|
||||
private _onClearFocusPreference: Emitter<ISetting> = new Emitter<ISetting>();
|
||||
public readonly onClearFocusPreference: Event<ISetting> = this._onClearFocusPreference.event;
|
||||
|
||||
public readonly onTriggeredFuzzy: Event<void>;
|
||||
|
||||
private filterResult: IFilterResult;
|
||||
|
||||
constructor(protected editor: ICodeEditor, public readonly preferencesModel: DefaultSettingsEditorModel,
|
||||
@@ -265,11 +260,17 @@ export class DefaultSettingsRenderer extends Disposable implements IPreferencesR
|
||||
this.settingsGroupTitleRenderer = this._register(instantiationService.createInstance(SettingsGroupTitleRenderer, editor));
|
||||
this.filteredMatchesRenderer = this._register(instantiationService.createInstance(FilteredMatchesRenderer, editor));
|
||||
this.editSettingActionRenderer = this._register(instantiationService.createInstance(EditSettingRenderer, editor, preferencesModel, this.settingHighlighter));
|
||||
this.feedbackWidgetRenderer = this._register(instantiationService.createInstance(FeedbackWidgetRenderer, editor));
|
||||
|
||||
this._register(this.editSettingActionRenderer.onUpdateSetting(e => this._onUpdatePreference.fire(e)));
|
||||
const paranthesisHidingRenderer = this._register(instantiationService.createInstance(StaticContentHidingRenderer, editor, preferencesModel.settingsGroups));
|
||||
this.hiddenAreasRenderer = this._register(instantiationService.createInstance(HiddenAreasRenderer, editor, [this.settingsGroupTitleRenderer, this.filteredMatchesRenderer, paranthesisHidingRenderer]));
|
||||
const parenthesisHidingRenderer = this._register(instantiationService.createInstance(StaticContentHidingRenderer, editor, preferencesModel.settingsGroups));
|
||||
|
||||
const hiddenAreasProviders = [this.settingsGroupTitleRenderer, this.filteredMatchesRenderer, parenthesisHidingRenderer];
|
||||
this.hiddenAreasRenderer = this._register(instantiationService.createInstance(HiddenAreasRenderer, editor, hiddenAreasProviders));
|
||||
|
||||
this._register(this.settingsGroupTitleRenderer.onHiddenAreasChanged(() => this.hiddenAreasRenderer.render()));
|
||||
|
||||
this.onTriggeredFuzzy = this.settingsHeaderRenderer.onClick;
|
||||
}
|
||||
|
||||
public get associatedPreferencesModel(): IPreferencesEditorModel<ISetting> {
|
||||
@@ -284,28 +285,32 @@ export class DefaultSettingsRenderer extends Disposable implements IPreferencesR
|
||||
public render() {
|
||||
this.settingsGroupTitleRenderer.render(this.preferencesModel.settingsGroups);
|
||||
this.editSettingActionRenderer.render(this.preferencesModel.settingsGroups, this._associatedPreferencesModel);
|
||||
this.feedbackWidgetRenderer.render(null);
|
||||
this.hiddenAreasRenderer.render();
|
||||
this.settingHighlighter.clear(true);
|
||||
this.settingsGroupTitleRenderer.showGroup(1);
|
||||
this.settingsGroupTitleRenderer.showGroup(0);
|
||||
this.hiddenAreasRenderer.render();
|
||||
}
|
||||
|
||||
public filterPreferences(filterResult: IFilterResult): void {
|
||||
public filterPreferences(filterResult: IFilterResult, fuzzySearchAvailable: boolean): void {
|
||||
this.filterResult = filterResult;
|
||||
if (!filterResult) {
|
||||
this.settingHighlighter.clear(true);
|
||||
this.filteredMatchesRenderer.render(null);
|
||||
this.settingsHeaderRenderer.render(this.preferencesModel.settingsGroups);
|
||||
this.settingsGroupTitleRenderer.render(this.preferencesModel.settingsGroups);
|
||||
this.settingsGroupTitleRenderer.showGroup(1);
|
||||
this.editSettingActionRenderer.render(this.preferencesModel.settingsGroups, this._associatedPreferencesModel);
|
||||
} else {
|
||||
this.filteredMatchesRenderer.render(filterResult);
|
||||
this.settingsHeaderRenderer.render(filterResult.filteredGroups);
|
||||
if (filterResult) {
|
||||
this.filteredMatchesRenderer.render(filterResult, this.preferencesModel.settingsGroups);
|
||||
this.settingsGroupTitleRenderer.render(filterResult.filteredGroups);
|
||||
this.feedbackWidgetRenderer.render(filterResult);
|
||||
this.settingsHeaderRenderer.render(filterResult, fuzzySearchAvailable);
|
||||
this.settingHighlighter.clear(true);
|
||||
this.editSettingActionRenderer.render(filterResult.filteredGroups, this._associatedPreferencesModel);
|
||||
} else {
|
||||
this.settingHighlighter.clear(true);
|
||||
this.filteredMatchesRenderer.render(null, this.preferencesModel.settingsGroups);
|
||||
this.feedbackWidgetRenderer.render(null);
|
||||
this.settingsHeaderRenderer.render(null);
|
||||
this.settingsGroupTitleRenderer.render(this.preferencesModel.settingsGroups);
|
||||
this.settingsGroupTitleRenderer.showGroup(0);
|
||||
this.editSettingActionRenderer.render(this.preferencesModel.settingsGroups, this._associatedPreferencesModel);
|
||||
}
|
||||
|
||||
this.hiddenAreasRenderer.render();
|
||||
}
|
||||
|
||||
@@ -372,6 +377,9 @@ export class StaticContentHidingRenderer extends Disposable implements HiddenAre
|
||||
|
||||
get hiddenAreas(): IRange[] {
|
||||
const model = this.editor.getModel();
|
||||
|
||||
// Hide extra chars for "search results" and "commonly used" groups
|
||||
const lastGroup = tail(this.settingsGroups);
|
||||
return [
|
||||
{
|
||||
startLineNumber: 1,
|
||||
@@ -385,6 +393,12 @@ export class StaticContentHidingRenderer extends Disposable implements HiddenAre
|
||||
endLineNumber: this.settingsGroups[0].range.endLineNumber + 4,
|
||||
endColumn: model.getLineMaxColumn(this.settingsGroups[0].range.endLineNumber + 4)
|
||||
},
|
||||
{
|
||||
startLineNumber: lastGroup.range.endLineNumber + 1,
|
||||
startColumn: model.getLineMinColumn(lastGroup.range.endLineNumber + 1),
|
||||
endLineNumber: Math.min(model.getLineCount(), lastGroup.range.endLineNumber + 4),
|
||||
endColumn: model.getLineMaxColumn(Math.min(model.getLineCount(), lastGroup.range.endLineNumber + 4))
|
||||
},
|
||||
{
|
||||
startLineNumber: model.getLineCount() - 1,
|
||||
startColumn: model.getLineMinColumn(model.getLineCount() - 1),
|
||||
@@ -398,20 +412,20 @@ export class StaticContentHidingRenderer extends Disposable implements HiddenAre
|
||||
|
||||
class DefaultSettingsHeaderRenderer extends Disposable {
|
||||
|
||||
private settingsHeaderWidget: SettingsHeaderWidget;
|
||||
private settingsHeaderWidget: DefaultSettingsHeaderWidget;
|
||||
public onClick: Event<void>;
|
||||
|
||||
constructor(private editor: ICodeEditor, scope: ConfigurationScope) {
|
||||
super();
|
||||
const title = scope === ConfigurationScope.RESOURCE ? nls.localize('defaultFolderSettingsTitle', "Default Folder Settings") : nls.localize('defaultSettingsTitle', "Default Settings");
|
||||
this.settingsHeaderWidget = this._register(new SettingsHeaderWidget(editor, title));
|
||||
this.settingsHeaderWidget = this._register(new DefaultSettingsHeaderWidget(editor, title));
|
||||
this.onClick = this.settingsHeaderWidget.onClick;
|
||||
}
|
||||
|
||||
public render(settingsGroups: ISettingsGroup[]) {
|
||||
if (settingsGroups.length) {
|
||||
this.settingsHeaderWidget.setMessage('');
|
||||
} else {
|
||||
this.settingsHeaderWidget.setMessage(nls.localize('noSettingsFound', "No Settings Found."));
|
||||
}
|
||||
public render(filterResult: IFilterResult, fuzzySearchAvailable = false) {
|
||||
const hasSettings = !filterResult || filterResult.filteredGroups.length > 0;
|
||||
const promptFuzzy = fuzzySearchAvailable && filterResult && !filterResult.metadata;
|
||||
this.settingsHeaderWidget.toggleMessage(hasSettings, promptFuzzy);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -441,9 +455,17 @@ export class SettingsGroupTitleRenderer extends Disposable implements HiddenArea
|
||||
|
||||
public render(settingsGroups: ISettingsGroup[]) {
|
||||
this.disposeWidgets();
|
||||
if (!settingsGroups) {
|
||||
return;
|
||||
}
|
||||
|
||||
this.settingsGroups = settingsGroups.slice();
|
||||
this.settingsGroupTitleWidgets = [];
|
||||
for (const group of this.settingsGroups.slice().reverse()) {
|
||||
if (group.sections.every(sect => sect.settings.length === 0)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
const settingsGroupTitleWidget = this.instantiationService.createInstance(SettingsGroupTitleWidget, this.editor, group);
|
||||
settingsGroupTitleWidget.render();
|
||||
this.settingsGroupTitleWidgets.push(settingsGroupTitleWidget);
|
||||
@@ -453,9 +475,11 @@ export class SettingsGroupTitleRenderer extends Disposable implements HiddenArea
|
||||
this.settingsGroupTitleWidgets.reverse();
|
||||
}
|
||||
|
||||
public showGroup(group: number) {
|
||||
this.hiddenGroups = this.settingsGroups.filter((g, i) => i !== group - 1);
|
||||
for (const groupTitleWidget of this.settingsGroupTitleWidgets.filter((g, i) => i !== group - 1)) {
|
||||
public showGroup(groupIdx: number) {
|
||||
const shownGroup = this.settingsGroupTitleWidgets[groupIdx].settingsGroup;
|
||||
|
||||
this.hiddenGroups = this.settingsGroups.filter(g => g !== shownGroup);
|
||||
for (const groupTitleWidget of this.settingsGroupTitleWidgets.filter(widget => widget.settingsGroup !== shownGroup)) {
|
||||
groupTitleWidget.toggleCollapse(true);
|
||||
}
|
||||
this._onHiddenAreasChanged.fire();
|
||||
@@ -526,6 +550,120 @@ export class HiddenAreasRenderer extends Disposable {
|
||||
}
|
||||
}
|
||||
|
||||
export class FeedbackWidgetRenderer extends Disposable {
|
||||
private static COMMENT_TEXT = 'Modify the below results to match your expectations. Assign scores to indicate their relevance. Replace this comment with any text feedback.';
|
||||
|
||||
private _feedbackWidget: FloatingClickWidget;
|
||||
private _currentResult: IFilterResult;
|
||||
|
||||
constructor(private editor: ICodeEditor,
|
||||
@IInstantiationService private instantiationService: IInstantiationService,
|
||||
@IWorkbenchEditorService private editorService: IWorkbenchEditorService,
|
||||
@ITelemetryService private telemetryService: ITelemetryService,
|
||||
@IMessageService private messageService: IMessageService
|
||||
) {
|
||||
super();
|
||||
}
|
||||
|
||||
public render(result: IFilterResult): void {
|
||||
this._currentResult = result;
|
||||
if (result && result.metadata) {
|
||||
this.showWidget();
|
||||
} else if (this._feedbackWidget) {
|
||||
this.disposeWidget();
|
||||
}
|
||||
}
|
||||
|
||||
private showWidget(): void {
|
||||
if (!this._feedbackWidget) {
|
||||
this._feedbackWidget = this._register(this.instantiationService.createInstance(FloatingClickWidget, this.editor, 'Provide feedback', null));
|
||||
this._register(this._feedbackWidget.onClick(() => this.getFeedback()));
|
||||
this._feedbackWidget.render();
|
||||
}
|
||||
}
|
||||
|
||||
private getFeedback(): void {
|
||||
if (!this.telemetryService.isOptedIn) {
|
||||
this.messageService.show(Severity.Error, 'Can\'t send feedback, user is opted out of telemetry');
|
||||
return;
|
||||
}
|
||||
|
||||
const result = this._currentResult;
|
||||
const actualResultNames = Object.keys(result.metadata.scoredResults);
|
||||
|
||||
const feedbackQuery = {};
|
||||
feedbackQuery['comment'] = FeedbackWidgetRenderer.COMMENT_TEXT;
|
||||
feedbackQuery['queryString'] = result.query;
|
||||
feedbackQuery['resultScores'] = {};
|
||||
actualResultNames.forEach(settingKey => {
|
||||
feedbackQuery['resultScores'][settingKey] = 10;
|
||||
});
|
||||
|
||||
const contents = JSON.stringify(feedbackQuery, undefined, ' ');
|
||||
this.editorService.openEditor({ contents, language: 'json' }, /*sideBySide=*/true).then(feedbackEditor => {
|
||||
const sendFeedbackWidget = this._register(this.instantiationService.createInstance(FloatingClickWidget, feedbackEditor.getControl(), 'Send feedback', null));
|
||||
sendFeedbackWidget.render();
|
||||
|
||||
this._register(sendFeedbackWidget.onClick(() => {
|
||||
this.sendFeedback(feedbackEditor.getControl() as ICodeEditor, result, result.metadata.scoredResults).then(() => {
|
||||
sendFeedbackWidget.dispose();
|
||||
this.messageService.show(Severity.Info, 'Feedback sent successfully');
|
||||
}, err => {
|
||||
this.messageService.show(Severity.Error, 'Error sending feedback: ' + err.message);
|
||||
});
|
||||
}));
|
||||
});
|
||||
}
|
||||
|
||||
private sendFeedback(feedbackEditor: ICodeEditor, result: IFilterResult, actualResults: IScoredResults): TPromise<void> {
|
||||
const model = feedbackEditor.getModel();
|
||||
const expectedQueryLines = model.getLinesContent();
|
||||
let expectedQuery: any;
|
||||
try {
|
||||
expectedQuery = JSON.parse(expectedQueryLines.join('\n'));
|
||||
} catch (e) {
|
||||
// invalid JSON
|
||||
return TPromise.wrapError(new Error('Invalid JSON: ' + e.message));
|
||||
}
|
||||
|
||||
const userComment = expectedQuery.comment === FeedbackWidgetRenderer.COMMENT_TEXT ? undefined : expectedQuery.comment;
|
||||
|
||||
/* __GDPR__
|
||||
"settingsSearchResultFeedback" : {
|
||||
"query" : { "classification": "CustomContent", "purpose": "FeatureInsight" },
|
||||
"userComment" : { "classification": "CustomerContent", "purpose": "FeatureInsight" },
|
||||
"actualResults" : { "classification": "SystemMetaData", "purpose": "FeatureInsight" },
|
||||
"expectedResults" : { "classification": "SystemMetaData", "purpose": "FeatureInsight" },
|
||||
"url" : { "classification": "CustomerContent", "purpose": "FeatureInsight" },
|
||||
"duration" : { "classification": "SystemMetaData", "purpose": "FeatureInsight" },
|
||||
"timestamp" : { "classification": "SystemMetaData", "purpose": "FeatureInsight" }
|
||||
}
|
||||
*/
|
||||
return this.telemetryService.publicLog('settingsSearchResultFeedback', {
|
||||
query: result.query,
|
||||
userComment,
|
||||
actualResults,
|
||||
expectedResults: expectedQuery.resultScores,
|
||||
url: result.metadata.remoteUrl,
|
||||
duration: result.metadata.duration,
|
||||
timestamp: result.metadata.timestamp
|
||||
});
|
||||
}
|
||||
|
||||
private disposeWidget(): void {
|
||||
if (this._feedbackWidget) {
|
||||
this._feedbackWidget.dispose();
|
||||
this._feedbackWidget = null;
|
||||
}
|
||||
}
|
||||
|
||||
public dispose() {
|
||||
this.disposeWidget();
|
||||
|
||||
super.dispose();
|
||||
}
|
||||
}
|
||||
|
||||
export class FilteredMatchesRenderer extends Disposable implements HiddenAreasProvider {
|
||||
|
||||
private decorationIds: string[] = [];
|
||||
@@ -537,7 +675,7 @@ export class FilteredMatchesRenderer extends Disposable implements HiddenAreasPr
|
||||
super();
|
||||
}
|
||||
|
||||
public render(result: IFilterResult): void {
|
||||
public render(result: IFilterResult, allSettingsGroups: ISettingsGroup[]): void {
|
||||
const model = this.editor.getModel();
|
||||
this.hiddenAreas = [];
|
||||
this.editor.changeDecorations(changeAccessor => {
|
||||
@@ -548,6 +686,8 @@ export class FilteredMatchesRenderer extends Disposable implements HiddenAreasPr
|
||||
this.editor.changeDecorations(changeAccessor => {
|
||||
this.decorationIds = changeAccessor.deltaDecorations(this.decorationIds, result.matches.map(match => this.createDecoration(match, model)));
|
||||
});
|
||||
} else {
|
||||
this.hiddenAreas = this.computeHiddenRanges(allSettingsGroups, allSettingsGroups, model);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -558,6 +698,7 @@ export class FilteredMatchesRenderer extends Disposable implements HiddenAreasPr
|
||||
stickiness: editorCommon.TrackedRangeStickiness.NeverGrowsWhenTypingAtEdges,
|
||||
className: 'findMatch'
|
||||
}
|
||||
|
||||
};
|
||||
}
|
||||
|
||||
@@ -565,7 +706,7 @@ export class FilteredMatchesRenderer extends Disposable implements HiddenAreasPr
|
||||
const notMatchesRanges: IRange[] = [];
|
||||
for (const group of allSettingsGroups) {
|
||||
const filteredGroup = filteredGroups.filter(g => g.title === group.title)[0];
|
||||
if (!filteredGroup) {
|
||||
if (!filteredGroup || filteredGroup.sections.every(sect => sect.settings.length === 0)) {
|
||||
notMatchesRanges.push({
|
||||
startLineNumber: group.range.startLineNumber - 1,
|
||||
startColumn: model.getLineMinColumn(group.range.startLineNumber - 1),
|
||||
@@ -796,10 +937,14 @@ class EditSettingRenderer extends Disposable {
|
||||
let configurationNode = configurationMap[setting.key];
|
||||
if (configurationNode) {
|
||||
if (this.isDefaultSettings()) {
|
||||
if (setting.key === 'launch') {
|
||||
// Do not show because of https://github.com/Microsoft/vscode/issues/32593
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
if (configurationNode.type === 'boolean' || configurationNode.enum) {
|
||||
if ((<SettingsEditorModel>this.masterSettingsModel).configurationTarget !== ConfigurationTarget.FOLDER) {
|
||||
if ((<SettingsEditorModel>this.masterSettingsModel).configurationTarget !== ConfigurationTarget.WORKSPACE_FOLDER) {
|
||||
return true;
|
||||
}
|
||||
if (configurationNode.scope === ConfigurationScope.RESOURCE) {
|
||||
@@ -847,7 +992,7 @@ class EditSettingRenderer extends Disposable {
|
||||
}
|
||||
|
||||
private onEditSettingClicked(editPreferenceWidget: EditPreferenceWidget<ISetting>, e: IEditorMouseEvent): void {
|
||||
const anchor = { x: e.event.posx + 1, y: e.event.posy + 10 };
|
||||
const anchor = { x: e.event.posx, y: e.event.posy + 10 };
|
||||
const actions = this.getSettings(editPreferenceWidget.getLine()).length === 1 ? this.getActions(editPreferenceWidget.preferences[0], this.getConfigurationsMap()[editPreferenceWidget.preferences[0].key])
|
||||
: editPreferenceWidget.preferences.map(setting => new ContextSubMenu(setting.key, this.getActions(setting, this.getConfigurationsMap()[setting.key])));
|
||||
this.contextMenuService.showContextMenu({
|
||||
@@ -888,8 +1033,8 @@ class EditSettingRenderer extends Disposable {
|
||||
}
|
||||
|
||||
private getDefaultActions(setting: ISetting): IAction[] {
|
||||
const settingInOtherModel = this.associatedPreferencesModel.getPreference(setting.key);
|
||||
if (this.isDefaultSettings()) {
|
||||
const settingInOtherModel = this.associatedPreferencesModel.getPreference(setting.key);
|
||||
return [<IAction>{
|
||||
id: 'setDefaultValue',
|
||||
label: settingInOtherModel ? nls.localize('replaceDefaultValue', "Replace in Settings") : nls.localize('copyDefaultValue', "Copy to Settings"),
|
||||
@@ -945,17 +1090,72 @@ class SettingHighlighter extends Disposable {
|
||||
}
|
||||
}
|
||||
|
||||
class UnsupportedWorkspaceSettingsRenderer extends Disposable {
|
||||
class UnsupportedSettingsRenderer extends Disposable {
|
||||
|
||||
constructor(private editor: editorCommon.ICommonCodeEditor, private workspaceSettingsEditorModel: SettingsEditorModel,
|
||||
private decorationIds: string[] = [];
|
||||
private renderingDelayer: Delayer<void> = new Delayer<void>(200);
|
||||
|
||||
constructor(
|
||||
private editor: editorCommon.ICommonCodeEditor,
|
||||
private settingsEditorModel: SettingsEditorModel,
|
||||
@IWorkspaceConfigurationService private configurationService: IWorkspaceConfigurationService,
|
||||
@IMarkerService private markerService: IMarkerService
|
||||
@IMarkerService private markerService: IMarkerService,
|
||||
@IEnvironmentService private environmentService: IEnvironmentService
|
||||
) {
|
||||
super();
|
||||
this._register(this.configurationService.onDidUpdateConfiguration(() => this.render()));
|
||||
this._register(this.editor.getModel().onDidChangeContent(() => this.renderingDelayer.trigger(() => this.render())));
|
||||
}
|
||||
|
||||
private getMarkerMessage(settingKey): string {
|
||||
public render(): void {
|
||||
const configurationRegistry = Registry.as<IConfigurationRegistry>(ConfigurationExtensions.Configuration).getConfigurationProperties();
|
||||
const ranges: IRange[] = [];
|
||||
const markerData: IMarkerData[] = [];
|
||||
for (const settingsGroup of this.settingsEditorModel.settingsGroups) {
|
||||
for (const section of settingsGroup.sections) {
|
||||
for (const setting of section.settings) {
|
||||
if (this.settingsEditorModel.configurationTarget === ConfigurationTarget.WORKSPACE || this.settingsEditorModel.configurationTarget === ConfigurationTarget.WORKSPACE_FOLDER) {
|
||||
// Show warnings for executable settings
|
||||
if (configurationRegistry[setting.key] && configurationRegistry[setting.key].isExecutable) {
|
||||
markerData.push({
|
||||
severity: Severity.Warning,
|
||||
startLineNumber: setting.keyRange.startLineNumber,
|
||||
startColumn: setting.keyRange.startColumn,
|
||||
endLineNumber: setting.keyRange.endLineNumber,
|
||||
endColumn: setting.keyRange.endColumn,
|
||||
message: this.getMarkerMessage(setting.key)
|
||||
});
|
||||
}
|
||||
}
|
||||
if (this.settingsEditorModel.configurationTarget === ConfigurationTarget.WORKSPACE_FOLDER) {
|
||||
// Dim and show information for window settings
|
||||
if (configurationRegistry[setting.key] && configurationRegistry[setting.key].scope === ConfigurationScope.WINDOW) {
|
||||
ranges.push({
|
||||
startLineNumber: setting.keyRange.startLineNumber,
|
||||
startColumn: setting.keyRange.startColumn - 1,
|
||||
endLineNumber: setting.valueRange.endLineNumber,
|
||||
endColumn: setting.valueRange.endColumn
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (markerData.length) {
|
||||
this.markerService.changeOne('preferencesEditor', this.settingsEditorModel.uri, markerData);
|
||||
} else {
|
||||
this.markerService.remove('preferencesEditor', [this.settingsEditorModel.uri]);
|
||||
}
|
||||
this.editor.changeDecorations(changeAccessor => this.decorationIds = changeAccessor.deltaDecorations(this.decorationIds, ranges.map(range => this.createDecoration(range, this.editor.getModel()))));
|
||||
}
|
||||
|
||||
private createDecoration(range: IRange, model: editorCommon.IModel): editorCommon.IModelDeltaDecoration {
|
||||
return {
|
||||
range,
|
||||
options: !this.environmentService.isBuilt || this.environmentService.isExtensionDevelopment ? UnsupportedSettingsRenderer._DIM_CONFIGUARATION_DEV_MODE : UnsupportedSettingsRenderer._DIM_CONFIGUARATION_
|
||||
};
|
||||
}
|
||||
|
||||
private getMarkerMessage(settingKey: string): string {
|
||||
switch (settingKey) {
|
||||
case 'php.validate.executablePath':
|
||||
return nls.localize('unsupportedPHPExecutablePathSetting', "This setting must be a User Setting. To configure PHP for the workspace, open a PHP file and click on 'PHP Path' in the status bar.");
|
||||
@@ -964,67 +1164,14 @@ class UnsupportedWorkspaceSettingsRenderer extends Disposable {
|
||||
}
|
||||
}
|
||||
|
||||
public render(): void {
|
||||
const unsupportedWorkspaceKeys = this.configurationService.getUnsupportedWorkspaceKeys();
|
||||
if (unsupportedWorkspaceKeys.length) {
|
||||
const markerData: IMarkerData[] = [];
|
||||
for (const unsupportedKey of unsupportedWorkspaceKeys) {
|
||||
const setting = this.workspaceSettingsEditorModel.getPreference(unsupportedKey);
|
||||
if (setting) {
|
||||
markerData.push({
|
||||
severity: Severity.Warning,
|
||||
startLineNumber: setting.keyRange.startLineNumber,
|
||||
startColumn: setting.keyRange.startColumn,
|
||||
endLineNumber: setting.keyRange.endLineNumber,
|
||||
endColumn: setting.keyRange.endColumn,
|
||||
message: this.getMarkerMessage(unsupportedKey)
|
||||
});
|
||||
}
|
||||
}
|
||||
if (markerData.length) {
|
||||
this.markerService.changeOne('preferencesEditor', this.workspaceSettingsEditorModel.uri, markerData);
|
||||
} else {
|
||||
this.markerService.remove('preferencesEditor', [this.workspaceSettingsEditorModel.uri]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public dispose(): void {
|
||||
this.markerService.remove('preferencesEditor', [this.workspaceSettingsEditorModel.uri]);
|
||||
super.dispose();
|
||||
}
|
||||
}
|
||||
|
||||
class UnsupportedWorkbenchSettingsRenderer extends Disposable {
|
||||
|
||||
private decorationIds: string[] = [];
|
||||
private renderingDelayer: Delayer<void> = new Delayer<void>(200);
|
||||
|
||||
constructor(private editor: editorCommon.ICommonCodeEditor, private workspaceSettingsEditorModel: SettingsEditorModel,
|
||||
@IWorkspaceConfigurationService private configurationService: IWorkspaceConfigurationService,
|
||||
) {
|
||||
super();
|
||||
this._register(this.editor.getModel().onDidChangeContent(() => this.renderingDelayer.trigger(() => this.render())));
|
||||
}
|
||||
|
||||
public render(): void {
|
||||
const ranges: IRange[] = [];
|
||||
const configurationRegistry = Registry.as<IConfigurationRegistry>(ConfigurationExtensions.Configuration).getConfigurationProperties();
|
||||
for (const settingsGroup of this.workspaceSettingsEditorModel.settingsGroups) {
|
||||
for (const section of settingsGroup.sections) {
|
||||
for (const setting of section.settings) {
|
||||
if (configurationRegistry[setting.key] && configurationRegistry[setting.key].scope === ConfigurationScope.WINDOW) {
|
||||
ranges.push({
|
||||
startLineNumber: setting.keyRange.startLineNumber,
|
||||
startColumn: setting.keyRange.startColumn - 1,
|
||||
endLineNumber: setting.valueRange.endLineNumber,
|
||||
endColumn: setting.valueRange.endColumn
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
this.markerService.remove('preferencesEditor', [this.settingsEditorModel.uri]);
|
||||
if (this.decorationIds) {
|
||||
this.decorationIds = this.editor.changeDecorations(changeAccessor => {
|
||||
return changeAccessor.deltaDecorations(this.decorationIds, []);
|
||||
});
|
||||
}
|
||||
this.editor.changeDecorations(changeAccessor => this.decorationIds = changeAccessor.deltaDecorations(this.decorationIds, ranges.map(range => this.createDecoration(range, this.editor.getModel()))));
|
||||
super.dispose();
|
||||
}
|
||||
|
||||
private static _DIM_CONFIGUARATION_ = ModelDecorationOptions.register({
|
||||
@@ -1034,21 +1181,12 @@ class UnsupportedWorkbenchSettingsRenderer extends Disposable {
|
||||
hoverMessage: new MarkdownString().appendText(nls.localize('unsupportedWorkbenchSetting', "This setting cannot be applied now. It will be applied when you open this folder directly."))
|
||||
});
|
||||
|
||||
private createDecoration(range: IRange, model: editorCommon.IModel): editorCommon.IModelDeltaDecoration {
|
||||
return {
|
||||
range,
|
||||
options: UnsupportedWorkbenchSettingsRenderer._DIM_CONFIGUARATION_
|
||||
};
|
||||
}
|
||||
|
||||
public dispose(): void {
|
||||
if (this.decorationIds) {
|
||||
this.decorationIds = this.editor.changeDecorations(changeAccessor => {
|
||||
return changeAccessor.deltaDecorations(this.decorationIds, []);
|
||||
});
|
||||
}
|
||||
super.dispose();
|
||||
}
|
||||
private static _DIM_CONFIGUARATION_DEV_MODE = ModelDecorationOptions.register({
|
||||
stickiness: editorCommon.TrackedRangeStickiness.NeverGrowsWhenTypingAtEdges,
|
||||
inlineClassName: 'dim-configuration',
|
||||
beforeContentClassName: 'unsupportedWorkbenhSettingInfo',
|
||||
hoverMessage: new MarkdownString().appendText(nls.localize('unsupportedWorkbenchSettingDevMode', "This setting cannot be applied now. It will be applied if you define it's scope as 'resource' while registering, or when you open this folder directly."))
|
||||
});
|
||||
}
|
||||
|
||||
class WorkspaceConfigurationRenderer extends Disposable {
|
||||
@@ -1064,11 +1202,11 @@ class WorkspaceConfigurationRenderer extends Disposable {
|
||||
}
|
||||
|
||||
public render(): void {
|
||||
if (this.workspaceContextService.hasMultiFolderWorkspace()) {
|
||||
if (this.workspaceContextService.getWorkbenchState() === WorkbenchState.WORKSPACE && this.workspaceSettingsEditorModel instanceof WorkspaceConfigurationEditorModel) {
|
||||
this.editor.changeDecorations(changeAccessor => this.decorationIds = changeAccessor.deltaDecorations(this.decorationIds, []));
|
||||
|
||||
const ranges: IRange[] = [];
|
||||
for (const settingsGroup of this.workspaceSettingsEditorModel.settingsGroups) {
|
||||
for (const settingsGroup of this.workspaceSettingsEditorModel.configurationGroups) {
|
||||
for (const section of settingsGroup.sections) {
|
||||
for (const setting of section.settings) {
|
||||
if (setting.key !== 'settings') {
|
||||
|
||||
326
src/vs/workbench/parts/preferences/browser/preferencesSearch.ts
Normal file
326
src/vs/workbench/parts/preferences/browser/preferencesSearch.ts
Normal file
@@ -0,0 +1,326 @@
|
||||
/*---------------------------------------------------------------------------------------------
|
||||
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
* Licensed under the Source EULA. See License.txt in the project root for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
import { TPromise } from 'vs/base/common/winjs.base';
|
||||
import Event, { Emitter } from 'vs/base/common/event';
|
||||
import { ISettingsEditorModel, IFilterResult, ISetting, ISettingsGroup, IWorkbenchSettingsConfiguration, IFilterMetadata } from 'vs/workbench/parts/preferences/common/preferences';
|
||||
import { IRange, Range } from 'vs/editor/common/core/range';
|
||||
import { distinct } from 'vs/base/common/arrays';
|
||||
import * as strings from 'vs/base/common/strings';
|
||||
import { IJSONSchema } from 'vs/base/common/jsonSchema';
|
||||
import { Registry } from 'vs/platform/registry/common/platform';
|
||||
import { IConfigurationRegistry, Extensions } from 'vs/platform/configuration/common/configurationRegistry';
|
||||
import { IMatch, or, matchesContiguousSubString, matchesPrefix, matchesCamelCase, matchesWords } from 'vs/base/common/filters';
|
||||
import { IWorkspaceConfigurationService } from 'vs/workbench/services/configuration/common/configuration';
|
||||
import { IEnvironmentService } from 'vs/platform/environment/common/environment';
|
||||
|
||||
export interface IEndpointDetails {
|
||||
urlBase: string;
|
||||
key: string;
|
||||
boost: number;
|
||||
}
|
||||
|
||||
export class PreferencesSearchProvider {
|
||||
private _onRemoteSearchEnablementChanged = new Emitter<boolean>();
|
||||
public onRemoteSearchEnablementChanged: Event<boolean> = this._onRemoteSearchEnablementChanged.event;
|
||||
|
||||
constructor(
|
||||
@IWorkspaceConfigurationService private configurationService: IWorkspaceConfigurationService,
|
||||
@IEnvironmentService private environmentService: IEnvironmentService
|
||||
) {
|
||||
configurationService.onDidChangeConfiguration(() => this._onRemoteSearchEnablementChanged.fire(this.remoteSearchEnabled));
|
||||
}
|
||||
|
||||
get remoteSearchEnabled(): boolean {
|
||||
if (this.environmentService.appQuality === 'stable') {
|
||||
return false;
|
||||
}
|
||||
|
||||
const endpoint = this.endpoint;
|
||||
return !!endpoint.urlBase && !!endpoint.key;
|
||||
}
|
||||
|
||||
get endpoint(): IEndpointDetails {
|
||||
const workbenchSettings = this.configurationService.getConfiguration<IWorkbenchSettingsConfiguration>().workbench.settings;
|
||||
return {
|
||||
urlBase: workbenchSettings.experimentalFuzzySearchEndpoint,
|
||||
key: workbenchSettings.experimentalFuzzySearchKey,
|
||||
boost: workbenchSettings.experimentalFuzzySearchBoost
|
||||
};
|
||||
}
|
||||
|
||||
startSearch(filter: string, remote: boolean): PreferencesSearchModel {
|
||||
return new PreferencesSearchModel(this, filter, remote);
|
||||
}
|
||||
}
|
||||
|
||||
export class PreferencesSearchModel {
|
||||
private _localProvider: LocalSearchProvider;
|
||||
private _remoteProvider: RemoteSearchProvider;
|
||||
|
||||
constructor(private provider: PreferencesSearchProvider, private filter: string, remote: boolean) {
|
||||
this._localProvider = new LocalSearchProvider(filter);
|
||||
|
||||
if (remote && filter) {
|
||||
this._remoteProvider = new RemoteSearchProvider(filter, this.provider.endpoint);
|
||||
}
|
||||
}
|
||||
|
||||
filterPreferences(preferencesModel: ISettingsEditorModel): TPromise<IFilterResult> {
|
||||
if (!this.filter) {
|
||||
return TPromise.wrap(null);
|
||||
}
|
||||
|
||||
if (this._remoteProvider) {
|
||||
return this._remoteProvider.filterPreferences(preferencesModel).then(null, err => {
|
||||
return this._localProvider.filterPreferences(preferencesModel);
|
||||
});
|
||||
} else {
|
||||
return this._localProvider.filterPreferences(preferencesModel);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
class LocalSearchProvider {
|
||||
private _filter: string;
|
||||
|
||||
constructor(filter: string) {
|
||||
this._filter = filter;
|
||||
}
|
||||
|
||||
filterPreferences(preferencesModel: ISettingsEditorModel): TPromise<IFilterResult> {
|
||||
const regex = strings.createRegExp(this._filter, false, { global: true });
|
||||
|
||||
const groupFilter = (group: ISettingsGroup) => {
|
||||
return regex.test(group.title);
|
||||
};
|
||||
|
||||
const settingFilter = (setting: ISetting) => {
|
||||
return new SettingMatches(this._filter, setting, (filter, setting) => preferencesModel.findValueMatches(filter, setting)).matches;
|
||||
};
|
||||
|
||||
return TPromise.wrap(preferencesModel.filterSettings(this._filter, groupFilter, settingFilter));
|
||||
}
|
||||
}
|
||||
|
||||
class RemoteSearchProvider {
|
||||
private _filter: string;
|
||||
private _remoteSearchP: TPromise<IFilterMetadata>;
|
||||
|
||||
constructor(filter: string, endpoint: IEndpointDetails) {
|
||||
this._filter = filter;
|
||||
this._remoteSearchP = filter ? getSettingsFromBing(filter, endpoint) : TPromise.wrap(null);
|
||||
}
|
||||
|
||||
filterPreferences(preferencesModel: ISettingsEditorModel): TPromise<IFilterResult> {
|
||||
return this._remoteSearchP.then(remoteResult => {
|
||||
const settingFilter = (setting: ISetting) => {
|
||||
if (!!remoteResult.scoredResults[setting.key]) {
|
||||
const settingMatches = new SettingMatches(this._filter, setting, (filter, setting) => preferencesModel.findValueMatches(filter, setting)).matches;
|
||||
if (settingMatches.length) {
|
||||
return settingMatches;
|
||||
} else {
|
||||
return [new Range(setting.keyRange.startLineNumber, setting.keyRange.startColumn, setting.keyRange.endLineNumber, setting.keyRange.startColumn)];
|
||||
}
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
};
|
||||
|
||||
if (remoteResult) {
|
||||
const sortedNames = Object.keys(remoteResult.scoredResults).sort((a, b) => remoteResult.scoredResults[b] - remoteResult.scoredResults[a]);
|
||||
const result = preferencesModel.filterSettings(this._filter, group => null, settingFilter, sortedNames);
|
||||
result.metadata = remoteResult;
|
||||
return result;
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
function getSettingsFromBing(filter: string, endpoint: IEndpointDetails): TPromise<IFilterMetadata> {
|
||||
const url = prepareUrl(filter, endpoint);
|
||||
console.log('fetching: ' + url);
|
||||
const start = Date.now();
|
||||
const p = fetch(url, {
|
||||
headers: new Headers({
|
||||
'User-Agent': 'request',
|
||||
'Content-Type': 'application/json; charset=utf-8',
|
||||
'api-key': endpoint.key
|
||||
})
|
||||
})
|
||||
.then(r => r.json())
|
||||
.then(result => {
|
||||
const timestamp = Date.now();
|
||||
const duration = timestamp - start;
|
||||
console.log('time: ' + duration / 1000);
|
||||
const suggestions = (result.value || [])
|
||||
.map(r => ({
|
||||
name: r.setting || r.Setting,
|
||||
score: r['@search.score']
|
||||
}));
|
||||
|
||||
const scoredResults = Object.create(null);
|
||||
suggestions.forEach(s => {
|
||||
const name = s.name
|
||||
.replace(/^"/, '')
|
||||
.replace(/"$/, '');
|
||||
scoredResults[name] = s.score;
|
||||
});
|
||||
|
||||
return <IFilterMetadata>{
|
||||
remoteUrl: url,
|
||||
duration,
|
||||
timestamp,
|
||||
scoredResults
|
||||
};
|
||||
});
|
||||
|
||||
return TPromise.as(p as any);
|
||||
}
|
||||
|
||||
const API_VERSION = 'api-version=2016-09-01-Preview';
|
||||
const QUERY_TYPE = 'querytype=full';
|
||||
const SCORING_PROFILE = 'scoringProfile=ranking';
|
||||
|
||||
function escapeSpecialChars(query: string): string {
|
||||
return query.replace(/\./g, ' ')
|
||||
.replace(/[\\/+\-&|!"~*?:(){}\[\]\^]/g, '\\$&')
|
||||
.replace(/ /g, ' ') // collapse spaces
|
||||
.trim();
|
||||
}
|
||||
|
||||
function prepareUrl(query: string, endpoint: IEndpointDetails): string {
|
||||
query = escapeSpecialChars(query);
|
||||
const boost = endpoint.boost || 1;
|
||||
const userQuery = `(${query})^${boost}`;
|
||||
|
||||
// Appending Fuzzy after each word.
|
||||
query = query.replace(/\ +/g, '~ ') + '~';
|
||||
|
||||
return `${endpoint.urlBase}?${API_VERSION}&search=${encodeURIComponent(userQuery + ' || ' + query)}&${QUERY_TYPE}&${SCORING_PROFILE}`;
|
||||
}
|
||||
|
||||
class SettingMatches {
|
||||
|
||||
private readonly descriptionMatchingWords: Map<string, IRange[]> = new Map<string, IRange[]>();
|
||||
private readonly keyMatchingWords: Map<string, IRange[]> = new Map<string, IRange[]>();
|
||||
private readonly valueMatchingWords: Map<string, IRange[]> = new Map<string, IRange[]>();
|
||||
|
||||
public readonly matches: IRange[];
|
||||
|
||||
constructor(searchString: string, setting: ISetting, private valuesMatcher: (filter: string, setting: ISetting) => IRange[]) {
|
||||
this.matches = distinct(this._findMatchesInSetting(searchString, setting), (match) => `${match.startLineNumber}_${match.startColumn}_${match.endLineNumber}_${match.endColumn}_`);
|
||||
}
|
||||
|
||||
private _findMatchesInSetting(searchString: string, setting: ISetting): IRange[] {
|
||||
const result = this._doFindMatchesInSetting(searchString, setting);
|
||||
if (setting.overrides && setting.overrides.length) {
|
||||
for (const subSetting of setting.overrides) {
|
||||
const subSettingMatches = new SettingMatches(searchString, subSetting, this.valuesMatcher);
|
||||
let words = searchString.split(' ');
|
||||
const descriptionRanges: IRange[] = this.getRangesForWords(words, this.descriptionMatchingWords, [subSettingMatches.descriptionMatchingWords, subSettingMatches.keyMatchingWords, subSettingMatches.valueMatchingWords]);
|
||||
const keyRanges: IRange[] = this.getRangesForWords(words, this.keyMatchingWords, [subSettingMatches.descriptionMatchingWords, subSettingMatches.keyMatchingWords, subSettingMatches.valueMatchingWords]);
|
||||
const subSettingKeyRanges: IRange[] = this.getRangesForWords(words, subSettingMatches.keyMatchingWords, [this.descriptionMatchingWords, this.keyMatchingWords, subSettingMatches.valueMatchingWords]);
|
||||
const subSettinValueRanges: IRange[] = this.getRangesForWords(words, subSettingMatches.valueMatchingWords, [this.descriptionMatchingWords, this.keyMatchingWords, subSettingMatches.keyMatchingWords]);
|
||||
result.push(...descriptionRanges, ...keyRanges, ...subSettingKeyRanges, ...subSettinValueRanges);
|
||||
result.push(...subSettingMatches.matches);
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
private _doFindMatchesInSetting(searchString: string, setting: ISetting): IRange[] {
|
||||
const registry: { [qualifiedKey: string]: IJSONSchema } = Registry.as<IConfigurationRegistry>(Extensions.Configuration).getConfigurationProperties();
|
||||
const schema: IJSONSchema = registry[setting.key];
|
||||
|
||||
let words = searchString.split(' ');
|
||||
const settingKeyAsWords: string = setting.key.split('.').join(' ');
|
||||
|
||||
for (const word of words) {
|
||||
for (let lineIndex = 0; lineIndex < setting.description.length; lineIndex++) {
|
||||
const descriptionMatches = matchesWords(word, setting.description[lineIndex], true);
|
||||
if (descriptionMatches) {
|
||||
this.descriptionMatchingWords.set(word, descriptionMatches.map(match => this.toDescriptionRange(setting, match, lineIndex)));
|
||||
}
|
||||
}
|
||||
|
||||
const keyMatches = or(matchesWords, matchesCamelCase)(word, settingKeyAsWords);
|
||||
if (keyMatches) {
|
||||
this.keyMatchingWords.set(word, keyMatches.map(match => this.toKeyRange(setting, match)));
|
||||
}
|
||||
|
||||
const valueMatches = typeof setting.value === 'string' ? matchesContiguousSubString(word, setting.value) : null;
|
||||
if (valueMatches) {
|
||||
this.valueMatchingWords.set(word, valueMatches.map(match => this.toValueRange(setting, match)));
|
||||
} else if (schema && schema.enum && schema.enum.some(enumValue => typeof enumValue === 'string' && !!matchesContiguousSubString(word, enumValue))) {
|
||||
this.valueMatchingWords.set(word, []);
|
||||
}
|
||||
}
|
||||
|
||||
const descriptionRanges: IRange[] = [];
|
||||
for (let lineIndex = 0; lineIndex < setting.description.length; lineIndex++) {
|
||||
const matches = or(matchesContiguousSubString)(searchString, setting.description[lineIndex] || '') || [];
|
||||
descriptionRanges.push(...matches.map(match => this.toDescriptionRange(setting, match, lineIndex)));
|
||||
}
|
||||
if (descriptionRanges.length === 0) {
|
||||
descriptionRanges.push(...this.getRangesForWords(words, this.descriptionMatchingWords, [this.keyMatchingWords, this.valueMatchingWords]));
|
||||
}
|
||||
|
||||
const keyMatches = or(matchesPrefix, matchesContiguousSubString)(searchString, setting.key);
|
||||
const keyRanges: IRange[] = keyMatches ? keyMatches.map(match => this.toKeyRange(setting, match)) : this.getRangesForWords(words, this.keyMatchingWords, [this.descriptionMatchingWords, this.valueMatchingWords]);
|
||||
|
||||
let valueRanges: IRange[] = [];
|
||||
if (setting.value && typeof setting.value === 'string') {
|
||||
const valueMatches = or(matchesPrefix, matchesContiguousSubString)(searchString, setting.value);
|
||||
valueRanges = valueMatches ? valueMatches.map(match => this.toValueRange(setting, match)) : this.getRangesForWords(words, this.valueMatchingWords, [this.keyMatchingWords, this.descriptionMatchingWords]);
|
||||
} else {
|
||||
valueRanges = this.valuesMatcher(searchString, setting);
|
||||
}
|
||||
|
||||
return [...descriptionRanges, ...keyRanges, ...valueRanges];
|
||||
}
|
||||
|
||||
private getRangesForWords(words: string[], from: Map<string, IRange[]>, others: Map<string, IRange[]>[]): IRange[] {
|
||||
const result: IRange[] = [];
|
||||
for (const word of words) {
|
||||
const ranges = from.get(word);
|
||||
if (ranges) {
|
||||
result.push(...ranges);
|
||||
} else if (others.every(o => !o.has(word))) {
|
||||
return [];
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
private toKeyRange(setting: ISetting, match: IMatch): IRange {
|
||||
return {
|
||||
startLineNumber: setting.keyRange.startLineNumber,
|
||||
startColumn: setting.keyRange.startColumn + match.start,
|
||||
endLineNumber: setting.keyRange.startLineNumber,
|
||||
endColumn: setting.keyRange.startColumn + match.end
|
||||
};
|
||||
}
|
||||
|
||||
private toDescriptionRange(setting: ISetting, match: IMatch, lineIndex: number): IRange {
|
||||
return {
|
||||
startLineNumber: setting.descriptionRanges[lineIndex].startLineNumber,
|
||||
startColumn: setting.descriptionRanges[lineIndex].startColumn + match.start,
|
||||
endLineNumber: setting.descriptionRanges[lineIndex].endLineNumber,
|
||||
endColumn: setting.descriptionRanges[lineIndex].startColumn + match.end
|
||||
};
|
||||
}
|
||||
|
||||
private toValueRange(setting: ISetting, match: IMatch): IRange {
|
||||
return {
|
||||
startLineNumber: setting.valueRange.startLineNumber,
|
||||
startColumn: setting.valueRange.startColumn + match.start + 1,
|
||||
endLineNumber: setting.valueRange.startLineNumber,
|
||||
endColumn: setting.valueRange.startColumn + match.end + 1
|
||||
};
|
||||
}
|
||||
}
|
||||
@@ -8,18 +8,16 @@ import * as network from 'vs/base/common/network';
|
||||
import { TPromise } from 'vs/base/common/winjs.base';
|
||||
import * as nls from 'vs/nls';
|
||||
import URI from 'vs/base/common/uri';
|
||||
import * as paths from 'vs/base/common/paths';
|
||||
import { ResourceMap } from 'vs/base/common/map';
|
||||
import * as labels from 'vs/base/common/labels';
|
||||
import * as strings from 'vs/base/common/strings';
|
||||
import { Disposable } from 'vs/base/common/lifecycle';
|
||||
import { Emitter } from 'vs/base/common/event';
|
||||
import { EditorInput } from 'vs/workbench/common/editor';
|
||||
import { IWorkbenchEditorService } from 'vs/workbench/services/editor/common/editorService';
|
||||
import { IWorkspaceContextService } from 'vs/platform/workspace/common/workspace';
|
||||
import { IWorkspaceContextService, WorkbenchState } from 'vs/platform/workspace/common/workspace';
|
||||
import { IWorkspaceConfigurationService } from 'vs/workbench/services/configuration/common/configuration';
|
||||
import { Position as EditorPosition, IEditor } from 'vs/platform/editor/common/editor';
|
||||
import { ICommonCodeEditor } from 'vs/editor/common/editorCommon';
|
||||
import { Position as EditorPosition, IEditor, IEditorOptions } from 'vs/platform/editor/common/editor';
|
||||
import { ICommonCodeEditor, IModel } from 'vs/editor/common/editorCommon';
|
||||
import { IEditorGroupService } from 'vs/workbench/services/group/common/groupService';
|
||||
import { IStorageService } from 'vs/platform/storage/common/storage';
|
||||
import { IFileService, FileOperationError, FileOperationResult } from 'vs/platform/files/common/files';
|
||||
@@ -27,9 +25,8 @@ import { IMessageService, Severity, IChoiceService } from 'vs/platform/message/c
|
||||
import { IExtensionService } from 'vs/platform/extensions/common/extensions';
|
||||
import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation';
|
||||
import { IEnvironmentService } from 'vs/platform/environment/common/environment';
|
||||
import { IConfigurationEditingService, ConfigurationTarget } from 'vs/workbench/services/configuration/common/configurationEditing';
|
||||
import { IPreferencesService, IPreferencesEditorModel, ISetting, getSettingsTargetName } from 'vs/workbench/parts/preferences/common/preferences';
|
||||
import { SettingsEditorModel, DefaultSettingsEditorModel, DefaultKeybindingsEditorModel, defaultKeybindingsContents, WorkspaceConfigModel } from 'vs/workbench/parts/preferences/common/preferencesModels';
|
||||
import { IPreferencesService, IPreferencesEditorModel, ISetting, getSettingsTargetName, FOLDER_SETTINGS_PATH, DEFAULT_SETTINGS_EDITOR_SETTING } from 'vs/workbench/parts/preferences/common/preferences';
|
||||
import { SettingsEditorModel, DefaultSettingsEditorModel, DefaultKeybindingsEditorModel, defaultKeybindingsContents, DefaultSettingsModel, WorkspaceConfigurationEditorModel } from 'vs/workbench/parts/preferences/common/preferencesModels';
|
||||
import { ITelemetryService } from 'vs/platform/telemetry/common/telemetry';
|
||||
import { DefaultPreferencesEditorInput, PreferencesEditorInput } from 'vs/workbench/parts/preferences/browser/preferencesEditor';
|
||||
import { KeybindingsEditorInput } from 'vs/workbench/parts/preferences/browser/keybindingsEditor';
|
||||
@@ -41,15 +38,9 @@ import { IKeybindingService } from 'vs/platform/keybinding/common/keybinding';
|
||||
import { IModelService } from 'vs/editor/common/services/modelService';
|
||||
import { IJSONEditingService } from 'vs/workbench/services/configuration/common/jsonEditing';
|
||||
import { ConfigurationScope } from 'vs/platform/configuration/common/configurationRegistry';
|
||||
|
||||
|
||||
interface IWorkbenchSettingsConfiguration {
|
||||
workbench: {
|
||||
settings: {
|
||||
openDefaultSettings: boolean;
|
||||
}
|
||||
};
|
||||
}
|
||||
import { ConfigurationTarget } from 'vs/platform/configuration/common/configuration';
|
||||
import { IModeService } from 'vs/editor/common/services/modeService';
|
||||
import { parse } from 'vs/base/common/json';
|
||||
|
||||
const emptyEditableSettingsContent = '{\n}';
|
||||
|
||||
@@ -57,12 +48,15 @@ export class PreferencesService extends Disposable implements IPreferencesServic
|
||||
|
||||
_serviceBrand: any;
|
||||
|
||||
// TODO:@sandy merge these models into editor inputs by extending resource editor model
|
||||
private defaultPreferencesEditorModels: ResourceMap<TPromise<IPreferencesEditorModel<any>>>;
|
||||
private lastOpenedSettingsInput: PreferencesEditorInput = null;
|
||||
|
||||
private _onDispose: Emitter<void> = new Emitter<void>();
|
||||
|
||||
private _defaultSettingsUriCounter = 0;
|
||||
private _defaultSettingsContentModel: DefaultSettingsModel;
|
||||
private _defaultResourceSettingsUriCounter = 0;
|
||||
private _defaultResourceSettingsContentModel: DefaultSettingsModel;
|
||||
|
||||
constructor(
|
||||
@IWorkbenchEditorService private editorService: IWorkbenchEditorService,
|
||||
@IEditorGroupService private editorGroupService: IEditorGroupService,
|
||||
@@ -76,14 +70,13 @@ export class PreferencesService extends Disposable implements IPreferencesServic
|
||||
@IEnvironmentService private environmentService: IEnvironmentService,
|
||||
@ITelemetryService private telemetryService: ITelemetryService,
|
||||
@ITextModelService private textModelResolverService: ITextModelService,
|
||||
@IConfigurationEditingService private configurationEditingService: IConfigurationEditingService,
|
||||
@IExtensionService private extensionService: IExtensionService,
|
||||
@IKeybindingService keybindingService: IKeybindingService,
|
||||
@IModelService private modelService: IModelService,
|
||||
@IJSONEditingService private jsonEditingService: IJSONEditingService
|
||||
@IJSONEditingService private jsonEditingService: IJSONEditingService,
|
||||
@IModeService private modeService: IModeService
|
||||
) {
|
||||
super();
|
||||
this.defaultPreferencesEditorModels = new ResourceMap<TPromise<IPreferencesEditorModel<any>>>();
|
||||
this.editorGroupService.onEditorsChanged(() => {
|
||||
const activeEditorInput = this.editorService.getActiveEditorInput();
|
||||
if (activeEditorInput instanceof PreferencesEditorInput) {
|
||||
@@ -103,10 +96,7 @@ export class PreferencesService extends Disposable implements IPreferencesServic
|
||||
});
|
||||
}
|
||||
|
||||
readonly defaultSettingsResource = URI.from({ scheme: network.Schemas.vscode, authority: 'defaultsettings', path: '/settings.json' });
|
||||
readonly defaultResourceSettingsResource = URI.from({ scheme: network.Schemas.vscode, authority: 'defaultsettings', path: '/resourceSettings.json' });
|
||||
readonly defaultKeybindingsResource = URI.from({ scheme: network.Schemas.vscode, authority: 'defaultsettings', path: '/keybindings.json' });
|
||||
private readonly workspaceConfigSettingsResource = URI.from({ scheme: network.Schemas.vscode, authority: 'settings', path: '/workspaceSettings.json' });
|
||||
|
||||
get userSettingsResource(): URI {
|
||||
return this.getEditableSettingsURI(ConfigurationTarget.USER);
|
||||
@@ -117,89 +107,66 @@ export class PreferencesService extends Disposable implements IPreferencesServic
|
||||
}
|
||||
|
||||
getFolderSettingsResource(resource: URI): URI {
|
||||
return this.getEditableSettingsURI(ConfigurationTarget.FOLDER, resource);
|
||||
return this.getEditableSettingsURI(ConfigurationTarget.WORKSPACE_FOLDER, resource);
|
||||
}
|
||||
|
||||
resolveContent(uri: URI): TPromise<string> {
|
||||
const workspaceSettingsUri = this.getEditableSettingsURI(ConfigurationTarget.WORKSPACE);
|
||||
if (workspaceSettingsUri && workspaceSettingsUri.fsPath === uri.fsPath) {
|
||||
return this.resolveSettingsContentFromWorkspaceConfiguration();
|
||||
resolveModel(uri: URI): TPromise<IModel> {
|
||||
if (this.isDefaultSettingsResource(uri) || this.isDefaultResourceSettingsResource(uri)) {
|
||||
return this.extensionService.onReady()
|
||||
.then(() => {
|
||||
const scope = this.isDefaultSettingsResource(uri) ? ConfigurationScope.WINDOW : ConfigurationScope.RESOURCE;
|
||||
const settingsModel = this.getDefaultSettingsModel(scope);
|
||||
const mode = this.modeService.getOrCreateMode('json');
|
||||
const model = this._register(this.modelService.createModel(settingsModel.content, mode, uri));
|
||||
return model;
|
||||
});
|
||||
}
|
||||
return this.createPreferencesEditorModel(uri)
|
||||
.then(preferencesEditorModel => preferencesEditorModel ? preferencesEditorModel.content : null);
|
||||
|
||||
if (this.defaultKeybindingsResource.toString() === uri.toString()) {
|
||||
const defaultKeybindingsEditorModel = this.instantiationService.createInstance(DefaultKeybindingsEditorModel, uri);
|
||||
const mode = this.modeService.getOrCreateMode('json');
|
||||
const model = this._register(this.modelService.createModel(defaultKeybindingsEditorModel.content, mode, uri));
|
||||
return TPromise.as(model);
|
||||
}
|
||||
|
||||
return TPromise.as(null);
|
||||
}
|
||||
|
||||
createPreferencesEditorModel(uri: URI): TPromise<IPreferencesEditorModel<any>> {
|
||||
let promise = this.defaultPreferencesEditorModels.get(uri);
|
||||
if (promise) {
|
||||
return promise;
|
||||
if (this.isDefaultSettingsResource(uri) || this.isDefaultResourceSettingsResource(uri)) {
|
||||
return this.createDefaultSettingsEditorModel(uri);
|
||||
}
|
||||
|
||||
if (this.defaultSettingsResource.fsPath === uri.fsPath) {
|
||||
promise = TPromise.join<any>([this.extensionService.onReady(), this.fetchMostCommonlyUsedSettings()])
|
||||
.then(result => {
|
||||
const mostCommonSettings = result[1];
|
||||
const model = this.instantiationService.createInstance(DefaultSettingsEditorModel, uri, mostCommonSettings, ConfigurationScope.WINDOW);
|
||||
return model;
|
||||
});
|
||||
this.defaultPreferencesEditorModels.set(uri, promise);
|
||||
return promise;
|
||||
}
|
||||
|
||||
if (this.defaultResourceSettingsResource.fsPath === uri.fsPath) {
|
||||
promise = TPromise.join<any>([this.extensionService.onReady(), this.fetchMostCommonlyUsedSettings()])
|
||||
.then(result => {
|
||||
const mostCommonSettings = result[1];
|
||||
const model = this.instantiationService.createInstance(DefaultSettingsEditorModel, uri, mostCommonSettings, ConfigurationScope.RESOURCE);
|
||||
return model;
|
||||
});
|
||||
this.defaultPreferencesEditorModels.set(uri, promise);
|
||||
return promise;
|
||||
}
|
||||
|
||||
if (this.defaultKeybindingsResource.fsPath === uri.fsPath) {
|
||||
const model = this.instantiationService.createInstance(DefaultKeybindingsEditorModel, uri);
|
||||
promise = TPromise.wrap(model);
|
||||
this.defaultPreferencesEditorModels.set(uri, promise);
|
||||
return promise;
|
||||
}
|
||||
|
||||
if (this.workspaceConfigSettingsResource.fsPath === uri.fsPath) {
|
||||
promise = this.createEditableSettingsEditorModel(ConfigurationTarget.WORKSPACE, uri);
|
||||
this.defaultPreferencesEditorModels.set(uri, promise);
|
||||
return promise;
|
||||
}
|
||||
|
||||
if (this.getEditableSettingsURI(ConfigurationTarget.USER).fsPath === uri.fsPath) {
|
||||
if (this.getEditableSettingsURI(ConfigurationTarget.USER).toString() === uri.toString()) {
|
||||
return this.createEditableSettingsEditorModel(ConfigurationTarget.USER, uri);
|
||||
}
|
||||
|
||||
const workspaceSettingsUri = this.getEditableSettingsURI(ConfigurationTarget.WORKSPACE);
|
||||
if (workspaceSettingsUri && workspaceSettingsUri.fsPath === uri.fsPath) {
|
||||
if (workspaceSettingsUri && workspaceSettingsUri.toString() === uri.toString()) {
|
||||
return this.createEditableSettingsEditorModel(ConfigurationTarget.WORKSPACE, workspaceSettingsUri);
|
||||
}
|
||||
|
||||
if (this.contextService.hasMultiFolderWorkspace()) {
|
||||
return this.createEditableSettingsEditorModel(ConfigurationTarget.FOLDER, uri);
|
||||
if (this.contextService.getWorkbenchState() === WorkbenchState.WORKSPACE) {
|
||||
return this.createEditableSettingsEditorModel(ConfigurationTarget.WORKSPACE_FOLDER, uri);
|
||||
}
|
||||
|
||||
return TPromise.wrap<IPreferencesEditorModel<any>>(null);
|
||||
}
|
||||
|
||||
openGlobalSettings(): TPromise<IEditor> {
|
||||
return this.doOpenSettings(ConfigurationTarget.USER, this.userSettingsResource);
|
||||
openGlobalSettings(options?: IEditorOptions, position?: EditorPosition): TPromise<IEditor> {
|
||||
return this.doOpenSettings(ConfigurationTarget.USER, this.userSettingsResource, options, position);
|
||||
}
|
||||
|
||||
openWorkspaceSettings(): TPromise<IEditor> {
|
||||
if (!this.contextService.hasWorkspace()) {
|
||||
openWorkspaceSettings(options?: IEditorOptions, position?: EditorPosition): TPromise<IEditor> {
|
||||
if (this.contextService.getWorkbenchState() === WorkbenchState.EMPTY) {
|
||||
this.messageService.show(Severity.Info, nls.localize('openFolderFirst', "Open a folder first to create workspace settings"));
|
||||
return TPromise.as(null);
|
||||
}
|
||||
return this.doOpenSettings(ConfigurationTarget.WORKSPACE, this.workspaceSettingsResource);
|
||||
return this.doOpenSettings(ConfigurationTarget.WORKSPACE, this.workspaceSettingsResource, options, position);
|
||||
}
|
||||
|
||||
openFolderSettings(folder: URI): TPromise<IEditor> {
|
||||
return this.doOpenSettings(ConfigurationTarget.FOLDER, this.getEditableSettingsURI(ConfigurationTarget.FOLDER, folder));
|
||||
openFolderSettings(folder: URI, options?: IEditorOptions, position?: EditorPosition): TPromise<IEditor> {
|
||||
return this.doOpenSettings(ConfigurationTarget.WORKSPACE_FOLDER, this.getEditableSettingsURI(ConfigurationTarget.WORKSPACE_FOLDER, folder), options, position);
|
||||
}
|
||||
|
||||
switchSettings(target: ConfigurationTarget, resource: URI): TPromise<void> {
|
||||
@@ -223,6 +190,11 @@ export class PreferencesService extends Disposable implements IPreferencesServic
|
||||
}
|
||||
|
||||
openGlobalKeybindingSettings(textual: boolean): TPromise<void> {
|
||||
/* __GDPR__
|
||||
"openKeybindings" : {
|
||||
"textual" : { "classification": "SystemMetaData", "purpose": "FeatureInsight" }
|
||||
}
|
||||
*/
|
||||
this.telemetryService.publicLog('openKeybindings', { textual });
|
||||
if (textual) {
|
||||
const emptyContents = '// ' + nls.localize('emptyKeybindingsHeader', "Place your key bindings in this file to overwrite the defaults") + '\n[\n]';
|
||||
@@ -254,30 +226,45 @@ export class PreferencesService extends Disposable implements IPreferencesServic
|
||||
});
|
||||
}
|
||||
|
||||
private doOpenSettings(configurationTarget: ConfigurationTarget, resource: URI): TPromise<IEditor> {
|
||||
const openDefaultSettings = !!this.configurationService.getConfiguration<IWorkbenchSettingsConfiguration>().workbench.settings.openDefaultSettings;
|
||||
private doOpenSettings(configurationTarget: ConfigurationTarget, resource: URI, options?: IEditorOptions, position?: EditorPosition): TPromise<IEditor> {
|
||||
const openDefaultSettings = !!this.configurationService.getValue(DEFAULT_SETTINGS_EDITOR_SETTING);
|
||||
return this.getOrCreateEditableSettingsEditorInput(configurationTarget, resource)
|
||||
.then(editableSettingsEditorInput => {
|
||||
if (!options) {
|
||||
options = { pinned: true };
|
||||
} else {
|
||||
options.pinned = true;
|
||||
}
|
||||
|
||||
if (openDefaultSettings) {
|
||||
const defaultPreferencesEditorInput = this.instantiationService.createInstance(DefaultPreferencesEditorInput, this.getDefaultSettingsResource(configurationTarget));
|
||||
const preferencesEditorInput = new PreferencesEditorInput(this.getPreferencesEditorInputName(configurationTarget, resource), editableSettingsEditorInput.getDescription(), defaultPreferencesEditorInput, <EditorInput>editableSettingsEditorInput);
|
||||
this.lastOpenedSettingsInput = preferencesEditorInput;
|
||||
return this.editorService.openEditor(preferencesEditorInput, { pinned: true });
|
||||
return this.editorService.openEditor(preferencesEditorInput, options, position);
|
||||
}
|
||||
return this.editorService.openEditor(editableSettingsEditorInput, { pinned: true });
|
||||
return this.editorService.openEditor(editableSettingsEditorInput, options, position);
|
||||
});
|
||||
}
|
||||
|
||||
private isDefaultSettingsResource(uri: URI): boolean {
|
||||
return uri.authority === 'defaultsettings' && uri.scheme === network.Schemas.vscode && !!uri.path.match(/\/(\d+\/)?settings\.json$/);
|
||||
}
|
||||
|
||||
private isDefaultResourceSettingsResource(uri: URI): boolean {
|
||||
return uri.authority === 'defaultsettings' && uri.scheme === network.Schemas.vscode && !!uri.path.match(/\/(\d+\/)?resourceSettings\.json$/);
|
||||
}
|
||||
|
||||
private getDefaultSettingsResource(configurationTarget: ConfigurationTarget): URI {
|
||||
if (configurationTarget === ConfigurationTarget.FOLDER) {
|
||||
return this.defaultResourceSettingsResource;
|
||||
if (configurationTarget === ConfigurationTarget.WORKSPACE_FOLDER) {
|
||||
return URI.from({ scheme: network.Schemas.vscode, authority: 'defaultsettings', path: `/${this._defaultResourceSettingsUriCounter++}/resourceSettings.json` });
|
||||
} else {
|
||||
return URI.from({ scheme: network.Schemas.vscode, authority: 'defaultsettings', path: `/${this._defaultSettingsUriCounter++}/settings.json` });
|
||||
}
|
||||
return this.defaultSettingsResource;
|
||||
}
|
||||
|
||||
private getPreferencesEditorInputName(target: ConfigurationTarget, resource: URI): string {
|
||||
const name = getSettingsTargetName(target, resource, this.contextService);
|
||||
return target === ConfigurationTarget.FOLDER ? nls.localize('folderSettingsName', "{0} (Folder Settings)", name) : name;
|
||||
return target === ConfigurationTarget.WORKSPACE_FOLDER ? nls.localize('folderSettingsName', "{0} (Folder Settings)", name) : name;
|
||||
}
|
||||
|
||||
private getOrCreateEditableSettingsEditorInput(target: ConfigurationTarget, resource: URI): TPromise<EditorInput> {
|
||||
@@ -288,9 +275,10 @@ export class PreferencesService extends Disposable implements IPreferencesServic
|
||||
private createEditableSettingsEditorModel(configurationTarget: ConfigurationTarget, resource: URI): TPromise<SettingsEditorModel> {
|
||||
const settingsUri = this.getEditableSettingsURI(configurationTarget, resource);
|
||||
if (settingsUri) {
|
||||
if (settingsUri.fsPath === this.workspaceConfigSettingsResource.fsPath) {
|
||||
return TPromise.join([this.textModelResolverService.createModelReference(settingsUri), this.textModelResolverService.createModelReference(this.contextService.getWorkspace().configuration)])
|
||||
.then(([reference, workspaceConfigReference]) => this.instantiationService.createInstance(WorkspaceConfigModel, reference, workspaceConfigReference, configurationTarget, this._onDispose.event));
|
||||
const workspace = this.contextService.getWorkspace();
|
||||
if (workspace.configuration && workspace.configuration.toString() === settingsUri.toString()) {
|
||||
return this.textModelResolverService.createModelReference(settingsUri)
|
||||
.then(reference => this.instantiationService.createInstance(WorkspaceConfigurationEditorModel, reference, configurationTarget));
|
||||
}
|
||||
return this.textModelResolverService.createModelReference(settingsUri)
|
||||
.then(reference => this.instantiationService.createInstance(SettingsEditorModel, reference, configurationTarget));
|
||||
@@ -298,17 +286,27 @@ export class PreferencesService extends Disposable implements IPreferencesServic
|
||||
return TPromise.wrap<SettingsEditorModel>(null);
|
||||
}
|
||||
|
||||
private resolveSettingsContentFromWorkspaceConfiguration(): TPromise<string> {
|
||||
if (this.contextService.hasMultiFolderWorkspace()) {
|
||||
return this.textModelResolverService.createModelReference(this.contextService.getWorkspace().configuration)
|
||||
.then(reference => {
|
||||
const model = reference.object.textEditorModel;
|
||||
const settingsContent = WorkspaceConfigModel.getSettingsContentFromConfigContent(model.getValue());
|
||||
reference.dispose();
|
||||
return TPromise.as(settingsContent ? settingsContent : emptyEditableSettingsContent);
|
||||
});
|
||||
private createDefaultSettingsEditorModel(defaultSettingsUri: URI): TPromise<DefaultSettingsEditorModel> {
|
||||
return this.textModelResolverService.createModelReference(defaultSettingsUri)
|
||||
.then(reference => {
|
||||
const scope = this.isDefaultSettingsResource(defaultSettingsUri) ? ConfigurationScope.WINDOW : ConfigurationScope.RESOURCE;
|
||||
return this.instantiationService.createInstance(DefaultSettingsEditorModel, defaultSettingsUri, reference, scope, this.getDefaultSettingsModel(scope).settingsGroups);
|
||||
});
|
||||
}
|
||||
|
||||
private getDefaultSettingsModel(scope: ConfigurationScope): DefaultSettingsModel {
|
||||
switch (scope) {
|
||||
case ConfigurationScope.WINDOW:
|
||||
if (!this._defaultSettingsContentModel) {
|
||||
this._defaultSettingsContentModel = new DefaultSettingsModel(this.getMostCommonlyUsedSettings(), scope);
|
||||
}
|
||||
return this._defaultSettingsContentModel;
|
||||
case ConfigurationScope.RESOURCE:
|
||||
if (!this._defaultResourceSettingsContentModel) {
|
||||
this._defaultResourceSettingsContentModel = new DefaultSettingsModel(this.getMostCommonlyUsedSettings(), scope);
|
||||
}
|
||||
return this._defaultResourceSettingsContentModel;
|
||||
}
|
||||
return TPromise.as(null);
|
||||
}
|
||||
|
||||
private getEditableSettingsURI(configurationTarget: ConfigurationTarget, resource?: URI): URI {
|
||||
@@ -316,32 +314,27 @@ export class PreferencesService extends Disposable implements IPreferencesServic
|
||||
case ConfigurationTarget.USER:
|
||||
return URI.file(this.environmentService.appSettingsPath);
|
||||
case ConfigurationTarget.WORKSPACE:
|
||||
if (this.contextService.getWorkbenchState() === WorkbenchState.EMPTY) {
|
||||
return null;
|
||||
}
|
||||
const workspace = this.contextService.getWorkspace();
|
||||
if (this.contextService.hasFolderWorkspace()) {
|
||||
// {{SQL CARBON EDIT}}
|
||||
return this.toResource(paths.join('.sqlops', 'settings.json'), workspace.roots[0]);
|
||||
}
|
||||
if (this.contextService.hasMultiFolderWorkspace()) {
|
||||
return workspace.configuration;
|
||||
}
|
||||
return null;
|
||||
case ConfigurationTarget.FOLDER:
|
||||
const root = this.contextService.getRoot(resource);
|
||||
// {{SQL CARBON EDIT}}
|
||||
return root ? this.toResource(paths.join('.sqlops', 'settings.json'), root) : null;
|
||||
return workspace.configuration || workspace.folders[0].toResource(FOLDER_SETTINGS_PATH);
|
||||
case ConfigurationTarget.WORKSPACE_FOLDER:
|
||||
const folder = this.contextService.getWorkspaceFolder(resource);
|
||||
return folder ? folder.toResource(FOLDER_SETTINGS_PATH) : null;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
private toResource(relativePath: string, root: URI): URI {
|
||||
return URI.file(paths.join(root.fsPath, relativePath));
|
||||
}
|
||||
|
||||
private createSettingsIfNotExists(target: ConfigurationTarget, resource: URI): TPromise<void> {
|
||||
if (this.contextService.hasMultiFolderWorkspace() && target === ConfigurationTarget.WORKSPACE) {
|
||||
if (!this.configurationService.keys().workspace.length) {
|
||||
return this.jsonEditingService.write(resource, { key: 'settings', value: {} }, true).then(null, () => { });
|
||||
}
|
||||
if (this.contextService.getWorkbenchState() === WorkbenchState.WORKSPACE && target === ConfigurationTarget.WORKSPACE) {
|
||||
return this.fileService.resolveContent(this.contextService.getWorkspace().configuration)
|
||||
.then(content => {
|
||||
if (Object.keys(parse(content.value)).indexOf('settings') === -1) {
|
||||
return this.jsonEditingService.write(resource, { key: 'settings', value: {} }, true).then(null, () => { });
|
||||
}
|
||||
return null;
|
||||
});
|
||||
}
|
||||
return this.createIfNotExists(resource, emptyEditableSettingsContent).then(() => { });
|
||||
}
|
||||
@@ -358,8 +351,8 @@ export class PreferencesService extends Disposable implements IPreferencesServic
|
||||
});
|
||||
}
|
||||
|
||||
private fetchMostCommonlyUsedSettings(): TPromise<string[]> {
|
||||
return TPromise.wrap([
|
||||
private getMostCommonlyUsedSettings(): string[] {
|
||||
return [
|
||||
'files.autoSave',
|
||||
'editor.fontSize',
|
||||
'editor.fontFamily',
|
||||
@@ -371,7 +364,7 @@ export class PreferencesService extends Disposable implements IPreferencesServic
|
||||
'editor.wordWrap',
|
||||
'files.exclude',
|
||||
'files.associations'
|
||||
]);
|
||||
];
|
||||
}
|
||||
|
||||
private getPosition(language: string, codeEditor: ICommonCodeEditor): TPromise<IPosition> {
|
||||
@@ -397,7 +390,7 @@ export class PreferencesService extends Disposable implements IPreferencesServic
|
||||
}
|
||||
return { lineNumber: setting.valueRange.startLineNumber, column: setting.valueRange.startColumn + 1 };
|
||||
}
|
||||
return this.configurationEditingService.writeConfiguration(ConfigurationTarget.USER, { key: languageKey, value: {} }, { donotSave: true })
|
||||
return this.configurationService.updateValue(languageKey, {}, ConfigurationTarget.USER)
|
||||
.then(() => {
|
||||
setting = settingsModel.getPreference(languageKey);
|
||||
let content = eol + this.spaces(2, configuration) + eol + this.spaces(1, configuration);
|
||||
@@ -416,7 +409,6 @@ export class PreferencesService extends Disposable implements IPreferencesServic
|
||||
|
||||
public dispose(): void {
|
||||
this._onDispose.fire();
|
||||
this.defaultPreferencesEditorModels.clear();
|
||||
super.dispose();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -10,6 +10,7 @@ import * as DOM from 'vs/base/browser/dom';
|
||||
import { TPromise } from 'vs/base/common/winjs.base';
|
||||
import { Disposable } from 'vs/base/common/lifecycle';
|
||||
import { Widget } from 'vs/base/browser/ui/widget';
|
||||
import { Checkbox } from 'vs/base/browser/ui/checkbox/checkbox';
|
||||
import Event, { Emitter } from 'vs/base/common/event';
|
||||
import { IKeyboardEvent } from 'vs/base/browser/keyboardEvent';
|
||||
import { KeyCode } from 'vs/base/common/keyCodes';
|
||||
@@ -20,9 +21,9 @@ import { IInstantiationService } from 'vs/platform/instantiation/common/instanti
|
||||
import { IContextViewService, IContextMenuService } from 'vs/platform/contextview/browser/contextView';
|
||||
import { ISettingsGroup, IPreferencesService, getSettingsTargetName } from 'vs/workbench/parts/preferences/common/preferences';
|
||||
import { IKeybindingService } from 'vs/platform/keybinding/common/keybinding';
|
||||
import { IWorkspaceContextService } from 'vs/platform/workspace/common/workspace';
|
||||
import { IWorkspaceContextService, WorkbenchState } from 'vs/platform/workspace/common/workspace';
|
||||
import { IAction, IActionRunner } from 'vs/base/common/actions';
|
||||
import { attachInputBoxStyler, attachStylerCallback, attachSelectBoxStyler } from 'vs/platform/theme/common/styler';
|
||||
import { attachInputBoxStyler, attachStylerCallback, attachSelectBoxStyler, attachCheckboxStyler } from 'vs/platform/theme/common/styler';
|
||||
import { IThemeService } from 'vs/platform/theme/common/themeService';
|
||||
import { Position } from 'vs/editor/common/core/position';
|
||||
import { ICursorPositionChangedEvent } from 'vs/editor/common/controller/cursorEvents';
|
||||
@@ -32,19 +33,20 @@ import { ISelectBoxStyles, defaultStyles } from 'vs/base/browser/ui/selectBox/se
|
||||
import { Separator } from 'vs/base/browser/ui/actionbar/actionbar';
|
||||
import { Color } from 'vs/base/common/color';
|
||||
import { SIDE_BAR_BACKGROUND } from 'vs/workbench/common/theme';
|
||||
import { ConfigurationTarget } from 'vs/workbench/services/configuration/common/configurationEditing';
|
||||
import { IMouseEvent } from 'vs/base/browser/mouseEvent';
|
||||
import { MarkdownString } from 'vs/base/common/htmlContent';
|
||||
import { ConfigurationTarget } from 'vs/platform/configuration/common/configuration';
|
||||
import { IMarginData } from 'vs/editor/browser/controller/mouseTarget';
|
||||
|
||||
export class SettingsHeaderWidget extends Widget implements IViewZone {
|
||||
|
||||
private id: number;
|
||||
private _domNode: HTMLElement;
|
||||
|
||||
private titleContainer: HTMLElement;
|
||||
protected titleContainer: HTMLElement;
|
||||
private messageElement: HTMLElement;
|
||||
|
||||
constructor(private editor: ICodeEditor, private title: string) {
|
||||
constructor(protected editor: ICodeEditor, private title: string) {
|
||||
super();
|
||||
this.create();
|
||||
this._register(this.editor.onDidChangeConfiguration(() => this.layout()));
|
||||
@@ -63,7 +65,7 @@ export class SettingsHeaderWidget extends Widget implements IViewZone {
|
||||
return 0;
|
||||
}
|
||||
|
||||
private create() {
|
||||
protected create() {
|
||||
this._domNode = DOM.$('.settings-header-widget');
|
||||
|
||||
this.titleContainer = DOM.append(this._domNode, DOM.$('.title-container'));
|
||||
@@ -101,6 +103,38 @@ export class SettingsHeaderWidget extends Widget implements IViewZone {
|
||||
}
|
||||
}
|
||||
|
||||
export class DefaultSettingsHeaderWidget extends SettingsHeaderWidget {
|
||||
|
||||
private linkElement: HTMLElement;
|
||||
private _onClick = this._register(new Emitter<void>());
|
||||
public onClick: Event<void> = this._onClick.event;
|
||||
|
||||
protected create() {
|
||||
super.create();
|
||||
|
||||
this.linkElement = DOM.append(this.titleContainer, DOM.$('a.settings-header-fuzzy-link'));
|
||||
this.linkElement.textContent = localize('defaultSettingsFuzzyPrompt', "Try fuzzy search!");
|
||||
|
||||
this.onclick(this.linkElement, e => this._onClick.fire());
|
||||
this.toggleMessage(true);
|
||||
}
|
||||
|
||||
public toggleMessage(hasSettings: boolean, promptFuzzy = false): void {
|
||||
if (hasSettings) {
|
||||
this.setMessage(localize('defaultSettings', "Place your settings in the right hand side editor to override."));
|
||||
DOM.addClass(this.linkElement, 'hidden');
|
||||
} else {
|
||||
this.setMessage(localize('noSettingsFound', "No Settings Found."));
|
||||
|
||||
if (promptFuzzy) {
|
||||
DOM.removeClass(this.linkElement, 'hidden');
|
||||
} else {
|
||||
DOM.addClass(this.linkElement, 'hidden');
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
export class SettingsGroupTitleWidget extends Widget implements IViewZone {
|
||||
|
||||
private id: number;
|
||||
@@ -271,7 +305,7 @@ export class SettingsTargetsWidget extends Widget {
|
||||
|
||||
private borderColor: Color;
|
||||
|
||||
constructor(parent: HTMLElement, private uri: URI, private target: ConfigurationTarget,
|
||||
constructor(parent: HTMLElement, private _uri: URI, private _configuartionTarget: ConfigurationTarget,
|
||||
@IWorkspaceContextService private workspaceContextService: IWorkspaceContextService,
|
||||
@IPreferencesService private preferencesService: IPreferencesService,
|
||||
@IContextMenuService private contextMenuService: IContextMenuService,
|
||||
@@ -285,15 +319,19 @@ export class SettingsTargetsWidget extends Widget {
|
||||
}));
|
||||
}
|
||||
|
||||
public setTarget(uri: URI, target: ConfigurationTarget): void {
|
||||
this.uri = uri;
|
||||
this.target = target;
|
||||
get configurationTarget(): ConfigurationTarget {
|
||||
return this._configuartionTarget;
|
||||
}
|
||||
|
||||
public updateTargets(uri: URI, configuartionTarget: ConfigurationTarget): void {
|
||||
this._uri = uri;
|
||||
this._configuartionTarget = configuartionTarget;
|
||||
this.updateLabel();
|
||||
}
|
||||
|
||||
private create(parent: HTMLElement): void {
|
||||
this.settingsTargetsContainer = DOM.append(parent, DOM.$('.settings-targets-widget'));
|
||||
this.settingsTargetsContainer.style.width = this.workspaceContextService.hasMultiFolderWorkspace() ? '200px' : '150px';
|
||||
this.settingsTargetsContainer.style.width = this.workspaceContextService.getWorkbenchState() === WorkbenchState.WORKSPACE ? '200px' : '150px';
|
||||
|
||||
const targetElement = DOM.append(this.settingsTargetsContainer, DOM.$('.settings-target'));
|
||||
this.targetLabel = DOM.append(targetElement, DOM.$('.settings-target-label'));
|
||||
@@ -308,8 +346,8 @@ export class SettingsTargetsWidget extends Widget {
|
||||
}
|
||||
|
||||
private updateLabel(): void {
|
||||
this.targetLabel.textContent = getSettingsTargetName(this.target, this.uri, this.workspaceContextService);
|
||||
const details = ConfigurationTarget.FOLDER === this.target ? localize('folderSettingsDetails', "Folder Settings") : '';
|
||||
this.targetLabel.textContent = getSettingsTargetName(this._configuartionTarget, this._uri, this.workspaceContextService);
|
||||
const details = ConfigurationTarget.WORKSPACE_FOLDER === this._configuartionTarget ? localize('folderSettingsDetails', "Folder Settings") : '';
|
||||
this.targetDetails.textContent = details;
|
||||
DOM.toggleClass(this.targetDetails, 'empty', !details);
|
||||
}
|
||||
@@ -332,31 +370,32 @@ export class SettingsTargetsWidget extends Widget {
|
||||
actions.push(<IAction>{
|
||||
id: 'userSettingsTarget',
|
||||
label: getSettingsTargetName(ConfigurationTarget.USER, userSettingsResource, this.workspaceContextService),
|
||||
checked: this.uri.fsPath === userSettingsResource.fsPath,
|
||||
checked: this._uri.toString() === userSettingsResource.toString(),
|
||||
enabled: true,
|
||||
run: () => this.onTargetClicked(userSettingsResource)
|
||||
});
|
||||
|
||||
if (this.workspaceContextService.hasWorkspace()) {
|
||||
if (this.workspaceContextService.getWorkbenchState() !== WorkbenchState.EMPTY) {
|
||||
const workspaceSettingsResource = this.preferencesService.workspaceSettingsResource;
|
||||
actions.push(<IAction>{
|
||||
id: 'workspaceSettingsTarget',
|
||||
label: getSettingsTargetName(ConfigurationTarget.WORKSPACE, workspaceSettingsResource, this.workspaceContextService),
|
||||
checked: this.uri.fsPath === workspaceSettingsResource.fsPath,
|
||||
checked: this._uri.toString() === workspaceSettingsResource.toString(),
|
||||
enabled: true,
|
||||
run: () => this.onTargetClicked(workspaceSettingsResource)
|
||||
});
|
||||
}
|
||||
|
||||
if (this.workspaceContextService.hasMultiFolderWorkspace()) {
|
||||
const workspaceFolders = this.workspaceContextService.getWorkspace().folders;
|
||||
if (this.workspaceContextService.getWorkbenchState() === WorkbenchState.WORKSPACE && workspaceFolders.length > 0) {
|
||||
actions.push(new Separator());
|
||||
actions.push(...this.workspaceContextService.getWorkspace().roots.map((root, index) => {
|
||||
actions.push(...workspaceFolders.map((folder, index) => {
|
||||
return <IAction>{
|
||||
id: 'folderSettingsTarget' + index,
|
||||
label: getSettingsTargetName(ConfigurationTarget.FOLDER, root, this.workspaceContextService),
|
||||
checked: this.uri.fsPath === root.fsPath,
|
||||
label: getSettingsTargetName(ConfigurationTarget.WORKSPACE_FOLDER, folder.uri, this.workspaceContextService),
|
||||
checked: this._uri.toString() === folder.uri.toString(),
|
||||
enabled: true,
|
||||
run: () => this.onTargetClicked(root)
|
||||
run: () => this.onTargetClicked(folder.uri)
|
||||
};
|
||||
}));
|
||||
}
|
||||
@@ -365,7 +404,7 @@ export class SettingsTargetsWidget extends Widget {
|
||||
}
|
||||
|
||||
private onTargetClicked(target: URI): void {
|
||||
if (this.uri.fsPath === target.fsPath) {
|
||||
if (this._uri.toString() === target.toString()) {
|
||||
return;
|
||||
}
|
||||
this._onDidTargetChange.fire(target);
|
||||
@@ -394,13 +433,12 @@ export class SearchWidget extends Widget {
|
||||
private countElement: HTMLElement;
|
||||
private searchContainer: HTMLElement;
|
||||
private inputBox: InputBox;
|
||||
private fuzzyToggle: Checkbox;
|
||||
private controlsDiv: HTMLElement;
|
||||
|
||||
private _onDidChange: Emitter<string> = this._register(new Emitter<string>());
|
||||
public readonly onDidChange: Event<string> = this._onDidChange.event;
|
||||
|
||||
private _onNavigate: Emitter<boolean> = this._register(new Emitter<boolean>());
|
||||
public readonly onNavigate: Event<boolean> = this._onNavigate.event;
|
||||
|
||||
private _onFocus: Emitter<void> = this._register(new Emitter<void>());
|
||||
public readonly onFocus: Event<void> = this._onFocus.event;
|
||||
|
||||
@@ -414,10 +452,31 @@ export class SearchWidget extends Widget {
|
||||
this.create(parent);
|
||||
}
|
||||
|
||||
public get fuzzyEnabled(): boolean {
|
||||
return this.fuzzyToggle.checked && this.fuzzyToggle.enabled;
|
||||
}
|
||||
|
||||
public set fuzzyEnabled(value: boolean) {
|
||||
this.fuzzyToggle.checked = value;
|
||||
}
|
||||
|
||||
private create(parent: HTMLElement) {
|
||||
this.domNode = DOM.append(parent, DOM.$('div.settings-header-widget'));
|
||||
this.createSearchContainer(DOM.append(this.domNode, DOM.$('div.settings-search-container')));
|
||||
this.countElement = DOM.append(this.domNode, DOM.$('.settings-count-widget'));
|
||||
this.controlsDiv = DOM.append(this.domNode, DOM.$('div.settings-search-controls'));
|
||||
this.fuzzyToggle = this._register(new Checkbox({
|
||||
actionClassName: 'prefs-fuzzy-search-toggle',
|
||||
isChecked: false,
|
||||
onChange: () => {
|
||||
this.inputBox.focus();
|
||||
this._onDidChange.fire();
|
||||
},
|
||||
title: localize('enableFuzzySearch', 'Enable experimental fuzzy search')
|
||||
}));
|
||||
DOM.append(this.controlsDiv, this.fuzzyToggle.domNode);
|
||||
this._register(attachCheckboxStyler(this.fuzzyToggle, this.themeService));
|
||||
|
||||
this.countElement = DOM.append(this.controlsDiv, DOM.$('.settings-count-widget'));
|
||||
this._register(attachStylerCallback(this.themeService, { badgeBackground, contrastBorder }, colors => {
|
||||
const background = colors.badgeBackground ? colors.badgeBackground.toString() : null;
|
||||
const border = colors.contrastBorder ? colors.contrastBorder.toString() : null;
|
||||
@@ -446,7 +505,6 @@ export class SearchWidget extends Widget {
|
||||
const searchInput = DOM.append(this.searchContainer, DOM.$('div.settings-search-input'));
|
||||
this.inputBox = this._register(this.createInputBox(searchInput));
|
||||
this._register(this.inputBox.onDidChange(value => this._onDidChange.fire(value)));
|
||||
this.onkeydown(this.inputBox.inputElement, (e) => this._onKeyDown(e));
|
||||
}
|
||||
|
||||
protected createInputBox(parent: HTMLElement): InputBox {
|
||||
@@ -460,10 +518,20 @@ export class SearchWidget extends Widget {
|
||||
this.countElement.textContent = message;
|
||||
this.inputBox.inputElement.setAttribute('aria-label', message);
|
||||
DOM.toggleClass(this.countElement, 'no-results', count === 0);
|
||||
this.inputBox.inputElement.style.paddingRight = DOM.getTotalWidth(this.countElement) + 20 + 'px';
|
||||
this.inputBox.inputElement.style.paddingRight = this.getControlsWidth() + 'px';
|
||||
this.styleCountElementForeground();
|
||||
}
|
||||
|
||||
public setFuzzyToggleVisible(visible: boolean): void {
|
||||
if (visible) {
|
||||
this.fuzzyToggle.domNode.classList.remove('hidden');
|
||||
this.fuzzyToggle.enable();
|
||||
} else {
|
||||
this.fuzzyToggle.domNode.classList.add('hidden');
|
||||
this.fuzzyToggle.disable();
|
||||
}
|
||||
}
|
||||
|
||||
private styleCountElementForeground() {
|
||||
const colorId = DOM.hasClass(this.countElement, 'no-results') ? errorForeground : badgeForeground;
|
||||
const color = this.themeService.getTheme().getColor(colorId);
|
||||
@@ -476,10 +544,14 @@ export class SearchWidget extends Widget {
|
||||
this.inputBox.inputElement.style.paddingRight = '0px';
|
||||
} else {
|
||||
DOM.removeClass(this.countElement, 'hide');
|
||||
this.inputBox.inputElement.style.paddingRight = DOM.getTotalWidth(this.countElement) + 20 + 'px';
|
||||
this.inputBox.inputElement.style.paddingRight = this.getControlsWidth() + 'px';
|
||||
}
|
||||
}
|
||||
|
||||
private getControlsWidth(): number {
|
||||
return DOM.getTotalWidth(this.countElement) + DOM.getTotalWidth(this.fuzzyToggle.domNode) + 20;
|
||||
}
|
||||
|
||||
public focus() {
|
||||
this.inputBox.focus();
|
||||
if (this.getValue()) {
|
||||
@@ -503,24 +575,6 @@ export class SearchWidget extends Widget {
|
||||
return this.inputBox.value = value;
|
||||
}
|
||||
|
||||
private _onKeyDown(keyboardEvent: IKeyboardEvent): void {
|
||||
let handled = false;
|
||||
switch (keyboardEvent.keyCode) {
|
||||
case KeyCode.Enter:
|
||||
this._onNavigate.fire(keyboardEvent.shiftKey);
|
||||
handled = true;
|
||||
break;
|
||||
case KeyCode.Escape:
|
||||
this.clear();
|
||||
handled = true;
|
||||
break;
|
||||
}
|
||||
if (handled) {
|
||||
keyboardEvent.preventDefault();
|
||||
keyboardEvent.stopPropagation();
|
||||
}
|
||||
}
|
||||
|
||||
public dispose(): void {
|
||||
if (this.options.focusKey) {
|
||||
this.options.focusKey.set(false);
|
||||
@@ -602,7 +656,8 @@ export class EditPreferenceWidget<T> extends Disposable {
|
||||
super();
|
||||
this._editPreferenceDecoration = [];
|
||||
this._register(this.editor.onMouseDown((e: IEditorMouseEvent) => {
|
||||
if (e.target.type !== MouseTargetType.GUTTER_GLYPH_MARGIN || /* after last line */ e.target.detail || !this.isVisible()) {
|
||||
const data = e.target.detail as IMarginData;
|
||||
if (e.target.type !== MouseTargetType.GUTTER_GLYPH_MARGIN || data.isAfterLines || !this.isVisible()) {
|
||||
return;
|
||||
}
|
||||
this._onClick.fire(e);
|
||||
|
||||
Reference in New Issue
Block a user