files.contribution.ts 15.8 KB
Newer Older
E
Erich Gamma 已提交
1 2 3 4 5 6 7 8
/*---------------------------------------------------------------------------------------------
 *  Copyright (c) Microsoft Corporation. All rights reserved.
 *  Licensed under the MIT License. See License.txt in the project root for license information.
 *--------------------------------------------------------------------------------------------*/

'use strict';

import URI from 'vs/base/common/uri';
9
import { ViewletRegistry, Extensions as ViewletExtensions, ViewletDescriptor, ToggleViewletAction } from 'vs/workbench/browser/viewlet';
E
Erich Gamma 已提交
10
import nls = require('vs/nls');
11
import { SyncActionDescriptor } from 'vs/platform/actions/common/actions';
12
import { Registry } from 'vs/platform/registry/common/platform';
13
import { IConfigurationRegistry, Extensions as ConfigurationExtensions, ConfigurationScope } from 'vs/platform/configuration/common/configurationRegistry';
14 15 16
import { IWorkbenchActionRegistry, Extensions as ActionExtensions } from 'vs/workbench/common/actionRegistry';
import { IWorkbenchContributionsRegistry, Extensions as WorkbenchExtensions } from 'vs/workbench/common/contributions';
import { IEditorRegistry, Extensions as EditorExtensions, IEditorInputFactory, EditorInput, IFileEditorInput } from 'vs/workbench/common/editor';
17
import { AutoSaveConfiguration, HotExitConfiguration, SUPPORTED_ENCODINGS } from 'vs/platform/files/common/files';
B
Benjamin Pasero 已提交
18
import { EditorDescriptor } from 'vs/workbench/browser/parts/editor/baseEditor';
19 20 21 22 23 24 25
import { FILE_EDITOR_INPUT_ID, VIEWLET_ID } from 'vs/workbench/parts/files/common/files';
import { FileEditorTracker } from 'vs/workbench/parts/files/common/editors/fileEditorTracker';
import { SaveErrorHandler } from 'vs/workbench/parts/files/browser/saveErrorHandler';
import { FileEditorInput } from 'vs/workbench/parts/files/common/editors/fileEditorInput';
import { TextFileEditor } from 'vs/workbench/parts/files/browser/editors/textFileEditor';
import { BinaryFileEditor } from 'vs/workbench/parts/files/browser/editors/binaryFileEditor';
import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation';
26
import { SyncDescriptor } from 'vs/platform/instantiation/common/descriptors';
A
Renames  
Alex Dima 已提交
27
import { IKeybindings } from 'vs/platform/keybinding/common/keybindingsRegistry';
B
Benjamin Pasero 已提交
28
import { IViewletService } from 'vs/workbench/services/viewlet/browser/viewlet';
29 30
import { IWorkbenchEditorService } from 'vs/workbench/services/editor/common/editorService';
import { KeyMod, KeyCode } from 'vs/base/common/keyCodes';
31
import * as platform from 'vs/base/common/platform';
32
import { IWorkspaceConfigurationService } from 'vs/workbench/services/configuration/common/configuration';
33
import { DirtyFilesTracker } from 'vs/workbench/parts/files/common/dirtyFilesTracker';
E
Erich Gamma 已提交
34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50

// Viewlet Action
export class OpenExplorerViewletAction extends ToggleViewletAction {
	public static ID = VIEWLET_ID;
	public static LABEL = nls.localize('showExplorerViewlet', "Show Explorer");

	constructor(
		id: string,
		label: string,
		@IViewletService viewletService: IViewletService,
		@IWorkbenchEditorService editorService: IWorkbenchEditorService
	) {
		super(id, label, VIEWLET_ID, viewletService, editorService);
	}
}

// Register Viewlet
B
Benjamin Pasero 已提交
51
Registry.as<ViewletRegistry>(ViewletExtensions.Viewlets).registerViewlet(new ViewletDescriptor(
E
Erich Gamma 已提交
52 53 54
	'vs/workbench/parts/files/browser/explorerViewlet',
	'ExplorerViewlet',
	VIEWLET_ID,
B
Benjamin Pasero 已提交
55
	nls.localize('explore', "Explorer"),
E
Erich Gamma 已提交
56 57 58 59
	'explore',
	0
));

