diff --git a/packages/plugin-ext/src/common/plugin-api-rpc.ts b/packages/plugin-ext/src/common/plugin-api-rpc.ts index d533974845a91..1e44cc9f44062 100644 --- a/packages/plugin-ext/src/common/plugin-api-rpc.ts +++ b/packages/plugin-ext/src/common/plugin-api-rpc.ts @@ -26,9 +26,9 @@ import { TextEditorLineNumbersStyle, EndOfLine, OverviewRulerLane, - IndentAction, FileOperationOptions, TextDocumentChangeReason, + IndentAction, } from '../plugin/types-impl'; import { UriComponents } from './uri-components'; import { @@ -1307,19 +1307,20 @@ export interface SerializedIndentationRule { unIndentedLinePattern?: SerializedRegExp; } -export interface EnterAction { +export interface SerializedOnEnterRule { + beforeText: SerializedRegExp; + afterText?: SerializedRegExp; + previousLineText?: SerializedRegExp; + action: SerializedEnterAction; +} + +export interface SerializedEnterAction { indentAction: IndentAction; outdentCurrentLine?: boolean; appendText?: string; removeText?: number; } -export interface SerializedOnEnterRule { - beforeText: SerializedRegExp; - afterText?: SerializedRegExp; - action: EnterAction; -} - export interface SerializedLanguageConfiguration { comments?: CommentRule; brackets?: CharacterPair[]; diff --git a/packages/plugin-ext/src/common/plugin-protocol.ts b/packages/plugin-ext/src/common/plugin-protocol.ts index 47fab8c9bcaca..28622bfafdec5 100644 --- a/packages/plugin-ext/src/common/plugin-protocol.ts +++ b/packages/plugin-ext/src/common/plugin-protocol.ts @@ -271,6 +271,7 @@ export interface PluginPackageLanguageContributionConfiguration { wordPattern?: string; indentationRules?: IndentationRules; folding?: FoldingRules; + onEnterRules?: OnEnterRule[]; } export interface PluginTaskDefinitionContribution { @@ -622,6 +623,7 @@ export interface LanguageConfiguration { comments?: CommentRule; folding?: FoldingRules; wordPattern?: string; + onEnterRules?: OnEnterRule[]; } /** @@ -670,6 +672,19 @@ export interface FoldingRules { markers?: FoldingMarkers; } +export interface OnEnterRule { + beforeText: string; + afterText?: string; + previousLineText?: string; + action: EnterAction; +} + +export interface EnterAction { + indent: 'none' | 'indent' | 'outdent' | 'indentOutdent'; + appendText?: string; + removeText?: number; +} + /** * Custom Editors contribution */ diff --git a/packages/plugin-ext/src/hosted/node/scanners/scanner-theia.ts b/packages/plugin-ext/src/hosted/node/scanners/scanner-theia.ts index 4803903e7b447..55eaa0520916d 100644 --- a/packages/plugin-ext/src/hosted/node/scanners/scanner-theia.ts +++ b/packages/plugin-ext/src/hosted/node/scanners/scanner-theia.ts @@ -660,7 +660,8 @@ export class TheiaPluginScanner implements PluginScanner { wordPattern: rawConfiguration.wordPattern, autoClosingPairs: this.extractValidAutoClosingPairs(rawLang.id, rawConfiguration), indentationRules: rawConfiguration.indentationRules, - surroundingPairs: this.extractValidSurroundingPairs(rawLang.id, rawConfiguration) + surroundingPairs: this.extractValidSurroundingPairs(rawLang.id, rawConfiguration), + onEnterRules: rawConfiguration.onEnterRules, }; result.configuration = configuration; } diff --git a/packages/plugin-ext/src/main/browser/languages-main.ts b/packages/plugin-ext/src/main/browser/languages-main.ts index d8221e0fd7960..ebfab0c9beb41 100644 --- a/packages/plugin-ext/src/main/browser/languages-main.ts +++ b/packages/plugin-ext/src/main/browser/languages-main.ts @@ -1075,7 +1075,8 @@ function reviveOnEnterRule(onEnterRule: SerializedOnEnterRule): monaco.languages return { beforeText: reviveRegExp(onEnterRule.beforeText)!, afterText: reviveRegExp(onEnterRule.afterText), - action: onEnterRule.action + previousLineText: reviveRegExp(onEnterRule.previousLineText), + action: onEnterRule.action, }; } diff --git a/packages/plugin-ext/src/main/browser/plugin-contribution-handler.ts b/packages/plugin-ext/src/main/browser/plugin-contribution-handler.ts index 9fb2c3f281a8d..8dc05bb00eb50 100644 --- a/packages/plugin-ext/src/main/browser/plugin-contribution-handler.ts +++ b/packages/plugin-ext/src/main/browser/plugin-contribution-handler.ts @@ -20,7 +20,7 @@ import { TextmateRegistry, getEncodedLanguageId, MonacoTextmateService, GrammarD import { MenusContributionPointHandler } from './menus/menus-contribution-handler'; import { PluginViewRegistry } from './view/plugin-view-registry'; import { PluginCustomEditorRegistry } from './custom-editors/plugin-custom-editor-registry'; -import { PluginContribution, IndentationRules, FoldingRules, ScopeMap, DeployedPlugin, GrammarsContribution } from '../../common'; +import { PluginContribution, IndentationRules, FoldingRules, ScopeMap, DeployedPlugin, GrammarsContribution, EnterAction, OnEnterRule } from '../../common'; import { DefaultUriLabelProviderContribution, LabelProviderContribution, @@ -172,7 +172,8 @@ export class PluginContributionHandler { comments: langConfiguration.comments, folding: this.convertFolding(langConfiguration.folding), surroundingPairs: langConfiguration.surroundingPairs, - indentationRules: this.convertIndentationRules(langConfiguration.indentationRules) + indentationRules: this.convertIndentationRules(langConfiguration.indentationRules), + onEnterRules: this.convertOnEnterRules(langConfiguration.onEnterRules), })); } } @@ -484,7 +485,6 @@ export class PluginContributionHandler { } return result; - } private convertTokenTypes(tokenTypes?: ScopeMap): ITokenTypeMap | undefined { @@ -530,4 +530,42 @@ export class PluginContributionHandler { return result; } + private convertOnEnterRules(onEnterRules?: OnEnterRule[]): monaco.languages.OnEnterRule[] | undefined { + if (!onEnterRules) { + return undefined; + } + + const result: monaco.languages.OnEnterRule[] = []; + for (const onEnterRule of onEnterRules) { + const rule: monaco.languages.OnEnterRule = { + beforeText: this.createRegex(onEnterRule.beforeText)!, + afterText: this.createRegex(onEnterRule.afterText), + previousLineText: this.createRegex(onEnterRule.previousLineText), + action: this.createEnterAction(onEnterRule.action), + }; + result.push(rule); + } + + return result; + } + + private createEnterAction(action: EnterAction): monaco.languages.EnterAction { + let indentAction: monaco.languages.IndentAction; + switch (action.indent) { + case 'indent': + indentAction = monaco.languages.IndentAction.Indent; + break; + case 'indentOutdent': + indentAction = monaco.languages.IndentAction.IndentOutdent; + break; + case 'outdent': + indentAction = monaco.languages.IndentAction.Outdent; + break; + default: + indentAction = monaco.languages.IndentAction.None; + break; + } + return { indentAction, appendText: action.appendText, removeText: action.removeText }; + } + } diff --git a/packages/plugin-ext/src/plugin/languages-utils.ts b/packages/plugin-ext/src/plugin/languages-utils.ts index b429e2f99f7d1..a5f20edf7ab05 100644 --- a/packages/plugin-ext/src/plugin/languages-utils.ts +++ b/packages/plugin-ext/src/plugin/languages-utils.ts @@ -24,9 +24,10 @@ export function serializeEnterRules(rules?: theia.OnEnterRule[]): SerializedOnEn return rules.map(r => ({ - action: r.action, beforeText: serializeRegExp(r.beforeText), - afterText: serializeRegExp(r.afterText) + afterText: serializeRegExp(r.afterText), + previousLineText: serializeRegExp(r.previousLineText), + action: r.action, } as SerializedOnEnterRule)); } diff --git a/packages/plugin/src/theia.d.ts b/packages/plugin/src/theia.d.ts index 0544ebd04a96f..1d518e80042c8 100644 --- a/packages/plugin/src/theia.d.ts +++ b/packages/plugin/src/theia.d.ts @@ -6709,6 +6709,10 @@ export module '@theia/plugin' { * This rule will only execute if the text after the cursor matches this regular expression. */ afterText?: RegExp; + /** + * This rule will only execute if the text above the current line matches this regular expression. + */ + previousLineText?: RegExp; /** * The action to execute. */