monaco-editor
Version:
A browser based code editor
233 lines (232 loc) • 9.13 kB
JavaScript
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
/**
* Assigned when the replace pattern is entirely static.
*/
var StaticValueReplacePattern = /** @class */ (function () {
function StaticValueReplacePattern(staticValue) {
this.staticValue = staticValue;
this.kind = 0 /* StaticValue */;
}
return StaticValueReplacePattern;
}());
/**
* Assigned when the replace pattern has replacemend patterns.
*/
var DynamicPiecesReplacePattern = /** @class */ (function () {
function DynamicPiecesReplacePattern(pieces) {
this.pieces = pieces;
this.kind = 1 /* DynamicPieces */;
}
return DynamicPiecesReplacePattern;
}());
var ReplacePattern = /** @class */ (function () {
function ReplacePattern(pieces) {
if (!pieces || pieces.length === 0) {
this._state = new StaticValueReplacePattern('');
}
else if (pieces.length === 1 && pieces[0].staticValue !== null) {
this._state = new StaticValueReplacePattern(pieces[0].staticValue);
}
else {
this._state = new DynamicPiecesReplacePattern(pieces);
}
}
ReplacePattern.fromStaticValue = function (value) {
return new ReplacePattern([ReplacePiece.staticValue(value)]);
};
Object.defineProperty(ReplacePattern.prototype, "hasReplacementPatterns", {
get: function () {
return (this._state.kind === 1 /* DynamicPieces */);
},
enumerable: true,
configurable: true
});
ReplacePattern.prototype.buildReplaceString = function (matches) {
if (this._state.kind === 0 /* StaticValue */) {
return this._state.staticValue;
}
var result = '';
for (var i = 0, len = this._state.pieces.length; i < len; i++) {
var piece = this._state.pieces[i];
if (piece.staticValue !== null) {
// static value ReplacePiece
result += piece.staticValue;
continue;
}
// match index ReplacePiece
result += ReplacePattern._substitute(piece.matchIndex, matches);
}
return result;
};
ReplacePattern._substitute = function (matchIndex, matches) {
if (matches === null) {
return '';
}
if (matchIndex === 0) {
return matches[0];
}
var remainder = '';
while (matchIndex > 0) {
if (matchIndex < matches.length) {
// A match can be undefined
var match = (matches[matchIndex] || '');
return match + remainder;
}
remainder = String(matchIndex % 10) + remainder;
matchIndex = Math.floor(matchIndex / 10);
}
return '$' + remainder;
};
return ReplacePattern;
}());
export { ReplacePattern };
/**
* A replace piece can either be a static string or an index to a specific match.
*/
var ReplacePiece = /** @class */ (function () {
function ReplacePiece(staticValue, matchIndex) {
this.staticValue = staticValue;
this.matchIndex = matchIndex;
}
ReplacePiece.staticValue = function (value) {
return new ReplacePiece(value, -1);
};
ReplacePiece.matchIndex = function (index) {
return new ReplacePiece(null, index);
};
return ReplacePiece;
}());
export { ReplacePiece };
var ReplacePieceBuilder = /** @class */ (function () {
function ReplacePieceBuilder(source) {
this._source = source;
this._lastCharIndex = 0;
this._result = [];
this._resultLen = 0;
this._currentStaticPiece = '';
}
ReplacePieceBuilder.prototype.emitUnchanged = function (toCharIndex) {
this._emitStatic(this._source.substring(this._lastCharIndex, toCharIndex));
this._lastCharIndex = toCharIndex;
};
ReplacePieceBuilder.prototype.emitStatic = function (value, toCharIndex) {
this._emitStatic(value);
this._lastCharIndex = toCharIndex;
};
ReplacePieceBuilder.prototype._emitStatic = function (value) {
if (value.length === 0) {
return;
}
this._currentStaticPiece += value;
};
ReplacePieceBuilder.prototype.emitMatchIndex = function (index, toCharIndex) {
if (this._currentStaticPiece.length !== 0) {
this._result[this._resultLen++] = ReplacePiece.staticValue(this._currentStaticPiece);
this._currentStaticPiece = '';
}
this._result[this._resultLen++] = ReplacePiece.matchIndex(index);
this._lastCharIndex = toCharIndex;
};
ReplacePieceBuilder.prototype.finalize = function () {
this.emitUnchanged(this._source.length);
if (this._currentStaticPiece.length !== 0) {
this._result[this._resultLen++] = ReplacePiece.staticValue(this._currentStaticPiece);
this._currentStaticPiece = '';
}
return new ReplacePattern(this._result);
};
return ReplacePieceBuilder;
}());
/**
* \n => inserts a LF
* \t => inserts a TAB
* \\ => inserts a "\".
* $$ => inserts a "$".
* $& and $0 => inserts the matched substring.
* $n => Where n is a non-negative integer lesser than 100, inserts the nth parenthesized submatch string
* everything else stays untouched
*
* Also see https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/replace#Specifying_a_string_as_a_parameter
*/
export function parseReplaceString(replaceString) {
if (!replaceString || replaceString.length === 0) {
return new ReplacePattern(null);
}
var result = new ReplacePieceBuilder(replaceString);
for (var i = 0, len = replaceString.length; i < len; i++) {
var chCode = replaceString.charCodeAt(i);
if (chCode === 92 /* Backslash */) {
// move to next char
i++;
if (i >= len) {
// string ends with a \
break;
}
var nextChCode = replaceString.charCodeAt(i);
// let replaceWithCharacter: string | null = null;
switch (nextChCode) {
case 92 /* Backslash */:
// \\ => inserts a "\"
result.emitUnchanged(i - 1);
result.emitStatic('\\', i + 1);
break;
case 110 /* n */:
// \n => inserts a LF
result.emitUnchanged(i - 1);
result.emitStatic('\n', i + 1);
break;
case 116 /* t */:
// \t => inserts a TAB
result.emitUnchanged(i - 1);
result.emitStatic('\t', i + 1);
break;
}
continue;
}
if (chCode === 36 /* DollarSign */) {
// move to next char
i++;
if (i >= len) {
// string ends with a $
break;
}
var nextChCode = replaceString.charCodeAt(i);
if (nextChCode === 36 /* DollarSign */) {
// $$ => inserts a "$"
result.emitUnchanged(i - 1);
result.emitStatic('$', i + 1);
continue;
}
if (nextChCode === 48 /* Digit0 */ || nextChCode === 38 /* Ampersand */) {
// $& and $0 => inserts the matched substring.
result.emitUnchanged(i - 1);
result.emitMatchIndex(0, i + 1);
continue;
}
if (49 /* Digit1 */ <= nextChCode && nextChCode <= 57 /* Digit9 */) {
// $n
var matchIndex = nextChCode - 48 /* Digit0 */;
// peek next char to probe for $nn
if (i + 1 < len) {
var nextNextChCode = replaceString.charCodeAt(i + 1);
if (48 /* Digit0 */ <= nextNextChCode && nextNextChCode <= 57 /* Digit9 */) {
// $nn
// move to next char
i++;
matchIndex = matchIndex * 10 + (nextNextChCode - 48 /* Digit0 */);
result.emitUnchanged(i - 2);
result.emitMatchIndex(matchIndex, i + 1);
continue;
}
}
result.emitUnchanged(i - 1);
result.emitMatchIndex(matchIndex, i + 1);
continue;
}
}
}
return result.finalize();
}