B
Benjamin Pasero 已提交
60
Registry.as<ViewletRegistry>(ViewletExtensions.Viewlets).setDefaultViewletId(VIEWLET_ID);
E
Erich Gamma 已提交
61

B
Benjamin Pasero 已提交
62
const openViewletKb: IKeybindings = {
E
Erich Gamma 已提交
63 64 65 66
	primary: KeyMod.CtrlCmd | KeyMod.Shift | KeyCode.KEY_E
};

// Register Action to Open Viewlet
B
Benjamin Pasero 已提交
67
const registry = Registry.as<IWorkbenchActionRegistry>(ActionExtensions.WorkbenchActions);
68
registry.registerWorkbenchAction(
E
Erich Gamma 已提交
69
	new SyncActionDescriptor(OpenExplorerViewletAction, OpenExplorerViewletAction.ID, OpenExplorerViewletAction.LABEL, openViewletKb),
70
	'View: Show Explorer',
71
	nls.localize('view', "View")
E
Erich Gamma 已提交
72 73 74
);

// Register file editors
B
Benjamin Pasero 已提交
75
Registry.as<IEditorRegistry>(EditorExtensions.Editors).registerEditor(
B
Benjamin Pasero 已提交
76
	new EditorDescriptor(
77
		TextFileEditor.ID, // explicit dependency because we don't want these editors lazy loaded
E
Erich Gamma 已提交
78 79
		nls.localize('textFileEditor', "Text File Editor"),
		'vs/workbench/parts/files/browser/editors/textFileEditor',
B
Benjamin Pasero 已提交
80
		'TextFileEditor'
E
Erich Gamma 已提交
81 82 83 84 85 86
	),
	[
		new SyncDescriptor<EditorInput>(FileEditorInput)
	]
);

B
Benjamin Pasero 已提交
87
Registry.as<IEditorRegistry>(EditorExtensions.Editors).registerEditor(
B
Benjamin Pasero 已提交
88
	new EditorDescriptor(
89
		BinaryFileEditor.ID, // explicit dependency because we don't want these editors lazy loaded
E
Erich Gamma 已提交
90 91
		nls.localize('binaryFileEditor', "Binary File Editor"),
		'vs/workbench/parts/files/browser/editors/binaryFileEditor',
B
Benjamin Pasero 已提交
92
		'BinaryFileEditor'
E
Erich Gamma 已提交
93 94 95 96 97 98
	),
	[
		new SyncDescriptor<EditorInput>(FileEditorInput)
	]
);

99 100 101 102 103 104
// Register default file input factory
Registry.as<IEditorRegistry>(EditorExtensions.Editors).registerFileInputFactory({
	createFileInput: (resource, encoding, instantiationService): IFileEditorInput => {
		return instantiationService.createInstance(FileEditorInput, resource, encoding);
	}
});
E
Erich Gamma 已提交
105 106

interface ISerializedFileInput {
107
	resource: string;
B
Benjamin Pasero 已提交
108
	resourceJSON: object;
109
	encoding?: string;
E
Erich Gamma 已提交
110 111 112 113 114
}

// Register Editor Input Factory
class FileEditorInputFactory implements IEditorInputFactory {

115 116 117 118
	constructor(
		@IWorkspaceConfigurationService private configurationService: IWorkspaceConfigurationService
	) {
	}
E
Erich Gamma 已提交
119 120

	public serialize(editorInput: EditorInput): string {
B
Benjamin Pasero 已提交
121
		const fileEditorInput = <FileEditorInput>editorInput;
122
		const resource = fileEditorInput.getResource();
B
Benjamin Pasero 已提交
123
		const fileInput: ISerializedFileInput = {
124 125
			resource: resource.toString(), // Keep for backwards compatibility
			resourceJSON: resource.toJSON()
E
Erich Gamma 已提交
126 127
		};

128
		const encoding = fileEditorInput.getPreferredEncoding();
129
		if (encoding && encoding !== this.configurationService.lookup('files.encoding', { resource }).value) {
130 131 132
			fileInput.encoding = encoding;
		}

E
Erich Gamma 已提交
133 134 135
		return JSON.stringify(fileInput);
	}

136 137 138 139 140
	public deserialize(instantiationService: IInstantiationService, serializedEditorInput: string): FileEditorInput {
		return instantiationService.invokeFunction<FileEditorInput>(accessor => {
			const fileInput: ISerializedFileInput = JSON.parse(serializedEditorInput);
			const resource = !!fileInput.resourceJSON ? URI.revive(fileInput.resourceJSON) : URI.parse(fileInput.resource);
			const encoding = fileInput.encoding;
E
Erich Gamma 已提交
141

142 143
			return accessor.get(IWorkbenchEditorService).createInput({ resource, encoding }) as FileEditorInput;
		});
E
Erich Gamma 已提交
144 145 146
	}
}

