提交 65463e2d 编写于 作者: A Alex Dima

Consolidate 5 descriptive mode supports into IRichEditSupport

上级 284014c8
...@@ -307,19 +307,21 @@ export class CursorCollection { ...@@ -307,19 +307,21 @@ export class CursorCollection {
} }
private getModeConfiguration(): IModeConfiguration { private getModeConfiguration(): IModeConfiguration {
var i: number; let i: number;
var result: IModeConfiguration = { let result: IModeConfiguration = {
electricChars: {}, electricChars: {},
autoClosingPairsOpen: {}, autoClosingPairsOpen: {},
autoClosingPairsClose: {}, autoClosingPairsClose: {},
surroundingPairs: {} surroundingPairs: {}
}; };
var electricChars: string[]; let richEditSupport = this.model.getMode().richEditSupport;
if (this.model.getMode().electricCharacterSupport) {
let electricChars: string[];
if (richEditSupport && richEditSupport.electricCharacter) {
try { try {
electricChars = this.model.getMode().electricCharacterSupport.getElectricCharacters(); electricChars = richEditSupport.electricCharacter.getElectricCharacters();
} catch(e) { } catch(e) {
Errors.onUnexpectedError(e); Errors.onUnexpectedError(e);
electricChars = null; electricChars = null;
...@@ -331,10 +333,10 @@ export class CursorCollection { ...@@ -331,10 +333,10 @@ export class CursorCollection {
} }
} }
var autoClosingPairs: IAutoClosingPair[]; let autoClosingPairs: IAutoClosingPair[];
if (this.model.getMode().characterPairSupport) { if (richEditSupport && richEditSupport.characterPair) {
try { try {
autoClosingPairs = this.model.getMode().characterPairSupport.getAutoClosingPairs(); autoClosingPairs = richEditSupport.characterPair.getAutoClosingPairs();
} catch(e) { } catch(e) {
Errors.onUnexpectedError(e); Errors.onUnexpectedError(e);
autoClosingPairs = null; autoClosingPairs = null;
...@@ -347,10 +349,10 @@ export class CursorCollection { ...@@ -347,10 +349,10 @@ export class CursorCollection {
} }
} }
var surroundingPairs: IAutoClosingPair[]; let surroundingPairs: IAutoClosingPair[];
if (this.model.getMode().characterPairSupport) { if (richEditSupport && richEditSupport.characterPair) {
try { try {
surroundingPairs = this.model.getMode().characterPairSupport.getSurroundingPairs(); surroundingPairs = richEditSupport.characterPair.getSurroundingPairs();
} catch(e) { } catch(e) {
Errors.onUnexpectedError(e); Errors.onUnexpectedError(e);
surroundingPairs = null; surroundingPairs = null;
......
...@@ -1035,7 +1035,9 @@ export class OneCursorOp { ...@@ -1035,7 +1035,9 @@ export class OneCursorOp {
return false; return false;
} }
if(!cursor.model.getMode().characterPairSupport) { let richEditSupport = cursor.model.getMode().richEditSupport;
if(!richEditSupport || !richEditSupport.characterPair) {
return false; return false;
} }
...@@ -1061,7 +1063,7 @@ export class OneCursorOp { ...@@ -1061,7 +1063,7 @@ export class OneCursorOp {
var shouldAutoClosePair = false; var shouldAutoClosePair = false;
try { try {
shouldAutoClosePair = cursor.model.getMode().characterPairSupport.shouldAutoClosePair(ch, lineContext, position.column - 1); shouldAutoClosePair = richEditSupport.characterPair.shouldAutoClosePair(ch, lineContext, position.column - 1);
} catch(e) { } catch(e) {
Errors.onUnexpectedError(e); Errors.onUnexpectedError(e);
} }
...@@ -1144,9 +1146,10 @@ export class OneCursorOp { ...@@ -1144,9 +1146,10 @@ export class OneCursorOp {
var lineContext = cursor.model.getLineContext(position.lineNumber); var lineContext = cursor.model.getLineContext(position.lineNumber);
var electricAction:IElectricAction; var electricAction:IElectricAction;
if(cursor.model.getMode().electricCharacterSupport) { let richEditSupport = cursor.model.getMode().richEditSupport;
if(richEditSupport && richEditSupport.electricCharacter) {
try { try {
electricAction = cursor.model.getMode().electricCharacterSupport.onElectricCharacter(lineContext, position.column - 2); electricAction = richEditSupport.electricCharacter.onElectricCharacter(lineContext, position.column - 2);
} catch(e) { } catch(e) {
Errors.onUnexpectedError(e); Errors.onUnexpectedError(e);
} }
......
...@@ -750,13 +750,9 @@ export interface IModeSupportChangedEvent { ...@@ -750,13 +750,9 @@ export interface IModeSupportChangedEvent {
emitOutputSupport:boolean; emitOutputSupport:boolean;
linkSupport:boolean; linkSupport:boolean;
configSupport:boolean; configSupport:boolean;
electricCharacterSupport:boolean;
commentsSupport:boolean;
characterPairSupport:boolean;
tokenTypeClassificationSupport:boolean;
quickFixSupport: boolean; quickFixSupport: boolean;
codeLensSupport: boolean; codeLensSupport: boolean;
onEnterSupport: boolean; richEditSupport: boolean;
} }
/** /**
......
...@@ -39,14 +39,19 @@ export interface INonWordTokenMap { ...@@ -39,14 +39,19 @@ export interface INonWordTokenMap {
export class WordHelper { export class WordHelper {
private static _safeGetWordDefinition(mode:Modes.IMode): RegExp { private static _safeGetWordDefinition(mode:Modes.IMode): RegExp {
var result: RegExp = null; let richEditSupport = mode.richEditSupport;
if (!richEditSupport) {
return null;
}
if (!richEditSupport.tokenTypeClassification) {
return null;
}
if (mode.tokenTypeClassificationSupport) { var result: RegExp = null;
try { try {
result = mode.tokenTypeClassificationSupport.getWordDefinition(); result = richEditSupport.tokenTypeClassification.getWordDefinition();
} catch(e) { } catch(e) {
Errors.onUnexpectedError(e); Errors.onUnexpectedError(e);
}
} }
return result; return result;
......
...@@ -282,26 +282,6 @@ export interface IMode { ...@@ -282,26 +282,6 @@ export interface IMode {
*/ */
configSupport?:IConfigurationSupport; configSupport?:IConfigurationSupport;
/**
* Optional adapter to support electric characters.
*/
electricCharacterSupport?:IElectricCharacterSupport;
/**
* Optional adapter to support comment insertion.
*/
commentsSupport?:ICommentsSupport;
/**
* Optional adapter to support insertion of character pair.
*/
characterPairSupport?:ICharacterPairSupport;
/**
* Optional adapter to support classification of tokens.
*/
tokenTypeClassificationSupport?:ITokenTypeClassificationSupport;
/** /**
* Optional adapter to support quick fix of typing errors. * Optional adapter to support quick fix of typing errors.
*/ */
...@@ -322,7 +302,10 @@ export interface IMode { ...@@ -322,7 +302,10 @@ export interface IMode {
*/ */
taskSupport?: ITaskSupport; taskSupport?: ITaskSupport;
onEnterSupport?: IOnEnterSupport; /**
* Optional adapter to support rich editing.
*/
richEditSupport?: IRichEditSupport;
} }
/** /**
...@@ -644,87 +627,6 @@ export interface IConfigurationSupport { ...@@ -644,87 +627,6 @@ export interface IConfigurationSupport {
configure(options:any):TPromise<boolean>; configure(options:any):TPromise<boolean>;
} }
/**
* Interface used to support electric characters
*/
export interface IElectricAction {
// Only one of the following properties should be defined:
// The line will be indented at the same level of the line
// which contains the matching given bracket type.
matchBracketType?:string;
// The text will be appended after the electric character.
appendText?:string;
// The number of characters to advance the cursor, useful with appendText
advanceCount?:number;
}
export enum IndentAction {
None,
Indent,
IndentOutdent,
Outdent
}
/**
* An action the editor executes when 'enter' is being pressed
*/
export interface IEnterAction {
indentAction:IndentAction;
appendText?:string;
removeText?:number;
}
export interface IElectricCharacterSupport {
getElectricCharacters():string[];
// Should return opening bracket type to match indentation with
onElectricCharacter(context:ILineContext, offset:number):IElectricAction;
onEnter(context:ILineContext, offset:number):IEnterAction;
}
export interface IOnEnterSupport {
onEnter(model:EditorCommon.ITokenizedModel, position: EditorCommon.IPosition): IEnterAction;
}
/**
* Interface used to support insertion of mode specific comments.
*/
export interface ICommentsConfiguration {
lineCommentTokens?:string[];
blockCommentStartToken?:string;
blockCommentEndToken?:string;
}
export interface ICommentsSupport {
getCommentsConfiguration():ICommentsConfiguration;
}
/**
* Interface used to support insertion of matching characters like brackets and qoutes.
*/
export interface IAutoClosingPair {
open:string;
close:string;
}
export interface ICharacterPairSupport {
getAutoClosingPairs():IAutoClosingPairConditional[];
shouldAutoClosePair(character:string, context:ILineContext, offset:number):boolean;
getSurroundingPairs():IAutoClosingPair[];
}
/**
* Interface used to support the classification of tokens.
*/
export interface ITokenTypeClassificationSupport {
getWordDefinition():RegExp;
}
export interface IResourceEdit { export interface IResourceEdit {
resource: URI; resource: URI;
range?: EditorCommon.IRange; range?: EditorCommon.IRange;
...@@ -826,4 +728,107 @@ export interface IAutoClosingPairConditional extends IAutoClosingPair { ...@@ -826,4 +728,107 @@ export interface IAutoClosingPairConditional extends IAutoClosingPair {
export interface ICharacterPairContribution { export interface ICharacterPairContribution {
autoClosingPairs: IAutoClosingPairConditional[]; autoClosingPairs: IAutoClosingPairConditional[];
surroundingPairs?: IAutoClosingPair[]; surroundingPairs?: IAutoClosingPair[];
} }
\ No newline at end of file
/**
* Interface used to support electric characters
*/
export interface IElectricAction {
// Only one of the following properties should be defined:
// The line will be indented at the same level of the line
// which contains the matching given bracket type.
matchBracketType?:string;
// The text will be appended after the electric character.
appendText?:string;
// The number of characters to advance the cursor, useful with appendText
advanceCount?:number;
}
export enum IndentAction {
None,
Indent,
IndentOutdent,
Outdent
}
/**
* An action the editor executes when 'enter' is being pressed
*/
export interface IEnterAction {
indentAction:IndentAction;
appendText?:string;
removeText?:number;
}
export interface IRichEditElectricCharacter {
getElectricCharacters():string[];
// Should return opening bracket type to match indentation with
onElectricCharacter(context:ILineContext, offset:number):IElectricAction;
onEnter(context:ILineContext, offset:number):IEnterAction;
}
export interface IRichEditOnEnter {
onEnter(model:EditorCommon.ITokenizedModel, position: EditorCommon.IPosition): IEnterAction;
}
/**
* Interface used to support insertion of mode specific comments.
*/
export interface ICommentsConfiguration {
lineCommentTokens?:string[];
blockCommentStartToken?:string;
blockCommentEndToken?:string;
}
export interface IRichEditComments {
getCommentsConfiguration():ICommentsConfiguration;
}
/**
* Interface used to support insertion of matching characters like brackets and qoutes.
*/
export interface IAutoClosingPair {
open:string;
close:string;
}
export interface IRichEditCharacterPair {
getAutoClosingPairs():IAutoClosingPairConditional[];
shouldAutoClosePair(character:string, context:ILineContext, offset:number):boolean;
getSurroundingPairs():IAutoClosingPair[];
}
/**
* Interface used to support the classification of tokens.
*/
export interface IRichEditTokenTypeClassification {
getWordDefinition():RegExp;
}
export interface IRichEditSupport {
/**
* Optional adapter for electric characters.
*/
electricCharacter?:IRichEditElectricCharacter;
/**
* Optional adapter for comment insertion.
*/
comments?:IRichEditComments;
/**
* Optional adapter for insertion of character pair.
*/
characterPair?:IRichEditCharacterPair;
/**
* Optional adapter for classification of tokens.
*/
tokenTypeClassification?:IRichEditTokenTypeClassification;
/**
* Optional adapter for custom Enter handling.
*/
onEnter?: IRichEditOnEnter;
}
...@@ -41,8 +41,6 @@ export class AbstractMode<W extends AbstractModeWorker> implements Modes.IMode { ...@@ -41,8 +41,6 @@ export class AbstractMode<W extends AbstractModeWorker> implements Modes.IMode {
public dirtyDiffSupport:Modes.IDirtyDiffSupport; public dirtyDiffSupport:Modes.IDirtyDiffSupport;
public linkSupport:Modes.ILinkSupport; public linkSupport:Modes.ILinkSupport;
public configSupport:Modes.IConfigurationSupport; public configSupport:Modes.IConfigurationSupport;
public commentsSupport:Modes.ICommentsSupport;
public tokenTypeClassificationSupport:Modes.ITokenTypeClassificationSupport;
public codeLensSupport:Modes.ICodeLensSupport; public codeLensSupport:Modes.ICodeLensSupport;
// adapters end // adapters end
...@@ -68,8 +66,6 @@ export class AbstractMode<W extends AbstractModeWorker> implements Modes.IMode { ...@@ -68,8 +66,6 @@ export class AbstractMode<W extends AbstractModeWorker> implements Modes.IMode {
this.dirtyDiffSupport = this; this.dirtyDiffSupport = this;
this.linkSupport = this; this.linkSupport = this;
this.configSupport = this; this.configSupport = this;
this.commentsSupport = this;
this.tokenTypeClassificationSupport = this;
this._workerPiecePromise = null; this._workerPiecePromise = null;
this._simplifiedMode = null; this._simplifiedMode = null;
...@@ -228,24 +224,12 @@ export class AbstractMode<W extends AbstractModeWorker> implements Modes.IMode { ...@@ -228,24 +224,12 @@ export class AbstractMode<W extends AbstractModeWorker> implements Modes.IMode {
} }
// END // END
public getWordDefinition():RegExp {
return NullMode.DEFAULT_WORD_REGEXP;
}
public getCommentsConfiguration():Modes.ICommentsConfiguration {
return null;
}
} }
class SimplifiedMode implements Modes.IMode { class SimplifiedMode implements Modes.IMode {
tokenizationSupport: Modes.ITokenizationSupport; tokenizationSupport: Modes.ITokenizationSupport;
electricCharacterSupport: Modes.IElectricCharacterSupport; richEditSupport: Modes.IRichEditSupport;
commentsSupport: Modes.ICommentsSupport;
characterPairSupport: Modes.ICharacterPairSupport;
tokenTypeClassificationSupport: Modes.ITokenTypeClassificationSupport;
onEnterSupport: Modes.IOnEnterSupport;
private _sourceMode: Modes.IMode; private _sourceMode: Modes.IMode;
private _eventEmitter: EventEmitter; private _eventEmitter: EventEmitter;
...@@ -259,7 +243,7 @@ class SimplifiedMode implements Modes.IMode { ...@@ -259,7 +243,7 @@ class SimplifiedMode implements Modes.IMode {
if (this._sourceMode.addSupportChangedListener) { if (this._sourceMode.addSupportChangedListener) {
this._sourceMode.addSupportChangedListener((e) => { this._sourceMode.addSupportChangedListener((e) => {
if (e.tokenizationSupport || e.electricCharacterSupport || e.commentsSupport || e.characterPairSupport || e.tokenTypeClassificationSupport || e.onEnterSupport) { if (e.tokenizationSupport || e.richEditSupport) {
this._assignSupports(); this._assignSupports();
let newEvent = SimplifiedMode._createModeSupportChangedEvent(e); let newEvent = SimplifiedMode._createModeSupportChangedEvent(e);
this._eventEmitter.emit('modeSupportChanged', newEvent); this._eventEmitter.emit('modeSupportChanged', newEvent);
...@@ -278,11 +262,7 @@ class SimplifiedMode implements Modes.IMode { ...@@ -278,11 +262,7 @@ class SimplifiedMode implements Modes.IMode {
private _assignSupports(): void { private _assignSupports(): void {
this.tokenizationSupport = this._sourceMode.tokenizationSupport; this.tokenizationSupport = this._sourceMode.tokenizationSupport;
this.electricCharacterSupport = this._sourceMode.electricCharacterSupport; this.richEditSupport = this._sourceMode.richEditSupport;
this.commentsSupport = this._sourceMode.commentsSupport;
this.characterPairSupport = this._sourceMode.characterPairSupport;
this.tokenTypeClassificationSupport = this._sourceMode.tokenTypeClassificationSupport;
this.onEnterSupport = this._sourceMode.onEnterSupport;
} }
private static _createModeSupportChangedEvent(originalModeEvent:EditorCommon.IModeSupportChangedEvent): EditorCommon.IModeSupportChangedEvent { private static _createModeSupportChangedEvent(originalModeEvent:EditorCommon.IModeSupportChangedEvent): EditorCommon.IModeSupportChangedEvent {
...@@ -306,12 +286,8 @@ class SimplifiedMode implements Modes.IMode { ...@@ -306,12 +286,8 @@ class SimplifiedMode implements Modes.IMode {
emitOutputSupport:false, emitOutputSupport:false,
linkSupport:false, linkSupport:false,
configSupport:false, configSupport:false,
electricCharacterSupport: originalModeEvent.electricCharacterSupport,
commentsSupport: originalModeEvent.commentsSupport,
characterPairSupport: originalModeEvent.characterPairSupport,
tokenTypeClassificationSupport: originalModeEvent.tokenTypeClassificationSupport,
quickFixSupport:false, quickFixSupport:false,
onEnterSupport: originalModeEvent.onEnterSupport richEditSupport: originalModeEvent.richEditSupport,
}; };
return event; return event;
} }
...@@ -392,7 +368,7 @@ export class FrankensteinMode extends AbstractMode<AbstractModeWorker> { ...@@ -392,7 +368,7 @@ export class FrankensteinMode extends AbstractMode<AbstractModeWorker> {
} }
function _createModeSupportChangedEvent(...changedSupports: string[]): EditorCommon.IModeSupportChangedEvent { function _createModeSupportChangedEvent(...changedSupports: string[]): EditorCommon.IModeSupportChangedEvent {
var event = { var event:EditorCommon.IModeSupportChangedEvent = {
codeLensSupport: false, codeLensSupport: false,
tokenizationSupport:false, tokenizationSupport:false,
occurrencesSupport:false, occurrencesSupport:false,
...@@ -412,12 +388,8 @@ function _createModeSupportChangedEvent(...changedSupports: string[]): EditorCom ...@@ -412,12 +388,8 @@ function _createModeSupportChangedEvent(...changedSupports: string[]): EditorCom
emitOutputSupport:false, emitOutputSupport:false,
linkSupport:false, linkSupport:false,
configSupport:false, configSupport:false,
electricCharacterSupport:false,
commentsSupport:false,
characterPairSupport:false,
tokenTypeClassificationSupport:false,
quickFixSupport:false, quickFixSupport:false,
onEnterSupport: false richEditSupport: false
}; };
changedSupports.forEach(support => event[support] = true); changedSupports.forEach(support => event[support] = true);
return event; return event;
......
...@@ -21,15 +21,15 @@ import {IInstantiationService} from 'vs/platform/instantiation/common/instantiat ...@@ -21,15 +21,15 @@ import {IInstantiationService} from 'vs/platform/instantiation/common/instantiat
import {IThreadService} from 'vs/platform/thread/common/thread'; import {IThreadService} from 'vs/platform/thread/common/thread';
import {IModeService} from 'vs/editor/common/services/modeService'; import {IModeService} from 'vs/editor/common/services/modeService';
import {IModelService} from 'vs/editor/common/services/modelService'; import {IModelService} from 'vs/editor/common/services/modelService';
import {RichEditSupport} from 'vs/editor/common/modes/supports/richEditSupport';
/** /**
* The MonarchMode creates a Monaco language mode given a certain language description * The MonarchMode creates a Monaco language mode given a certain language description
*/ */
export class MonarchMode<W extends AbstractModeWorker> extends AbstractMode<W> { export class MonarchMode<W extends AbstractModeWorker> extends AbstractMode<W> {
public tokenizationSupport: Modes.ITokenizationSupport; public tokenizationSupport: Modes.ITokenizationSupport;
public electricCharacterSupport: Modes.IElectricCharacterSupport; public richEditSupport: Modes.IRichEditSupport;
public characterPairSupport: Modes.ICharacterPairSupport;
public onEnterSupport: Modes.IOnEnterSupport;
constructor( constructor(
descriptor:Modes.IModeDescriptor, descriptor:Modes.IModeDescriptor,
...@@ -42,11 +42,9 @@ export class MonarchMode<W extends AbstractModeWorker> extends AbstractMode<W> { ...@@ -42,11 +42,9 @@ export class MonarchMode<W extends AbstractModeWorker> extends AbstractMode<W> {
super(descriptor, instantiationService, threadService); super(descriptor, instantiationService, threadService);
this.tokenizationSupport = createTokenizationSupport(modeService, this, lexer); this.tokenizationSupport = createTokenizationSupport(modeService, this, lexer);
this.electricCharacterSupport = new Supports.BracketElectricCharacterSupport(this, MonarchDefinition.createBracketElectricCharacterContribution(lexer));
this.commentsSupport = new Supports.CommentsSupport(MonarchDefinition.createCommentsSupport(lexer)); this.richEditSupport = new RichEditSupport(this.getId(), MonarchDefinition.createRichEditSupport(lexer));
this.tokenTypeClassificationSupport = new Supports.TokenTypeClassificationSupport(MonarchDefinition.createTokenTypeClassificationSupportContribution(lexer));
this.characterPairSupport = new Supports.CharacterPairSupport(this, MonarchDefinition.createCharacterPairContribution(lexer));
this.suggestSupport = new Supports.ComposableSuggestSupport(this, MonarchDefinition.createSuggestSupport(modelService, this, lexer)); this.suggestSupport = new Supports.ComposableSuggestSupport(this, MonarchDefinition.createSuggestSupport(modelService, this, lexer));
this.onEnterSupport = new OnEnterSupport(this.getId(), MonarchDefinition.createOnEnterSupportOptions(lexer));
} }
} }
...@@ -17,35 +17,39 @@ import EditorCommon = require('vs/editor/common/editorCommon'); ...@@ -17,35 +17,39 @@ import EditorCommon = require('vs/editor/common/editorCommon');
import {IModelService} from 'vs/editor/common/services/modelService'; import {IModelService} from 'vs/editor/common/services/modelService';
import Modes = require('vs/editor/common/modes'); import Modes = require('vs/editor/common/modes');
import {IOnEnterSupportOptions} from 'vs/editor/common/modes/supports/onEnter'; import {IOnEnterSupportOptions} from 'vs/editor/common/modes/supports/onEnter';
import {CharacterPair, IRichEditConfiguration} from 'vs/editor/common/modes/supports/richEditSupport';
export function createCommentsSupport(lexer: MonarchCommonTypes.ILexer): Supports.ICommentsSupportContribution { export function createRichEditSupport(lexer: MonarchCommonTypes.ILexer): IRichEditConfiguration {
return {
commentsConfiguration: {
lineCommentTokens: [lexer.lineComment],
blockCommentStartToken: lexer.blockCommentStart,
blockCommentEndToken: lexer.blockCommentEnd
}
};
}
export function createBracketElectricCharacterContribution(lexer: MonarchCommonTypes.ILexer): Supports.IBracketElectricCharacterContribution { function toBracket(input:Modes.IBracketPair): CharacterPair {
return { return [input.open, input.close];
brackets: lexer.standardBrackets, }
regexBrackets: lexer.enhancedBrackets,
caseInsensitive: lexer.ignoreCase,
embeddedElectricCharacters: lexer.outdentTriggers.split('')
};
}
export function createTokenTypeClassificationSupportContribution(lexer: MonarchCommonTypes.ILexer): Supports.ITokenTypeClassificationSupportContribution { function toBrackets(input:Modes.IBracketPair[]): CharacterPair[] {
return { return input.map(toBracket);
wordDefinition: lexer.wordDefinition }
};
}
export function createCharacterPairContribution(lexer: MonarchCommonTypes.ILexer): Modes.ICharacterPairContribution {
return { return {
autoClosingPairs: lexer.autoClosingPairs
wordPattern: lexer.wordDefinition,
comments: {
lineComment: lexer.lineComment,
blockComment: [lexer.blockCommentStart, lexer.blockCommentEnd]
},
brackets: toBrackets(lexer.standardBrackets),
__electricCharacterSupport: {
brackets: lexer.standardBrackets,
regexBrackets: lexer.enhancedBrackets,
caseInsensitive: lexer.ignoreCase,
embeddedElectricCharacters: lexer.outdentTriggers.split('')
},
__characterPairSupport: {
autoClosingPairs: lexer.autoClosingPairs
}
}; };
} }
...@@ -67,12 +71,6 @@ function _addSuggestionsAtPosition(model: EditorCommon.IModel, position:EditorCo ...@@ -67,12 +71,6 @@ function _addSuggestionsAtPosition(model: EditorCommon.IModel, position:EditorCo
return superSuggestions; return superSuggestions;
} }
export function createOnEnterSupportOptions(lexer:MonarchCommonTypes.ILexer): IOnEnterSupportOptions {
return {
brackets: lexer.standardBrackets
};
}
export function createSuggestSupport(modelService: IModelService, mode:Modes.IMode, lexer:MonarchCommonTypes.ILexer): Supports.IComposableSuggestContribution { export function createSuggestSupport(modelService: IModelService, mode:Modes.IMode, lexer:MonarchCommonTypes.ILexer): Supports.IComposableSuggestContribution {
if (lexer.suggestSupport.textualCompletions && mode instanceof AbstractMode) { if (lexer.suggestSupport.textualCompletions && mode instanceof AbstractMode) {
return { return {
......
...@@ -80,10 +80,14 @@ export class NullMode implements Modes.IMode { ...@@ -80,10 +80,14 @@ export class NullMode implements Modes.IMode {
public static ID = 'vs.editor.modes.nullMode'; public static ID = 'vs.editor.modes.nullMode';
public tokenTypeClassificationSupport: Modes.ITokenTypeClassificationSupport; public richEditSupport: Modes.IRichEditSupport;
constructor() { constructor() {
this.tokenTypeClassificationSupport = this; this.richEditSupport = {
tokenTypeClassification: {
getWordDefinition: () => NullMode.DEFAULT_WORD_REGEXP
}
};
} }
public getId():string { public getId():string {
...@@ -93,10 +97,6 @@ export class NullMode implements Modes.IMode { ...@@ -93,10 +97,6 @@ export class NullMode implements Modes.IMode {
public toSimplifiedMode(): Modes.IMode { public toSimplifiedMode(): Modes.IMode {
return this; return this;
} }
public getWordDefinition():RegExp {
return NullMode.DEFAULT_WORD_REGEXP;
}
} }
export function nullTokenize(mode: Modes.IMode, buffer:string, state: Modes.IState, deltaOffset:number = 0, stopAtOffset?:number): Modes.ILineTokens { export function nullTokenize(mode: Modes.IMode, buffer:string, state: Modes.IState, deltaOffset:number = 0, stopAtOffset?:number): Modes.ILineTokens {
......
...@@ -503,57 +503,6 @@ export class TokenizationSupport extends AbstractSupport implements Modes.IToken ...@@ -503,57 +503,6 @@ export class TokenizationSupport extends AbstractSupport implements Modes.IToken
} }
} }
export interface IBracketElectricCharacterContribution {
brackets: Modes.IBracketPair[];
regexBrackets?: Modes.IRegexBracketPair[];
docComment?: Modes.IDocComment;
caseInsensitive?: boolean;
embeddedElectricCharacters?: string[];
}
export class BracketElectricCharacterSupport extends AbstractSupport implements Modes.IElectricCharacterSupport {
private contribution: IBracketElectricCharacterContribution;
private brackets: Brackets;
constructor(mode:Modes.IMode, contribution: IBracketElectricCharacterContribution) {
super(mode);
this.contribution = contribution;
this.brackets = new Brackets(contribution.brackets, contribution.regexBrackets,
contribution.docComment, contribution.caseInsensitive);
}
public getElectricCharacters(): string[]{
if (Array.isArray(this.contribution.embeddedElectricCharacters)) {
return this.contribution.embeddedElectricCharacters.concat(this.brackets.getElectricCharacters());
}
return this.brackets.getElectricCharacters();
}
public onElectricCharacter(context:Modes.ILineContext, offset:number): Modes.IElectricAction {
return handleEvent(context, offset, (nestedMode:Modes.IMode, context:Modes.ILineContext, offset:number) => {
if (this.mode === nestedMode) {
return this.brackets.onElectricCharacter(context, offset);
} else if (nestedMode.electricCharacterSupport) {
return nestedMode.electricCharacterSupport.onElectricCharacter(context, offset);
} else {
return null;
}
});
}
public onEnter(context: Modes.ILineContext, offset: number): Modes.IEnterAction {
return handleEvent(context, offset, (nestedMode:Modes.IMode, context:Modes.ILineContext, offset:number) => {
if (this.mode === nestedMode) {
return this.brackets.onEnter(context, offset);
} else if (nestedMode.electricCharacterSupport) {
return nestedMode.electricCharacterSupport.onEnter(context, offset);
} else {
return null;
}
});
}
}
// TODO@Alex -> refactor to use `brackets` from language configuration // TODO@Alex -> refactor to use `brackets` from language configuration
export function getBracketFor(tokenType:string, tokenText:string, mode:Modes.IMode): Modes.Bracket { export function getBracketFor(tokenType:string, tokenText:string, mode:Modes.IMode): Modes.Bracket {
if (tokenText === '{' || tokenText === '(' || tokenText === '[') { if (tokenText === '{' || tokenText === '(' || tokenText === '[') {
...@@ -786,61 +735,6 @@ export class ComposableSuggestSupport extends SuggestSupport { ...@@ -786,61 +735,6 @@ export class ComposableSuggestSupport extends SuggestSupport {
} }
export class CharacterPairSupport extends AbstractSupport implements Modes.ICharacterPairSupport {
private _autoClosingPairs: Modes.IAutoClosingPairConditional[];
private _surroundingPairs: Modes.IAutoClosingPair[];
constructor(mode: Modes.IMode, contribution: Modes.ICharacterPairContribution) {
super(mode);
this._autoClosingPairs = contribution.autoClosingPairs;
this._surroundingPairs = Array.isArray(contribution.surroundingPairs) ? contribution.surroundingPairs : contribution.autoClosingPairs;
}
public getAutoClosingPairs(): Modes.IAutoClosingPair[] {
return this._autoClosingPairs;
}
public shouldAutoClosePair(character:string, context:Modes.ILineContext, offset:number): boolean {
return handleEvent(context, offset, (nestedMode:Modes.IMode, context:Modes.ILineContext, offset:number) => {
if (this.mode === nestedMode) {
// Always complete on empty line
if (context.getTokenCount() === 0) {
return true;
}
var tokenIndex = context.findIndexOfOffset(offset - 1);
var tokenType = context.getTokenType(tokenIndex);
for (var i = 0; i < this._autoClosingPairs.length; ++i) {
if (this._autoClosingPairs[i].open === character) {
if (this._autoClosingPairs[i].notIn) {
for (var notInIndex = 0; notInIndex < this._autoClosingPairs[i].notIn.length; ++notInIndex) {
if (tokenType.indexOf(this._autoClosingPairs[i].notIn[notInIndex]) > -1) {
return false;
}
}
}
break;
}
}
return true;
} else if (nestedMode.characterPairSupport) {
return nestedMode.characterPairSupport.shouldAutoClosePair(character, context, offset);
} else {
return null;
}
});
}
public getSurroundingPairs(): Modes.IAutoClosingPair[]{
return this._surroundingPairs;
}
}
export interface IReplaceSupportHelper { export interface IReplaceSupportHelper {
valueSetReplace(valueSet: string[], value: string, up: boolean): string; valueSetReplace(valueSet: string[], value: string, up: boolean): string;
valueSetsReplace(valueSets: string[][], value: string, up: boolean): string; valueSetsReplace(valueSets: string[][], value: string, up: boolean): string;
...@@ -1012,41 +906,3 @@ export class MainInplaceReplaceSupport extends AbstractInplaceReplaceSupport { ...@@ -1012,41 +906,3 @@ export class MainInplaceReplaceSupport extends AbstractInplaceReplaceSupport {
return this.modelService.getModel(resource); return this.modelService.getModel(resource);
} }
} }
export interface ICommentsSupportContribution {
commentsConfiguration: Modes.ICommentsConfiguration;
}
export class CommentsSupport implements Modes.ICommentsSupport {
private _contribution: ICommentsSupportContribution;
constructor(contribution:ICommentsSupportContribution) {
this._contribution = contribution;
}
public getCommentsConfiguration(): Modes.ICommentsConfiguration {
return this._contribution.commentsConfiguration;
}
}
export interface ITokenTypeClassificationSupportContribution {
wordDefinition?: RegExp;
}
export class TokenTypeClassificationSupport implements Modes.ITokenTypeClassificationSupport {
private _contribution: ITokenTypeClassificationSupportContribution;
constructor(contribution: ITokenTypeClassificationSupportContribution) {
this._contribution = contribution;
}
public getWordDefinition(): RegExp {
if (typeof this._contribution.wordDefinition === 'undefined') {
return NullMode.DEFAULT_WORD_REGEXP;
}
return this._contribution.wordDefinition;
}
}
\ No newline at end of file
/*---------------------------------------------------------------------------------------------
* 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 {handleEvent} from 'vs/editor/common/modes/supports';
import * as Modes from 'vs/editor/common/modes';
export class CharacterPairSupport implements Modes.IRichEditCharacterPair {
private _modeId: string;
private _autoClosingPairs: Modes.IAutoClosingPairConditional[];
private _surroundingPairs: Modes.IAutoClosingPair[];
constructor(modeId: string, contribution: Modes.ICharacterPairContribution) {
this._modeId = modeId;
this._autoClosingPairs = contribution.autoClosingPairs;
this._surroundingPairs = Array.isArray(contribution.surroundingPairs) ? contribution.surroundingPairs : contribution.autoClosingPairs;
}
public getAutoClosingPairs(): Modes.IAutoClosingPair[] {
return this._autoClosingPairs;
}
public shouldAutoClosePair(character:string, context:Modes.ILineContext, offset:number): boolean {
return handleEvent(context, offset, (nestedMode:Modes.IMode, context:Modes.ILineContext, offset:number) => {
if (this._modeId === nestedMode.getId()) {
// Always complete on empty line
if (context.getTokenCount() === 0) {
return true;
}
var tokenIndex = context.findIndexOfOffset(offset - 1);
var tokenType = context.getTokenType(tokenIndex);
for (var i = 0; i < this._autoClosingPairs.length; ++i) {
if (this._autoClosingPairs[i].open === character) {
if (this._autoClosingPairs[i].notIn) {
for (var notInIndex = 0; notInIndex < this._autoClosingPairs[i].notIn.length; ++notInIndex) {
if (tokenType.indexOf(this._autoClosingPairs[i].notIn[notInIndex]) > -1) {
return false;
}
}
}
break;
}
}
return true;
} else if (nestedMode.richEditSupport && nestedMode.richEditSupport.characterPair) {
return nestedMode.richEditSupport.characterPair.shouldAutoClosePair(character, context, offset);
} else {
return null;
}
});
}
public getSurroundingPairs(): Modes.IAutoClosingPair[]{
return this._surroundingPairs;
}
}
/*---------------------------------------------------------------------------------------------
* 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 * as Modes from 'vs/editor/common/modes';
export interface ICommentsSupportContribution {
commentsConfiguration: Modes.ICommentsConfiguration;
}
export class CommentsSupport implements Modes.IRichEditComments {
private _contribution: ICommentsSupportContribution;
constructor(contribution:ICommentsSupportContribution) {
this._contribution = contribution;
}
public getCommentsConfiguration(): Modes.ICommentsConfiguration {
return this._contribution.commentsConfiguration;
}
}
/*---------------------------------------------------------------------------------------------
* 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 {Brackets} from 'vs/editor/common/modes/autoIndentation';
import * as Modes from 'vs/editor/common/modes';
import {handleEvent} from 'vs/editor/common/modes/supports';
export interface IBracketElectricCharacterContribution {
brackets: Modes.IBracketPair[];
regexBrackets?: Modes.IRegexBracketPair[];
docComment?: Modes.IDocComment;
caseInsensitive?: boolean;
embeddedElectricCharacters?: string[];
}
export class BracketElectricCharacterSupport implements Modes.IRichEditElectricCharacter {
private _modeId: string;
private contribution: IBracketElectricCharacterContribution;
private brackets: Brackets;
constructor(modeId: string, contribution: IBracketElectricCharacterContribution) {
this._modeId = modeId;
this.contribution = contribution;
this.brackets = new Brackets(contribution.brackets, contribution.regexBrackets,
contribution.docComment, contribution.caseInsensitive);
}
public getElectricCharacters(): string[]{
if (Array.isArray(this.contribution.embeddedElectricCharacters)) {
return this.contribution.embeddedElectricCharacters.concat(this.brackets.getElectricCharacters());
}
return this.brackets.getElectricCharacters();
}
public onElectricCharacter(context:Modes.ILineContext, offset:number): Modes.IElectricAction {
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;
}
});
}
public onEnter(context: Modes.ILineContext, offset: number): Modes.IEnterAction {
return handleEvent(context, offset, (nestedMode:Modes.IMode, context:Modes.ILineContext, offset:number) => {
if (this._modeId === nestedMode.getId()) {
return this.brackets.onEnter(context, offset);
} else if (nestedMode.richEditSupport && nestedMode.richEditSupport.electricCharacter) {
return nestedMode.richEditSupport.electricCharacter.onEnter(context, offset);
} else {
return null;
}
});
}
}
...@@ -5,7 +5,7 @@ ...@@ -5,7 +5,7 @@
'use strict'; 'use strict';
import {handleEvent} from 'vs/editor/common/modes/supports'; import {handleEvent} from 'vs/editor/common/modes/supports';
import {IEnterAction, IndentAction, IOnEnterSupport, ILineContext, IMode} from 'vs/editor/common/modes'; import {IEnterAction, IndentAction, IRichEditOnEnter, ILineContext, IMode} from 'vs/editor/common/modes';
import EditorCommon = require('vs/editor/common/editorCommon'); import EditorCommon = require('vs/editor/common/editorCommon');
import Errors = require('vs/base/common/errors'); import Errors = require('vs/base/common/errors');
import Strings = require('vs/base/common/strings'); import Strings = require('vs/base/common/strings');
...@@ -40,7 +40,7 @@ interface IProcessedBracketPair extends IBracketPair { ...@@ -40,7 +40,7 @@ interface IProcessedBracketPair extends IBracketPair {
closeRegExp: RegExp; closeRegExp: RegExp;
} }
export class OnEnterSupport implements IOnEnterSupport { export class OnEnterSupport implements IRichEditOnEnter {
private static _INDENT: IEnterAction = { indentAction: IndentAction.Indent }; private static _INDENT: IEnterAction = { indentAction: IndentAction.Indent };
private static _INDENT_OUTDENT: IEnterAction = { indentAction: IndentAction.IndentOutdent }; private static _INDENT_OUTDENT: IEnterAction = { indentAction: IndentAction.IndentOutdent };
...@@ -78,8 +78,8 @@ export class OnEnterSupport implements IOnEnterSupport { ...@@ -78,8 +78,8 @@ export class OnEnterSupport implements IOnEnterSupport {
return handleEvent(context, position.column - 1, (nestedMode:IMode, context:ILineContext, offset:number) => { return handleEvent(context, position.column - 1, (nestedMode:IMode, context:ILineContext, offset:number) => {
if (this._modeId === nestedMode.getId()) { if (this._modeId === nestedMode.getId()) {
return this._onEnter(model, position); return this._onEnter(model, position);
} else if (nestedMode.onEnterSupport) { } else if (nestedMode.richEditSupport && nestedMode.richEditSupport.onEnter) {
return nestedMode.onEnterSupport.onEnter(model, position); return nestedMode.richEditSupport.onEnter.onEnter(model, position);
} else { } else {
return null; return null;
} }
...@@ -184,19 +184,21 @@ export class OnEnterSupport implements IOnEnterSupport { ...@@ -184,19 +184,21 @@ export class OnEnterSupport implements IOnEnterSupport {
export function getRawEnterActionAtPosition(model:EditorCommon.ITokenizedModel, lineNumber:number, column:number): IEnterAction { export function getRawEnterActionAtPosition(model:EditorCommon.ITokenizedModel, lineNumber:number, column:number): IEnterAction {
let enterAction:IEnterAction; let enterAction:IEnterAction;
if (model.getMode().onEnterSupport) { let richEditSupport = model.getMode().richEditSupport;
if (richEditSupport && richEditSupport.onEnter) {
try { try {
enterAction = model.getMode().onEnterSupport.onEnter(model, new Position(lineNumber, column)); enterAction = richEditSupport.onEnter.onEnter(model, new Position(lineNumber, column));
} catch (e) { } catch (e) {
Errors.onUnexpectedError(e); Errors.onUnexpectedError(e);
} }
} }
if (!enterAction) { if (!enterAction) {
if (model.getMode().electricCharacterSupport) { if (richEditSupport && richEditSupport.electricCharacter) {
let lineContext = model.getLineContext(lineNumber); let lineContext = model.getLineContext(lineNumber);
try { try {
enterAction = model.getMode().electricCharacterSupport.onEnter(lineContext, column - 1); enterAction = richEditSupport.electricCharacter.onEnter(lineContext, column - 1);
} catch(e) { } catch(e) {
Errors.onUnexpectedError(e); Errors.onUnexpectedError(e);
} }
......
/*---------------------------------------------------------------------------------------------
* 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 * as Modes from 'vs/editor/common/modes';
import {OnEnterSupport, IOnEnterSupportOptions, IIndentationRules, IOnEnterRegExpRules} from 'vs/editor/common/modes/supports/onEnter';
import {CharacterPairSupport} from 'vs/editor/common/modes/supports/characterPair';
import {BracketElectricCharacterSupport, IBracketElectricCharacterContribution} from 'vs/editor/common/modes/supports/electricCharacter';
import {TokenTypeClassificationSupport} from 'vs/editor/common/modes/supports/tokenTypeClassification';
import {CommentsSupport, ICommentsSupportContribution} from 'vs/editor/common/modes/supports/comments';
export type CharacterPair = [string, string];
export interface CommentRule {
lineComment?: string;
blockComment?: CharacterPair;
}
export interface IRichEditConfiguration {
comments?: CommentRule;
brackets?: CharacterPair[];
wordPattern?: RegExp;
indentationRules?: IIndentationRules;
onEnterRules?: IOnEnterRegExpRules[];
__electricCharacterSupport?: IBracketElectricCharacterContribution;
__characterPairSupport?: Modes.ICharacterPairContribution;
}
export class RichEditSupport implements Modes.IRichEditSupport {
public electricCharacter: Modes.IRichEditElectricCharacter;
public comments: Modes.IRichEditComments;
public characterPair: Modes.IRichEditCharacterPair;
public tokenTypeClassification: Modes.IRichEditTokenTypeClassification;
public onEnter: Modes.IRichEditOnEnter;
constructor(modeId:string, conf:IRichEditConfiguration) {
this._handleOnEnter(modeId, conf);
this._handleComments(modeId, conf);
if (conf.__characterPairSupport) {
this.characterPair = new CharacterPairSupport(modeId, conf.__characterPairSupport);
}
if (conf.__electricCharacterSupport) {
this.electricCharacter = new BracketElectricCharacterSupport(modeId, conf.__electricCharacterSupport);
}
this.tokenTypeClassification = new TokenTypeClassificationSupport({
wordDefinition: conf.wordPattern
});
}
private _handleOnEnter(modeId:string, conf:IRichEditConfiguration): void {
// on enter
let onEnter: IOnEnterSupportOptions = {};
let empty = true;
let {brackets, indentationRules, onEnterRules} = conf;
if (brackets) {
empty = false;
onEnter.brackets = brackets.map(pair => {
let [open, close] = pair;
return { open, close };
});
}
if (indentationRules) {
empty = false;
onEnter.indentationRules = indentationRules;
}
if (onEnterRules) {
empty = false;
onEnter.regExpRules = <any>onEnterRules;
}
if (!empty) {
this.onEnter = new OnEnterSupport(modeId, onEnter);
}
}
private _handleComments(modeId:string, conf:IRichEditConfiguration): void {
let {comments} = conf;
// comment configuration
if (comments) {
let contrib: ICommentsSupportContribution = { commentsConfiguration: {} };
if (comments.lineComment) {
contrib.commentsConfiguration.lineCommentTokens = [comments.lineComment];
}
if (comments.blockComment) {
let [blockStart, blockEnd] = comments.blockComment;
contrib.commentsConfiguration.blockCommentStartToken = blockStart;
contrib.commentsConfiguration.blockCommentEndToken = blockEnd;
}
this.comments = new CommentsSupport(contrib);
}
}
}
/*---------------------------------------------------------------------------------------------
* 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 * as Modes from 'vs/editor/common/modes';
import {NullMode} from 'vs/editor/common/modes/nullMode';
export interface ITokenTypeClassificationSupportContribution {
wordDefinition?: RegExp;
}
export class TokenTypeClassificationSupport implements Modes.IRichEditTokenTypeClassification {
private _contribution: ITokenTypeClassificationSupportContribution;
constructor(contribution: ITokenTypeClassificationSupportContribution) {
this._contribution = contribution;
}
public getWordDefinition(): RegExp {
if (typeof this._contribution.wordDefinition === 'undefined') {
return NullMode.DEFAULT_WORD_REGEXP;
}
return this._contribution.wordDefinition;
}
}
...@@ -11,6 +11,7 @@ import Supports = require ('vs/editor/common/modes/supports'); ...@@ -11,6 +11,7 @@ import Supports = require ('vs/editor/common/modes/supports');
import MonarchTypes = require('vs/editor/common/modes/monarch/monarchTypes'); import MonarchTypes = require('vs/editor/common/modes/monarch/monarchTypes');
import {IOnEnterSupportOptions} from 'vs/editor/common/modes/supports/onEnter'; import {IOnEnterSupportOptions} from 'vs/editor/common/modes/supports/onEnter';
import {IDisposable} from 'vs/base/common/lifecycle'; import {IDisposable} from 'vs/base/common/lifecycle';
import {IRichEditConfiguration} from 'vs/editor/common/modes/supports/richEditSupport';
export var IModeService = createDecorator<IModeService>('modeService'); export var IModeService = createDecorator<IModeService>('modeService');
...@@ -34,11 +35,8 @@ export interface IModeService { ...@@ -34,11 +35,8 @@ export interface IModeService {
getOrCreateModeByLanguageName(languageName: string): TPromise<Modes.IMode>; getOrCreateModeByLanguageName(languageName: string): TPromise<Modes.IMode>;
getOrCreateModeByFilenameOrFirstLine(filename: string, firstLine?:string): TPromise<Modes.IMode>; getOrCreateModeByFilenameOrFirstLine(filename: string, firstLine?:string): TPromise<Modes.IMode>;
registerDeclarativeCharacterPairSupport(modeId: string, support: Modes.ICharacterPairContribution): IDisposable;
registerCodeLensSupport(modeId: string, support: Modes.ICodeLensSupport): IDisposable; registerCodeLensSupport(modeId: string, support: Modes.ICodeLensSupport): IDisposable;
registerDeclarativeCommentsSupport(modeId: string, support: Supports.ICommentsSupportContribution): IDisposable;
registerDeclarativeDeclarationSupport(modeId: string, contribution: Supports.IDeclarationContribution): IDisposable; registerDeclarativeDeclarationSupport(modeId: string, contribution: Supports.IDeclarationContribution): IDisposable;
registerDeclarativeElectricCharacterSupport(modeId: string, support: Supports.IBracketElectricCharacterContribution): IDisposable;
registerExtraInfoSupport(modeId: string, support: Modes.IExtraInfoSupport): IDisposable; registerExtraInfoSupport(modeId: string, support: Modes.IExtraInfoSupport): IDisposable;
registerFormattingSupport(modeId: string, support: Modes.IFormattingSupport): IDisposable; registerFormattingSupport(modeId: string, support: Modes.IFormattingSupport): IDisposable;
registerInplaceReplaceSupport(modeId: string, support: Modes.IInplaceReplaceSupport): IDisposable; registerInplaceReplaceSupport(modeId: string, support: Modes.IInplaceReplaceSupport): IDisposable;
...@@ -50,8 +48,7 @@ export interface IModeService { ...@@ -50,8 +48,7 @@ export interface IModeService {
registerRenameSupport(modeId: string, support: Modes.IRenameSupport): IDisposable; registerRenameSupport(modeId: string, support: Modes.IRenameSupport): IDisposable;
registerDeclarativeSuggestSupport(modeId: string, declaration: Supports.ISuggestContribution): IDisposable; registerDeclarativeSuggestSupport(modeId: string, declaration: Supports.ISuggestContribution): IDisposable;
registerTokenizationSupport(modeId: string, callback: (mode: Modes.IMode) => Modes.ITokenizationSupport): IDisposable; registerTokenizationSupport(modeId: string, callback: (mode: Modes.IMode) => Modes.ITokenizationSupport): IDisposable;
registerDeclarativeTokenTypeClassificationSupport(modeId: string, support: Supports.ITokenTypeClassificationSupportContribution): IDisposable; registerRichEditSupport(modeId: string, support: IRichEditConfiguration): IDisposable;
registerDeclarativeOnEnterSupport(modeId: string, support: IOnEnterSupportOptions): IDisposable;
registerMonarchDefinition(modeId:string, language:MonarchTypes.ILanguage): IDisposable; registerMonarchDefinition(modeId:string, language:MonarchTypes.ILanguage): IDisposable;
} }
...@@ -25,6 +25,7 @@ import MonarchCommonTypes = require('vs/editor/common/modes/monarch/monarchCommo ...@@ -25,6 +25,7 @@ import MonarchCommonTypes = require('vs/editor/common/modes/monarch/monarchCommo
import {OnEnterSupport, IOnEnterSupportOptions} from 'vs/editor/common/modes/supports/onEnter'; import {OnEnterSupport, IOnEnterSupportOptions} from 'vs/editor/common/modes/supports/onEnter';
import {IDisposable, combinedDispose, empty as EmptyDisposable} from 'vs/base/common/lifecycle'; import {IDisposable, combinedDispose, empty as EmptyDisposable} from 'vs/base/common/lifecycle';
import {createAsyncDescriptor0, createAsyncDescriptor1} from 'vs/platform/instantiation/common/descriptors'; import {createAsyncDescriptor0, createAsyncDescriptor1} from 'vs/platform/instantiation/common/descriptors';
import {RichEditSupport, IRichEditConfiguration} from 'vs/editor/common/modes/supports/richEditSupport';
interface IModeConfigurationMap { [modeId: string]: any; } interface IModeConfigurationMap { [modeId: string]: any; }
...@@ -263,15 +264,7 @@ export class ModeServiceImpl implements IModeService { ...@@ -263,15 +264,7 @@ export class ModeServiceImpl implements IModeService {
return createTokenizationSupport(this, mode, lexer); return createTokenizationSupport(this, mode, lexer);
}), }),
this.registerDeclarativeCommentsSupport(modeId, MonarchDefinition.createCommentsSupport(lexer)), this.registerRichEditSupport(modeId, MonarchDefinition.createRichEditSupport(lexer))
this.registerDeclarativeElectricCharacterSupport(modeId, MonarchDefinition.createBracketElectricCharacterContribution(lexer)),
this.registerDeclarativeTokenTypeClassificationSupport(modeId, MonarchDefinition.createTokenTypeClassificationSupportContribution(lexer)),
this.registerDeclarativeCharacterPairSupport(modeId, MonarchDefinition.createCharacterPairContribution(lexer)),
this.registerDeclarativeOnEnterSupport(modeId, MonarchDefinition.createOnEnterSupportOptions(lexer))
); );
} }
...@@ -280,26 +273,18 @@ export class ModeServiceImpl implements IModeService { ...@@ -280,26 +273,18 @@ export class ModeServiceImpl implements IModeService {
return this.doRegisterMonarchDefinition(modeId, lexer); return this.doRegisterMonarchDefinition(modeId, lexer);
} }
public registerDeclarativeCharacterPairSupport(modeId: string, support: Modes.ICharacterPairContribution): IDisposable {
return this.registerModeSupport(modeId, 'characterPairSupport', (mode) => new Supports.CharacterPairSupport(mode, support));
}
public registerCodeLensSupport(modeId: string, support: Modes.ICodeLensSupport): IDisposable { public registerCodeLensSupport(modeId: string, support: Modes.ICodeLensSupport): IDisposable {
return this.registerModeSupport(modeId, 'codeLensSupport', (mode) => support); return this.registerModeSupport(modeId, 'codeLensSupport', (mode) => support);
} }
public registerDeclarativeCommentsSupport(modeId: string, support: Supports.ICommentsSupportContribution): IDisposable { public registerRichEditSupport(modeId: string, support: IRichEditConfiguration): IDisposable {
return this.registerModeSupport(modeId, 'commentsSupport', (mode) => new Supports.CommentsSupport(support)); return this.registerModeSupport(modeId, 'richEditSupport', (mode) => new RichEditSupport(modeId, support));
} }
public registerDeclarativeDeclarationSupport(modeId: string, contribution: Supports.IDeclarationContribution): IDisposable { public registerDeclarativeDeclarationSupport(modeId: string, contribution: Supports.IDeclarationContribution): IDisposable {
return this.registerModeSupport(modeId, 'declarationSupport', (mode) => new Supports.DeclarationSupport(mode, contribution)); return this.registerModeSupport(modeId, 'declarationSupport', (mode) => new Supports.DeclarationSupport(mode, contribution));
} }
public registerDeclarativeElectricCharacterSupport(modeId: string, support: Supports.IBracketElectricCharacterContribution): IDisposable {
return this.registerModeSupport(modeId, 'electricCharacterSupport', (mode) => new Supports.BracketElectricCharacterSupport(mode, support));
}
public registerExtraInfoSupport(modeId: string, support: Modes.IExtraInfoSupport): IDisposable { public registerExtraInfoSupport(modeId: string, support: Modes.IExtraInfoSupport): IDisposable {
return this.registerModeSupport(modeId, 'extraInfoSupport', (mode) => support); return this.registerModeSupport(modeId, 'extraInfoSupport', (mode) => support);
} }
...@@ -343,14 +328,6 @@ export class ModeServiceImpl implements IModeService { ...@@ -343,14 +328,6 @@ export class ModeServiceImpl implements IModeService {
public registerTokenizationSupport(modeId: string, callback: (mode: Modes.IMode) => Modes.ITokenizationSupport): IDisposable { public registerTokenizationSupport(modeId: string, callback: (mode: Modes.IMode) => Modes.ITokenizationSupport): IDisposable {
return this.registerModeSupport(modeId, 'tokenizationSupport', callback); return this.registerModeSupport(modeId, 'tokenizationSupport', callback);
} }
public registerDeclarativeTokenTypeClassificationSupport(modeId: string, support: Supports.ITokenTypeClassificationSupportContribution): IDisposable {
return this.registerModeSupport(modeId, 'tokenTypeClassificationSupport', (mode) => new Supports.TokenTypeClassificationSupport(support));
}
public registerDeclarativeOnEnterSupport(modeId: string, opts: IOnEnterSupportOptions): IDisposable {
return this.registerModeSupport(modeId, 'onEnterSupport', (mode) => new OnEnterSupport(modeId, opts));
}
} }
export class MainThreadModeServiceImpl extends ModeServiceImpl { export class MainThreadModeServiceImpl extends ModeServiceImpl {
......
...@@ -121,7 +121,8 @@ export class BlockCommentCommand implements EditorCommon.ICommand { ...@@ -121,7 +121,8 @@ export class BlockCommentCommand implements EditorCommon.ICommand {
var endLineNumber = this._selection.endLineNumber; var endLineNumber = this._selection.endLineNumber;
var endColumn = this._selection.endColumn; var endColumn = this._selection.endColumn;
var commentsSupport = model.getModeAtPosition(startLineNumber, startColumn).commentsSupport; let richEditSupport = model.getModeAtPosition(startLineNumber, startColumn).richEditSupport;
var commentsSupport = richEditSupport? richEditSupport.comments : null;
if (!commentsSupport) { if (!commentsSupport) {
// Mode does not support comments // Mode does not support comments
return; return;
......
...@@ -81,7 +81,7 @@ export class LineCommentCommand implements EditorCommon.ICommand { ...@@ -81,7 +81,7 @@ export class LineCommentCommand implements EditorCommon.ICommand {
if (seenModes[modeId]) { if (seenModes[modeId]) {
commentStr = seenModes[modeId]; commentStr = seenModes[modeId];
} else { } else {
config = (mode.commentsSupport ? mode.commentsSupport.getCommentsConfiguration() : null); config = (mode.richEditSupport && mode.richEditSupport.comments ? mode.richEditSupport.comments.getCommentsConfiguration() : null);
commentStr = (config && config.lineCommentTokens && config.lineCommentTokens.length > 0 ? config.lineCommentTokens[0] : null); commentStr = (config && config.lineCommentTokens && config.lineCommentTokens.length > 0 ? config.lineCommentTokens[0] : null);
if (commentStr === null || commentStr.length === 0) { if (commentStr === null || commentStr.length === 0) {
// Mode does not support line comments // Mode does not support line comments
...@@ -273,7 +273,8 @@ export class LineCommentCommand implements EditorCommon.ICommand { ...@@ -273,7 +273,8 @@ export class LineCommentCommand implements EditorCommon.ICommand {
* Given an unsuccessful analysis, delegate to the block comment command * Given an unsuccessful analysis, delegate to the block comment command
*/ */
private _executeBlockComment(model:EditorCommon.ITokenizedModel, builder:EditorCommon.IEditOperationBuilder, s:EditorCommon.IEditorSelection): void { private _executeBlockComment(model:EditorCommon.ITokenizedModel, builder:EditorCommon.IEditOperationBuilder, s:EditorCommon.IEditorSelection): void {
var commentsSupport = model.getModeAtPosition(s.startLineNumber, s.startColumn).commentsSupport; let richEditSupport = model.getModeAtPosition(s.startLineNumber, s.startColumn).richEditSupport;
var commentsSupport = richEditSupport ? richEditSupport.comments : null;
if (!commentsSupport) { if (!commentsSupport) {
// Mode does not support comments // Mode does not support comments
return; return;
......
...@@ -12,6 +12,7 @@ import Supports = require ('vs/editor/common/modes/supports'); ...@@ -12,6 +12,7 @@ import Supports = require ('vs/editor/common/modes/supports');
import {IOnEnterSupportOptions} from 'vs/editor/common/modes/supports/onEnter'; import {IOnEnterSupportOptions} from 'vs/editor/common/modes/supports/onEnter';
import json = require('vs/base/common/json'); import json = require('vs/base/common/json');
import {ICharacterPairContribution} from 'vs/editor/common/modes'; import {ICharacterPairContribution} from 'vs/editor/common/modes';
import {IRichEditConfiguration} from 'vs/editor/common/modes/supports/richEditSupport';
type CharacterPair = [string, string]; type CharacterPair = [string, string];
...@@ -62,47 +63,33 @@ export class LanguageConfigurationFileHandler { ...@@ -62,47 +63,33 @@ export class LanguageConfigurationFileHandler {
} }
private _handleConfig(modeId:string, configuration:ILanguageConfiguration): void { private _handleConfig(modeId:string, configuration:ILanguageConfiguration): void {
if (configuration.comments) {
let comments = configuration.comments;
let contrib: Supports.ICommentsSupportContribution = { commentsConfiguration: {} };
if (comments.lineComment) { let richEditConfig:IRichEditConfiguration = {};
contrib.commentsConfiguration.lineCommentTokens = [comments.lineComment];
}
if (comments.blockComment) {
contrib.commentsConfiguration.blockCommentStartToken = comments.blockComment[0];
contrib.commentsConfiguration.blockCommentEndToken = comments.blockComment[1];
}
this._modeService.registerDeclarativeCommentsSupport(modeId, contrib); if (configuration.comments) {
richEditConfig.comments = configuration.comments;
} }
if (configuration.brackets) { if (configuration.brackets) {
let brackets = configuration.brackets; richEditConfig.brackets = configuration.brackets;
let onEnterContrib: IOnEnterSupportOptions = {}; richEditConfig.__characterPairSupport = {
onEnterContrib.brackets = brackets.map(pair => { autoClosingPairs: configuration.brackets.map(pair => {
let [open, close] = pair;
return { open: open, close: close };
});
this._modeService.registerDeclarativeOnEnterSupport(modeId, onEnterContrib);
let characterPairContrib: ICharacterPairContribution = {
autoClosingPairs: brackets.map(pair => {
let [open, close] = pair; let [open, close] = pair;
return { open: open, close: close }; return { open: open, close: close };
}) })
}; }
this._modeService.registerDeclarativeCharacterPairSupport(modeId, characterPairContrib);
} }
// TMSyntax hard-codes these and tokenizes them as brackets // TMSyntax hard-codes these and tokenizes them as brackets
this._modeService.registerDeclarativeElectricCharacterSupport(modeId, { richEditConfig.__electricCharacterSupport = {
brackets: [ brackets: [
{ tokenType:'delimiter.curly.' + modeId, open: '{', close: '}', isElectric: true }, { tokenType:'delimiter.curly.' + modeId, open: '{', close: '}', isElectric: true },
{ tokenType:'delimiter.square.' + modeId, open: '[', close: ']', isElectric: true }, { tokenType:'delimiter.square.' + modeId, open: '[', close: ']', isElectric: true },
{ tokenType:'delimiter.paren.' + modeId, open: '(', close: ')', isElectric: true } { tokenType:'delimiter.paren.' + modeId, open: '(', close: ')', isElectric: true }
] ]
}); };
this._modeService.registerRichEditSupport(modeId, richEditConfig);
} }
} }
...@@ -11,6 +11,7 @@ import modesUtil = require('vs/editor/test/common/modesUtil'); ...@@ -11,6 +11,7 @@ import modesUtil = require('vs/editor/test/common/modesUtil');
import monarchCompile = require('vs/editor/common/modes/monarch/monarchCompile'); import monarchCompile = require('vs/editor/common/modes/monarch/monarchCompile');
import MonarchDefinition = require('vs/editor/common/modes/monarch/monarchDefinition'); import MonarchDefinition = require('vs/editor/common/modes/monarch/monarchDefinition');
import {OnEnterSupport} from 'vs/editor/common/modes/supports/onEnter'; import {OnEnterSupport} from 'vs/editor/common/modes/supports/onEnter';
import {RichEditSupport} from 'vs/editor/common/modes/supports/richEditSupport';
export enum Bracket { export enum Bracket {
None = 0, None = 0,
...@@ -47,8 +48,8 @@ export function testOnEnter(name:string, language: types.ILanguage, callback:(as ...@@ -47,8 +48,8 @@ export function testOnEnter(name:string, language: types.ILanguage, callback:(as
suite(language.displayName || name, () => { suite(language.displayName || name, () => {
test('onEnter', () => { test('onEnter', () => {
var lexer = monarchCompile.compile(language); var lexer = monarchCompile.compile(language);
var onEnterSupport = new OnEnterSupport('test', MonarchDefinition.createOnEnterSupportOptions(lexer)); var richEditSupport = new RichEditSupport('test', MonarchDefinition.createRichEditSupport(lexer));
callback(modesUtil.createOnEnterAsserter('test', onEnterSupport)); callback(modesUtil.createOnEnterAsserter('test', richEditSupport));
}); });
}); });
} }
\ No newline at end of file
...@@ -13,6 +13,7 @@ import {Selection} from 'vs/editor/common/core/selection'; ...@@ -13,6 +13,7 @@ import {Selection} from 'vs/editor/common/core/selection';
import {Cursor} from 'vs/editor/common/controller/cursor'; import {Cursor} from 'vs/editor/common/controller/cursor';
import * as Modes from 'vs/editor/common/modes'; import * as Modes from 'vs/editor/common/modes';
import {OnEnterSupport} from 'vs/editor/common/modes/supports/onEnter'; import {OnEnterSupport} from 'vs/editor/common/modes/supports/onEnter';
import {RichEditSupport} from 'vs/editor/common/modes/supports/richEditSupport';
function testShiftCommand(lines: string[], selection: Selection, expectedLines: string[], expectedSelection: Selection): void { function testShiftCommand(lines: string[], selection: Selection, expectedLines: string[], expectedSelection: Selection): void {
TU.testCommand(lines, null, selection, (sel) => new ShiftCommand(sel, { TU.testCommand(lines, null, selection, (sel) => new ShiftCommand(sel, {
...@@ -32,16 +33,17 @@ function testUnshiftCommand(lines: string[], selection: Selection, expectedLines ...@@ -32,16 +33,17 @@ function testUnshiftCommand(lines: string[], selection: Selection, expectedLines
class DocBlockCommentMode implements Modes.IMode { class DocBlockCommentMode implements Modes.IMode {
public onEnterSupport: Modes.IOnEnterSupport; public richEditSupport: Modes.IRichEditSupport;
constructor() { constructor() {
this.onEnterSupport = new OnEnterSupport(this.getId(), { this.richEditSupport = new RichEditSupport(this.getId(), {
brackets: [ brackets: [
{ open: '(', close: ')' }, ['(', ')'],
{ open: '{', close: '}' }, ['{', '}'],
{ open: '[', close: ']' } ['[', ']']
], ],
regExpRules: [
onEnterRules: [
{ {
// e.g. /** | */ // e.g. /** | */
beforeText: /^\s*\/\*\*(?!\/)([^\*]|\*(?!\/))*$/, beforeText: /^\s*\/\*\*(?!\/)([^\*]|\*(?!\/))*$/,
......
...@@ -15,7 +15,7 @@ import {Handler, EventType, IPosition, ISelection, EndOfLinePreference} from 'vs ...@@ -15,7 +15,7 @@ import {Handler, EventType, IPosition, ISelection, EndOfLinePreference} from 'vs
import {MockConfiguration} from 'vs/editor/test/common/mocks/mockConfiguration'; import {MockConfiguration} from 'vs/editor/test/common/mocks/mockConfiguration';
import {EditOperation} from 'vs/editor/common/core/editOperation'; import {EditOperation} from 'vs/editor/common/core/editOperation';
import {AbstractState} from 'vs/editor/common/modes/abstractState'; import {AbstractState} from 'vs/editor/common/modes/abstractState';
import {CharacterPairSupport} from 'vs/editor/common/modes/supports'; import {RichEditSupport} from 'vs/editor/common/modes/supports/richEditSupport';
let H = Handler; let H = Handler;
...@@ -768,28 +768,32 @@ class TestMode { ...@@ -768,28 +768,32 @@ class TestMode {
} }
class SurroundingMode extends TestMode { class SurroundingMode extends TestMode {
public characterPairSupport: Modes.ICharacterPairSupport; public richEditSupport: Modes.IRichEditSupport;
constructor() { constructor() {
super(); super();
this.characterPairSupport = new CharacterPairSupport(this, { this.richEditSupport = new RichEditSupport(this.getId(), {
autoClosingPairs: [{ open: '(', close: ')' }] __characterPairSupport: {
autoClosingPairs: [{ open: '(', close: ')' }]
}
}); });
} }
} }
class OnEnterMode extends TestMode { class OnEnterMode extends TestMode {
public electricCharacterSupport: Modes.IElectricCharacterSupport; public richEditSupport: Modes.IRichEditSupport;
constructor(indentAction: Modes.IndentAction) { constructor(indentAction: Modes.IndentAction) {
super(); super();
this.electricCharacterSupport = { this.richEditSupport = {
getElectricCharacters: ():string[] => null, electricCharacter: {
onElectricCharacter: (context:Modes.ILineContext, offset:number): Modes.IElectricAction => null, getElectricCharacters: ():string[] => null,
onEnter: (context:Modes.ILineContext, offset:number): Modes.IEnterAction => { onElectricCharacter: (context:Modes.ILineContext, offset:number): Modes.IElectricAction => null,
return { onEnter: (context:Modes.ILineContext, offset:number): Modes.IEnterAction => {
indentAction: indentAction return {
}; indentAction: indentAction
};
}
} }
}; };
} }
......
...@@ -4,47 +4,45 @@ ...@@ -4,47 +4,45 @@
*--------------------------------------------------------------------------------------------*/ *--------------------------------------------------------------------------------------------*/
'use strict'; 'use strict';
import modes = require('vs/editor/common/modes'); import Modes = require('vs/editor/common/modes');
import {Arrays} from 'vs/editor/common/core/arrays'; import {Arrays} from 'vs/editor/common/core/arrays';
import {RichEditSupport} from 'vs/editor/common/modes/supports/richEditSupport';
class SimpleTokenTypeClassificationMode implements modes.IMode { class SimpleTokenTypeClassificationMode implements Modes.IMode {
private _id:string; private _id:string;
public tokenTypeClassificationSupport: modes.ITokenTypeClassificationSupport;
constructor(id:string, tokenTypeClassificationSupport: modes.ITokenTypeClassificationSupport) { public richEditSupport: Modes.IRichEditSupport;
constructor(id:string, wordRegExp:RegExp) {
this._id = id; this._id = id;
this.tokenTypeClassificationSupport = tokenTypeClassificationSupport; this.richEditSupport = new RichEditSupport(this._id, {
wordPattern: wordRegExp
});
} }
public getId(): string { public getId(): string {
return this._id; return this._id;
} }
public toSimplifiedMode(): modes.IMode { public toSimplifiedMode(): Modes.IMode {
return this; return this;
} }
} }
export function createMockMode(id:string, wordRegExp:RegExp = null):modes.IMode { export function createMockMode(id:string, wordRegExp:RegExp = null):Modes.IMode {
var tokenTypeClassificationSupport: modes.ITokenTypeClassificationSupport; return new SimpleTokenTypeClassificationMode(id, wordRegExp);
if (wordRegExp) {
tokenTypeClassificationSupport = {
getWordDefinition: () => wordRegExp
};
}
return new SimpleTokenTypeClassificationMode(id, tokenTypeClassificationSupport);
} }
export interface TokenText { export interface TokenText {
text: string; text: string;
type: string; type: string;
bracket?: modes.Bracket; bracket?: Modes.Bracket;
} }
export function createLineContextFromTokenText(tokens: TokenText[]): modes.ILineContext { export function createLineContextFromTokenText(tokens: TokenText[]): Modes.ILineContext {
var line = ''; var line = '';
var processedTokens: modes.IToken[] = []; var processedTokens: Modes.IToken[] = [];
var indexSoFar = 0; var indexSoFar = 0;
for (var i = 0; i < tokens.length; ++i){ for (var i = 0; i < tokens.length; ++i){
...@@ -56,17 +54,17 @@ export function createLineContextFromTokenText(tokens: TokenText[]): modes.ILine ...@@ -56,17 +54,17 @@ export function createLineContextFromTokenText(tokens: TokenText[]): modes.ILine
return new TestLineContext(line, processedTokens, null); return new TestLineContext(line, processedTokens, null);
} }
export function createLineContext(line:string, tokens:modes.ILineTokens): modes.ILineContext { export function createLineContext(line:string, tokens:Modes.ILineTokens): Modes.ILineContext {
return new TestLineContext(line, tokens.tokens, tokens.modeTransitions); return new TestLineContext(line, tokens.tokens, tokens.modeTransitions);
} }
class TestLineContext implements modes.ILineContext { class TestLineContext implements Modes.ILineContext {
public modeTransitions: modes.IModeTransition[]; public modeTransitions: Modes.IModeTransition[];
private _line:string; private _line:string;
private _tokens: modes.IToken[]; private _tokens: Modes.IToken[];
constructor(line:string, tokens: modes.IToken[], modeTransitions:modes.IModeTransition[]) { constructor(line:string, tokens: Modes.IToken[], modeTransitions:Modes.IModeTransition[]) {
this.modeTransitions = modeTransitions; this.modeTransitions = modeTransitions;
this._line = line; this._line = line;
this._tokens = tokens; this._tokens = tokens;
......
...@@ -38,7 +38,7 @@ export function createOnElectricCharacter(mode:modes.IMode): IOnElectricCharacte ...@@ -38,7 +38,7 @@ export function createOnElectricCharacter(mode:modes.IMode): IOnElectricCharacte
return function onElectricCharacter(line:string, offset:number, state?:modes.IState): modes.IElectricAction { return function onElectricCharacter(line:string, offset:number, state?:modes.IState): modes.IElectricAction {
state = state || mode.tokenizationSupport.getInitialState(); state = state || mode.tokenizationSupport.getInitialState();
var lineTokens = mode.tokenizationSupport.tokenize(line, state); var lineTokens = mode.tokenizationSupport.tokenize(line, state);
return mode.electricCharacterSupport.onElectricCharacter(createLineContext(line, lineTokens), offset); return mode.richEditSupport.electricCharacter.onElectricCharacter(createLineContext(line, lineTokens), offset);
}; };
} }
...@@ -50,7 +50,7 @@ export function createOnEnter(mode:modes.IMode): IOnEnterFunc { ...@@ -50,7 +50,7 @@ export function createOnEnter(mode:modes.IMode): IOnEnterFunc {
return function onEnter(line:string, offset:number, state?:modes.IState): modes.IEnterAction { return function onEnter(line:string, offset:number, state?:modes.IState): modes.IEnterAction {
state = state || mode.tokenizationSupport.getInitialState(); state = state || mode.tokenizationSupport.getInitialState();
var lineTokens = mode.tokenizationSupport.tokenize(line, state); var lineTokens = mode.tokenizationSupport.tokenize(line, state);
return mode.electricCharacterSupport.onEnter(createLineContext(line, lineTokens), offset); return mode.richEditSupport.electricCharacter.onEnter(createLineContext(line, lineTokens), offset);
}; };
} }
...@@ -103,13 +103,13 @@ class SimpleMode implements modes.IMode { ...@@ -103,13 +103,13 @@ class SimpleMode implements modes.IMode {
} }
} }
export function createOnEnterAsserter(modeId:string, onEnterSupport: modes.IOnEnterSupport): IOnEnterAsserter { export function createOnEnterAsserter(modeId:string, richEditSupport: modes.IRichEditSupport): IOnEnterAsserter {
var assertOne = (oneLineAboveText:string, beforeText:string, afterText:string, expected: modes.IndentAction) => { var assertOne = (oneLineAboveText:string, beforeText:string, afterText:string, expected: modes.IndentAction) => {
var model = new Model( var model = new Model(
[ oneLineAboveText, beforeText + afterText ].join('\n'), [ oneLineAboveText, beforeText + afterText ].join('\n'),
new SimpleMode(modeId) new SimpleMode(modeId)
); );
var actual = onEnterSupport.onEnter(model, { lineNumber: 2, column: beforeText.length + 1 }); var actual = richEditSupport.onEnter.onEnter(model, { lineNumber: 2, column: beforeText.length + 1 });
if (expected === modes.IndentAction.None) { if (expected === modes.IndentAction.None) {
assert.equal(actual, null, oneLineAboveText + '\\n' + beforeText + '|' + afterText); assert.equal(actual, null, oneLineAboveText + '\\n' + beforeText + '|' + afterText);
} else { } else {
......
...@@ -9,6 +9,7 @@ import supports = require('vs/editor/common/modes/supports'); ...@@ -9,6 +9,7 @@ import supports = require('vs/editor/common/modes/supports');
import {AbstractMode} from 'vs/editor/common/modes/abstractMode'; import {AbstractMode} from 'vs/editor/common/modes/abstractMode';
import {AbstractState} from 'vs/editor/common/modes/abstractState'; import {AbstractState} from 'vs/editor/common/modes/abstractState';
import {AbstractModeWorker} from 'vs/editor/common/modes/abstractModeWorker'; import {AbstractModeWorker} from 'vs/editor/common/modes/abstractModeWorker';
import {RichEditSupport} from 'vs/editor/common/modes/supports/richEditSupport';
export class CommentState extends AbstractState { export class CommentState extends AbstractState {
...@@ -32,21 +33,21 @@ export class CommentState extends AbstractState { ...@@ -32,21 +33,21 @@ export class CommentState extends AbstractState {
export class CommentMode extends AbstractMode<AbstractModeWorker> { export class CommentMode extends AbstractMode<AbstractModeWorker> {
private commentsConfig:modes.ICommentsConfiguration;
public tokenizationSupport: modes.ITokenizationSupport; public tokenizationSupport: modes.ITokenizationSupport;
public richEditSupport: modes.IRichEditSupport;
constructor(commentsConfig:modes.ICommentsConfiguration) { constructor(commentsConfig:modes.ICommentsConfiguration) {
super({ id: 'tests.commentMode', workerParticipants: [] }, null, null); super({ id: 'tests.commentMode', workerParticipants: [] }, null, null);
this.commentsConfig = commentsConfig;
this.tokenizationSupport = new supports.TokenizationSupport(this, { this.tokenizationSupport = new supports.TokenizationSupport(this, {
getInitialState: () => new CommentState(this, 0) getInitialState: () => new CommentState(this, 0)
}, false, false); }, false, false);
}
public getCommentsConfiguration():modes.ICommentsConfiguration { this.richEditSupport = {
return this.commentsConfig; comments: {
getCommentsConfiguration: () => commentsConfig
}
};
} }
} }
......
...@@ -20,6 +20,7 @@ import {IMarker} from 'vs/platform/markers/common/markers'; ...@@ -20,6 +20,7 @@ import {IMarker} from 'vs/platform/markers/common/markers';
import {OnEnterSupport} from 'vs/editor/common/modes/supports/onEnter'; import {OnEnterSupport} from 'vs/editor/common/modes/supports/onEnter';
import {IInstantiationService} from 'vs/platform/instantiation/common/instantiation'; import {IInstantiationService} from 'vs/platform/instantiation/common/instantiation';
import {IThreadService} from 'vs/platform/thread/common/thread'; import {IThreadService} from 'vs/platform/thread/common/thread';
import {RichEditSupport} from 'vs/editor/common/modes/supports/richEditSupport';
export enum States { export enum States {
Selector, Selector,
...@@ -279,8 +280,7 @@ export class State extends AbstractState { ...@@ -279,8 +280,7 @@ export class State extends AbstractState {
export class CSSMode extends AbstractMode<cssWorker.CSSWorker> { export class CSSMode extends AbstractMode<cssWorker.CSSWorker> {
public tokenizationSupport: Modes.ITokenizationSupport; public tokenizationSupport: Modes.ITokenizationSupport;
public electricCharacterSupport: Modes.IElectricCharacterSupport; public richEditSupport: Modes.IRichEditSupport;
public characterPairSupport: Modes.ICharacterPairSupport;
public referenceSupport: Modes.IReferenceSupport; public referenceSupport: Modes.IReferenceSupport;
public logicalSelectionSupport: Modes.ILogicalSelectionSupport; public logicalSelectionSupport: Modes.ILogicalSelectionSupport;
...@@ -290,7 +290,6 @@ export class CSSMode extends AbstractMode<cssWorker.CSSWorker> { ...@@ -290,7 +290,6 @@ export class CSSMode extends AbstractMode<cssWorker.CSSWorker> {
public declarationSupport: Modes.IDeclarationSupport; public declarationSupport: Modes.IDeclarationSupport;
public suggestSupport: Modes.ISuggestSupport; public suggestSupport: Modes.ISuggestSupport;
public quickFixSupport: Modes.IQuickFixSupport; public quickFixSupport: Modes.IQuickFixSupport;
public onEnterSupport: Modes.IOnEnterSupport;
constructor( constructor(
descriptor:Modes.IModeDescriptor, descriptor:Modes.IModeDescriptor,
...@@ -302,9 +301,37 @@ export class CSSMode extends AbstractMode<cssWorker.CSSWorker> { ...@@ -302,9 +301,37 @@ export class CSSMode extends AbstractMode<cssWorker.CSSWorker> {
this.tokenizationSupport = new supports.TokenizationSupport(this, { this.tokenizationSupport = new supports.TokenizationSupport(this, {
getInitialState: () => new State(this, States.Selector, false, null, false, 0) getInitialState: () => new State(this, States.Selector, false, null, false, 0)
}, false, false); }, false, false);
this.electricCharacterSupport = new supports.BracketElectricCharacterSupport(this, { brackets: [
{ tokenType: 'punctuation.bracket.css', open: '{', close: '}', isElectric: true } this.richEditSupport = new RichEditSupport(this.getId(), {
] }); // TODO@Martin: This definition does not work with umlauts for example
wordPattern: /(#?-?\d*\.\d\w*%?)|((::|[@#.!:])?[\w-?]+%?)|::|[@#.!:]/g,
comments: {
blockComment: ['/*', '*/']
},
brackets: [
['{', '}'],
['[', ']'],
['(', ')']
],
__electricCharacterSupport: {
brackets: [
{ tokenType: 'punctuation.bracket.css', open: '{', close: '}', isElectric: true }
]
},
__characterPairSupport: {
autoClosingPairs: [
{ open: '{', close: '}' },
{ open: '[', close: ']' },
{ open: '(', close: ')' },
{ open: '"', close: '"', notIn: ['string'] },
{ open: '\'', close: '\'', notIn: ['string'] }
]
}
});
this.occurrencesSupport = this; this.occurrencesSupport = this;
this.extraInfoSupport = this; this.extraInfoSupport = this;
...@@ -317,27 +344,11 @@ export class CSSMode extends AbstractMode<cssWorker.CSSWorker> { ...@@ -317,27 +344,11 @@ export class CSSMode extends AbstractMode<cssWorker.CSSWorker> {
tokens: [cssTokenTypes.TOKEN_VALUE + '.css'], tokens: [cssTokenTypes.TOKEN_VALUE + '.css'],
findDeclaration: (resource, position) => this.findDeclaration(resource, position)}); findDeclaration: (resource, position) => this.findDeclaration(resource, position)});
this.characterPairSupport = new supports.CharacterPairSupport(this, {
autoClosingPairs:
[ { open: '{', close: '}' },
{ open: '[', close: ']' },
{ open: '(', close: ')' },
{ open: '"', close: '"', notIn: ['string'] },
{ open: '\'', close: '\'', notIn: ['string'] }
]});
this.suggestSupport = new supports.SuggestSupport(this, { this.suggestSupport = new supports.SuggestSupport(this, {
triggerCharacters: [' ', ':'], triggerCharacters: [' ', ':'],
excludeTokens: ['comment.css', 'string.css'], excludeTokens: ['comment.css', 'string.css'],
suggest: (resource, position) => this.suggest(resource, position)}); suggest: (resource, position) => this.suggest(resource, position)});
this.onEnterSupport = new OnEnterSupport(this.getId(), {
brackets: [
{ open: '(', close: ')' },
{ open: '{', close: '}' },
{ open: '[', close: ']' }
]
});
this.quickFixSupport = this; this.quickFixSupport = this;
} }
...@@ -376,15 +387,6 @@ export class CSSMode extends AbstractMode<cssWorker.CSSWorker> { ...@@ -376,15 +387,6 @@ export class CSSMode extends AbstractMode<cssWorker.CSSWorker> {
return this._worker((w) => w.getOutline(resource)); return this._worker((w) => w.getOutline(resource));
} }
public getCommentsConfiguration():Modes.ICommentsConfiguration {
return { blockCommentStartToken: '/*', blockCommentEndToken: '*/' };
}
// TODO@Martin: This definition does not work with umlauts for example
public getWordDefinition():RegExp {
return /(#?-?\d*\.\d\w*%?)|((::|[@#.!:])?[\w-?]+%?)|::|[@#.!:]/g;
}
static $findColorDeclarations = OneWorkerAttr(CSSMode, CSSMode.prototype.findColorDeclarations); static $findColorDeclarations = OneWorkerAttr(CSSMode, CSSMode.prototype.findColorDeclarations);
public findColorDeclarations(resource:URI):WinJS.TPromise<{range:EditorCommon.IRange; value:string; }[]> { public findColorDeclarations(resource:URI):WinJS.TPromise<{range:EditorCommon.IRange; value:string; }[]> {
return this._worker((w) => w.findColorDeclarations(resource)); return this._worker((w) => w.findColorDeclarations(resource));
......
...@@ -21,8 +21,8 @@ suite('CSS Colorizing', () => { ...@@ -21,8 +21,8 @@ suite('CSS Colorizing', () => {
suiteSetup((done) => { suiteSetup((done) => {
modesUtil.load('css').then(mode => { modesUtil.load('css').then(mode => {
tokenizationSupport = mode.tokenizationSupport; tokenizationSupport = mode.tokenizationSupport;
assertOnEnter = modesUtil.createOnEnterAsserter(mode.getId(), mode.onEnterSupport); assertOnEnter = modesUtil.createOnEnterAsserter(mode.getId(), mode.richEditSupport);
wordDefinition = mode.tokenTypeClassificationSupport.getWordDefinition(); wordDefinition = mode.richEditSupport.tokenTypeClassification.getWordDefinition();
done(); done();
}); });
}); });
......
...@@ -14,6 +14,8 @@ import htmlWorker = require('vs/languages/html/common/htmlWorker'); ...@@ -14,6 +14,8 @@ import htmlWorker = require('vs/languages/html/common/htmlWorker');
import {IInstantiationService} from 'vs/platform/instantiation/common/instantiation'; import {IInstantiationService} from 'vs/platform/instantiation/common/instantiation';
import {IThreadService} from 'vs/platform/thread/common/thread'; import {IThreadService} from 'vs/platform/thread/common/thread';
import {IModeService} from 'vs/editor/common/services/modeService'; import {IModeService} from 'vs/editor/common/services/modeService';
import {RichEditSupport} from 'vs/editor/common/modes/supports/richEditSupport';
import {createWordRegExp} from 'vs/editor/common/modes/abstractMode';
export enum States { export enum States {
HTML, HTML,
...@@ -115,29 +117,44 @@ export class HandlebarsMode extends htmlMode.HTMLMode<htmlWorker.HTMLWorker> { ...@@ -115,29 +117,44 @@ export class HandlebarsMode extends htmlMode.HTMLMode<htmlWorker.HTMLWorker> {
super(descriptor, instantiationService, threadService, modeService); super(descriptor, instantiationService, threadService, modeService);
this.formattingSupport = null; this.formattingSupport = null;
this.onEnterSupport = new OnEnterSupport(this.getId(), {
brackets: [
{ open: '<!--', close: '-->' },
{ open: '{{', close: '}}' },
]
});
} }
public asyncCtor(): winjs.Promise { protected _createRichEditSupport(embeddedAutoClosingPairs: Modes.IAutoClosingPair[]): Modes.IRichEditSupport {
return super.asyncCtor().then(() => { return new RichEditSupport(this.getId(), {
var pairs = this.characterPairSupport.getAutoClosingPairs().slice(0).concat([
{ open: '{', close: '}'}
]);
this.characterPairSupport = new supports.CharacterPairSupport(this, { wordPattern: createWordRegExp('#-?%'),
autoClosingPairs: pairs.slice(0),
comments: {
blockComment: ['<!--', '-->']
},
brackets: [
['<!--', '-->'],
['{{', '}}']
],
__electricCharacterSupport: {
brackets: [],
regexBrackets: [{
tokenType: htmlMode.htmlTokenTypes.getTag('$1'),
open: new RegExp(`<(?!(?:${htmlMode.EMPTY_ELEMENTS.join("|")}))(\\w[\\w\\d]*)([^/>]*(?!/)>)[^<]*$`, 'i'),
closeComplete: '</$1>',
close: /<\/(\w[\w\d]*)\s*>$/i
}],
caseInsensitive: true,
embeddedElectricCharacters: ['*', '}', ']', ')']
},
__characterPairSupport: {
autoClosingPairs: embeddedAutoClosingPairs.slice(0).concat([
{ open: '{', close: '}'}
]),
surroundingPairs: [ surroundingPairs: [
{ open: '<', close: '>' }, { open: '<', close: '>' },
{ open: '"', close: '"' }, { open: '"', close: '"' },
{ open: '\'', close: '\'' } { open: '\'', close: '\'' }
] ]
}); }
}); });
} }
......
...@@ -25,8 +25,10 @@ import {IInstantiationService} from 'vs/platform/instantiation/common/instantiat ...@@ -25,8 +25,10 @@ import {IInstantiationService} from 'vs/platform/instantiation/common/instantiat
import {IThreadService } from 'vs/platform/thread/common/thread'; import {IThreadService } from 'vs/platform/thread/common/thread';
import * as htmlTokenTypes from 'vs/languages/html/common/htmlTokenTypes'; import * as htmlTokenTypes from 'vs/languages/html/common/htmlTokenTypes';
import {EMPTY_ELEMENTS} from 'vs/languages/html/common/htmlEmptyTagsShared'; import {EMPTY_ELEMENTS} from 'vs/languages/html/common/htmlEmptyTagsShared';
import {RichEditSupport} from 'vs/editor/common/modes/supports/richEditSupport';
export { htmlTokenTypes }; // export to be used by Razor. We are the main module, so Razor should get ot from use. export { htmlTokenTypes }; // export to be used by Razor. We are the main module, so Razor should get ot from use.
export { EMPTY_ELEMENTS }; // export to be used by Razor. We are the main module, so Razor should get ot from use.
export enum States { export enum States {
Content, Content,
...@@ -273,8 +275,7 @@ export class State extends AbstractState { ...@@ -273,8 +275,7 @@ export class State extends AbstractState {
export class HTMLMode<W extends htmlWorker.HTMLWorker> extends AbstractMode<W> implements supports.ITokenizationCustomization { export class HTMLMode<W extends htmlWorker.HTMLWorker> extends AbstractMode<W> implements supports.ITokenizationCustomization {
public tokenizationSupport: Modes.ITokenizationSupport; public tokenizationSupport: Modes.ITokenizationSupport;
public electricCharacterSupport: Modes.IElectricCharacterSupport; public richEditSupport: Modes.IRichEditSupport;
public characterPairSupport: Modes.ICharacterPairSupport;
public extraInfoSupport:Modes.IExtraInfoSupport; public extraInfoSupport:Modes.IExtraInfoSupport;
public occurrencesSupport:Modes.IOccurrencesSupport; public occurrencesSupport:Modes.IOccurrencesSupport;
...@@ -283,7 +284,6 @@ export class HTMLMode<W extends htmlWorker.HTMLWorker> extends AbstractMode<W> i ...@@ -283,7 +284,6 @@ export class HTMLMode<W extends htmlWorker.HTMLWorker> extends AbstractMode<W> i
public formattingSupport: Modes.IFormattingSupport; public formattingSupport: Modes.IFormattingSupport;
public parameterHintsSupport: Modes.IParameterHintsSupport; public parameterHintsSupport: Modes.IParameterHintsSupport;
public suggestSupport: Modes.ISuggestSupport; public suggestSupport: Modes.ISuggestSupport;
public onEnterSupport: Modes.IOnEnterSupport;
private modeService:IModeService; private modeService:IModeService;
...@@ -298,17 +298,6 @@ export class HTMLMode<W extends htmlWorker.HTMLWorker> extends AbstractMode<W> i ...@@ -298,17 +298,6 @@ export class HTMLMode<W extends htmlWorker.HTMLWorker> extends AbstractMode<W> i
this.modeService = modeService; this.modeService = modeService;
this.tokenizationSupport = new supports.TokenizationSupport(this, this, true, true); this.tokenizationSupport = new supports.TokenizationSupport(this, this, true, true);
this.electricCharacterSupport = new supports.BracketElectricCharacterSupport(this,
{
brackets: [],
regexBrackets:[
{ tokenType: htmlTokenTypes.getTag('$1'),
open: new RegExp(`<(?!(?:${EMPTY_ELEMENTS.join("|")}))(\\w[\\w\\d]*)([^/>]*(?!/)>)[^<]*$`, 'i'),
closeComplete: '</$1>',
close: /<\/(\w[\w\d]*)\s*>$/i }],
caseInsensitive:true,
embeddedElectricCharacters: ['*', '}', ']', ')']
});
this.formattingSupport = this; this.formattingSupport = this;
this.extraInfoSupport = this; this.extraInfoSupport = this;
...@@ -331,12 +320,6 @@ export class HTMLMode<W extends htmlWorker.HTMLWorker> extends AbstractMode<W> i ...@@ -331,12 +320,6 @@ export class HTMLMode<W extends htmlWorker.HTMLWorker> extends AbstractMode<W> i
triggerCharacters: ['.', ':', '<', '"', '=', '/'], triggerCharacters: ['.', ':', '<', '"', '=', '/'],
excludeTokens: ['comment'], excludeTokens: ['comment'],
suggest: (resource, position) => this.suggest(resource, position)}); suggest: (resource, position) => this.suggest(resource, position)});
this.onEnterSupport = new OnEnterSupport(this.getId(), {
brackets: [
{ open: '<!--', close: '-->' }
]
});
} }
public asyncCtor(): winjs.Promise { public asyncCtor(): winjs.Promise {
...@@ -345,13 +328,42 @@ export class HTMLMode<W extends htmlWorker.HTMLWorker> extends AbstractMode<W> i ...@@ -345,13 +328,42 @@ export class HTMLMode<W extends htmlWorker.HTMLWorker> extends AbstractMode<W> i
this.modeService.getOrCreateMode('text/css') this.modeService.getOrCreateMode('text/css')
]).then((embeddableModes) => { ]).then((embeddableModes) => {
var autoClosingPairs = this._getAutoClosingPairs(embeddableModes); var autoClosingPairs = this._getAutoClosingPairs(embeddableModes);
this.richEditSupport = this._createRichEditSupport(autoClosingPairs);
});
}
protected _createRichEditSupport(embeddedAutoClosingPairs: Modes.IAutoClosingPair[]): Modes.IRichEditSupport {
return new RichEditSupport(this.getId(), {
this.characterPairSupport = new supports.CharacterPairSupport(this, { wordPattern: createWordRegExp('#-?%'),
autoClosingPairs: autoClosingPairs.slice(0),
comments: {
blockComment: ['<!--', '-->']
},
brackets: [
['<!--', '-->']
],
__electricCharacterSupport: {
brackets: [],
regexBrackets: [{
tokenType: htmlTokenTypes.getTag('$1'),
open: new RegExp(`<(?!(?:${EMPTY_ELEMENTS.join("|")}))(\\w[\\w\\d]*)([^/>]*(?!/)>)[^<]*$`, 'i'),
closeComplete: '</$1>',
close: /<\/(\w[\w\d]*)\s*>$/i
}],
caseInsensitive: true,
embeddedElectricCharacters: ['*', '}', ']', ')']
},
__characterPairSupport: {
autoClosingPairs: embeddedAutoClosingPairs.slice(0),
surroundingPairs: [ surroundingPairs: [
{ open: '"', close: '"' }, { open: '"', close: '"' },
{ open: '\'', close: '\'' } { open: '\'', close: '\'' }
]}); ]
}
}); });
} }
...@@ -377,12 +389,13 @@ export class HTMLMode<W extends htmlWorker.HTMLWorker> extends AbstractMode<W> i ...@@ -377,12 +389,13 @@ export class HTMLMode<W extends htmlWorker.HTMLWorker> extends AbstractMode<W> i
} }
private _collectAutoClosingPairs(result:{[key:string]:string;}, mode:Modes.IMode): void { private _collectAutoClosingPairs(result:{[key:string]:string;}, mode:Modes.IMode): void {
if (mode && mode.characterPairSupport) { if (!mode || !mode.richEditSupport || !mode.richEditSupport.characterPair) {
var acp = mode.characterPairSupport.getAutoClosingPairs(); return;
if (acp !== null) { }
for(var i = 0; i < acp.length; i++) { var acp = mode.richEditSupport.characterPair.getAutoClosingPairs();
result[acp[i].open] = acp[i].close; if (acp !== null) {
} for(var i = 0; i < acp.length; i++) {
result[acp[i].open] = acp[i].close;
} }
} }
} }
...@@ -443,15 +456,6 @@ export class HTMLMode<W extends htmlWorker.HTMLWorker> extends AbstractMode<W> i ...@@ -443,15 +456,6 @@ export class HTMLMode<W extends htmlWorker.HTMLWorker> extends AbstractMode<W> i
return null; return null;
} }
public static WORD_DEFINITION = createWordRegExp('#-?%');
public getWordDefinition():RegExp {
return HTMLMode.WORD_DEFINITION;
}
public getCommentsConfiguration():Modes.ICommentsConfiguration {
return { blockCommentStartToken: '<!--', blockCommentEndToken: '-->' };
}
protected _getWorkerDescriptor(): AsyncDescriptor2<Modes.IMode, Modes.IWorkerParticipant[], htmlWorker.HTMLWorker> { protected _getWorkerDescriptor(): AsyncDescriptor2<Modes.IMode, Modes.IWorkerParticipant[], htmlWorker.HTMLWorker> {
return createAsyncDescriptor2('vs/languages/html/common/htmlWorker', 'HTMLWorker'); return createAsyncDescriptor2('vs/languages/html/common/htmlWorker', 'HTMLWorker');
} }
......
...@@ -609,7 +609,7 @@ suite('Colorizing - HTML', () => { ...@@ -609,7 +609,7 @@ suite('Colorizing - HTML', () => {
test('onEnter', function() { test('onEnter', function() {
var model = new Model('<script type=\"text/javascript\">function f() { foo(); }', _mode); var model = new Model('<script type=\"text/javascript\">function f() { foo(); }', _mode);
var actual = _mode.onEnterSupport.onEnter(model, { var actual = _mode.richEditSupport.onEnter.onEnter(model, {
lineNumber: 1, lineNumber: 1,
column: 46 column: 46
}); });
......
...@@ -19,6 +19,7 @@ import {OnEnterSupport} from 'vs/editor/common/modes/supports/onEnter'; ...@@ -19,6 +19,7 @@ import {OnEnterSupport} from 'vs/editor/common/modes/supports/onEnter';
import {IThreadService} from 'vs/platform/thread/common/thread'; import {IThreadService} from 'vs/platform/thread/common/thread';
import {IInstantiationService} from 'vs/platform/instantiation/common/instantiation'; import {IInstantiationService} from 'vs/platform/instantiation/common/instantiation';
import {ITelemetryService} from 'vs/platform/telemetry/common/telemetry'; import {ITelemetryService} from 'vs/platform/telemetry/common/telemetry';
import {RichEditSupport} from 'vs/editor/common/modes/supports/richEditSupport';
export class JSMode extends typescriptMode.TypeScriptMode<javascriptWorker.JavaScriptWorker> { export class JSMode extends typescriptMode.TypeScriptMode<javascriptWorker.JavaScriptWorker> {
...@@ -29,7 +30,6 @@ export class JSMode extends typescriptMode.TypeScriptMode<javascriptWorker.JavaS ...@@ -29,7 +30,6 @@ export class JSMode extends typescriptMode.TypeScriptMode<javascriptWorker.JavaS
public logicalSelectionSupport: Modes.ILogicalSelectionSupport; public logicalSelectionSupport: Modes.ILogicalSelectionSupport;
public typeDeclarationSupport: Modes.ITypeDeclarationSupport; public typeDeclarationSupport: Modes.ITypeDeclarationSupport;
public suggestSupport: Modes.ISuggestSupport; public suggestSupport: Modes.ISuggestSupport;
public onEnterSupport: Modes.IOnEnterSupport;
constructor( constructor(
descriptor:Modes.IModeDescriptor, descriptor:Modes.IModeDescriptor,
...@@ -53,31 +53,21 @@ export class JSMode extends typescriptMode.TypeScriptMode<javascriptWorker.JavaS ...@@ -53,31 +53,21 @@ export class JSMode extends typescriptMode.TypeScriptMode<javascriptWorker.JavaS
excludeTokens: ['string.js', 'string.escape.js'], excludeTokens: ['string.js', 'string.escape.js'],
getParameterHints: (resource, position) => this.getParameterHints(resource, position)}); getParameterHints: (resource, position) => this.getParameterHints(resource, position)});
this.electricCharacterSupport = new supports.BracketElectricCharacterSupport(this, this.richEditSupport = new RichEditSupport(this.getId(), {
{ wordPattern: createWordRegExp('$'),
brackets: [
{ tokenType: 'delimiter.bracket.js', open: '{', close: '}', isElectric: true },
{ tokenType: 'delimiter.array.js', open: '[', close: ']', isElectric: true },
{ tokenType: 'delimiter.parenthesis.js', open: '(', close: ')', isElectric: true } ],
docComment: { scope: 'comment.doc', open: '/**', lineStart: ' * ', close: ' */' }
});
this.characterPairSupport = new supports.CharacterPairSupport(this, { comments: {
autoClosingPairs: lineComment: '//',
[ { open: '{', close: '}' }, blockComment: ['/*', '*/']
{ open: '[', close: ']' }, },
{ open: '(', close: ')' },
{ open: '"', close: '"', notIn: ['string'] },
{ open: '\'', close: '\'', notIn: ['string', 'comment'] }
]});
this.onEnterSupport = new OnEnterSupport(this.getId(), {
brackets: [ brackets: [
{ open: '(', close: ')' }, ['{', '}'],
{ open: '{', close: '}' }, ['[', ']'],
{ open: '[', close: ']' } ['(', ')']
], ],
regExpRules: [
onEnterRules: [
{ {
// e.g. /** | */ // e.g. /** | */
beforeText: /^\s*\/\*\*(?!\/)([^\*]|\*(?!\/))*$/, beforeText: /^\s*\/\*\*(?!\/)([^\*]|\*(?!\/))*$/,
...@@ -99,7 +89,26 @@ export class JSMode extends typescriptMode.TypeScriptMode<javascriptWorker.JavaS ...@@ -99,7 +89,26 @@ export class JSMode extends typescriptMode.TypeScriptMode<javascriptWorker.JavaS
beforeText: /^(\t|(\ \ ))*\ \*\/\s*$/, beforeText: /^(\t|(\ \ ))*\ \*\/\s*$/,
action: { indentAction: Modes.IndentAction.None, removeText: 1 } action: { indentAction: Modes.IndentAction.None, removeText: 1 }
} }
] ],
__electricCharacterSupport: {
brackets: [
{ tokenType: 'delimiter.bracket.js', open: '{', close: '}', isElectric: true },
{ tokenType: 'delimiter.array.js', open: '[', close: ']', isElectric: true },
{ tokenType: 'delimiter.parenthesis.js', open: '(', close: ')', isElectric: true }
],
docComment: { scope: 'comment.doc', open: '/**', lineStart: ' * ', close: ' */' }
},
__characterPairSupport: {
autoClosingPairs: [
{ open: '{', close: '}' },
{ open: '[', close: ']' },
{ open: '(', close: ')' },
{ open: '"', close: '"', notIn: ['string'] },
{ open: '\'', close: '\'', notIn: ['string', 'comment'] }
]
}
}); });
this.suggestSupport = new supports.SuggestSupport(this, { this.suggestSupport = new supports.SuggestSupport(this, {
...@@ -136,15 +145,6 @@ export class JSMode extends typescriptMode.TypeScriptMode<javascriptWorker.JavaS ...@@ -136,15 +145,6 @@ export class JSMode extends typescriptMode.TypeScriptMode<javascriptWorker.JavaS
return createAsyncDescriptor2('vs/languages/javascript/common/javascriptWorker', 'JavaScriptWorker'); return createAsyncDescriptor2('vs/languages/javascript/common/javascriptWorker', 'JavaScriptWorker');
} }
public getCommentsConfiguration(): Modes.ICommentsConfiguration {
return { lineCommentTokens: ['//'], blockCommentStartToken: '/*', blockCommentEndToken: '*/' };
}
private static JS_WORD_DEFINITION = createWordRegExp('$');
public getWordDefinition(): RegExp {
return JSMode.JS_WORD_DEFINITION;
}
public get filter() { public get filter() {
return void 0; return void 0;
} }
......
...@@ -13,17 +13,15 @@ import modesUtil = require('vs/editor/test/common/modesUtil'); ...@@ -13,17 +13,15 @@ import modesUtil = require('vs/editor/test/common/modesUtil');
suite('JS - Auto Indent', () => { suite('JS - Auto Indent', () => {
var wordDefinition:RegExp; var wordDefinition:RegExp;
var onEnter: modesUtil.IOnEnterFunc;
var assertOnEnter: modesUtil.IOnEnterAsserter; var assertOnEnter: modesUtil.IOnEnterAsserter;
var onElectricCharacter: modesUtil.IOnElectricCharacterFunc; var onElectricCharacter: modesUtil.IOnElectricCharacterFunc;
var assertWords = modesUtil.assertWords; var assertWords = modesUtil.assertWords;
suiteSetup((done) => { suiteSetup((done) => {
modesUtil.load('javascript').then(mode => { modesUtil.load('javascript').then(mode => {
onEnter = modesUtil.createOnEnter(mode); assertOnEnter = modesUtil.createOnEnterAsserter(mode.getId(), mode.richEditSupport);
assertOnEnter = modesUtil.createOnEnterAsserter(mode.getId(), mode.onEnterSupport);
onElectricCharacter = modesUtil.createOnElectricCharacter(mode); onElectricCharacter = modesUtil.createOnElectricCharacter(mode);
wordDefinition = mode.tokenTypeClassificationSupport.getWordDefinition(); wordDefinition = mode.richEditSupport.tokenTypeClassification.getWordDefinition();
done(); done();
}); });
}); });
......
...@@ -22,12 +22,12 @@ import {AsyncDescriptor2, createAsyncDescriptor2} from 'vs/platform/instantiatio ...@@ -22,12 +22,12 @@ import {AsyncDescriptor2, createAsyncDescriptor2} from 'vs/platform/instantiatio
import {OnEnterSupport} from 'vs/editor/common/modes/supports/onEnter'; import {OnEnterSupport} from 'vs/editor/common/modes/supports/onEnter';
import {IJSONContributionRegistry, Extensions, ISchemaContributions} from 'vs/platform/jsonschemas/common/jsonContributionRegistry'; import {IJSONContributionRegistry, Extensions, ISchemaContributions} from 'vs/platform/jsonschemas/common/jsonContributionRegistry';
import {IInstantiationService} from 'vs/platform/instantiation/common/instantiation'; import {IInstantiationService} from 'vs/platform/instantiation/common/instantiation';
import {RichEditSupport} from 'vs/editor/common/modes/supports/richEditSupport';
export class JSONMode extends AbstractMode<jsonWorker.JSONWorker> implements Modes.IExtraInfoSupport, Modes.IOutlineSupport, IThreadSynchronizableObject<ISchemaContributions> { export class JSONMode extends AbstractMode<jsonWorker.JSONWorker> implements Modes.IExtraInfoSupport, Modes.IOutlineSupport, IThreadSynchronizableObject<ISchemaContributions> {
public tokenizationSupport: Modes.ITokenizationSupport; public tokenizationSupport: Modes.ITokenizationSupport;
public electricCharacterSupport: Modes.IElectricCharacterSupport; public richEditSupport: Modes.IRichEditSupport;
public characterPairSupport: Modes.ICharacterPairSupport;
public extraInfoSupport: Modes.IExtraInfoSupport; public extraInfoSupport: Modes.IExtraInfoSupport;
public outlineSupport: Modes.IOutlineSupport; public outlineSupport: Modes.IOutlineSupport;
...@@ -37,8 +37,6 @@ export class JSONMode extends AbstractMode<jsonWorker.JSONWorker> implements Mod ...@@ -37,8 +37,6 @@ export class JSONMode extends AbstractMode<jsonWorker.JSONWorker> implements Mod
public outlineGroupLabel : { [name: string]: string; }; public outlineGroupLabel : { [name: string]: string; };
public onEnterSupport: Modes.IOnEnterSupport;
constructor( constructor(
descriptor:Modes.IModeDescriptor, descriptor:Modes.IModeDescriptor,
@IInstantiationService instantiationService: IInstantiationService, @IInstantiationService instantiationService: IInstantiationService,
...@@ -47,10 +45,36 @@ export class JSONMode extends AbstractMode<jsonWorker.JSONWorker> implements Mod ...@@ -47,10 +45,36 @@ export class JSONMode extends AbstractMode<jsonWorker.JSONWorker> implements Mod
super(descriptor, instantiationService, threadService); super(descriptor, instantiationService, threadService);
this.tokenizationSupport = tokenization.createTokenizationSupport(this, true); this.tokenizationSupport = tokenization.createTokenizationSupport(this, true);
this.electricCharacterSupport = new supports.BracketElectricCharacterSupport(this, { brackets: [
{ tokenType:'delimiter.bracket.json', open: '{', close: '}', isElectric: true }, this.richEditSupport = new RichEditSupport(this.getId(), {
{ tokenType:'delimiter.array.json', open: '[', close: ']', isElectric: true }
] }); wordPattern: createWordRegExp('.-'),
comments: {
lineComment: '//',
blockComment: ['/*', '*/']
},
brackets: [
['{', '}'],
['[', ']']
],
__electricCharacterSupport: {
brackets: [
{ tokenType:'delimiter.bracket.json', open: '{', close: '}', isElectric: true },
{ tokenType:'delimiter.array.json', open: '[', close: ']', isElectric: true }
]
},
__characterPairSupport: {
autoClosingPairs: [
{ open: '{', close: '}', notIn: ['string'] },
{ open: '[', close: ']', notIn: ['string'] },
{ open: '"', close: '"', notIn: ['string'] }
]
}
});
this.extraInfoSupport = this; this.extraInfoSupport = this;
...@@ -66,24 +90,10 @@ export class JSONMode extends AbstractMode<jsonWorker.JSONWorker> implements Mod ...@@ -66,24 +90,10 @@ export class JSONMode extends AbstractMode<jsonWorker.JSONWorker> implements Mod
this.formattingSupport = this; this.formattingSupport = this;
this.characterPairSupport = new supports.CharacterPairSupport(this, {
autoClosingPairs:
[ { open: '{', close: '}', notIn: ['string'] },
{ open: '[', close: ']', notIn: ['string'] },
{ open: '"', close: '"', notIn: ['string'] }
]});
this.suggestSupport = new supports.SuggestSupport(this, { this.suggestSupport = new supports.SuggestSupport(this, {
triggerCharacters: [], triggerCharacters: [],
excludeTokens: ['comment.line.json', 'comment.block.json'], excludeTokens: ['comment.line.json', 'comment.block.json'],
suggest: (resource, position) => this.suggest(resource, position)}); suggest: (resource, position) => this.suggest(resource, position)});
this.onEnterSupport = new OnEnterSupport(this.getId(), {
brackets: [
{ open: '{', close: '}' },
{ open: '[', close: ']' }
]
});
} }
public creationDone(): void { public creationDone(): void {
...@@ -142,17 +152,4 @@ export class JSONMode extends AbstractMode<jsonWorker.JSONWorker> implements Mod ...@@ -142,17 +152,4 @@ export class JSONMode extends AbstractMode<jsonWorker.JSONWorker> implements Mod
public formatRange(resource:URI, range:EditorCommon.IRange, options:Modes.IFormattingOptions):WinJS.TPromise<EditorCommon.ISingleEditOperation[]> { public formatRange(resource:URI, range:EditorCommon.IRange, options:Modes.IFormattingOptions):WinJS.TPromise<EditorCommon.ISingleEditOperation[]> {
return this._worker((w) => w.format(resource, range, options)); return this._worker((w) => w.format(resource, range, options));
} }
public getCommentsConfiguration():Modes.ICommentsConfiguration {
return {
lineCommentTokens: ['//'],
blockCommentStartToken: '/*',
blockCommentEndToken: '*/'
};
}
private static WORD_DEFINITION = createWordRegExp('.-');
public getWordDefinition():RegExp {
return JSONMode.WORD_DEFINITION;
}
} }
\ No newline at end of file
...@@ -20,7 +20,7 @@ suite('JSON - tokenization', () => { ...@@ -20,7 +20,7 @@ suite('JSON - tokenization', () => {
setup((done) => { setup((done) => {
modesUtil.load('json').then(mode => { modesUtil.load('json').then(mode => {
tokenizationSupport = mode.tokenizationSupport; tokenizationSupport = mode.tokenizationSupport;
assertOnEnter = modesUtil.createOnEnterAsserter(mode.getId(), mode.onEnterSupport); assertOnEnter = modesUtil.createOnEnterAsserter(mode.getId(), mode.richEditSupport);
done(); done();
}); });
}); });
......
...@@ -21,7 +21,7 @@ suite('LESS-tokenization', () => { ...@@ -21,7 +21,7 @@ suite('LESS-tokenization', () => {
setup((done) => { setup((done) => {
modesUtil.load('less', ['javascript']).then(mode => { modesUtil.load('less', ['javascript']).then(mode => {
tokenizationSupport = mode.tokenizationSupport; tokenizationSupport = mode.tokenizationSupport;
assertOnEnter = modesUtil.createOnEnterAsserter(mode.getId(), mode.onEnterSupport); assertOnEnter = modesUtil.createOnEnterAsserter(mode.getId(), mode.richEditSupport);
done(); done();
}); });
}); });
......
...@@ -35,6 +35,9 @@ export const language = ...@@ -35,6 +35,9 @@ export const language =
autoClosingPairs: [], autoClosingPairs: [],
blockCommentStart: '<!--',
blockCommentEnd: '-->',
// escape codes // escape codes
control: /[\\`*_\[\]{}()#+\-\.!]/, control: /[\\`*_\[\]{}()#+\-\.!]/,
noncontrol: /[^\\`*_\[\]{}()#+\-\.!]/, noncontrol: /[^\\`*_\[\]{}()#+\-\.!]/,
...@@ -221,10 +224,6 @@ export class MarkdownMode extends Monarch.MonarchMode<MarkdownWorker.MarkdownWor ...@@ -221,10 +224,6 @@ export class MarkdownMode extends Monarch.MonarchMode<MarkdownWorker.MarkdownWor
this.emitOutputSupport = this; this.emitOutputSupport = this;
} }
public getCommentsConfiguration(): Modes.ICommentsConfiguration {
return { blockCommentStartToken: '<!--', blockCommentEndToken: '-->' };
}
static $getEmitOutput = OneWorkerAttr(MarkdownMode, MarkdownMode.prototype.getEmitOutput); static $getEmitOutput = OneWorkerAttr(MarkdownMode, MarkdownMode.prototype.getEmitOutput);
public getEmitOutput(resource: URI, absoluteWorkerResourcesPath?: string): WinJS.TPromise<Modes.IEmitOutput> { // TODO@Ben technical debt: worker cannot resolve paths absolute public getEmitOutput(resource: URI, absoluteWorkerResourcesPath?: string): WinJS.TPromise<Modes.IEmitOutput> { // TODO@Ben technical debt: worker cannot resolve paths absolute
return this._worker((w) => w.getEmitOutput(resource, absoluteWorkerResourcesPath)); return this._worker((w) => w.getEmitOutput(resource, absoluteWorkerResourcesPath));
...@@ -233,4 +232,4 @@ export class MarkdownMode extends Monarch.MonarchMode<MarkdownWorker.MarkdownWor ...@@ -233,4 +232,4 @@ export class MarkdownMode extends Monarch.MonarchMode<MarkdownWorker.MarkdownWor
protected _getWorkerDescriptor(): AsyncDescriptor2<Modes.IMode, Modes.IWorkerParticipant[], MarkdownWorker.MarkdownWorker> { protected _getWorkerDescriptor(): AsyncDescriptor2<Modes.IMode, Modes.IWorkerParticipant[], MarkdownWorker.MarkdownWorker> {
return createAsyncDescriptor2('vs/languages/markdown/common/markdownWorker', 'MarkdownWorker'); return createAsyncDescriptor2('vs/languages/markdown/common/markdownWorker', 'MarkdownWorker');
} }
} }
\ No newline at end of file
...@@ -15,6 +15,7 @@ import {OnEnterSupport} from 'vs/editor/common/modes/supports/onEnter'; ...@@ -15,6 +15,7 @@ import {OnEnterSupport} from 'vs/editor/common/modes/supports/onEnter';
import {IInstantiationService} from 'vs/platform/instantiation/common/instantiation'; import {IInstantiationService} from 'vs/platform/instantiation/common/instantiation';
import {IThreadService} from 'vs/platform/thread/common/thread'; import {IThreadService} from 'vs/platform/thread/common/thread';
import {AbstractModeWorker} from 'vs/editor/common/modes/abstractModeWorker'; import {AbstractModeWorker} from 'vs/editor/common/modes/abstractModeWorker';
import {RichEditSupport} from 'vs/editor/common/modes/supports/richEditSupport';
var bracketsSource : Modes.IBracketPair[]= [ var bracketsSource : Modes.IBracketPair[]= [
{ tokenType:'delimiter.bracket.php', open: '{', close: '}', isElectric: true }, { tokenType:'delimiter.bracket.php', open: '{', close: '}', isElectric: true },
...@@ -460,10 +461,7 @@ export class PHPEnterHTMLState extends PHPState { ...@@ -460,10 +461,7 @@ export class PHPEnterHTMLState extends PHPState {
export class PHPMode extends AbstractMode<AbstractModeWorker> implements supports.ITokenizationCustomization { export class PHPMode extends AbstractMode<AbstractModeWorker> implements supports.ITokenizationCustomization {
public tokenizationSupport: Modes.ITokenizationSupport; public tokenizationSupport: Modes.ITokenizationSupport;
public electricCharacterSupport: Modes.IElectricCharacterSupport; public richEditSupport: Modes.IRichEditSupport;
public characterPairSupport: Modes.ICharacterPairSupport;
public onEnterSupport: Modes.IOnEnterSupport;
private modeService:IModeService; private modeService:IModeService;
...@@ -476,30 +474,41 @@ export class PHPMode extends AbstractMode<AbstractModeWorker> implements support ...@@ -476,30 +474,41 @@ export class PHPMode extends AbstractMode<AbstractModeWorker> implements support
super(descriptor, instantiationService, threadService); super(descriptor, instantiationService, threadService);
this.modeService = modeService; this.modeService = modeService;
this.electricCharacterSupport = new supports.BracketElectricCharacterSupport(this, { brackets: bracketsSource });
this.tokenizationSupport = new supports.TokenizationSupport(this, this, true, false); this.tokenizationSupport = new supports.TokenizationSupport(this, this, true, false);
this.characterPairSupport = new supports.CharacterPairSupport(this, { this.richEditSupport = new RichEditSupport(this.getId(), {
autoClosingPairs: wordPattern: createWordRegExp('$_'),
[ { open: '{', close: '}', notIn: ['string.php'] },
comments: {
lineComment: '//',
blockComment: ['/*', '*/']
},
brackets: [
['{', '}'],
['[', ']'],
['(', ')']
],
__electricCharacterSupport: {
brackets: bracketsSource
},
__characterPairSupport: {
autoClosingPairs: [
{ open: '{', close: '}', notIn: ['string.php'] },
{ open: '[', close: ']', notIn: ['string.php'] }, { open: '[', close: ']', notIn: ['string.php'] },
{ open: '(', close: ')', notIn: ['string.php'] }, { open: '(', close: ')', notIn: ['string.php'] },
{ open: '"', close: '"', notIn: ['string.php'] }, { open: '"', close: '"', notIn: ['string.php'] },
{ open: '\'', close: '\'', notIn: ['string.php'] } { open: '\'', close: '\'', notIn: ['string.php'] }
]}); ]
}
});
this.suggestSupport = new supports.SuggestSupport(this, { this.suggestSupport = new supports.SuggestSupport(this, {
triggerCharacters: ['.', ':', '$'], triggerCharacters: ['.', ':', '$'],
excludeTokens: ['comment'], excludeTokens: ['comment'],
suggest: (resource, position) => this.suggest(resource, position)}); suggest: (resource, position) => this.suggest(resource, position)});
this.onEnterSupport = new OnEnterSupport(this.getId(), {
brackets: [
{ open: '(', close: ')' },
{ open: '{', close: '}' },
{ open: '[', close: ']' }
]
});
} }
public asyncCtor(): WinJS.Promise { public asyncCtor(): WinJS.Promise {
...@@ -550,13 +559,4 @@ export class PHPMode extends AbstractMode<AbstractModeWorker> implements support ...@@ -550,13 +559,4 @@ export class PHPMode extends AbstractMode<AbstractModeWorker> implements support
// such that when we enter HTML again, we can recover the HTML state from .parent // such that when we enter HTML again, we can recover the HTML state from .parent
(<PHPPlain>myStateAfterNestedMode).parent = lastNestedModeState; (<PHPPlain>myStateAfterNestedMode).parent = lastNestedModeState;
} }
public getCommentsConfiguration():Modes.ICommentsConfiguration {
return { lineCommentTokens: ['//','#'], blockCommentStartToken: '/*', blockCommentEndToken: '*/' };
}
private static WORD_DEFINITION = createWordRegExp('$_');
public getWordDefinition():RegExp {
return PHPMode.WORD_DEFINITION;
}
} }
...@@ -26,8 +26,8 @@ suite('Syntax Highlighting - PHP', () => { ...@@ -26,8 +26,8 @@ suite('Syntax Highlighting - PHP', () => {
setup((done) => { setup((done) => {
modesUtil.load('php').then(mode => { modesUtil.load('php').then(mode => {
tokenizationSupport = mode.tokenizationSupport; tokenizationSupport = mode.tokenizationSupport;
assertOnEnter = modesUtil.createOnEnterAsserter(mode.getId(), mode.onEnterSupport); assertOnEnter = modesUtil.createOnEnterAsserter(mode.getId(), mode.richEditSupport);
wordDefinition = mode.tokenTypeClassificationSupport.getWordDefinition(); wordDefinition = mode.richEditSupport.tokenTypeClassification.getWordDefinition();
done(); done();
}); });
}); });
......
...@@ -16,6 +16,7 @@ import {RAZORWorker} from 'vs/languages/razor/common/razorWorker'; ...@@ -16,6 +16,7 @@ import {RAZORWorker} from 'vs/languages/razor/common/razorWorker';
import {IInstantiationService} from 'vs/platform/instantiation/common/instantiation'; import {IInstantiationService} from 'vs/platform/instantiation/common/instantiation';
import {IThreadService} from 'vs/platform/thread/common/thread'; import {IThreadService} from 'vs/platform/thread/common/thread';
import {IModeService} from 'vs/editor/common/services/modeService'; import {IModeService} from 'vs/editor/common/services/modeService';
import {RichEditSupport} from 'vs/editor/common/modes/supports/richEditSupport';
// for a brief description of the razor syntax see http://www.mikesdotnetting.com/Article/153/Inline-Razor-Syntax-Overview // for a brief description of the razor syntax see http://www.mikesdotnetting.com/Article/153/Inline-Razor-Syntax-Overview
...@@ -65,13 +66,42 @@ export class RAZORMode extends htmlMode.HTMLMode<RAZORWorker> { ...@@ -65,13 +66,42 @@ export class RAZORMode extends htmlMode.HTMLMode<RAZORWorker> {
super(descriptor, instantiationService, threadService, modeService); super(descriptor, instantiationService, threadService, modeService);
this.formattingSupport = null; this.formattingSupport = null;
}
protected _createRichEditSupport(embeddedAutoClosingPairs: Modes.IAutoClosingPair[]): Modes.IRichEditSupport {
return new RichEditSupport(this.getId(), {
wordPattern: createWordRegExp('#?%'),
comments: {
blockComment: ['<!--', '-->']
},
this.onEnterSupport = new OnEnterSupport(this.getId(), {
brackets: [ brackets: [
{ open: '<!--', close: '-->' }, ['<!--', '-->'],
{ open: '{', close: '}' }, ['{', '}'],
{ open: '(', close: ')' }, ['(', ')']
] ],
__electricCharacterSupport: {
brackets: [],
regexBrackets: [{
tokenType: htmlMode.htmlTokenTypes.getTag('$1'),
open: new RegExp(`<(?!(?:${htmlMode.EMPTY_ELEMENTS.join("|")}))(\\w[\\w\\d]*)([^/>]*(?!/)>)[^<]*$`, 'i'),
closeComplete: '</$1>',
close: /<\/(\w[\w\d]*)\s*>$/i
}],
caseInsensitive: true,
embeddedElectricCharacters: ['*', '}', ']', ')']
},
__characterPairSupport: {
autoClosingPairs: embeddedAutoClosingPairs.slice(0),
surroundingPairs: [
{ open: '"', close: '"' },
{ open: '\'', close: '\'' }
]
}
}); });
} }
...@@ -83,11 +113,6 @@ export class RAZORMode extends htmlMode.HTMLMode<RAZORWorker> { ...@@ -83,11 +113,6 @@ export class RAZORMode extends htmlMode.HTMLMode<RAZORWorker> {
return new RAZORState(this, htmlMode.States.Content, '', '', '', '', ''); return new RAZORState(this, htmlMode.States.Content, '', '', '', '', '');
} }
public static WORD_DEFINITION = createWordRegExp('#?%');
public getWordDefinition():RegExp {
return RAZORMode.WORD_DEFINITION;
}
public getLeavingNestedModeData(line:string, state:Modes.IState): supports.ILeavingNestedModeData { public getLeavingNestedModeData(line:string, state:Modes.IState): supports.ILeavingNestedModeData {
var leavingNestedModeData = super.getLeavingNestedModeData(line, state); var leavingNestedModeData = super.getLeavingNestedModeData(line, state);
if (leavingNestedModeData) { if (leavingNestedModeData) {
...@@ -96,4 +121,3 @@ export class RAZORMode extends htmlMode.HTMLMode<RAZORWorker> { ...@@ -96,4 +121,3 @@ export class RAZORMode extends htmlMode.HTMLMode<RAZORWorker> {
return leavingNestedModeData; return leavingNestedModeData;
} }
} }
...@@ -18,7 +18,7 @@ suite('Sass Colorizer', () => { ...@@ -18,7 +18,7 @@ suite('Sass Colorizer', () => {
setup((done) => { setup((done) => {
modesUtil.load('sass').then(mode => { modesUtil.load('sass').then(mode => {
tokenizationSupport = mode.tokenizationSupport; tokenizationSupport = mode.tokenizationSupport;
assertOnEnter = modesUtil.createOnEnterAsserter(mode.getId(), mode.onEnterSupport); assertOnEnter = modesUtil.createOnEnterAsserter(mode.getId(), mode.richEditSupport);
done(); done();
}); });
}); });
......
...@@ -26,6 +26,7 @@ import {ITelemetryService} from 'vs/platform/telemetry/common/telemetry'; ...@@ -26,6 +26,7 @@ import {ITelemetryService} from 'vs/platform/telemetry/common/telemetry';
import {IThreadService, ThreadAffinity} from 'vs/platform/thread/common/thread'; import {IThreadService, ThreadAffinity} from 'vs/platform/thread/common/thread';
import {OnEnterSupport} from 'vs/editor/common/modes/supports/onEnter'; import {OnEnterSupport} from 'vs/editor/common/modes/supports/onEnter';
import {IInstantiationService} from 'vs/platform/instantiation/common/instantiation'; import {IInstantiationService} from 'vs/platform/instantiation/common/instantiation';
import {RichEditSupport} from 'vs/editor/common/modes/supports/richEditSupport';
class SemanticValidator { class SemanticValidator {
...@@ -128,8 +129,7 @@ class SemanticValidator { ...@@ -128,8 +129,7 @@ class SemanticValidator {
export class TypeScriptMode<W extends typescriptWorker.TypeScriptWorker2> extends AbstractMode<W> implements lifecycle.IDisposable { export class TypeScriptMode<W extends typescriptWorker.TypeScriptWorker2> extends AbstractMode<W> implements lifecycle.IDisposable {
public tokenizationSupport: Modes.ITokenizationSupport; public tokenizationSupport: Modes.ITokenizationSupport;
public electricCharacterSupport: Modes.IElectricCharacterSupport; public richEditSupport: Modes.IRichEditSupport;
public characterPairSupport: Modes.ICharacterPairSupport;
public referenceSupport: Modes.IReferenceSupport; public referenceSupport: Modes.IReferenceSupport;
public extraInfoSupport:Modes.IExtraInfoSupport; public extraInfoSupport:Modes.IExtraInfoSupport;
public occurrencesSupport:Modes.IOccurrencesSupport; public occurrencesSupport:Modes.IOccurrencesSupport;
...@@ -143,8 +143,6 @@ export class TypeScriptMode<W extends typescriptWorker.TypeScriptWorker2> extend ...@@ -143,8 +143,6 @@ export class TypeScriptMode<W extends typescriptWorker.TypeScriptWorker2> extend
public renameSupport: Modes.IRenameSupport; public renameSupport: Modes.IRenameSupport;
public suggestSupport: Modes.ISuggestSupport; public suggestSupport: Modes.ISuggestSupport;
public onEnterSupport: Modes.IOnEnterSupport;
private _telemetryService: ITelemetryService; private _telemetryService: ITelemetryService;
private _disposables: lifecycle.IDisposable[] = []; private _disposables: lifecycle.IDisposable[] = [];
private _projectResolver: WinJS.TPromise<typescript.IProjectResolver2>; private _projectResolver: WinJS.TPromise<typescript.IProjectResolver2>;
...@@ -195,50 +193,21 @@ export class TypeScriptMode<W extends typescriptWorker.TypeScriptWorker2> extend ...@@ -195,50 +193,21 @@ export class TypeScriptMode<W extends typescriptWorker.TypeScriptWorker2> extend
this.renameSupport = this; this.renameSupport = this;
this.tokenizationSupport = tokenization.createTokenizationSupport(this, tokenization.Language.TypeScript); this.tokenizationSupport = tokenization.createTokenizationSupport(this, tokenization.Language.TypeScript);
this.electricCharacterSupport = new supports.BracketElectricCharacterSupport(this, { this.richEditSupport = new RichEditSupport(this.getId(), {
brackets: [ wordPattern: createWordRegExp('$'),
{ tokenType:'delimiter.bracket.ts', open: '{', close: '}', isElectric: true },
{ tokenType:'delimiter.array.ts', open: '[', close: ']', isElectric: true },
{ tokenType:'delimiter.parenthesis.ts', open: '(', close: ')', isElectric: true }
],
docComment: {scope:'comment.doc', open:'/**', lineStart:' * ', close:' */'} });
this.referenceSupport = new supports.ReferenceSupport(this, {
tokens: ['identifier.ts'],
findReferences: (resource, position, includeDeclaration) => this.findReferences(resource, position, includeDeclaration)});
this.declarationSupport = new supports.DeclarationSupport(this, {
tokens: ['identifier.ts', 'string.ts', 'attribute.value.vs'],
findDeclaration: (resource, position) => this.findDeclaration(resource, position)});
this.parameterHintsSupport = new supports.ParameterHintsSupport(this, {
triggerCharacters: ['(', ','],
excludeTokens: ['string.ts'],
getParameterHints: (resource, position) => this.getParameterHints(resource, position)});
this.characterPairSupport = new supports.CharacterPairSupport(this, {
autoClosingPairs:
[ { open: '{', close: '}' },
{ open: '[', close: ']' },
{ open: '(', close: ')' },
{ open: '"', close: '"', notIn: ['string'] },
{ open: '\'', close: '\'', notIn: ['string', 'comment'] },
{ open: '`', close: '`' }
]});
this.suggestSupport = new supports.SuggestSupport(this, { comments: {
triggerCharacters: ['.'], lineComment: '//',
excludeTokens: ['string', 'comment', 'number'], blockComment: ['/*', '*/']
suggest: (resource, position) => this.suggest(resource, position), },
getSuggestionDetails: (resource, position, suggestion) => this.getSuggestionDetails(resource, position, suggestion)});
this.onEnterSupport = new OnEnterSupport(this.getId(), {
brackets: [ brackets: [
{ open: '{', close: '}' }, ['{', '}'],
{ open: '[', close: ']' }, ['[', ']'],
{ open: '(', close: ')' }, ['(', ')']
], ],
regExpRules: [
onEnterRules: [
{ {
// e.g. /** | */ // e.g. /** | */
beforeText: /^\s*\/\*\*(?!\/)([^\*]|\*(?!\/))*$/, beforeText: /^\s*\/\*\*(?!\/)([^\*]|\*(?!\/))*$/,
...@@ -260,8 +229,47 @@ export class TypeScriptMode<W extends typescriptWorker.TypeScriptWorker2> extend ...@@ -260,8 +229,47 @@ export class TypeScriptMode<W extends typescriptWorker.TypeScriptWorker2> extend
beforeText: /^(\t|(\ \ ))*\ \*\/\s*$/, beforeText: /^(\t|(\ \ ))*\ \*\/\s*$/,
action: { indentAction: Modes.IndentAction.None, removeText: 1 } action: { indentAction: Modes.IndentAction.None, removeText: 1 }
} }
] ],
__electricCharacterSupport: {
brackets: [
{ tokenType:'delimiter.bracket.ts', open: '{', close: '}', isElectric: true },
{ tokenType:'delimiter.array.ts', open: '[', close: ']', isElectric: true },
{ tokenType:'delimiter.parenthesis.ts', open: '(', close: ')', isElectric: true }
],
docComment: {scope:'comment.doc', open:'/**', lineStart:' * ', close:' */'}
},
__characterPairSupport: {
autoClosingPairs: [
{ open: '{', close: '}' },
{ open: '[', close: ']' },
{ open: '(', close: ')' },
{ open: '"', close: '"', notIn: ['string'] },
{ open: '\'', close: '\'', notIn: ['string', 'comment'] },
{ open: '`', close: '`' }
]
}
}); });
this.referenceSupport = new supports.ReferenceSupport(this, {
tokens: ['identifier.ts'],
findReferences: (resource, position, includeDeclaration) => this.findReferences(resource, position, includeDeclaration)});
this.declarationSupport = new supports.DeclarationSupport(this, {
tokens: ['identifier.ts', 'string.ts', 'attribute.value.vs'],
findDeclaration: (resource, position) => this.findDeclaration(resource, position)});
this.parameterHintsSupport = new supports.ParameterHintsSupport(this, {
triggerCharacters: ['(', ','],
excludeTokens: ['string.ts'],
getParameterHints: (resource, position) => this.getParameterHints(resource, position)});
this.suggestSupport = new supports.SuggestSupport(this, {
triggerCharacters: ['.'],
excludeTokens: ['string', 'comment', 'number'],
suggest: (resource, position) => this.suggest(resource, position),
getSuggestionDetails: (resource, position, suggestion) => this.getSuggestionDetails(resource, position, suggestion)});
} }
public dispose(): void { public dispose(): void {
...@@ -367,10 +375,6 @@ export class TypeScriptMode<W extends typescriptWorker.TypeScriptWorker2> extend ...@@ -367,10 +375,6 @@ export class TypeScriptMode<W extends typescriptWorker.TypeScriptWorker2> extend
return createAsyncDescriptor2('vs/languages/typescript/common/typescriptWorker2', 'TypeScriptWorker2'); return createAsyncDescriptor2('vs/languages/typescript/common/typescriptWorker2', 'TypeScriptWorker2');
} }
public getCommentsConfiguration():Modes.ICommentsConfiguration {
return { lineCommentTokens: ['//'], blockCommentStartToken: '/*', blockCommentEndToken: '*/' };
}
static $_pickAWorkerToValidate = OneWorkerAttr(TypeScriptMode, TypeScriptMode.prototype._pickAWorkerToValidate, TypeScriptMode.prototype._syncProjects, ThreadAffinity.Group3); static $_pickAWorkerToValidate = OneWorkerAttr(TypeScriptMode, TypeScriptMode.prototype._pickAWorkerToValidate, TypeScriptMode.prototype._syncProjects, ThreadAffinity.Group3);
public _pickAWorkerToValidate(): WinJS.Promise { public _pickAWorkerToValidate(): WinJS.Promise {
return this._worker((w) => w.enableValidator()); return this._worker((w) => w.enableValidator());
...@@ -432,11 +436,6 @@ export class TypeScriptMode<W extends typescriptWorker.TypeScriptWorker2> extend ...@@ -432,11 +436,6 @@ export class TypeScriptMode<W extends typescriptWorker.TypeScriptWorker2> extend
return this._worker((w) => w.getEmitOutput(resource, type)); return this._worker((w) => w.getEmitOutput(resource, type));
} }
private static WORD_DEFINITION = createWordRegExp('$');
public getWordDefinition():RegExp {
return TypeScriptMode.WORD_DEFINITION;
}
static $findReferences = OneWorkerAttr(TypeScriptMode, TypeScriptMode.prototype.findReferences, TypeScriptMode.prototype._syncProjects, ThreadAffinity.Group3); static $findReferences = OneWorkerAttr(TypeScriptMode, TypeScriptMode.prototype.findReferences, TypeScriptMode.prototype._syncProjects, ThreadAffinity.Group3);
public findReferences(resource:URI, position:EditorCommon.IPosition, includeDeclaration:boolean):WinJS.TPromise<Modes.IReference[]> { public findReferences(resource:URI, position:EditorCommon.IPosition, includeDeclaration:boolean):WinJS.TPromise<Modes.IReference[]> {
return this._worker((w) => w.findReferences(resource, position, includeDeclaration)); return this._worker((w) => w.findReferences(resource, position, includeDeclaration));
......
...@@ -19,7 +19,7 @@ suite('TS/JS - syntax highlighting', () => { ...@@ -19,7 +19,7 @@ suite('TS/JS - syntax highlighting', () => {
setup((done) => { setup((done) => {
modesUtil.load('javascript').then(mode => { modesUtil.load('javascript').then(mode => {
tokenizationSupport = mode.tokenizationSupport; tokenizationSupport = mode.tokenizationSupport;
assertOnEnter = modesUtil.createOnEnterAsserter(mode.getId(), mode.onEnterSupport); assertOnEnter = modesUtil.createOnEnterAsserter(mode.getId(), mode.richEditSupport);
done(); done();
}); });
}); });
......
...@@ -5,7 +5,6 @@ ...@@ -5,7 +5,6 @@
'use strict'; 'use strict';
import {Emitter} from 'vs/base/common/event'; import {Emitter} from 'vs/base/common/event';
import {IBracketElectricCharacterContribution} from 'vs/editor/common/modes/supports';
import {score} from 'vs/editor/common/modes/languageSelector'; import {score} from 'vs/editor/common/modes/languageSelector';
import {Remotable, IThreadService} from 'vs/platform/thread/common/thread'; import {Remotable, IThreadService} from 'vs/platform/thread/common/thread';
import * as errors from 'vs/base/common/errors'; import * as errors from 'vs/base/common/errors';
...@@ -26,8 +25,6 @@ import {registerApiCommands} from 'vs/workbench/api/node/extHostApiCommands'; ...@@ -26,8 +25,6 @@ import {registerApiCommands} from 'vs/workbench/api/node/extHostApiCommands';
import * as extHostTypes from 'vs/workbench/api/node/extHostTypes'; import * as extHostTypes from 'vs/workbench/api/node/extHostTypes';
import Modes = require('vs/editor/common/modes'); import Modes = require('vs/editor/common/modes');
import {IModeService} from 'vs/editor/common/services/modeService'; import {IModeService} from 'vs/editor/common/services/modeService';
import {ICommentsSupportContribution, ITokenTypeClassificationSupportContribution} from 'vs/editor/common/modes/supports';
import {IOnEnterSupportOptions} from 'vs/editor/common/modes/supports/onEnter';
import URI from 'vs/base/common/uri'; import URI from 'vs/base/common/uri';
import Severity from 'vs/base/common/severity'; import Severity from 'vs/base/common/severity';
import {IDisposable} from 'vs/base/common/lifecycle'; import {IDisposable} from 'vs/base/common/lifecycle';
...@@ -395,104 +392,21 @@ export class ExtHostAPIImplementation { ...@@ -395,104 +392,21 @@ export class ExtHostAPIImplementation {
private _setLanguageConfiguration(modeId: string, configuration: vscode.LanguageConfiguration): vscode.Disposable { private _setLanguageConfiguration(modeId: string, configuration: vscode.LanguageConfiguration): vscode.Disposable {
let disposables: IDisposable[] = []; let {wordPattern} = configuration;
let {comments, wordPattern} = configuration;
// comment configuration
if (comments) {
let contrib: ICommentsSupportContribution = { commentsConfiguration: {} };
if (comments.lineComment) {
contrib.commentsConfiguration.lineCommentTokens = [comments.lineComment];
}
if (comments.blockComment) {
let [blockStart, blockEnd] = comments.blockComment;
contrib.commentsConfiguration.blockCommentStartToken = blockStart;
contrib.commentsConfiguration.blockCommentEndToken = blockEnd;
}
let d = this.Modes_CommentsSupport_register(modeId, contrib);
disposables.push(d);
}
// word definition // word definition
if (wordPattern) { if (wordPattern) {
setWordDefinitionFor(modeId, wordPattern); setWordDefinitionFor(modeId, wordPattern);
let d = this.Modes_TokenTypeClassificationSupport_register(modeId, {
wordDefinition: wordPattern
});
disposables.push(d);
} else { } else {
setWordDefinitionFor(modeId, null); setWordDefinitionFor(modeId, null);
} }
// on enter return this.Modes_RichEditSupport_register(modeId, configuration);
let onEnter: IOnEnterSupportOptions = {};
let empty = true;
let {brackets, indentationRules, onEnterRules} = configuration;
if (brackets) {
empty = false;
onEnter.brackets = brackets.map(pair => {
let [open, close] = pair;
return { open, close };
});
}
if (indentationRules) {
empty = false;
onEnter.indentationRules = indentationRules;
}
if (onEnterRules) {
empty = false;
onEnter.regExpRules = <any>onEnterRules;
}
if (!empty) {
let d = this.Modes_OnEnterSupport_register(modeId, onEnter);
disposables.push(d);
}
if (configuration.__electricCharacterSupport) {
disposables.push(
this.Modes_ElectricCharacterSupport_register(modeId, configuration.__electricCharacterSupport)
);
}
if (configuration.__characterPairSupport) {
disposables.push(
this.Modes_CharacterPairSupport_register(modeId, configuration.__characterPairSupport)
);
}
return extHostTypes.Disposable.from(...disposables);
} }
private Modes_CommentsSupport_register(modeId: string, commentsSupport: ICommentsSupportContribution): IDisposable { private Modes_RichEditSupport_register(modeId: string, configuration:vscode.LanguageConfiguration): IDisposable {
let disposeToken = ExtHostAPIImplementation.generateDisposeToken(); let disposeToken = ExtHostAPIImplementation.generateDisposeToken();
this._proxy.Modes_CommentsSupport_register(disposeToken, modeId, commentsSupport); this._proxy.Modes_RichEditSupport_register(disposeToken, modeId, configuration);
return this._disposableFromToken(disposeToken);
}
private Modes_TokenTypeClassificationSupport_register(modeId: string, tokenTypeClassificationSupport:ITokenTypeClassificationSupportContribution): IDisposable {
let disposeToken = ExtHostAPIImplementation.generateDisposeToken();
this._proxy.Modes_TokenTypeClassificationSupport_register(disposeToken, modeId, tokenTypeClassificationSupport);
return this._disposableFromToken(disposeToken);
}
private Modes_ElectricCharacterSupport_register(modeId: string, electricCharacterSupport:IBracketElectricCharacterContribution): IDisposable {
let disposeToken = ExtHostAPIImplementation.generateDisposeToken();
this._proxy.Modes_ElectricCharacterSupport_register(disposeToken, modeId, electricCharacterSupport);
return this._disposableFromToken(disposeToken);
}
private Modes_CharacterPairSupport_register(modeId: string, characterPairSupport:Modes.ICharacterPairContribution): IDisposable {
let disposeToken = ExtHostAPIImplementation.generateDisposeToken();
this._proxy.Modes_CharacterPairSupport_register(disposeToken, modeId, characterPairSupport);
return this._disposableFromToken(disposeToken);
}
private Modes_OnEnterSupport_register(modeId: string, opts: IOnEnterSupportOptions): IDisposable {
let disposeToken = ExtHostAPIImplementation.generateDisposeToken();
this._proxy.Modes_OnEnterSupport_register(disposeToken, modeId, opts);
return this._disposableFromToken(disposeToken); return this._disposableFromToken(disposeToken);
} }
} }
...@@ -562,23 +476,7 @@ export class MainProcessVSCodeAPIHelper { ...@@ -562,23 +476,7 @@ export class MainProcessVSCodeAPIHelper {
} }
} }
public Modes_CommentsSupport_register(disposeToken:string, modeId: string, commentsSupport: ICommentsSupportContribution): void { public Modes_RichEditSupport_register(disposeToken:string, modeId: string, configuration:vscode.LanguageConfiguration): void {
this._token2Dispose[disposeToken] = this._modeService.registerDeclarativeCommentsSupport(modeId, commentsSupport); this._token2Dispose[disposeToken] = this._modeService.registerRichEditSupport(modeId, <any>configuration);
}
public Modes_TokenTypeClassificationSupport_register(disposeToken:string, modeId: string, tokenTypeClassificationSupport:ITokenTypeClassificationSupportContribution): void {
this._token2Dispose[disposeToken] = this._modeService.registerDeclarativeTokenTypeClassificationSupport(modeId, tokenTypeClassificationSupport);
}
public Modes_ElectricCharacterSupport_register(disposeToken:string, modeId: string, electricCharacterSupport:IBracketElectricCharacterContribution): void {
this._token2Dispose[disposeToken] = this._modeService.registerDeclarativeElectricCharacterSupport(modeId, electricCharacterSupport);
}
public Modes_CharacterPairSupport_register(disposeToken:string, modeId: string, characterPairSupport:Modes.ICharacterPairContribution): void {
this._token2Dispose[disposeToken] = this._modeService.registerDeclarativeCharacterPairSupport(modeId, characterPairSupport);
}
public Modes_OnEnterSupport_register(disposeToken:string, modeId: string, opts:IOnEnterSupportOptions): void {
this._token2Dispose[disposeToken] = this._modeService.registerDeclarativeOnEnterSupport(modeId, <any>opts);
} }
} }
\ No newline at end of file
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册