Skip to content

Commit 4d8ae34

Browse files
committed
Changeset: Add documentation for textLinesMutator()
1 parent 0de41ee commit 4d8ae34

File tree

1 file changed

+106
-3
lines changed

1 file changed

+106
-3
lines changed

src/static/js/Changeset.js

Lines changed: 106 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -550,22 +550,37 @@ exports.textLinesMutator = (lines) => {
550550
// is not actually a newline, but for the purposes of N and L values,
551551
// the caller should pretend it is, and for things to work right in that case, the input
552552
// to insert() should be a single line with no newlines.
553+
554+
// The splice holds information which lines are to be deleted or changed.
555+
// curSplice[0] is an index into the lines array
556+
// curSplice[1] is the number of lines that will be removed from lines
557+
// the other elements represent mutated (changed by ops) lines or new lines (added by ops)
553558
const curSplice = [0, 0];
554559
let inSplice = false;
555-
// position in document after curSplice is applied:
560+
561+
// position in lines after curSplice is applied:
556562
let curLine = 0;
557563
let curCol = 0;
558564
// invariant: if (inSplice) then (curLine is in curSplice[0] + curSplice.length - {2,3}) &&
559565
// curLine >= curSplice[0]
560566
// invariant: if (inSplice && (curLine >= curSplice[0] + curSplice.length - 2)) then
561567
// curCol == 0
562568

569+
/**
570+
* Adds and/or removes entries at a specific offset in lines array
571+
* It is called when leaving the splice
572+
* @param {Array} s curSplice
573+
*/
563574
const lines_applySplice = (s) => {
564575
lines.splice.apply(lines, s);
565576
};
566577

567578
const lines_toSource = () => lines.toSource();
568579

580+
/**
581+
* Get a line from lines at given index
582+
* @param {Number} idx an index
583+
*/
569584
const lines_get = (idx) => {
570585
if (lines.get) {
571586
return lines.get(idx);
@@ -575,6 +590,11 @@ exports.textLinesMutator = (lines) => {
575590
};
576591
// can be unimplemented if removeLines's return value not needed
577592

593+
/**
594+
* Return a slice from lines array
595+
* @param {Number} start the start index
596+
* @param {Number} end the end index
597+
*/
578598
const lines_slice = (start, end) => {
579599
if (lines.slice) {
580600
return lines.slice(start, end);
@@ -583,6 +603,9 @@ exports.textLinesMutator = (lines) => {
583603
}
584604
};
585605

606+
/**
607+
* Return the length of lines array
608+
*/
586609
const lines_length = () => {
587610
if ((typeof lines.length) === 'number') {
588611
return lines.length;
@@ -591,42 +614,71 @@ exports.textLinesMutator = (lines) => {
591614
}
592615
};
593616

617+
/**
618+
* Starts a new splice.
619+
*/
594620
const enterSplice = () => {
595621
curSplice[0] = curLine;
596622
curSplice[1] = 0;
623+
// TODO(doc) when is this the case?
624+
// check all enterSplice calls and changes to curCol
597625
if (curCol > 0) {
598626
putCurLineInSplice();
599627
}
600628
inSplice = true;
601629
};
602630

631+
/**
632+
* Changes the lines array according to the values in curSplice
633+
* and resets curSplice.
634+
* This is called via close or TODO(doc)
635+
*/
603636
const leaveSplice = () => {
604637
lines_applySplice(curSplice);
605638
curSplice.length = 2;
606639
curSplice[0] = curSplice[1] = 0;
607640
inSplice = false;
608641
};
609642

643+
/**
644+
* Indicates if curLine is already in the splice. This is necessary because the last element in
645+
* curSplice is curLine when this line is currently worked on (e.g. when skipping are inserting)
646+
*
647+
* TODO(doc) why aren't removals considered?
648+
* @returns {Boolean} true if curLine is in splice
649+
*/
610650
const isCurLineInSplice = () => (curLine - curSplice[0] < (curSplice.length - 2));
611651

612652
const debugPrint = (typ) => { /* eslint-disable-line no-unused-vars */
613653
print(`${typ}: ${curSplice.toSource()} / ${curLine},${curCol} / ${lines_toSource()}`);
614654
};
615655

656+
/**
657+
* Incorporates current line into the splice
658+
* and marks its old position to be deleted.
659+
*
660+
* @returns {Number} the index of the added line in curSplice
661+
*/
616662
const putCurLineInSplice = () => {
617663
if (!isCurLineInSplice()) {
618664
curSplice.push(lines_get(curSplice[0] + curSplice[1]));
619665
curSplice[1]++;
620666
}
621-
return 2 + curLine - curSplice[0];
667+
return 2 + curLine - curSplice[0]; // TODO should be the same as curSplice.length - 1
622668
};
623669

670+
/**
671+
* It will skip some newlines by putting them into the splice.
672+
*
673+
* @param {Boolean} includeInSplice indicates if attributes are present
674+
*/
624675
const skipLines = (L, includeInSplice) => {
625676
if (L) {
626677
if (includeInSplice) {
627678
if (!inSplice) {
628679
enterSplice();
629680
}
681+
// TODO(doc) should this count the number of characters that are skipped to check?
630682
for (let i = 0; i < L; i++) {
631683
curCol = 0;
632684
putCurLineInSplice();
@@ -635,6 +687,7 @@ exports.textLinesMutator = (lines) => {
635687
} else {
636688
if (inSplice) {
637689
if (L > 1) {
690+
// TODO(doc) figure out why single lines are incorporated into splice instead of ignored
638691
leaveSplice();
639692
} else {
640693
putCurLineInSplice();
@@ -647,6 +700,13 @@ exports.textLinesMutator = (lines) => {
647700
}
648701
};
649702

703+
/**
704+
* Skip some characters. Can contain newlines.
705+
*
706+
* @param {Number} N number of characters to skip
707+
* @param {Number} L number of newlines to skip
708+
* @param {Boolean} includeInSplice indicates if attributes are present
709+
*/
650710
const skip = (N, L, includeInSplice) => {
651711
if (N) {
652712
if (L) {
@@ -656,20 +716,33 @@ exports.textLinesMutator = (lines) => {
656716
enterSplice();
657717
}
658718
if (inSplice) {
719+
// although the line is put into splice curLine is not increased, because
720+
// only some chars are skipped, not the whole line
659721
putCurLineInSplice();
660722
}
661723
curCol += N;
662724
}
663725
}
664726
};
665727

728+
/**
729+
* Remove whole lines from lines array
730+
*
731+
* @param {Number} L number of lines to be removed
732+
*/
666733
const removeLines = (L) => {
667734
let removed = '';
668735
if (L) {
669736
if (!inSplice) {
670737
enterSplice();
671738
}
672739

740+
/**
741+
* Gets a string of joined lines after the end of the splice
742+
*
743+
* @param k {Number} number of lines
744+
* @returns {String} joined lines
745+
*/
673746
const nextKLinesText = (k) => {
674747
const m = curSplice[0] + curSplice[1];
675748
return lines_slice(m, m + k).join('');
@@ -697,6 +770,12 @@ exports.textLinesMutator = (lines) => {
697770
return removed;
698771
};
699772

773+
/**
774+
* Remove text from lines array
775+
*
776+
* @param N {Number} characters to delete
777+
* @param L {Number} lines to delete
778+
*/
700779
const remove = (N, L) => {
701780
let removed = '';
702781
if (N) {
@@ -706,6 +785,8 @@ exports.textLinesMutator = (lines) => {
706785
if (!inSplice) {
707786
enterSplice();
708787
}
788+
// although the line is put into splice, curLine is not increased, because
789+
// only some chars are removed not the whole line
709790
const sline = putCurLineInSplice();
710791
removed = curSplice[sline].substring(curCol, curCol + N);
711792
curSplice[sline] = curSplice[sline].substring(0, curCol) +
@@ -715,6 +796,12 @@ exports.textLinesMutator = (lines) => {
715796
return removed;
716797
};
717798

799+
/**
800+
* Inserts text into lines array.
801+
*
802+
* @param text {String} the text to insert
803+
* @param L {Number} number of newlines in text
804+
*/
718805
const insert = (text, L) => {
719806
if (text) {
720807
if (!inSplice) {
@@ -726,18 +813,25 @@ exports.textLinesMutator = (lines) => {
726813
const sline = curSplice.length - 1;
727814
const theLine = curSplice[sline];
728815
const lineCol = curCol;
816+
// insert the first new line
729817
curSplice[sline] = theLine.substring(0, lineCol) + newLines[0];
730818
curLine++;
731819
newLines.splice(0, 1);
820+
// insert the remaining new lines
732821
Array.prototype.push.apply(curSplice, newLines);
733822
curLine += newLines.length;
823+
// insert the remaining chars from the "old" line (e.g. the line we were in
824+
// when we started to insert new lines)
734825
curSplice.push(theLine.substring(lineCol));
735-
curCol = 0;
826+
curCol = 0; // TODO(doc) why is this not set to the length of last line?
736827
} else {
737828
Array.prototype.push.apply(curSplice, newLines);
738829
curLine += newLines.length;
739830
}
740831
} else {
832+
// there are no additional lines
833+
// although the line is put into splice, curLine is not increased, because
834+
// there may be more chars in the line (newline is not reached)
741835
const sline = putCurLineInSplice();
742836
if (!curSplice[sline]) {
743837
console.error('curSplice[sline] not populated, actual curSplice contents is ', curSplice, '. Possibly related to https://github.com/ether/etherpad-lite/issues/2802');
@@ -749,6 +843,12 @@ exports.textLinesMutator = (lines) => {
749843
}
750844
};
751845

846+
/**
847+
* Checks if curLine (the line we are in when curSplice is applied) is the last line
848+
* in lines.
849+
*
850+
* @return {Boolean} indicates if there are lines left
851+
*/
752852
const hasMore = () => {
753853
let docLines = lines_length();
754854
if (inSplice) {
@@ -757,6 +857,9 @@ exports.textLinesMutator = (lines) => {
757857
return curLine < docLines;
758858
};
759859

860+
/**
861+
* Closes the splice
862+
*/
760863
const close = () => {
761864
if (inSplice) {
762865
leaveSplice();

0 commit comments

Comments
 (0)