B
Benjamin Pasero 已提交
147
Registry.as<IEditorRegistry>(EditorExtensions.Editors).registerEditorInputFactory(FILE_EDITOR_INPUT_ID, FileEditorInputFactory);
E
Erich Gamma 已提交
148

149
// Register File Editor Tracker
B
Benjamin Pasero 已提交
150
Registry.as<IWorkbenchContributionsRegistry>(WorkbenchExtensions.Workbench).registerWorkbenchContribution(
151
	FileEditorTracker
E
Erich Gamma 已提交
152 153
);

B
Benjamin Pasero 已提交
154 155 156 157 158
// Register Save Error Handler
Registry.as<IWorkbenchContributionsRegistry>(WorkbenchExtensions.Workbench).registerWorkbenchContribution(
	SaveErrorHandler
);

159 160 161 162 163
// Register Dirty Files Tracker
Registry.as<IWorkbenchContributionsRegistry>(WorkbenchExtensions.Workbench).registerWorkbenchContribution(
	DirtyFilesTracker
);

E
Erich Gamma 已提交
164
// Configuration
B
Benjamin Pasero 已提交
165
const configurationRegistry = Registry.as<IConfigurationRegistry>(ConfigurationExtensions.Configuration);
E
Erich Gamma 已提交
166 167 168

