@jupyter-lsp/jupyterlab-lsp
Version:
Language Server Protocol integration for JupyterLab
125 lines • 5.45 kB
JavaScript
import { positionAtOffset } from '@jupyterlab/lsp';
export function getIndexOfCaptureGroup(expression, matchedString, valueOfCapturedGroup) {
// TODO: use https://github.com/tc39/proposal-regexp-match-indices once supported in >95% of browsers
// (probably around 2025)
// get index of the part that is being extracted to foreign document
let capturedGroups = expression.exec(matchedString);
if (capturedGroups == null) {
console.warn(`No capture group found for ${expression} in ${matchedString}`);
return -1;
}
let offsetInMatch = 0;
// first element is a full match
let fullMatched = capturedGroups[0];
for (let group of capturedGroups.slice(1)) {
if (typeof group === 'undefined') {
continue;
}
if (group === valueOfCapturedGroup) {
offsetInMatch += fullMatched.indexOf(group);
break;
}
let groupEndOffset = fullMatched.indexOf(group) + group.length;
fullMatched = fullMatched.slice(groupEndOffset);
offsetInMatch += groupEndOffset;
}
return offsetInMatch;
}
export class RegExpForeignCodeExtractor {
constructor(options) {
this.cellType = ['code'];
this.language = options.language;
this.options = options;
this.globalExpression = new RegExp(options.pattern, 'g');
this.testExpression = new RegExp(options.pattern, 'g');
this.expression = new RegExp(options.pattern);
this.standalone = this.options.isStandalone;
this.fileExtension = this.options.fileExtension;
}
hasForeignCode(code) {
const result = this.testExpression.test(code);
this.testExpression.lastIndex = 0;
return result;
}
extractForeignCode(code) {
const lines = code.split('\n');
const extracts = new Array();
let startedFrom = this.globalExpression.lastIndex;
let match = this.globalExpression.exec(code);
let hostCodeFragment;
let chosenReplacer;
let isNewApiReplacer = false;
if (typeof this.options.foreignReplacer !== 'undefined') {
chosenReplacer = this.options.foreignReplacer;
isNewApiReplacer = true;
}
else if (typeof this.options.foreignCaptureGroups !== 'undefined') {
chosenReplacer = '$' + this.options.foreignCaptureGroups.join('$');
isNewApiReplacer = true;
}
else if (this.options.extractToForeign) {
chosenReplacer = this.options.extractToForeign;
}
else {
console.warn(`Foreign replacer not defined for extractor: {this.expression} - this is deprecated; use 'foreignReplacer' to define it`);
return [];
}
while (match != null) {
let matchedString = match[0];
let positionShift = null;
let foreignCodeFragment = matchedString.replace(this.expression,
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
// @ts-ignore
chosenReplacer);
let prefix = '';
if (typeof this.options.extractArguments !== 'undefined') {
prefix = matchedString.replace(this.expression,
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
// @ts-ignore
this.options.extractArguments);
positionShift = positionAtOffset(prefix.length, prefix.split('\n'));
}
// NOTE:
// match.index + matchedString.length === this.sticky_expression.lastIndex
let endIndex = this.globalExpression.lastIndex;
if (this.options.keepInHost || this.options.keepInHost == null) {
hostCodeFragment = code.substring(startedFrom, endIndex);
}
else {
if (startedFrom === match.index) {
hostCodeFragment = '';
}
else {
hostCodeFragment = code.substring(startedFrom, match.index) + '\n';
}
}
let foreignCodeGroupValue = foreignCodeFragment;
if (isNewApiReplacer) {
foreignCodeGroupValue = matchedString.replace(this.expression, '$' + Math.min(...this.options.foreignCaptureGroups));
}
const foreignGroupIndexInMatch = getIndexOfCaptureGroup(this.expression, matchedString, foreignCodeGroupValue);
let startOffset = match.index + foreignGroupIndexInMatch;
let start = positionAtOffset(startOffset, lines);
let end = positionAtOffset(startOffset + foreignCodeFragment.length, lines);
extracts.push({
hostCode: hostCodeFragment,
foreignCode: prefix + foreignCodeFragment,
range: { start, end },
virtualShift: positionShift
});
startedFrom = this.globalExpression.lastIndex;
match = this.globalExpression.exec(code);
}
if (startedFrom !== code.length) {
let finalHostCodeFragment = code.substring(startedFrom, code.length);
extracts.push({
hostCode: finalHostCodeFragment,
foreignCode: null,
range: null,
virtualShift: null
});
}
return extracts;
}
}
//# sourceMappingURL=regexp.js.map