Skip to content

Commit 4f9a3c0

Browse files
committed
Changeset: Turn smartOpAssembler() into a real class
1 parent d14d473 commit 4f9a3c0

File tree

1 file changed

+93
-104
lines changed

1 file changed

+93
-104
lines changed

src/static/js/Changeset.js

Lines changed: 93 additions & 104 deletions
Original file line numberDiff line numberDiff line change
@@ -424,15 +424,93 @@ const opsFromText = function* (opcode, text, attribs = '', pool = null) {
424424
* - strips final "="
425425
* - ignores 0-length changes
426426
* - reorders consecutive + and - (which MergingOpAssembler doesn't do)
427-
*
428-
* @typedef {object} SmartOpAssembler
429-
* @property {Function} append -
430-
* @property {Function} appendOpWithText -
431-
* @property {Function} clear -
432-
* @property {Function} endDocument -
433-
* @property {Function} getLengthChange -
434-
* @property {Function} toString -
435427
*/
428+
class SmartOpAssembler {
429+
constructor() {
430+
this._minusAssem = new MergingOpAssembler();
431+
this._plusAssem = new MergingOpAssembler();
432+
this._keepAssem = new MergingOpAssembler();
433+
this._assem = exports.stringAssembler();
434+
this._lastOpcode = '';
435+
this._lengthChange = 0;
436+
}
437+
438+
clear() {
439+
this._minusAssem.clear();
440+
this._plusAssem.clear();
441+
this._keepAssem.clear();
442+
this._assem.clear();
443+
this._lengthChange = 0;
444+
}
445+
446+
_flushKeeps() {
447+
this._assem.append(this._keepAssem.toString());
448+
this._keepAssem.clear();
449+
}
450+
451+
_flushPlusMinus() {
452+
this._assem.append(this._minusAssem.toString());
453+
this._minusAssem.clear();
454+
this._assem.append(this._plusAssem.toString());
455+
this._plusAssem.clear();
456+
}
457+
458+
append(op) {
459+
if (!op.opcode) return;
460+
if (!op.chars) return;
461+
462+
if (op.opcode === '-') {
463+
if (this._lastOpcode === '=') {
464+
this._flushKeeps();
465+
}
466+
this._minusAssem.append(op);
467+
this._lengthChange -= op.chars;
468+
} else if (op.opcode === '+') {
469+
if (this._lastOpcode === '=') {
470+
this._flushKeeps();
471+
}
472+
this._plusAssem.append(op);
473+
this._lengthChange += op.chars;
474+
} else if (op.opcode === '=') {
475+
if (this._lastOpcode !== '=') {
476+
this._flushPlusMinus();
477+
}
478+
this._keepAssem.append(op);
479+
}
480+
this._lastOpcode = op.opcode;
481+
}
482+
483+
/**
484+
* Generates operations from the given text and attributes.
485+
*
486+
* @deprecated Use `opsFromText` instead.
487+
* @param {('-'|'+'|'=')} opcode - The operator to use.
488+
* @param {string} text - The text to remove/add/keep.
489+
* @param {(string|Iterable<Attribute>)} attribs - The attributes to apply to the operations.
490+
* @param {?AttributePool} pool - Attribute pool. Only required if `attribs` is an iterable of
491+
* attribute key, value pairs.
492+
*/
493+
appendOpWithText(opcode, text, attribs, pool) {
494+
padutils.warnWithStack(
495+
'Changeset.SmartOpAssembler.prototype.appendOpWithText() is deprecated; ' +
496+
'use opsFromText() instead.');
497+
for (const op of opsFromText(opcode, text, attribs, pool)) this.append(op);
498+
}
499+
500+
toString() {
501+
this._flushPlusMinus();
502+
this._flushKeeps();
503+
return this._assem.toString();
504+
}
505+
506+
endDocument() {
507+
this._keepAssem.endDocument();
508+
}
509+
510+
getLengthChange() {
511+
return this._lengthChange;
512+
}
513+
}
436514

437515
/**
438516
* Used to check if a Changeset is valid. This function does not check things that require access to
@@ -448,7 +526,7 @@ exports.checkRep = (cs) => {
448526
const ops = unpacked.ops;
449527
let charBank = unpacked.charBank;
450528

451-
const assem = exports.smartOpAssembler();
529+
const assem = new SmartOpAssembler();
452530
let oldPos = 0;
453531
let calcNewLen = 0;
454532
for (const o of exports.deserializeOps(ops)) {
@@ -492,96 +570,7 @@ exports.checkRep = (cs) => {
492570
/**
493571
* @returns {SmartOpAssembler}
494572
*/
495-
exports.smartOpAssembler = () => {
496-
const minusAssem = new MergingOpAssembler();
497-
const plusAssem = new MergingOpAssembler();
498-
const keepAssem = new MergingOpAssembler();
499-
const assem = exports.stringAssembler();
500-
let lastOpcode = '';
501-
let lengthChange = 0;
502-
503-
const flushKeeps = () => {
504-
assem.append(keepAssem.toString());
505-
keepAssem.clear();
506-
};
507-
508-
const flushPlusMinus = () => {
509-
assem.append(minusAssem.toString());
510-
minusAssem.clear();
511-
assem.append(plusAssem.toString());
512-
plusAssem.clear();
513-
};
514-
515-
const append = (op) => {
516-
if (!op.opcode) return;
517-
if (!op.chars) return;
518-
519-
if (op.opcode === '-') {
520-
if (lastOpcode === '=') {
521-
flushKeeps();
522-
}
523-
minusAssem.append(op);
524-
lengthChange -= op.chars;
525-
} else if (op.opcode === '+') {
526-
if (lastOpcode === '=') {
527-
flushKeeps();
528-
}
529-
plusAssem.append(op);
530-
lengthChange += op.chars;
531-
} else if (op.opcode === '=') {
532-
if (lastOpcode !== '=') {
533-
flushPlusMinus();
534-
}
535-
keepAssem.append(op);
536-
}
537-
lastOpcode = op.opcode;
538-
};
539-
540-
/**
541-
* Generates operations from the given text and attributes.
542-
*
543-
* @deprecated Use `opsFromText` instead.
544-
* @param {('-'|'+'|'=')} opcode - The operator to use.
545-
* @param {string} text - The text to remove/add/keep.
546-
* @param {(string|Iterable<Attribute>)} attribs - The attributes to apply to the operations.
547-
* @param {?AttributePool} pool - Attribute pool. Only required if `attribs` is an iterable of
548-
* attribute key, value pairs.
549-
*/
550-
const appendOpWithText = (opcode, text, attribs, pool) => {
551-
padutils.warnWithStack('Changeset.smartOpAssembler().appendOpWithText() is deprecated; ' +
552-
'use opsFromText() instead.');
553-
for (const op of opsFromText(opcode, text, attribs, pool)) append(op);
554-
};
555-
556-
const toString = () => {
557-
flushPlusMinus();
558-
flushKeeps();
559-
return assem.toString();
560-
};
561-
562-
const clear = () => {
563-
minusAssem.clear();
564-
plusAssem.clear();
565-
keepAssem.clear();
566-
assem.clear();
567-
lengthChange = 0;
568-
};
569-
570-
const endDocument = () => {
571-
keepAssem.endDocument();
572-
};
573-
574-
const getLengthChange = () => lengthChange;
575-
576-
return {
577-
append,
578-
toString,
579-
clear,
580-
endDocument,
581-
appendOpWithText,
582-
getLengthChange,
583-
};
584-
};
573+
exports.smartOpAssembler = () => new SmartOpAssembler();
585574

586575
/**
587576
* @returns {MergingOpAssembler}
@@ -1023,7 +1012,7 @@ const applyZip = (in1, in2, func) => {
10231012
const ops2 = exports.deserializeOps(in2);
10241013
let next1 = ops1.next();
10251014
let next2 = ops2.next();
1026-
const assem = exports.smartOpAssembler();
1015+
const assem = new SmartOpAssembler();
10271016
while (!next1.done || !next2.done) {
10281017
if (!next1.done && !next1.value.opcode) next1 = ops1.next();
10291018
if (!next2.done && !next2.value.opcode) next2 = ops2.next();
@@ -1484,7 +1473,7 @@ exports.makeSplice = (oldFullText, spliceStart, numRemoved, newText, optNewTextA
14841473
const oldText = oldFullText.substring(spliceStart, spliceStart + numRemoved);
14851474
const newLen = oldLen + newText.length - oldText.length;
14861475

1487-
const assem = exports.smartOpAssembler();
1476+
const assem = new SmartOpAssembler();
14881477
const ops = (function* () {
14891478
yield* opsFromText('=', oldFullText.substring(0, spliceStart));
14901479
yield* opsFromText('-', oldText);
@@ -1615,7 +1604,7 @@ exports.moveOpsToNewPool = (cs, oldPool, newPool) => {
16151604
* @returns {string}
16161605
*/
16171606
exports.makeAttribution = (text) => {
1618-
const assem = exports.smartOpAssembler();
1607+
const assem = new SmartOpAssembler();
16191608
for (const op of opsFromText('+', text)) assem.append(op);
16201609
return assem.toString();
16211610
};
@@ -1871,7 +1860,7 @@ exports.attribsAttributeValue = (attribs, key, pool) => {
18711860
* @returns {Builder}
18721861
*/
18731862
exports.builder = (oldLen) => {
1874-
const assem = exports.smartOpAssembler();
1863+
const assem = new SmartOpAssembler();
18751864
const o = new Op();
18761865
const charBank = exports.stringAssembler();
18771866

@@ -1976,7 +1965,7 @@ exports.makeAttribsString = (opcode, attribs, pool) => {
19761965
exports.subattribution = (astr, start, optEnd) => {
19771966
const attOps = exports.deserializeOps(astr);
19781967
let attOpsNext = attOps.next();
1979-
const assem = exports.smartOpAssembler();
1968+
const assem = new SmartOpAssembler();
19801969
let attOp = new Op();
19811970
const csOp = new Op();
19821971

0 commit comments

Comments
 (0)