configurationRegistry.registerConfiguration({
	'id': 'files',
169
	'order': 9,
170
	'title': nls.localize('filesConfigurationTitle', "Files"),
E
Erich Gamma 已提交
171 172 173 174 175
	'type': 'object',
	'properties': {
		'files.exclude': {
			'type': 'object',
			'description': nls.localize('exclude', "Configure glob patterns for excluding files and folders."),
P
Peter V 已提交
176
			'default': { '**/.git': true, '**/.svn': true, '**/.hg': true, '**/CVS': true, '**/.DS_Store': true },
177
			'scope': ConfigurationScope.FOLDER,
E
Erich Gamma 已提交
178 179 180 181 182 183 184 185 186 187 188 189 190
			'additionalProperties': {
				'anyOf': [
					{
						'type': 'boolean',
						'description': nls.localize('files.exclude.boolean', "The glob pattern to match file paths against. Set to true or false to enable or disable the pattern."),
					},
					{
						'type': 'object',
						'properties': {
							'when': {
								'type': 'string', // expression ({ "**/*.js": { "when": "$(basename).js" } })
								'pattern': '\\w*\\$\\(basename\\)\\w*',
								'default': '$(basename).ext',
B
Benjamin Pasero 已提交
191
								'description': nls.localize('files.exclude.when', "Additional check on the siblings of a matching file. Use $(basename) as variable for the matching file name.")
E
Erich Gamma 已提交
192 193 194 195 196 197
							}
						}
					}
				]
			}
		},
B
Benjamin Pasero 已提交
198
		'files.associations': {
199
			'type': 'object',
B
Benjamin Pasero 已提交
200
			'description': nls.localize('associations', "Configure file associations to languages (e.g. \"*.extension\": \"html\"). These have precedence over the default associations of the languages installed."),
201
		},
E
Erich Gamma 已提交
202 203 204 205 206
		'files.encoding': {
			'type': 'string',
			'enum': Object.keys(SUPPORTED_ENCODINGS),
			'default': 'utf8',
			'description': nls.localize('encoding', "The default character set encoding to use when reading and writing files."),
S
Sandeep Somavarapu 已提交
207
			'scope': ConfigurationScope.FOLDER
E
Erich Gamma 已提交
208
		},
209
		'files.autoGuessEncoding': {
210 211
			'type': 'boolean',
			'default': false,
S
Sandeep Somavarapu 已提交
212 213
			'description': nls.localize('autoGuessEncoding', "When enabled, will attempt to guess the character set encoding when opening files"),
			'scope': ConfigurationScope.FOLDER
214
		},
215 216 217 218 219 220 221
		'files.eol': {
			'type': 'string',
			'enum': [
				'\n',
				'\r\n'
			],
			'default': (platform.isLinux || platform.isMacintosh) ? '\n' : '\r\n',
222
			'description': nls.localize('eol', "The default end of line character. Use \\n for LF and \\r\\n for CRLF."),
223
		},
E
Erich Gamma 已提交
224 225 226
		'files.trimTrailingWhitespace': {
			'type': 'boolean',
			'default': false,
227
			'description': nls.localize('trimTrailingWhitespace', "When enabled, will trim trailing whitespace when saving a file."),
S
Sandeep Somavarapu 已提交
228 229
			'overridable': true,
			'scope': ConfigurationScope.FOLDER
230 231 232 233
		},
		'files.insertFinalNewline': {
			'type': 'boolean',
			'default': false,
234
			'description': nls.localize('insertFinalNewline', "When enabled, insert a final new line at the end of the file when saving it."),
S
Sandeep Somavarapu 已提交
235 236
			'overridable': true,
			'scope': ConfigurationScope.FOLDER
237
		},
238 239
		'files.autoSave': {
			'type': 'string',
S
Sandeep Somavarapu 已提交
240
			'enum': [AutoSaveConfiguration.OFF, AutoSaveConfiguration.AFTER_DELAY, AutoSaveConfiguration.ON_FOCUS_CHANGE, , AutoSaveConfiguration.ON_WINDOW_CHANGE],
241
			'enumDescriptions': [
242 243 244 245
				nls.localize({ comment: ['This is the description for a setting. Values surrounded by single quotes are not to be translated.'], key: 'files.autoSave.off' }, "A dirty file is never automatically saved."),
				nls.localize({ comment: ['This is the description for a setting. Values surrounded by single quotes are not to be translated.'], key: 'files.autoSave.afterDelay' }, "A dirty file is automatically saved after the configured 'files.autoSaveDelay'."),
				nls.localize({ comment: ['This is the description for a setting. Values surrounded by single quotes are not to be translated.'], key: 'files.autoSave.onFocusChange' }, "A dirty file is automatically saved when the editor loses focus."),
				nls.localize({ comment: ['This is the description for a setting. Values surrounded by single quotes are not to be translated.'], key: 'files.autoSave.onWindowChange' }, "A dirty file is automatically saved when the window loses focus.")
246
			],
247
			'default': AutoSaveConfiguration.OFF,
B
Benjamin Pasero 已提交
248
			'description': nls.localize({ comment: ['This is the description for a setting. Values surrounded by single quotes are not to be translated.'], key: 'autoSave' }, "Controls auto save of dirty files. Accepted values:  '{0}', '{1}', '{2}' (editor loses focus), '{3}' (window loses focus). If set to '{4}', you can configure the delay in 'files.autoSaveDelay'.", AutoSaveConfiguration.OFF, AutoSaveConfiguration.AFTER_DELAY, AutoSaveConfiguration.ON_FOCUS_CHANGE, AutoSaveConfiguration.ON_WINDOW_CHANGE, AutoSaveConfiguration.AFTER_DELAY)
249
		},
250
		'files.autoSaveDelay': {
251
			'type': 'number',
252
			'default': 1000,
B
Benjamin Pasero 已提交
253
			'description': nls.localize({ comment: ['This is the description for a setting. Values surrounded by single quotes are not to be translated.'], key: 'autoSaveDelay' }, "Controls the delay in ms after which a dirty file is saved automatically. Only applies when 'files.autoSave' is set to '{0}'", AutoSaveConfiguration.AFTER_DELAY)
254 255
		},
		'files.watcherExclude': {
256
			'type': 'object',
257
			'default': platform.isWindows /* https://github.com/Microsoft/vscode/issues/23954 */ ? { '**/.git/objects/**': true, '**/.git/subtree-cache/**': true, '**/node_modules/*/**': true } : { '**/.git/objects/**': true, '**/.git/subtree-cache/**': true, '**/node_modules/**': true },
S
Sandeep Somavarapu 已提交
258 259
			'description': nls.localize('watcherExclude', "Configure glob patterns of file paths to exclude from file watching. Changing this setting requires a restart. When you experience Code consuming lots of cpu time on startup, you can exclude large folders to reduce the initial load."),
			'scope': ConfigurationScope.FOLDER
D
Daniel Imms 已提交
260 261
		},
		'files.hotExit': {
262
			'type': 'string',
D
Daniel Imms 已提交
263 264
			'enum': [HotExitConfiguration.OFF, HotExitConfiguration.ON_EXIT, HotExitConfiguration.ON_EXIT_AND_WINDOW_CLOSE],
			'default': HotExitConfiguration.ON_EXIT,
D
Daniel Imms 已提交
265 266
			'enumDescriptions': [
				nls.localize('hotExit.off', 'Disable hot exit.'),
B
Benjamin Pasero 已提交
267
				nls.localize('hotExit.onExit', 'Hot exit will be triggered when the application is closed, that is when the last window is closed on Windows/Linux or when the workbench.action.quit command is triggered (command palette, keybinding, menu). All windows with backups will be restored upon next launch.'),
268
				nls.localize('hotExit.onExitAndWindowClose', 'Hot exit will be triggered when the application is closed, that is when the last window is closed on Windows/Linux or when the workbench.action.quit command is triggered (command palette, keybinding, menu), and also for any window with a folder opened regardless of whether it\'s the last window. All windows without folders opened will be restored upon next launch. To restore folder windows as they were before shutdown set "window.restoreWindows" to "all".')
D
Daniel Imms 已提交
269 270
			],
			'description': nls.localize('hotExit', "Controls whether unsaved files are remembered between sessions, allowing the save prompt when exiting the editor to be skipped.", HotExitConfiguration.ON_EXIT, HotExitConfiguration.ON_EXIT_AND_WINDOW_CLOSE)
271
		},
272
		'files.useExperimentalFileWatcher': {
273 274
			'type': 'boolean',
			'default': false,
275
			'description': nls.localize('useExperimentalFileWatcher', "Use the new experimental file watcher.")
276
		},
277 278 279
		'files.defaultLanguage': {
			'type': 'string',
			'description': nls.localize('defaultLanguage', "The default language mode that is assigned to new files.")
280 281 282 283 284 285
		}
	}
});

