diff --git a/src/vs/editor/common/commands/shiftCommand.ts b/src/vs/editor/common/commands/shiftCommand.ts index 7d5bdbcab7a0267e8a870d7e2652505178686198..63e2e77aee6568eed0b6b2e12d52de6f106d3745 100644 --- a/src/vs/editor/common/commands/shiftCommand.ts +++ b/src/vs/editor/common/commands/shiftCommand.ts @@ -9,7 +9,7 @@ import {CursorMoveHelper} from 'vs/editor/common/controller/cursorMoveHelper'; import {Range} from 'vs/editor/common/core/range'; import {Selection} from 'vs/editor/common/core/selection'; import {ICommand, ICursorStateComputerData, IEditOperationBuilder, ITokenizedModel} from 'vs/editor/common/editorCommon'; -import {getRawEnterActionAtPosition} from 'vs/editor/common/modes/supports/onEnter'; +import {LanguageConfigurationRegistry} from 'vs/editor/common/modes/languageConfigurationRegistry'; export interface IShiftCommandOpts { isUnshift: boolean; @@ -101,7 +101,7 @@ export class ShiftCommand implements ICommand { if (contentStartVisibleColumn % tabSize !== 0) { // The current line is "miss-aligned", so let's see if this is expected... // This can only happen when it has trailing commas in the indent - let enterAction = getRawEnterActionAtPosition(model, lineNumber - 1, model.getLineMaxColumn(lineNumber - 1)); + let enterAction = LanguageConfigurationRegistry.getRawEnterActionAtPosition(model, lineNumber - 1, model.getLineMaxColumn(lineNumber - 1)); if (enterAction) { extraSpaces = previousLineExtraSpaces; if (enterAction.appendText) { diff --git a/src/vs/editor/common/controller/cursorCollection.ts b/src/vs/editor/common/controller/cursorCollection.ts index 395273ddfcffe7086b684d0e1bf9530e38f45d2d..e10d3adc52122f0d9b60e762567f6d39be686d39 100644 --- a/src/vs/editor/common/controller/cursorCollection.ts +++ b/src/vs/editor/common/controller/cursorCollection.ts @@ -10,6 +10,7 @@ import {Selection} from 'vs/editor/common/core/selection'; import {IConfiguration, IModel, ISelection} from 'vs/editor/common/editorCommon'; import {IAutoClosingPair} from 'vs/editor/common/modes'; import {Position} from 'vs/editor/common/core/position'; +import {LanguageConfigurationRegistry} from 'vs/editor/common/modes/languageConfigurationRegistry'; export interface ICursorCollectionState { primary: IOneCursorState; @@ -326,51 +327,50 @@ export class CursorCollection { surroundingPairs: {} }; - let richEditSupport = this.model.getMode().richEditSupport; - let electricChars: string[]; - if (richEditSupport && richEditSupport.electricCharacter) { + let electricCharSupport = LanguageConfigurationRegistry.getElectricCharacterSupport(this.model.getMode()); + if (electricCharSupport) { + let electricChars: string[] = null; try { - electricChars = richEditSupport.electricCharacter.getElectricCharacters(); + electricChars = electricCharSupport.getElectricCharacters(); } catch(e) { onUnexpectedError(e); electricChars = null; } - } - if (electricChars) { - for (i = 0; i < electricChars.length; i++) { - result.electricChars[electricChars[i]] = true; + if (electricChars) { + for (i = 0; i < electricChars.length; i++) { + result.electricChars[electricChars[i]] = true; + } } } - let autoClosingPairs: IAutoClosingPair[]; - if (richEditSupport && richEditSupport.characterPair) { + let characterPairSupport = LanguageConfigurationRegistry.getCharacterPairSupport(this.model.getMode()); + if (characterPairSupport) { + let autoClosingPairs: IAutoClosingPair[]; try { - autoClosingPairs = richEditSupport.characterPair.getAutoClosingPairs(); + autoClosingPairs = characterPairSupport.getAutoClosingPairs(); } catch(e) { onUnexpectedError(e); autoClosingPairs = null; } - } - if (autoClosingPairs) { - for (i = 0; i < autoClosingPairs.length; i++) { - result.autoClosingPairsOpen[autoClosingPairs[i].open] = autoClosingPairs[i].close; - result.autoClosingPairsClose[autoClosingPairs[i].close] = autoClosingPairs[i].open; + if (autoClosingPairs) { + for (i = 0; i < autoClosingPairs.length; i++) { + result.autoClosingPairsOpen[autoClosingPairs[i].open] = autoClosingPairs[i].close; + result.autoClosingPairsClose[autoClosingPairs[i].close] = autoClosingPairs[i].open; + } } - } - let surroundingPairs: IAutoClosingPair[]; - if (richEditSupport && richEditSupport.characterPair) { + let surroundingPairs: IAutoClosingPair[]; try { - surroundingPairs = richEditSupport.characterPair.getSurroundingPairs(); + surroundingPairs = characterPairSupport.getSurroundingPairs(); } catch(e) { onUnexpectedError(e); surroundingPairs = null; } - } - if (surroundingPairs) { - for (i = 0; i < surroundingPairs.length; i++) { - result.surroundingPairs[surroundingPairs[i].open] = surroundingPairs[i].close; + if (surroundingPairs) { + for (i = 0; i < surroundingPairs.length; i++) { + result.surroundingPairs[surroundingPairs[i].open] = surroundingPairs[i].close; + } } } diff --git a/src/vs/editor/common/controller/oneCursor.ts b/src/vs/editor/common/controller/oneCursor.ts index 1764dc4bbfc1b3fa0512076d070e4c5f7b8a5e39..81473d4dbd3bbc8c7a78043aa41c01d2385b1238 100644 --- a/src/vs/editor/common/controller/oneCursor.ts +++ b/src/vs/editor/common/controller/oneCursor.ts @@ -15,7 +15,7 @@ import {Range} from 'vs/editor/common/core/range'; import {Selection} from 'vs/editor/common/core/selection'; import * as editorCommon from 'vs/editor/common/editorCommon'; import {IElectricAction, IndentAction} from 'vs/editor/common/modes'; -import {getEnterActionAtPosition} from 'vs/editor/common/modes/supports/onEnter'; +import {LanguageConfigurationRegistry} from 'vs/editor/common/modes/languageConfigurationRegistry'; export interface IPostOperationRunnable { (ctx: IOneCursorOperationContext): void; @@ -1196,7 +1196,7 @@ export class OneCursorOp { } ctx.shouldPushStackElementBefore = true; - let r = getEnterActionAtPosition(cursor.model, position.lineNumber, position.column); + let r = LanguageConfigurationRegistry.getEnterActionAtPosition(cursor.model, position.lineNumber, position.column); let enterAction = r.enterAction; let indentation = r.indentation; @@ -1269,9 +1269,9 @@ export class OneCursorOp { return false; } - let richEditSupport = cursor.model.getMode().richEditSupport; + let characterPairSupport = LanguageConfigurationRegistry.getCharacterPairSupport(cursor.model.getMode()); - if(!richEditSupport || !richEditSupport.characterPair) { + if(!characterPairSupport) { return false; } @@ -1297,7 +1297,7 @@ export class OneCursorOp { let shouldAutoClosePair = false; try { - shouldAutoClosePair = richEditSupport.characterPair.shouldAutoClosePair(ch, lineContext, position.column - 1); + shouldAutoClosePair = characterPairSupport.shouldAutoClosePair(ch, lineContext, position.column - 1); } catch(e) { onUnexpectedError(e); } @@ -1380,10 +1380,10 @@ export class OneCursorOp { let lineContext = cursor.model.getLineContext(position.lineNumber); let electricAction:IElectricAction; - let richEditSupport = cursor.model.getMode().richEditSupport; - if(richEditSupport && richEditSupport.electricCharacter) { + let electricCharSupport = LanguageConfigurationRegistry.getElectricCharacterSupport(cursor.model.getMode()); + if (electricCharSupport) { try { - electricAction = richEditSupport.electricCharacter.onElectricCharacter(lineContext, position.column - 2); + electricAction = electricCharSupport.onElectricCharacter(lineContext, position.column - 2); } catch(e) { onUnexpectedError(e); } @@ -1488,7 +1488,7 @@ export class OneCursorOp { return '\t'; } - let r = getEnterActionAtPosition(cursor.model, lastLineNumber, cursor.model.getLineMaxColumn(lastLineNumber)); + let r = LanguageConfigurationRegistry.getEnterActionAtPosition(cursor.model, lastLineNumber, cursor.model.getLineMaxColumn(lastLineNumber)); let indentation: string; if (r.enterAction.indentAction === IndentAction.Outdent) { diff --git a/src/vs/editor/common/model/textModelWithTokens.ts b/src/vs/editor/common/model/textModelWithTokens.ts index fd8b9739a3f76cdc7771e5078d03c278138def6f..ac292366d216333f7e4716c70dde46252d4106bf 100644 --- a/src/vs/editor/common/model/textModelWithTokens.ts +++ b/src/vs/editor/common/model/textModelWithTokens.ts @@ -25,6 +25,7 @@ import {ModeTransition} from 'vs/editor/common/core/modeTransition'; import {LineToken} from 'vs/editor/common/model/lineToken'; import {TokensInflatorMap} from 'vs/editor/common/model/tokensBinaryEncoding'; import {Position} from 'vs/editor/common/core/position'; +import {LanguageConfigurationRegistry} from 'vs/editor/common/modes/languageConfigurationRegistry'; class ModeToModelBinder implements IDisposable { @@ -761,7 +762,7 @@ export class TextModelWithTokens extends TextModel implements editorCommon.IToke let modeTransitions = this._lines[position.lineNumber - 1].getModeTransitions(this._mode); let currentModeIndex = ModeTransition.findIndexInSegmentsArray(modeTransitions, position.column - 1); let currentMode = modeTransitions[currentModeIndex]; - let currentModeBrackets = currentMode.mode.richEditSupport ? currentMode.mode.richEditSupport.brackets : null; + let currentModeBrackets = LanguageConfigurationRegistry.getBracketsSupport(currentMode.mode); if (!currentModeBrackets) { return null; @@ -791,7 +792,7 @@ export class TextModelWithTokens extends TextModel implements editorCommon.IToke let modeTransitions = this._lines[lineNumber - 1].getModeTransitions(this._mode); let currentModeIndex = ModeTransition.findIndexInSegmentsArray(modeTransitions, position.column - 1); let currentMode = modeTransitions[currentModeIndex]; - let currentModeBrackets = currentMode.mode.richEditSupport ? currentMode.mode.richEditSupport.brackets : null; + let currentModeBrackets = LanguageConfigurationRegistry.getBracketsSupport(currentMode.mode); // If position is in between two tokens, try first looking in the previous token if (currentTokenIndex > 0 && currentTokenStart === position.column - 1) { @@ -807,7 +808,7 @@ export class TextModelWithTokens extends TextModel implements editorCommon.IToke // check if previous token is in a different mode if (currentModeIndex > 0 && currentMode.startIndex === position.column - 1) { prevMode = modeTransitions[currentModeIndex - 1]; - prevModeBrackets = prevMode.mode.richEditSupport ? prevMode.mode.richEditSupport.brackets : null; + prevModeBrackets = LanguageConfigurationRegistry.getBracketsSupport(prevMode.mode); } if (prevModeBrackets) { diff --git a/src/vs/editor/common/model/textModelWithTokensHelpers.ts b/src/vs/editor/common/model/textModelWithTokensHelpers.ts index c55991f1d495abf661d3ffd509599024cf9dc8c6..b6bfc188424c783cabf98e7bc5da783fdf1b413c 100644 --- a/src/vs/editor/common/model/textModelWithTokensHelpers.ts +++ b/src/vs/editor/common/model/textModelWithTokensHelpers.ts @@ -8,6 +8,7 @@ import {IPosition, IWordAtPosition} from 'vs/editor/common/editorCommon'; import {IMode, IModeTransition} from 'vs/editor/common/modes'; import {NullMode} from 'vs/editor/common/modes/nullMode'; import {ModeTransition} from 'vs/editor/common/core/modeTransition'; +import {LanguageConfigurationRegistry} from 'vs/editor/common/modes/languageConfigurationRegistry'; export interface ITextSource { @@ -27,7 +28,7 @@ export interface INonWordTokenMap { export class WordHelper { private static _safeGetWordDefinition(mode:IMode): RegExp { - return (mode.richEditSupport ? mode.richEditSupport.wordDefinition : null); + return LanguageConfigurationRegistry.getWordDefinition(mode); } public static ensureValidWordDefinition(wordDefinition?:RegExp): RegExp { diff --git a/src/vs/editor/common/modes/languageConfigurationRegistry.ts b/src/vs/editor/common/modes/languageConfigurationRegistry.ts index 09aa5e4c377e9d0462051b01de57bf6fb5d2f0dd..4f2f7c48078a43e9d19b86782c93368d7b095133 100644 --- a/src/vs/editor/common/modes/languageConfigurationRegistry.ts +++ b/src/vs/editor/common/modes/languageConfigurationRegistry.ts @@ -5,13 +5,18 @@ 'use strict'; import {ICommentsConfiguration, IRichEditBrackets, IRichEditCharacterPair, IAutoClosingPair, - IAutoClosingPairConditional, IRichEditOnEnter, IRichEditSupport, CharacterPair} from 'vs/editor/common/modes'; + IAutoClosingPairConditional, IRichEditOnEnter, IRichEditSupport, CharacterPair, + IMode, IRichEditElectricCharacter, IEnterAction, IndentAction} from 'vs/editor/common/modes'; import {NullMode} from 'vs/editor/common/modes/nullMode'; import {CharacterPairSupport} from 'vs/editor/common/modes/supports/characterPair'; import {BracketElectricCharacterSupport, IBracketElectricCharacterContribution} from 'vs/editor/common/modes/supports/electricCharacter'; import {IIndentationRules, IOnEnterRegExpRules, IOnEnterSupportOptions, OnEnterSupport} from 'vs/editor/common/modes/supports/onEnter'; import {RichEditBrackets} from 'vs/editor/common/modes/supports/richEditBrackets'; -// import Event, {Emitter} from 'vs/base/common/event'; +import Event, {Emitter} from 'vs/base/common/event'; +import {ITokenizedModel} from 'vs/editor/common/editorCommon'; +import {onUnexpectedError} from 'vs/base/common/errors'; +import {Position} from 'vs/editor/common/core/position'; +import * as strings from 'vs/base/common/strings'; export interface CommentRule { lineComment?: string; @@ -58,11 +63,11 @@ export class RichEditSupport implements IRichEditSupport { this._handleComments(modeId, this._conf); if (this._conf.autoClosingPairs) { - this.characterPair = new CharacterPairSupport(modeId, this._conf); + this.characterPair = new CharacterPairSupport(LanguageConfigurationRegistry, modeId, this._conf); } if (this._conf.__electricCharacterSupport || this._conf.brackets) { - this.electricCharacter = new BracketElectricCharacterSupport(modeId, this.brackets, this._conf.__electricCharacterSupport); + this.electricCharacter = new BracketElectricCharacterSupport(LanguageConfigurationRegistry, modeId, this.brackets, this._conf.__electricCharacterSupport); } this.wordDefinition = this._conf.wordPattern || NullMode.DEFAULT_WORD_REGEXP; @@ -100,7 +105,7 @@ export class RichEditSupport implements IRichEditSupport { } if (!empty) { - this.onEnter = new OnEnterSupport(modeId, onEnter); + this.onEnter = new OnEnterSupport(LanguageConfigurationRegistry, modeId, onEnter); } } @@ -124,20 +129,114 @@ export class RichEditSupport implements IRichEditSupport { } -// export class LanguageConfigurationRegistryImpl { +export class LanguageConfigurationRegistryImpl { -// private _entries: {[languageId:string]:RichEditSupport;}; + // private _entries: {[languageId:string]:RichEditSupport;}; -// private _onDidChange: Emitter = new Emitter(); -// public onDidChange: Event = this._onDidChange.event; + private _onDidChange: Emitter = new Emitter(); + public onDidChange: Event = this._onDidChange.event; -// constructor() { -// this._entries = Object.create(null); -// } + constructor() { + // this._entries = Object.create(null); + } + + // public register(languageId:string, configuration:IRichLanguageConfiguration): void { + // console.log('TODO!'); + // } + + public getElectricCharacterSupport(mode:IMode): IRichEditElectricCharacter { + if (!mode.richEditSupport) { + return null; + } + return mode.richEditSupport.electricCharacter || null; + } + + public getComments(mode:IMode): ICommentsConfiguration { + if (!mode.richEditSupport) { + return null; + } + return mode.richEditSupport.comments || null; + } + + public getCharacterPairSupport(mode:IMode): IRichEditCharacterPair { + if (!mode.richEditSupport) { + return null; + } + return mode.richEditSupport.characterPair || null; + } + + public getWordDefinition(mode:IMode): RegExp { + if (!mode.richEditSupport) { + return null; + } + return mode.richEditSupport.wordDefinition || null; + } + + public getOnEnterSupport(mode:IMode): IRichEditOnEnter { + if (!mode.richEditSupport) { + return null; + } + return mode.richEditSupport.onEnter || null; + } + + public getRawEnterActionAtPosition(model:ITokenizedModel, lineNumber:number, column:number): IEnterAction { + let result:IEnterAction; + + let onEnterSupport = this.getOnEnterSupport(model.getMode()); -// public register(languageId:string, configuration:IRichLanguageConfiguration): void { -// console.log('TODO!'); -// } -// } + if (onEnterSupport) { + try { + result = onEnterSupport.onEnter(model, new Position(lineNumber, column)); + } catch (e) { + onUnexpectedError(e); + } + } + + return result; + } + + public getEnterActionAtPosition(model:ITokenizedModel, lineNumber:number, column:number): { enterAction: IEnterAction; indentation: string; } { + let lineText = model.getLineContent(lineNumber); + let indentation = strings.getLeadingWhitespace(lineText); + if (indentation.length > column - 1) { + indentation = indentation.substring(0, column - 1); + } + + let enterAction = this.getRawEnterActionAtPosition(model, lineNumber, column); + if (!enterAction) { + enterAction = { + indentAction: IndentAction.None, + appendText: '', + }; + } else { + if(!enterAction.appendText) { + if ( + (enterAction.indentAction === IndentAction.Indent) || + (enterAction.indentAction === IndentAction.IndentOutdent) + ) { + enterAction.appendText = '\t'; + } else { + enterAction.appendText = ''; + } + } + } + + if (enterAction.removeText) { + indentation = indentation.substring(0, indentation.length - 1); + } + + return { + enterAction: enterAction, + indentation: indentation + }; + } + + public getBracketsSupport(mode:IMode): IRichEditBrackets { + if (!mode.richEditSupport) { + return null; + } + return mode.richEditSupport.brackets || null; + } +} -// export const LanguageConfigurationRegistry = new LanguageConfigurationRegistryImpl(); \ No newline at end of file +export const LanguageConfigurationRegistry = new LanguageConfigurationRegistryImpl(); diff --git a/src/vs/editor/common/modes/supports/characterPair.ts b/src/vs/editor/common/modes/supports/characterPair.ts index cc49392b049cb0ebf32f409498855cc7b0f565d5..d61d987823284255b2fbdb6967cce07e03f3a63c 100644 --- a/src/vs/editor/common/modes/supports/characterPair.ts +++ b/src/vs/editor/common/modes/supports/characterPair.ts @@ -6,14 +6,17 @@ import {IAutoClosingPair, IAutoClosingPairConditional, ILineContext, IMode, IRichEditCharacterPair, CharacterPair} from 'vs/editor/common/modes'; import {handleEvent} from 'vs/editor/common/modes/supports'; +import {LanguageConfigurationRegistryImpl} from 'vs/editor/common/modes/languageConfigurationRegistry'; export class CharacterPairSupport implements IRichEditCharacterPair { + private _registry: LanguageConfigurationRegistryImpl; private _modeId: string; private _autoClosingPairs: IAutoClosingPairConditional[]; private _surroundingPairs: IAutoClosingPair[]; - constructor(modeId: string, config: { brackets?: CharacterPair[]; autoClosingPairs?: IAutoClosingPairConditional[], surroundingPairs?: IAutoClosingPair[]}) { + constructor(registry: LanguageConfigurationRegistryImpl, modeId: string, config: { brackets?: CharacterPair[]; autoClosingPairs?: IAutoClosingPairConditional[], surroundingPairs?: IAutoClosingPair[]}) { + this._registry = registry; this._modeId = modeId; this._autoClosingPairs = config.autoClosingPairs; if (!this._autoClosingPairs) { @@ -52,11 +55,14 @@ export class CharacterPairSupport implements IRichEditCharacterPair { } return true; - } else if (nestedMode.richEditSupport && nestedMode.richEditSupport.characterPair) { - return nestedMode.richEditSupport.characterPair.shouldAutoClosePair(character, context, offset); - } else { - return null; } + + let characterPairSupport = this._registry.getCharacterPairSupport(nestedMode); + if (characterPairSupport) { + return characterPairSupport.shouldAutoClosePair(character, context, offset); + } + + return null; }); } diff --git a/src/vs/editor/common/modes/supports/electricCharacter.ts b/src/vs/editor/common/modes/supports/electricCharacter.ts index 592d81975adc6dab26f1bcfd1425499f0fbfce31..56f292c74b7c23ac2f1fc33e42360b0a51bc7080 100644 --- a/src/vs/editor/common/modes/supports/electricCharacter.ts +++ b/src/vs/editor/common/modes/supports/electricCharacter.ts @@ -8,6 +8,7 @@ import * as strings from 'vs/base/common/strings'; import * as modes from 'vs/editor/common/modes'; import {handleEvent, ignoreBracketsInToken} from 'vs/editor/common/modes/supports'; import {BracketsUtils} from 'vs/editor/common/modes/supports/richEditBrackets'; +import {LanguageConfigurationRegistryImpl} from 'vs/editor/common/modes/languageConfigurationRegistry'; /** * Definition of documentation comments (e.g. Javadoc/JSdoc) @@ -26,11 +27,13 @@ export interface IBracketElectricCharacterContribution { export class BracketElectricCharacterSupport implements modes.IRichEditElectricCharacter { + private _registry: LanguageConfigurationRegistryImpl; private _modeId: string; private contribution: IBracketElectricCharacterContribution; private brackets: Brackets; - constructor(modeId: string, brackets: modes.IRichEditBrackets, contribution: IBracketElectricCharacterContribution) { + constructor(registry:LanguageConfigurationRegistryImpl, modeId: string, brackets: modes.IRichEditBrackets, contribution: IBracketElectricCharacterContribution) { + this._registry = registry; this._modeId = modeId; this.contribution = contribution || {}; this.brackets = new Brackets(modeId, brackets, this.contribution.docComment); @@ -47,11 +50,12 @@ export class BracketElectricCharacterSupport implements modes.IRichEditElectricC return handleEvent(context, offset, (nestedMode:modes.IMode, context:modes.ILineContext, offset:number) => { if (this._modeId === nestedMode.getId()) { return this.brackets.onElectricCharacter(context, offset); - } else if (nestedMode.richEditSupport && nestedMode.richEditSupport.electricCharacter) { - return nestedMode.richEditSupport.electricCharacter.onElectricCharacter(context, offset); - } else { - return null; } + let electricCharacterSupport = this._registry.getElectricCharacterSupport(nestedMode); + if (electricCharacterSupport) { + return electricCharacterSupport.onElectricCharacter(context, offset); + } + return null; }); } } diff --git a/src/vs/editor/common/modes/supports/onEnter.ts b/src/vs/editor/common/modes/supports/onEnter.ts index 72bb27cc6b7d355d03617ae8fc2ec7ed5a17b102..96b1ad215eaed2396c71005fc6a2329365b32e43 100644 --- a/src/vs/editor/common/modes/supports/onEnter.ts +++ b/src/vs/editor/common/modes/supports/onEnter.ts @@ -6,10 +6,10 @@ import {onUnexpectedError} from 'vs/base/common/errors'; import * as strings from 'vs/base/common/strings'; -import {Position} from 'vs/editor/common/core/position'; import {IPosition, ITextModel, ITokenizedModel} from 'vs/editor/common/editorCommon'; import {IEnterAction, ILineContext, IMode, IRichEditOnEnter, IndentAction, CharacterPair} from 'vs/editor/common/modes'; import {handleEvent} from 'vs/editor/common/modes/supports'; +import {LanguageConfigurationRegistryImpl} from 'vs/editor/common/modes/languageConfigurationRegistry'; export interface IIndentationRules { decreaseIndentPattern: RegExp; @@ -43,12 +43,14 @@ export class OnEnterSupport implements IRichEditOnEnter { private static _INDENT_OUTDENT: IEnterAction = { indentAction: IndentAction.IndentOutdent }; private static _OUTDENT: IEnterAction = { indentAction: IndentAction.Outdent }; + private _registry: LanguageConfigurationRegistryImpl; private _modeId: string; private _brackets: IProcessedBracketPair[]; private _indentationRules: IIndentationRules; private _regExpRules: IOnEnterRegExpRules[]; - constructor(modeId: string, opts?:IOnEnterSupportOptions) { + constructor(registry: LanguageConfigurationRegistryImpl, modeId: string, opts?:IOnEnterSupportOptions) { + this._registry = registry; opts = opts || {}; opts.brackets = opts.brackets || [ ['(', ')'], @@ -75,11 +77,14 @@ export class OnEnterSupport implements IRichEditOnEnter { return handleEvent(context, position.column - 1, (nestedMode:IMode, context:ILineContext, offset:number) => { if (this._modeId === nestedMode.getId()) { return this._onEnter(model, position); - } else if (nestedMode.richEditSupport && nestedMode.richEditSupport.onEnter) { - return nestedMode.richEditSupport.onEnter.onEnter(model, position); - } else { - return null; } + + let onEnterSupport = this._registry.getOnEnterSupport(nestedMode); + if (onEnterSupport) { + return onEnterSupport.onEnter(model, position); + } + + return null; }); } @@ -178,53 +183,3 @@ export class OnEnterSupport implements IRichEditOnEnter { } } -export function getRawEnterActionAtPosition(model:ITokenizedModel, lineNumber:number, column:number): IEnterAction { - let result:IEnterAction; - let richEditSupport = model.getMode().richEditSupport; - - if (richEditSupport && richEditSupport.onEnter) { - try { - result = richEditSupport.onEnter.onEnter(model, new Position(lineNumber, column)); - } catch (e) { - onUnexpectedError(e); - } - } - - return result; -} - -export function getEnterActionAtPosition(model:ITokenizedModel, lineNumber:number, column:number): { enterAction: IEnterAction; indentation: string; } { - let lineText = model.getLineContent(lineNumber); - let indentation = strings.getLeadingWhitespace(lineText); - if (indentation.length > column - 1) { - indentation = indentation.substring(0, column - 1); - } - - let enterAction = getRawEnterActionAtPosition(model, lineNumber, column); - if (!enterAction) { - enterAction = { - indentAction: IndentAction.None, - appendText: '', - }; - } else { - if(!enterAction.appendText) { - if ( - (enterAction.indentAction === IndentAction.Indent) || - (enterAction.indentAction === IndentAction.IndentOutdent) - ) { - enterAction.appendText = '\t'; - } else { - enterAction.appendText = ''; - } - } - } - - if (enterAction.removeText) { - indentation = indentation.substring(0, indentation.length - 1); - } - - return { - enterAction: enterAction, - indentation: indentation - }; -} diff --git a/src/vs/editor/contrib/comment/common/blockCommentCommand.ts b/src/vs/editor/contrib/comment/common/blockCommentCommand.ts index 30d6bd41cfca5ea7158de752ec7805ff9e93a13d..d473bd08ce9f2403df63397cebe826f5d5ce7217 100644 --- a/src/vs/editor/contrib/comment/common/blockCommentCommand.ts +++ b/src/vs/editor/contrib/comment/common/blockCommentCommand.ts @@ -10,6 +10,7 @@ import {Range} from 'vs/editor/common/core/range'; import {Selection} from 'vs/editor/common/core/selection'; import * as editorCommon from 'vs/editor/common/editorCommon'; import {ICommentsConfiguration} from 'vs/editor/common/modes'; +import {LanguageConfigurationRegistry} from 'vs/editor/common/modes/languageConfigurationRegistry'; export class BlockCommentCommand implements editorCommon.ICommand { @@ -121,8 +122,8 @@ export class BlockCommentCommand implements editorCommon.ICommand { var endLineNumber = this._selection.endLineNumber; var endColumn = this._selection.endColumn; - let richEditSupport = model.getModeAtPosition(startLineNumber, startColumn).richEditSupport; - let config = richEditSupport ? richEditSupport.comments : null; + let mode = model.getModeAtPosition(startLineNumber, startColumn); + let config = LanguageConfigurationRegistry.getComments(mode); if (!config || !config.blockCommentStartToken || !config.blockCommentEndToken) { // Mode does not support block comments return; diff --git a/src/vs/editor/contrib/comment/common/lineCommentCommand.ts b/src/vs/editor/contrib/comment/common/lineCommentCommand.ts index 57cb19c4942a10f138f632bce2a920f9fe053d9b..8df30be9e3f9c16259ac1af27e18254c22e073c7 100644 --- a/src/vs/editor/contrib/comment/common/lineCommentCommand.ts +++ b/src/vs/editor/contrib/comment/common/lineCommentCommand.ts @@ -12,6 +12,7 @@ import {Selection} from 'vs/editor/common/core/selection'; import * as editorCommon from 'vs/editor/common/editorCommon'; import {ICommentsConfiguration, IMode} from 'vs/editor/common/modes'; import {BlockCommentCommand} from './blockCommentCommand'; +import {LanguageConfigurationRegistry} from 'vs/editor/common/modes/languageConfigurationRegistry'; export interface IInsertionPoint { ignore: boolean; @@ -81,7 +82,7 @@ export class LineCommentCommand implements editorCommon.ICommand { if (seenModes[modeId]) { commentStr = seenModes[modeId]; } else { - config = (mode.richEditSupport ? mode.richEditSupport.comments : null); + config = LanguageConfigurationRegistry.getComments(mode); commentStr = (config ? config.lineCommentToken : null); if (!commentStr) { // Mode does not support line comments @@ -273,8 +274,8 @@ export class LineCommentCommand implements editorCommon.ICommand { * Given an unsuccessful analysis, delegate to the block comment command */ private _executeBlockComment(model:editorCommon.ITokenizedModel, builder:editorCommon.IEditOperationBuilder, s:Selection): void { - let richEditSupport = model.getModeAtPosition(s.startLineNumber, s.startColumn).richEditSupport; - let config = richEditSupport ? richEditSupport.comments : null; + let mode = model.getModeAtPosition(s.startLineNumber, s.startColumn); + let config = LanguageConfigurationRegistry.getComments(mode); if (!config || !config.blockCommentStartToken || !config.blockCommentEndToken) { // Mode does not support block comments return; diff --git a/src/vs/editor/contrib/smartSelect/common/tokenTree.ts b/src/vs/editor/contrib/smartSelect/common/tokenTree.ts index 6df5003825925ab15216ead967d12b0f997bb5ee..45a9e860c19712943dec937a21223453e81e5057 100644 --- a/src/vs/editor/contrib/smartSelect/common/tokenTree.ts +++ b/src/vs/editor/contrib/smartSelect/common/tokenTree.ts @@ -10,6 +10,7 @@ import {ILineTokens, IModel, IPosition, IRange, IRichEditBracket} from 'vs/edito import {IModeTransition, IRichEditBrackets} from 'vs/editor/common/modes'; import {ignoreBracketsInToken} from 'vs/editor/common/modes/supports'; import {BracketsUtils} from 'vs/editor/common/modes/supports/richEditBrackets'; +import {LanguageConfigurationRegistry} from 'vs/editor/common/modes/languageConfigurationRegistry'; export enum TokenTreeBracket { None = 0, @@ -159,7 +160,7 @@ class TokenScanner { this._currentModeIndex++; this._nextModeStart = (this._currentModeIndex + 1 < this._currentLineModeTransitions.length ? this._currentLineModeTransitions[this._currentModeIndex + 1].startIndex : this._currentLineText.length + 1); let mode = (this._currentModeIndex < this._currentLineModeTransitions.length ? this._currentLineModeTransitions[this._currentModeIndex] : null); - this._currentModeBrackets = (mode && mode.mode.richEditSupport ? mode.mode.richEditSupport.brackets : null); + this._currentModeBrackets = (mode ? LanguageConfigurationRegistry.getBracketsSupport(mode.mode) : null); } let tokenType = this._currentLineTokens.getTokenType(this._currentTokenIndex); diff --git a/src/vs/editor/test/common/modes/supports/onEnter.test.ts b/src/vs/editor/test/common/modes/supports/onEnter.test.ts index b050594c95fa180de5e049742b5521efbc68aad7..4ec3eb1488872f2babcd71cf370c90dd13184d65 100644 --- a/src/vs/editor/test/common/modes/supports/onEnter.test.ts +++ b/src/vs/editor/test/common/modes/supports/onEnter.test.ts @@ -11,7 +11,7 @@ import {OnEnterSupport} from 'vs/editor/common/modes/supports/onEnter'; suite('OnEnter', () => { test('uses indentationRules', () => { - var support = new OnEnterSupport(null, { + var support = new OnEnterSupport(null, null, { indentationRules: { decreaseIndentPattern: /^\s*((?!\S.*\/[*]).*[*]\/\s*)?[})\]]|^\s*(case\b.*|default):\s*(\/\/.*|\/[*].*[*]\/\s*)?$/, increaseIndentPattern: /(\{[^}"']*|\([^)"']*|\[[^\]"']*|^\s*(\{\}|\(\)|\[\]|(case\b.*|default):))\s*(\/\/.*|\/[*].*[*]\/\s*)?$/, @@ -42,7 +42,7 @@ suite('OnEnter', () => { ['(', ')'], ['begin', 'end'] ]; - var support = new OnEnterSupport(null, { + var support = new OnEnterSupport(null, null, { brackets: brackets }); var testIndentAction = (beforeText:string, afterText:string, expected:IndentAction) => { @@ -75,7 +75,7 @@ suite('OnEnter', () => { }); test('uses regExpRules', () => { - var support = new OnEnterSupport(null, { + var support = new OnEnterSupport(null, null, { regExpRules: [ { beforeText: /^\s*\/\*\*(?!\/)([^\*]|\*(?!\/))*$/, diff --git a/src/vs/languages/css/test/common/css.test.ts b/src/vs/languages/css/test/common/css.test.ts index 8509272daf867833fb068ceb07071db751c881a8..efcf4b1b695e24faa2f989ab9b371b5aabe4e0c1 100644 --- a/src/vs/languages/css/test/common/css.test.ts +++ b/src/vs/languages/css/test/common/css.test.ts @@ -11,6 +11,7 @@ import {NULL_THREAD_SERVICE} from 'vs/platform/test/common/nullThreadService'; import {IThreadService} from 'vs/platform/thread/common/thread'; import {InstantiationService} from 'vs/platform/instantiation/common/instantiationService'; import {ServiceCollection} from 'vs/platform/instantiation/common/serviceCollection'; +import {LanguageConfigurationRegistry} from 'vs/editor/common/modes/languageConfigurationRegistry'; suite('CSS Colorizing', () => { @@ -32,7 +33,7 @@ suite('CSS Colorizing', () => { tokenizationSupport = mode.tokenizationSupport; assertOnEnter = modesUtil.createOnEnterAsserter(mode.getId(), mode.richEditSupport); - wordDefinition = mode.richEditSupport.wordDefinition; + wordDefinition = LanguageConfigurationRegistry.getWordDefinition(mode); })(); test('Skip whitespace', () => { diff --git a/src/vs/languages/html/test/common/html.test.ts b/src/vs/languages/html/test/common/html.test.ts index e1f71a088b74af26f9c47accf2da0d4ec4cc0d65..8494b82c8f98933e9c4a586f5cf6f259c2dd7628 100644 --- a/src/vs/languages/html/test/common/html.test.ts +++ b/src/vs/languages/html/test/common/html.test.ts @@ -5,12 +5,10 @@ 'use strict'; import assert = require('assert'); -import EditorCommon = require('vs/editor/common/editorCommon'); import Modes = require('vs/editor/common/modes'); import modesUtil = require('vs/editor/test/common/modesUtil'); import {Model} from 'vs/editor/common/model/model'; import {getTag, DELIM_END, DELIM_START, DELIM_ASSIGN, ATTRIB_NAME, ATTRIB_VALUE, COMMENT, DELIM_COMMENT, DELIM_DOCTYPE, DOCTYPE} from 'vs/languages/html/common/htmlTokenTypes'; -import {getRawEnterActionAtPosition} from 'vs/editor/common/modes/supports/onEnter'; import {TextModelWithTokens} from 'vs/editor/common/model/textModelWithTokens'; import {TextModel} from 'vs/editor/common/model/textModel'; import {Range} from 'vs/editor/common/core/range'; @@ -23,7 +21,7 @@ import {InstantiationService} from 'vs/platform/instantiation/common/instantiati import {HTMLMode} from 'vs/languages/html/common/html'; import htmlWorker = require('vs/languages/html/common/htmlWorker'); import {MockTokenizingMode} from 'vs/editor/test/common/mocks/mockMode'; -import {RichEditSupport} from 'vs/editor/common/modes/languageConfigurationRegistry'; +import {RichEditSupport, LanguageConfigurationRegistry} from 'vs/editor/common/modes/languageConfigurationRegistry'; class MockJSMode extends MockTokenizingMode { @@ -97,6 +95,7 @@ suite('Colorizing - HTML', () => { let tokenizationSupport: Modes.ITokenizationSupport; let _mode: Modes.IMode; + let onEnterSupport: Modes.IRichEditOnEnter; (function() { let threadService = NULL_THREAD_SERVICE; @@ -115,6 +114,8 @@ suite('Colorizing - HTML', () => { ); tokenizationSupport = _mode.tokenizationSupport; + + onEnterSupport = LanguageConfigurationRegistry.getOnEnterSupport(_mode); })(); test('Open Start Tag #1', () => { @@ -708,7 +709,7 @@ suite('Colorizing - HTML', () => { test('onEnter 1', function() { var model = new Model('