提交 83356510 编写于 作者: B Benjamin Pasero

use config write API to write file associations (for #11974)

上级 91115aa7
...@@ -21,10 +21,10 @@ import {IMode} from 'vs/editor/common/modes'; ...@@ -21,10 +21,10 @@ import {IMode} from 'vs/editor/common/modes';
import {UntitledEditorInput} from 'vs/workbench/common/editor/untitledEditorInput'; import {UntitledEditorInput} from 'vs/workbench/common/editor/untitledEditorInput';
import {IFileEditorInput, EncodingMode, IEncodingSupport, asFileEditorInput, getUntitledOrFileResource} from 'vs/workbench/common/editor'; import {IFileEditorInput, EncodingMode, IEncodingSupport, asFileEditorInput, getUntitledOrFileResource} from 'vs/workbench/common/editor';
import {IDisposable, combinedDisposable, dispose} from 'vs/base/common/lifecycle'; import {IDisposable, combinedDisposable, dispose} from 'vs/base/common/lifecycle';
import {IUntitledEditorService} from 'vs/workbench/services/untitled/common/untitledEditorService';
import {IMessageService, Severity} from 'vs/platform/message/common/message'; import {IMessageService, Severity} from 'vs/platform/message/common/message';
import {IUntitledEditorService} from 'vs/workbench/services/untitled/common/untitledEditorService';
import {IConfigurationEditingService, ConfigurationTarget} from 'vs/workbench/services/configuration/common/configurationEditing';
import {IEditorAction, ICommonCodeEditor, IModelContentChangedEvent, IModelOptionsChangedEvent, IModelModeChangedEvent, ICursorPositionChangedEvent} from 'vs/editor/common/editorCommon'; import {IEditorAction, ICommonCodeEditor, IModelContentChangedEvent, IModelOptionsChangedEvent, IModelModeChangedEvent, ICursorPositionChangedEvent} from 'vs/editor/common/editorCommon';
import {OpenGlobalSettingsAction} from 'vs/workbench/browser/actions/openSettings';
import {ICodeEditor, IDiffEditor} from 'vs/editor/browser/editorBrowser'; import {ICodeEditor, IDiffEditor} from 'vs/editor/browser/editorBrowser';
import {TrimTrailingWhitespaceAction} from 'vs/editor/contrib/linesOperations/common/linesOperations'; import {TrimTrailingWhitespaceAction} from 'vs/editor/contrib/linesOperations/common/linesOperations';
import {EndOfLineSequence, ITokenizedModel, EditorType, ITextModel, IDiffEditorModel, IEditor} from 'vs/editor/common/editorCommon'; import {EndOfLineSequence, ITokenizedModel, EditorType, ITextModel, IDiffEditorModel, IEditor} from 'vs/editor/common/editorCommon';
...@@ -299,7 +299,7 @@ export class EditorStatus implements IStatusbarItem { ...@@ -299,7 +299,7 @@ export class EditorStatus implements IStatusbarItem {
this.editorGroupService.onEditorsChanged(() => this.onEditorsChanged()), this.editorGroupService.onEditorsChanged(() => this.onEditorsChanged()),
this.untitledEditorService.onDidChangeEncoding(r => this.onResourceEncodingChange(r)), this.untitledEditorService.onDidChangeEncoding(r => this.onResourceEncodingChange(r)),
this.textFileService.models.onModelEncodingChanged(e => this.onResourceEncodingChange(e.resource)), this.textFileService.models.onModelEncodingChanged(e => this.onResourceEncodingChange(e.resource)),
TabFocus.onDidChangeTabFocus((e) => this.onTabFocusModeChange()) TabFocus.onDidChangeTabFocus(e => this.onTabFocusModeChange())
); );
return combinedDisposable(this.toDispose); return combinedDisposable(this.toDispose);
...@@ -533,7 +533,7 @@ export class EditorStatus implements IStatusbarItem { ...@@ -533,7 +533,7 @@ export class EditorStatus implements IStatusbarItem {
info.charactersSelected = 0; info.charactersSelected = 0;
const textModel = getTextModel(editorWidget); const textModel = getTextModel(editorWidget);
if (textModel) { if (textModel) {
info.selections.forEach((selection) => { info.selections.forEach(selection => {
info.charactersSelected += textModel.getValueLengthInRange(selection); info.charactersSelected += textModel.getValueLengthInRange(selection);
}); });
} }
...@@ -633,7 +633,9 @@ export class ChangeModeAction extends Action { ...@@ -633,7 +633,9 @@ export class ChangeModeAction extends Action {
actionLabel: string, actionLabel: string,
@IModeService private modeService: IModeService, @IModeService private modeService: IModeService,
@IWorkbenchEditorService private editorService: IWorkbenchEditorService, @IWorkbenchEditorService private editorService: IWorkbenchEditorService,
@IConfigurationEditingService private configurationEditingService: IConfigurationEditingService,
@IMessageService private messageService: IMessageService, @IMessageService private messageService: IMessageService,
@IConfigurationService private configurationService: IConfigurationService,
@IInstantiationService private instantiationService: IInstantiationService, @IInstantiationService private instantiationService: IInstantiationService,
@IQuickOpenService private quickOpenService: IQuickOpenService @IQuickOpenService private quickOpenService: IQuickOpenService
) { ) {
...@@ -641,7 +643,6 @@ export class ChangeModeAction extends Action { ...@@ -641,7 +643,6 @@ export class ChangeModeAction extends Action {
} }
public run(): TPromise<any> { public run(): TPromise<any> {
const languages = this.modeService.getRegisteredLanguageNames();
let activeEditor = this.editorService.getActiveEditor(); let activeEditor = this.editorService.getActiveEditor();
if (!(activeEditor instanceof BaseTextEditor)) { if (!(activeEditor instanceof BaseTextEditor)) {
return this.quickOpenService.pick([{ label: nls.localize('noEditor', "No text editor active at this time") }]); return this.quickOpenService.pick([{ label: nls.localize('noEditor', "No text editor active at this time") }]);
...@@ -661,6 +662,7 @@ export class ChangeModeAction extends Action { ...@@ -661,6 +662,7 @@ export class ChangeModeAction extends Action {
} }
// All languages are valid picks // All languages are valid picks
const languages = this.modeService.getRegisteredLanguageNames();
const picks: IPickOpenEntry[] = languages.sort().map((lang, index) => { const picks: IPickOpenEntry[] = languages.sort().map((lang, index) => {
let description: string; let description: string;
if (currentModeId === lang) { if (currentModeId === lang) {
...@@ -677,19 +679,15 @@ export class ChangeModeAction extends Action { ...@@ -677,19 +679,15 @@ export class ChangeModeAction extends Action {
picks[0].separator = { border: true, label: nls.localize('languagesPicks', "languages") }; picks[0].separator = { border: true, label: nls.localize('languagesPicks', "languages") };
// Offer action to configure via settings // Offer action to configure via settings
let configureLabel = nls.localize('configureAssociations', "Configure File Associations..."); let configureModeAssociations: IPickOpenEntry;
if (fileinput) { if (fileinput) {
const resource = fileinput.getResource(); const resource = fileinput.getResource();
const ext = paths.extname(resource.fsPath) || paths.basename(resource.fsPath); configureModeAssociations = {
if (ext) { label: nls.localize('configureAssociationsExt', "Configure File Association for '{0}'...", paths.extname(resource.fsPath) || paths.basename(resource.fsPath))
configureLabel = nls.localize('configureAssociationsExt', "Configure File Association for '{0}'...", ext); };
}
}
const configureModeAssociations: IPickOpenEntry = { picks.unshift(configureModeAssociations);
label: configureLabel }
};
picks.unshift(configureModeAssociations);
// Offer to "Auto Detect" // Offer to "Auto Detect"
const autoDetectMode: IPickOpenEntry = { const autoDetectMode: IPickOpenEntry = {
...@@ -699,7 +697,7 @@ export class ChangeModeAction extends Action { ...@@ -699,7 +697,7 @@ export class ChangeModeAction extends Action {
picks.unshift(autoDetectMode); picks.unshift(autoDetectMode);
} }
return this.quickOpenService.pick(picks, { placeHolder: nls.localize('pickLanguage', "Select Language Mode") }).then((language) => { return this.quickOpenService.pick(picks, { placeHolder: nls.localize('pickLanguage', "Select Language Mode") }).then(language => {
if (language) { if (language) {
activeEditor = this.editorService.getActiveEditor(); activeEditor = this.editorService.getActiveEditor();
if (activeEditor instanceof BaseTextEditor) { if (activeEditor instanceof BaseTextEditor) {
...@@ -720,16 +718,13 @@ export class ChangeModeAction extends Action { ...@@ -720,16 +718,13 @@ export class ChangeModeAction extends Action {
if (language === autoDetectMode) { if (language === autoDetectMode) {
mode = this.modeService.getOrCreateModeByFilenameOrFirstLine(getUntitledOrFileResource(activeEditor.input, true).fsPath, textModel.getLineContent(1)); mode = this.modeService.getOrCreateModeByFilenameOrFirstLine(getUntitledOrFileResource(activeEditor.input, true).fsPath, textModel.getLineContent(1));
} else if (language === configureModeAssociations) { } else if (language === configureModeAssociations) {
const action = this.instantiationService.createInstance(OpenGlobalSettingsAction, OpenGlobalSettingsAction.ID, OpenGlobalSettingsAction.LABEL); this.configureFileAssociation(fileinput.getResource());
action.run().done(() => action.dispose(), errors.onUnexpectedError);
this.messageService.show(Severity.Info, nls.localize('persistFileAssociations', "You can configure filename to language associations in the **files.associations** section. The changes may need a restart to take effect on already opened files."));
} else { } else {
mode = this.modeService.getOrCreateModeByLanguageName(language.label); mode = this.modeService.getOrCreateModeByLanguageName(language.label);
} }
// Change mode // Change mode
models.forEach((textModel) => { models.forEach(textModel => {
if (!!(<ITokenizedModel>textModel).getMode) { if (!!(<ITokenizedModel>textModel).getMode) {
(<ITokenizedModel>textModel).setMode(mode); (<ITokenizedModel>textModel).setMode(mode);
} }
...@@ -738,6 +733,39 @@ export class ChangeModeAction extends Action { ...@@ -738,6 +733,39 @@ export class ChangeModeAction extends Action {
} }
}); });
} }
private configureFileAssociation(resource: uri): void {
const languages = this.modeService.getRegisteredLanguageNames();
const picks: IPickOpenEntry[] = languages.sort().map((lang, index) => {
return <IPickOpenEntry>{
id: this.modeService.getModeIdForLanguageName(lang.toLowerCase()),
label: lang
};
});
TPromise.timeout(50 /* quick open is sensitive to being opened so soon after another */).done(() => {
const extension = paths.extname(resource.fsPath);
const basename = paths.basename(resource.fsPath);
this.quickOpenService.pick(picks, { placeHolder: nls.localize('pickLanguageToConfigure', "Select Language Mode to Associate with '{0}'", extension || basename) }).done(language => {
if (language) {
const config = this.configurationService.getConfiguration<IFilesConfiguration>();
const currentAssociations = (config && config.files && config.files.associations) || Object.create(null);
let associationKey: string;
if (extension && basename[0] !== '.') {
associationKey = `*${extension}`; // only use "*.ext" if the file path is in the form of <name>.<ext>
} else {
associationKey = basename; // otherwise use the basename (e.g. .gitignore, Dockerfile)
}
currentAssociations[associationKey] = language.id;
this.configurationEditingService.writeConfiguration(ConfigurationTarget.USER, { key: 'files.associations', value: currentAssociations }).done(null, (error) => this.messageService.show(Severity.Error, error.toString()));
}
});
});
}
} }
export interface IChangeEOLEntry extends IPickOpenEntry { export interface IChangeEOLEntry extends IPickOpenEntry {
...@@ -828,7 +856,7 @@ export class ChangeEOLAction extends Action { ...@@ -828,7 +856,7 @@ export class ChangeEOLAction extends Action {
const selectedIndex = (textModel.getEOL() === '\n') ? 0 : 1; const selectedIndex = (textModel.getEOL() === '\n') ? 0 : 1;
return this.quickOpenService.pick(EOLOptions, { placeHolder: nls.localize('pickEndOfLine', "Select End of Line Sequence"), autoFocus: { autoFocusIndex: selectedIndex } }).then((eol) => { return this.quickOpenService.pick(EOLOptions, { placeHolder: nls.localize('pickEndOfLine', "Select End of Line Sequence"), autoFocus: { autoFocusIndex: selectedIndex } }).then(eol => {
if (eol) { if (eol) {
activeEditor = this.editorService.getActiveEditor(); activeEditor = this.editorService.getActiveEditor();
if (activeEditor instanceof BaseTextEditor && isWritableCodeEditor(activeEditor)) { if (activeEditor instanceof BaseTextEditor && isWritableCodeEditor(activeEditor)) {
...@@ -887,7 +915,7 @@ export class ChangeEncodingAction extends Action { ...@@ -887,7 +915,7 @@ export class ChangeEncodingAction extends Action {
pickActionPromise = this.quickOpenService.pick([reopenWithEncodingPick, saveWithEncodingPick], { placeHolder: nls.localize('pickAction', "Select Action"), matchOnDetail: true }); pickActionPromise = this.quickOpenService.pick([reopenWithEncodingPick, saveWithEncodingPick], { placeHolder: nls.localize('pickAction', "Select Action"), matchOnDetail: true });
} }
return pickActionPromise.then((action) => { return pickActionPromise.then(action => {
if (!action) { if (!action) {
return; return;
} }
...@@ -927,7 +955,7 @@ export class ChangeEncodingAction extends Action { ...@@ -927,7 +955,7 @@ export class ChangeEncodingAction extends Action {
return this.quickOpenService.pick(picks, { return this.quickOpenService.pick(picks, {
placeHolder: isReopenWithEncoding ? nls.localize('pickEncodingForReopen', "Select File Encoding to Reopen File") : nls.localize('pickEncodingForSave', "Select File Encoding to Save with"), placeHolder: isReopenWithEncoding ? nls.localize('pickEncodingForReopen', "Select File Encoding to Reopen File") : nls.localize('pickEncodingForSave', "Select File Encoding to Save with"),
autoFocus: { autoFocusIndex: typeof directMatchIndex === 'number' ? directMatchIndex : typeof aliasMatchIndex === 'number' ? aliasMatchIndex : void 0 } autoFocus: { autoFocusIndex: typeof directMatchIndex === 'number' ? directMatchIndex : typeof aliasMatchIndex === 'number' ? aliasMatchIndex : void 0 }
}).then((encoding) => { }).then(encoding => {
if (encoding) { if (encoding) {
activeEditor = this.editorService.getActiveEditor(); activeEditor = this.editorService.getActiveEditor();
encodingSupport = <any>asFileOrUntitledEditorInput(activeEditor.input); encodingSupport = <any>asFileOrUntitledEditorInput(activeEditor.input);
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册