configurationRegistry.registerConfiguration({
	id: 'editor',
286 287
	order: 5,
	title: nls.localize('editorConfigurationTitle', "Editor"),
288 289
	type: 'object',
	properties: {
290 291 292
		'editor.formatOnSave': {
			'type': 'boolean',
			'default': false,
293 294
			'description': nls.localize('formatOnSave', "Format a file on save. A formatter must be available, the file must not be auto-saved, and editor must not be shutting down."),
			'overridable': true
E
Erich Gamma 已提交
295 296 297 298 299 300
		}
	}
});

configurationRegistry.registerConfiguration({
	'id': 'explorer',
301
	'order': 10,
302
	'title': nls.localize('explorerConfigurationTitle', "File Explorer"),
E
Erich Gamma 已提交
303 304
	'type': 'object',
	'properties': {
305
		'explorer.openEditors.visible': {
E
Erich Gamma 已提交
306
			'type': 'number',
I
isidor 已提交
307
			'description': nls.localize({ key: 'openEditorsVisible', comment: ['Open is an adjective'] }, "Number of editors shown in the Open Editors pane. Set it to 0 to hide the pane."),
E
Erich Gamma 已提交
308 309
			'default': 9
		},
310
		'explorer.openEditors.dynamicHeight': {
E
Erich Gamma 已提交
311
			'type': 'boolean',
I
isidor 已提交
312
			'description': nls.localize({ key: 'dynamicHeight', comment: ['Open is an adjective'] }, "Controls if the height of the open editors section should adapt dynamically to the number of elements or not."),
E
Erich Gamma 已提交
313
			'default': true
314 315 316
		},
		'explorer.autoReveal': {
			'type': 'boolean',
317
			'description': nls.localize('autoReveal', "Controls if the explorer should automatically reveal and select files when opening them."),
318
			'default': true
319 320 321 322 323
		},
		'explorer.enableDragAndDrop': {
			'type': 'boolean',
			'description': nls.localize('enableDragAndDrop', "Controls if the explorer should allow to move files and folders via drag and drop."),
			'default': true
E
Erich Gamma 已提交
324 325
		}
	}
326
});