mirror of
https://github.com/microsoft/vscode.git
synced 2026-09-27 10:37:38 +01:00
Allow to change indent options on models
This commit is contained in:
@@ -1255,8 +1255,14 @@ export interface ITextModelCreationOptions {
|
||||
defaultEOL: DefaultEndOfLine;
|
||||
}
|
||||
|
||||
export interface ITextModelUpdateOptions {
|
||||
tabSize?: number;
|
||||
insertSpaces?: boolean;
|
||||
}
|
||||
|
||||
export interface IModelOptionsChangedEvent {
|
||||
// TODO@Alex TODO@indent
|
||||
tabSize: boolean;
|
||||
insertSpaces: boolean;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -1710,6 +1716,10 @@ export interface IEditableTextModel extends ITextModelWithMarkers {
|
||||
|
||||
getOneIndent(): string;
|
||||
|
||||
updateOptions(newOpts:ITextModelUpdateOptions): void;
|
||||
|
||||
detectIndentation(defaultInsertSpaces:boolean, defaultTabSize:number): void;
|
||||
|
||||
/**
|
||||
* Push a stack element onto the undo stack. This acts as an undo/redo point.
|
||||
* The idea is to use `pushEditOperations` to edit the model and then to
|
||||
|
||||
@@ -38,7 +38,7 @@ export class TextModel extends OrderGuaranteeEventEmitter implements editorCommo
|
||||
private _BOM:string;
|
||||
|
||||
constructor(allowedEventTypes:string[], rawText:editorCommon.IRawText) {
|
||||
allowedEventTypes.push(editorCommon.EventType.ModelContentChanged);
|
||||
allowedEventTypes.push(editorCommon.EventType.ModelContentChanged, editorCommon.EventType.ModelOptionsChanged);
|
||||
super(allowedEventTypes);
|
||||
|
||||
this._options = rawText.options;
|
||||
@@ -56,6 +56,42 @@ export class TextModel extends OrderGuaranteeEventEmitter implements editorCommo
|
||||
return this._options;
|
||||
}
|
||||
|
||||
public updateOptions(newOpts:editorCommon.ITextModelUpdateOptions): void {
|
||||
let somethingChanged = false;
|
||||
let changed:editorCommon.IModelOptionsChangedEvent = {
|
||||
tabSize: false,
|
||||
insertSpaces: false
|
||||
};
|
||||
|
||||
if (typeof newOpts.insertSpaces !== 'undefined') {
|
||||
if (this._options.insertSpaces !== newOpts.insertSpaces) {
|
||||
somethingChanged = true;
|
||||
changed.insertSpaces = true;
|
||||
this._options.insertSpaces = newOpts.insertSpaces;
|
||||
}
|
||||
}
|
||||
if (typeof newOpts.tabSize !== 'undefined') {
|
||||
if (this._options.tabSize !== newOpts.tabSize) {
|
||||
somethingChanged = true;
|
||||
changed.tabSize = true;
|
||||
this._options.tabSize = newOpts.tabSize;
|
||||
}
|
||||
}
|
||||
|
||||
if (somethingChanged) {
|
||||
this.emit(editorCommon.EventType.ModelOptionsChanged, changed);
|
||||
}
|
||||
}
|
||||
|
||||
public detectIndentation(defaultInsertSpaces:boolean, defaultTabSize:number): void {
|
||||
let lines = this._lines.map(line => line.text);
|
||||
let guessedIndentation = guessIndentation(lines, defaultTabSize, defaultInsertSpaces);
|
||||
this.updateOptions({
|
||||
insertSpaces: guessedIndentation.insertSpaces,
|
||||
tabSize: guessedIndentation.tabSize
|
||||
});
|
||||
}
|
||||
|
||||
private _normalizeIndentationFromWhitespace(str:string): string {
|
||||
let tabSize = this._options.tabSize;
|
||||
let insertSpaces = this._options.insertSpaces;
|
||||
|
||||
@@ -8,7 +8,7 @@ import Event from 'vs/base/common/event';
|
||||
import URI from 'vs/base/common/uri';
|
||||
import {TPromise} from 'vs/base/common/winjs.base';
|
||||
import {ServiceIdentifier, createDecorator} from 'vs/platform/instantiation/common/instantiation';
|
||||
import {IModel} from 'vs/editor/common/editorCommon';
|
||||
import {IModel, ITextModelCreationOptions} from 'vs/editor/common/editorCommon';
|
||||
import {IMode} from 'vs/editor/common/modes';
|
||||
|
||||
export var IModelService = createDecorator<IModelService>('modelService');
|
||||
@@ -22,6 +22,8 @@ export interface IModelService {
|
||||
|
||||
getModels(): IModel[];
|
||||
|
||||
getCreationOptions(): ITextModelCreationOptions;
|
||||
|
||||
getModel(resource: URI): IModel;
|
||||
|
||||
onModelAdded: Event<IModel>;
|
||||
|
||||
@@ -170,6 +170,17 @@ class ModelMarkerHandler {
|
||||
}
|
||||
}
|
||||
|
||||
interface IRawConfig {
|
||||
files?: {
|
||||
eol?: any;
|
||||
};
|
||||
editor?: {
|
||||
tabSize?: any;
|
||||
insertSpaces?: any;
|
||||
detectIndentation?: any;
|
||||
};
|
||||
}
|
||||
|
||||
export class ModelServiceImpl implements IModelService {
|
||||
public serviceId = IModelService;
|
||||
|
||||
@@ -210,20 +221,20 @@ export class ModelServiceImpl implements IModelService {
|
||||
this._workerHelper = this._threadService.getRemotable(ModelServiceWorkerHelper);
|
||||
this._configurationService = configurationService;
|
||||
|
||||
let readDefaultEOL = (config:any) => {
|
||||
let readConfig = (config:IRawConfig) => {
|
||||
const eol = config.files && config.files.eol;
|
||||
|
||||
let newTabSize = DEFAULT_INDENTATION.tabSize;
|
||||
let tabSize = DEFAULT_INDENTATION.tabSize;
|
||||
if (config.editor && typeof config.editor.tabSize !== 'undefined') {
|
||||
let parsedTabSize = parseInt(config.editor.tabSize, 10);
|
||||
if (!isNaN(parsedTabSize)) {
|
||||
newTabSize = parsedTabSize;
|
||||
tabSize = parsedTabSize;
|
||||
}
|
||||
}
|
||||
|
||||
let newInsertSpaces = DEFAULT_INDENTATION.insertSpaces;
|
||||
let insertSpaces = DEFAULT_INDENTATION.insertSpaces;
|
||||
if (config.editor && typeof config.editor.insertSpaces !== 'undefined') {
|
||||
newInsertSpaces = (config.editor.insertSpaces === 'false' ? false : Boolean(config.editor.insertSpaces));
|
||||
insertSpaces = (config.editor.insertSpaces === 'false' ? false : Boolean(config.editor.insertSpaces));
|
||||
}
|
||||
|
||||
let newDefaultEOL = this._modelCreationOptions.defaultEOL;
|
||||
@@ -234,19 +245,23 @@ export class ModelServiceImpl implements IModelService {
|
||||
}
|
||||
|
||||
let detectIndentation = DEFAULT_INDENTATION.detectIndentation;
|
||||
if (config.editor && typeof config.editor.detectIndentation !== 'undefined') {
|
||||
detectIndentation = (config.editor.detectIndentation === 'false' ? false : Boolean(config.editor.detectIndentation));
|
||||
}
|
||||
|
||||
this._modelCreationOptions = {
|
||||
tabSize: newTabSize,
|
||||
insertSpaces: newInsertSpaces,
|
||||
this._setModelOptions({
|
||||
tabSize: tabSize,
|
||||
insertSpaces: insertSpaces,
|
||||
detectIndentation: detectIndentation,
|
||||
defaultEOL: newDefaultEOL
|
||||
};
|
||||
});
|
||||
|
||||
};
|
||||
this._configurationServiceSubscription = this._configurationService.addListener2(ConfigurationServiceEventTypes.UPDATED, (e: IConfigurationServiceEvent) => {
|
||||
readDefaultEOL(e.config);
|
||||
readConfig(e.config);
|
||||
});
|
||||
this._configurationService.loadConfiguration().then((config) => {
|
||||
readDefaultEOL(config);
|
||||
readConfig(config);
|
||||
});
|
||||
|
||||
this._models = {};
|
||||
@@ -260,6 +275,26 @@ export class ModelServiceImpl implements IModelService {
|
||||
}
|
||||
}
|
||||
|
||||
public getCreationOptions(): editorCommon.ITextModelCreationOptions {
|
||||
return this._modelCreationOptions;
|
||||
}
|
||||
|
||||
private _setModelOptions(newOpts: editorCommon.ITextModelCreationOptions): void {
|
||||
if (
|
||||
(this._modelCreationOptions.detectIndentation === newOpts.detectIndentation)
|
||||
&& (this._modelCreationOptions.insertSpaces === newOpts.insertSpaces)
|
||||
&& (this._modelCreationOptions.tabSize === newOpts.tabSize)
|
||||
) {
|
||||
// Same indent opts, no need to touch created models
|
||||
this._modelCreationOptions = newOpts;
|
||||
return;
|
||||
}
|
||||
this._modelCreationOptions = newOpts;
|
||||
|
||||
// TODO@Alex TODO@indent
|
||||
// console.log('I NEED TO UPDATE EXISTING MODELS!!!');
|
||||
}
|
||||
|
||||
public dispose(): void {
|
||||
if(this._markerServiceSubscription) {
|
||||
this._markerServiceSubscription.dispose();
|
||||
|
||||
@@ -10,6 +10,7 @@ import {ICommonCodeEditor, IEditorActionDescriptorData} from 'vs/editor/common/e
|
||||
import {CommonEditorRegistry, EditorActionDescriptor} from 'vs/editor/common/editorCommonExtensions';
|
||||
import {IndentationToSpacesCommand, IndentationToTabsCommand} from 'vs/editor/contrib/indentation/common/indentationCommands';
|
||||
import {IQuickOpenService} from 'vs/workbench/services/quickopen/common/quickOpenService';
|
||||
import {IModelService} from 'vs/editor/common/services/modelService';
|
||||
|
||||
export class IndentationToSpacesAction extends EditorAction {
|
||||
static ID = 'editor.action.indentationToSpaces';
|
||||
@@ -26,10 +27,9 @@ export class IndentationToSpacesAction extends EditorAction {
|
||||
let modelOpts = model.getOptions();
|
||||
const command = new IndentationToSpacesCommand(this.editor.getSelection(), modelOpts.tabSize);
|
||||
this.editor.executeCommands(this.id, [command]);
|
||||
// TODO@Alex TODO@indent
|
||||
// model.updateOptions({
|
||||
// insertSpaces: true
|
||||
// });
|
||||
model.updateOptions({
|
||||
insertSpaces: true
|
||||
});
|
||||
|
||||
return TPromise.as(true);
|
||||
}
|
||||
@@ -50,10 +50,9 @@ export class IndentationToTabsAction extends EditorAction {
|
||||
let modelOpts = model.getOptions();
|
||||
const command = new IndentationToTabsCommand(this.editor.getSelection(), modelOpts.tabSize);
|
||||
this.editor.executeCommands(this.id, [command]);
|
||||
// TODO@Alex TODO@indent
|
||||
// model.updateOptions({
|
||||
// insertSpaces: false
|
||||
// });
|
||||
model.updateOptions({
|
||||
insertSpaces: false
|
||||
});
|
||||
|
||||
return TPromise.as(true);
|
||||
}
|
||||
@@ -63,7 +62,8 @@ export class ChangeIndentationSizeAction extends EditorAction {
|
||||
|
||||
constructor(descriptor: IEditorActionDescriptorData, editor: ICommonCodeEditor,
|
||||
private insertSpaces: boolean,
|
||||
private quickOpenService: IQuickOpenService
|
||||
private quickOpenService: IQuickOpenService,
|
||||
private modelService:IModelService
|
||||
) {
|
||||
super(descriptor, editor);
|
||||
}
|
||||
@@ -73,22 +73,22 @@ export class ChangeIndentationSizeAction extends EditorAction {
|
||||
if (!model) {
|
||||
return;
|
||||
}
|
||||
let modelOpts = model.getOptions();
|
||||
|
||||
let creationOpts = this.modelService.getCreationOptions();
|
||||
const picks = [1, 2, 3, 4, 5, 6, 7, 8].map(n => ({
|
||||
id: n.toString(),
|
||||
label: n.toString(),
|
||||
description: n === modelOpts.tabSize ? nls.localize('configuredTabSize', "Configured Tab Size") : null
|
||||
description: n === creationOpts.tabSize ? nls.localize('configuredTabSize', "Configured Tab Size") : null
|
||||
}));
|
||||
const autoFocusIndex = Math.min(modelOpts.tabSize - 1, 7);
|
||||
const autoFocusIndex = Math.min(creationOpts.tabSize - 1, 7);
|
||||
|
||||
return TPromise.timeout(50 /* quick open is sensitive to being opened so soon after another */).then(() =>
|
||||
this.quickOpenService.pick(picks, { placeHolder: nls.localize('selectTabWidth', "Select Tab Size for Current File"), autoFocus: { autoFocusIndex } }).then(pick => {
|
||||
if (pick) {
|
||||
// TODO@Alex TODO@indent
|
||||
// model.updateOptions({
|
||||
// tabSize: parseInt(pick.label)
|
||||
// insertSpaces: this.insertSpaces
|
||||
// });
|
||||
model.updateOptions({
|
||||
tabSize: parseInt(pick.label, 10),
|
||||
insertSpaces: this.insertSpaces
|
||||
});
|
||||
}
|
||||
|
||||
return true;
|
||||
@@ -101,10 +101,13 @@ export class IndentUsingTabs extends ChangeIndentationSizeAction {
|
||||
|
||||
static ID = 'editor.action.indentUsingTabs';
|
||||
|
||||
constructor(descriptor: IEditorActionDescriptorData, editor: ICommonCodeEditor,
|
||||
@IQuickOpenService quickOpenService: IQuickOpenService
|
||||
constructor(
|
||||
descriptor: IEditorActionDescriptorData,
|
||||
editor: ICommonCodeEditor,
|
||||
@IQuickOpenService quickOpenService: IQuickOpenService,
|
||||
@IModelService modelService:IModelService
|
||||
) {
|
||||
super(descriptor, editor, false, quickOpenService);
|
||||
super(descriptor, editor, false, quickOpenService, modelService);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -112,10 +115,36 @@ export class IndentUsingSpaces extends ChangeIndentationSizeAction {
|
||||
|
||||
static ID = 'editor.action.indentUsingSpaces';
|
||||
|
||||
constructor(descriptor: IEditorActionDescriptorData, editor: ICommonCodeEditor,
|
||||
@IQuickOpenService quickOpenService: IQuickOpenService
|
||||
constructor(
|
||||
descriptor: IEditorActionDescriptorData,
|
||||
editor: ICommonCodeEditor,
|
||||
@IQuickOpenService quickOpenService: IQuickOpenService,
|
||||
@IModelService modelService:IModelService
|
||||
) {
|
||||
super(descriptor, editor, true, quickOpenService);
|
||||
super(descriptor, editor, true, quickOpenService, modelService);
|
||||
}
|
||||
}
|
||||
|
||||
export class DetectIndentation extends EditorAction {
|
||||
|
||||
static ID = 'editor.action.detectIndentation';
|
||||
|
||||
constructor(
|
||||
descriptor: IEditorActionDescriptorData,
|
||||
editor: ICommonCodeEditor,
|
||||
@IModelService private modelService:IModelService
|
||||
) {
|
||||
super(descriptor, editor);
|
||||
}
|
||||
|
||||
public run(): TPromise<boolean> {
|
||||
let model = this.editor.getModel();
|
||||
if (!model) {
|
||||
return;
|
||||
}
|
||||
|
||||
let creationOpts = this.modelService.getCreationOptions();
|
||||
model.detectIndentation(creationOpts.insertSpaces, creationOpts.tabSize);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -140,4 +169,5 @@ CommonEditorRegistry.registerEditorAction(new EditorActionDescriptor(Indentation
|
||||
CommonEditorRegistry.registerEditorAction(new EditorActionDescriptor(IndentationToTabsAction, IndentationToTabsAction.ID, nls.localize('indentationToTabs', "Convert Indentation to Tabs")));
|
||||
CommonEditorRegistry.registerEditorAction(new EditorActionDescriptor(IndentUsingSpaces, IndentUsingSpaces.ID, nls.localize('indentUsingSpaces', "Indent Using Spaces")));
|
||||
CommonEditorRegistry.registerEditorAction(new EditorActionDescriptor(IndentUsingTabs, IndentUsingTabs.ID, nls.localize('indentUsingTabs', "Indent Using Tabs")));
|
||||
CommonEditorRegistry.registerEditorAction(new EditorActionDescriptor(DetectIndentation, DetectIndentation.ID, nls.localize('detectIndentation', "Detect Indentation from Content")));
|
||||
CommonEditorRegistry.registerEditorAction(new EditorActionDescriptor(ToggleRenderWhitespaceAction, ToggleRenderWhitespaceAction.ID, nls.localize('toggleRenderWhitespace', "Toggle Render Whitespace")));
|
||||
|
||||
@@ -19,7 +19,6 @@ export interface ITextEditorConfigurationUpdate {
|
||||
insertSpaces?: boolean | string;
|
||||
}
|
||||
export interface IResolvedTextEditorConfiguration {
|
||||
IResolvedTextEditorConfiguration: any; // TODO@Alex TODO@indent
|
||||
tabSize: number;
|
||||
insertSpaces: boolean;
|
||||
}
|
||||
@@ -199,7 +198,6 @@ export class MainThreadTextEditor {
|
||||
private static _readConfiguration(model:EditorCommon.IModel): IResolvedTextEditorConfiguration {
|
||||
let indent = model.getOptions();
|
||||
return {
|
||||
IResolvedTextEditorConfiguration: null, // TODO@Alex TODO@indent
|
||||
insertSpaces: indent.insertSpaces,
|
||||
tabSize: indent.tabSize
|
||||
};
|
||||
|
||||
@@ -24,7 +24,7 @@ import {ICommonCodeEditor} from 'vs/editor/common/editorCommon';
|
||||
import {OpenGlobalSettingsAction} from 'vs/workbench/browser/actions/openSettings';
|
||||
import {ICodeEditor, IDiffEditor} from 'vs/editor/browser/editorBrowser';
|
||||
import {EndOfLineSequence, ITokenizedModel, EditorType, IEditorSelection, ITextModel, IDiffEditorModel, IEditor} from 'vs/editor/common/editorCommon';
|
||||
import {IndentUsingSpaces, IndentUsingTabs, IndentationToSpacesAction, IndentationToTabsAction} from 'vs/editor/contrib/indentation/common/indentation';
|
||||
import {IndentUsingSpaces, IndentUsingTabs, DetectIndentation, IndentationToSpacesAction, IndentationToTabsAction} from 'vs/editor/contrib/indentation/common/indentation';
|
||||
import {EventType, ResourceEvent, EditorEvent, TextEditorSelectionEvent} from 'vs/workbench/common/events';
|
||||
import {BaseTextEditor} from 'vs/workbench/browser/parts/editor/textEditor';
|
||||
import {IEditor as IBaseEditor} from 'vs/platform/editor/common/editor';
|
||||
@@ -732,9 +732,9 @@ class ChangeIndentationAction extends Action {
|
||||
}
|
||||
|
||||
const control = <ICommonCodeEditor>activeEditor.getControl();
|
||||
const picks = [control.getAction(IndentUsingSpaces.ID), control.getAction(IndentUsingTabs.ID), control.getAction(IndentationToSpacesAction.ID), control.getAction(IndentationToTabsAction.ID)];
|
||||
const picks = [control.getAction(IndentUsingSpaces.ID), control.getAction(IndentUsingTabs.ID), control.getAction(DetectIndentation.ID), control.getAction(IndentationToSpacesAction.ID), control.getAction(IndentationToTabsAction.ID)];
|
||||
(<IPickOpenEntry>picks[0]).separator = { label: nls.localize('indentView', "change view") };
|
||||
(<IPickOpenEntry>picks[2]).separator = { label: nls.localize('indentConvert', "convert file"), border: true };
|
||||
(<IPickOpenEntry>picks[3]).separator = { label: nls.localize('indentConvert', "convert file"), border: true };
|
||||
|
||||
return this.quickOpenService.pick(picks, { placeHolder: nls.localize('pickAction', "Select Action") }).then(action => action && action.run());
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user