find @-moz-doc sections faster in the editor

This commit is contained in:
tophf 2019-09-22 15:24:59 +03:00
parent d8c2cd449e
commit d8e2dcb2e8

View File

@ -5,6 +5,7 @@
function createAppliesToLineWidget(cm) { function createAppliesToLineWidget(cm) {
const THROTTLE_DELAY = 400; const THROTTLE_DELAY = 400;
const RX_SPACE = /(?:\s+|\s*\/\*)+/y;
let TPL, EVENTS, CLICK_ROUTE; let TPL, EVENTS, CLICK_ROUTE;
let widgets = []; let widgets = [];
let fromLine, toLine, actualStyle; let fromLine, toLine, actualStyle;
@ -294,21 +295,15 @@ function createAppliesToLineWidget(cm) {
const toPos = {line: widgets[j] ? widgets[j].line.lineNo() : toLine + 1, ch: 0}; const toPos = {line: widgets[j] ? widgets[j].line.lineNo() : toLine + 1, ch: 0};
// calc index->pos lookup table // calc index->pos lookup table
let line = 0;
let index = 0; let index = 0;
let fromIndex, toIndex; const lineIndexes = [0];
const lineIndexes = [index]; cm.doc.iter(0, toPos.line + 1, ({text}) => {
cm.doc.iter(({text}) => {
fromIndex = line === fromPos.line ? index : fromIndex;
lineIndexes.push((index += text.length + 1)); lineIndexes.push((index += text.length + 1));
line++;
toIndex = line >= toPos.line ? index : toIndex;
return toIndex;
}); });
// splice // splice
i = Math.max(0, i); i = Math.max(0, i);
widgets.splice(i, 0, ...createWidgets(fromIndex, toIndex, widgets.splice(i, j - i), lineIndexes)); widgets.splice(i, 0, ...createWidgets(fromPos, toPos, widgets.splice(i, j - i), lineIndexes));
fromLine = null; fromLine = null;
toLine = null; toLine = null;
@ -317,7 +312,7 @@ function createAppliesToLineWidget(cm) {
function *createWidgets(start, end, removed, lineIndexes) { function *createWidgets(start, end, removed, lineIndexes) {
let i = 0; let i = 0;
let itemHeight; let itemHeight;
for (const section of findAppliesTo(start, end)) { for (const section of findAppliesTo(start, end, lineIndexes)) {
let removedWidget = removed[i]; let removedWidget = removed[i];
while (removedWidget && removedWidget.line.lineNo() < section.pos.line) { while (removedWidget && removedWidget.line.lineNo() < section.pos.line) {
clearWidget(removed[i]); clearWidget(removed[i]);
@ -488,40 +483,77 @@ function createAppliesToLineWidget(cm) {
}; };
} }
function *findAppliesTo(posStart, posEnd) { function *findAppliesTo(posStart, posEnd, lineIndexes) {
const text = cm.getValue(); const funcRe = /^(url|url-prefix|domain|regexp)$/i;
const re = /^[\t ]*@-moz-document[\s\n]+/gm; let pos;
const applyRe = new RegExp([ const eatToken = sticky => {
/(?:\/\*[\s\S]*?(?:\*\/\s*|$))*/, if (!sticky) skipSpace(pos, posEnd);
/(url|url-prefix|domain|regexp)/, pos.ch++;
/\(((['"])(?:\\\\|\\\n|\\\3|[^\n])*?\3|[^)\n]*)\)\s*(,\s*)?/, const token = cm.getTokenAt(pos);
].map(rx => rx.source).join(''), 'giy'); pos.ch = token.end;
let match; return CodeMirror.cmpPos(pos, posEnd) <= 0 ? token : {};
re.lastIndex = posStart; };
while ((match = re.exec(text))) { const docCur = cm.getSearchCursor('@-moz-document', posStart);
if (match.index >= posEnd) { while (docCur.findNext() &&
return; CodeMirror.cmpPos(docCur.pos.to, posEnd) <= 0) {
} if (!/\bdef\b/.test(cm.getTokenTypeAt(docCur.pos.from))) continue;
const applies = []; const applies = [];
let m; pos = docCur.pos.to;
applyRe.lastIndex = re.lastIndex; do {
while ((m = applyRe.exec(text))) { skipSpace(pos, posEnd);
const funcIndex = lineIndexes[pos.line] + pos.ch;
const func = eatToken().string;
// no space allowed before the opening parenthesis
if (!funcRe.test(func) || eatToken(true).string !== '(') break;
const url = eatToken();
if (url.type !== 'string' || eatToken().string !== ')') break;
const unquotedUrl = unquote(url.string);
const apply = createApply( const apply = createApply(
m.index, funcIndex,
m[1], func,
unquote(m[2]), unquotedUrl,
unquote(m[2]) !== m[2] unquotedUrl !== url.string
); );
applies.push(apply); applies.push(apply);
re.lastIndex = applyRe.lastIndex; } while (eatToken().string === ',');
}
yield { yield {
pos: cm.posFromIndex(match.index), pos: docCur.pos.from,
applies applies
}; };
} }
} }
function skipSpace(pos, posEnd) {
let {ch, line} = pos;
let lookForEnd;
line--;
cm.doc.iter(pos.line, posEnd.line + 1, ({text}) => {
line++;
while (true) {
if (lookForEnd) {
ch = text.indexOf('*/', ch) + 1;
if (!ch) {
return;
}
ch++;
lookForEnd = false;
}
RX_SPACE.lastIndex = ch;
const m = RX_SPACE.exec(text);
if (!m) {
return true;
}
ch += m[0].length;
lookForEnd = m[0].includes('/*');
if (ch < text.length && !lookForEnd) {
return true;
}
}
});
pos.line = line;
pos.ch = ch;
}
function unquote(s) { function unquote(s) {
const first = s.charAt(0); const first = s.charAt(0);
return (first === '"' || first === "'") && s.endsWith(first) ? s.slice(1, -1) : s; return (first === '"' || first === "'") && s.endsWith(first) ? s.slice(1, -1) : s;