File modules/editor/codemirror/src/model/chunk.min.js
Last commit: Tue May 22 22:39:53 2018 +0200 Jan Dankert Fix für PHP 7.2: 'Object' darf nun nicht mehr als Klassennamen verwendet werden. AUCH NICHT IN EINEM NAMESPACE! WTF, wozu habe ich das in einen verfickten Namespace gepackt? Wozu soll der sonst da sein??? Amateure. Daher nun notgedrungen unbenannt in 'BaseObject'.
1 import { cleanUpLine } from "../line/line_data.js" 2 import { indexOf } from "../util/misc.js" 3 import { signalLater } from "../util/operation_group.js" 4 5 // The document is represented as a BTree consisting of leaves, with 6 // chunk of lines in them, and branches, with up to ten leaves or 7 // other branch nodes below them. The top node is always a branch 8 // node, and is the document object itself (meaning it has 9 // additional methods and properties). 10 // 11 // All nodes have parent links. The tree is used both to go from 12 // line numbers to line objects, and to go from objects to numbers. 13 // It also indexes by height, and is used to convert between height 14 // and line object, and to find the total height of the document. 15 // 16 // See also http://marijnhaverbeke.nl/blog/codemirror-line-tree.html 17 18 export function LeafChunk(lines) { 19 this.lines = lines 20 this.parent = null 21 let height = 0 22 for (let i = 0; i < lines.length; ++i) { 23 lines[i].parent = this 24 height += lines[i].height 25 } 26 this.height = height 27 } 28 29 LeafChunk.prototype = { 30 chunkSize() { return this.lines.length }, 31 32 // Remove the n lines at offset 'at'. 33 removeInner(at, n) { 34 for (let i = at, e = at + n; i < e; ++i) { 35 let line = this.lines[i] 36 this.height -= line.height 37 cleanUpLine(line) 38 signalLater(line, "delete") 39 } 40 this.lines.splice(at, n) 41 }, 42 43 // Helper used to collapse a small branch into a single leaf. 44 collapse(lines) { 45 lines.push.apply(lines, this.lines) 46 }, 47 48 // Insert the given array of lines at offset 'at', count them as 49 // having the given height. 50 insertInner(at, lines, height) { 51 this.height += height 52 this.lines = this.lines.slice(0, at).concat(lines).concat(this.lines.slice(at)) 53 for (let i = 0; i < lines.length; ++i) lines[i].parent = this 54 }, 55 56 // Used to iterate over a part of the tree. 57 iterN(at, n, op) { 58 for (let e = at + n; at < e; ++at) 59 if (op(this.lines[at])) return true 60 } 61 } 62 63 export function BranchChunk(children) { 64 this.children = children 65 let size = 0, height = 0 66 for (let i = 0; i < children.length; ++i) { 67 let ch = children[i] 68 size += ch.chunkSize(); height += ch.height 69 ch.parent = this 70 } 71 this.size = size 72 this.height = height 73 this.parent = null 74 } 75 76 BranchChunk.prototype = { 77 chunkSize() { return this.size }, 78 79 removeInner(at, n) { 80 this.size -= n 81 for (let i = 0; i < this.children.length; ++i) { 82 let child = this.children[i], sz = child.chunkSize() 83 if (at < sz) { 84 let rm = Math.min(n, sz - at), oldHeight = child.height 85 child.removeInner(at, rm) 86 this.height -= oldHeight - child.height 87 if (sz == rm) { this.children.splice(i--, 1); child.parent = null } 88 if ((n -= rm) == 0) break 89 at = 0 90 } else at -= sz 91 } 92 // If the result is smaller than 25 lines, ensure that it is a 93 // single leaf node. 94 if (this.size - n < 25 && 95 (this.children.length > 1 || !(this.children[0] instanceof LeafChunk))) { 96 let lines = [] 97 this.collapse(lines) 98 this.children = [new LeafChunk(lines)] 99 this.children[0].parent = this 100 } 101 }, 102 103 collapse(lines) { 104 for (let i = 0; i < this.children.length; ++i) this.children[i].collapse(lines) 105 }, 106 107 insertInner(at, lines, height) { 108 this.size += lines.length 109 this.height += height 110 for (let i = 0; i < this.children.length; ++i) { 111 let child = this.children[i], sz = child.chunkSize() 112 if (at <= sz) { 113 child.insertInner(at, lines, height) 114 if (child.lines && child.lines.length > 50) { 115 // To avoid memory thrashing when child.lines is huge (e.g. first view of a large file), it's never spliced. 116 // Instead, small slices are taken. They're taken in order because sequential memory accesses are fastest. 117 let remaining = child.lines.length % 25 + 25 118 for (let pos = remaining; pos < child.lines.length;) { 119 let leaf = new LeafChunk(child.lines.slice(pos, pos += 25)) 120 child.height -= leaf.height 121 this.children.splice(++i, 0, leaf) 122 leaf.parent = this 123 } 124 child.lines = child.lines.slice(0, remaining) 125 this.maybeSpill() 126 } 127 break 128 } 129 at -= sz 130 } 131 }, 132 133 // When a node has grown, check whether it should be split. 134 maybeSpill() { 135 if (this.children.length <= 10) return 136 let me = this 137 do { 138 let spilled = me.children.splice(me.children.length - 5, 5) 139 let sibling = new BranchChunk(spilled) 140 if (!me.parent) { // Become the parent node 141 let copy = new BranchChunk(me.children) 142 copy.parent = me 143 me.children = [copy, sibling] 144 me = copy 145 } else { 146 me.size -= sibling.size 147 me.height -= sibling.height 148 let myIndex = indexOf(me.parent.children, me) 149 me.parent.children.splice(myIndex + 1, 0, sibling) 150 } 151 sibling.parent = me.parent 152 } while (me.children.length > 10) 153 me.parent.maybeSpill() 154 }, 155 156 iterN(at, n, op) { 157 for (let i = 0; i < this.children.length; ++i) { 158 let child = this.children[i], sz = child.chunkSize() 159 if (at < sz) { 160 let used = Math.min(n, sz - at) 161 if (child.iterN(at, used, op)) return true 162 if ((n -= used) == 0) break 163 at = 0 164 } else at -= sz 165 } 166 } 167 }
Downloadmodules/editor/codemirror/src/model/chunk.min.js
History Tue, 22 May 2018 22:39:53 +0200 Jan Dankert Fix für PHP 7.2: 'Object' darf nun nicht mehr als Klassennamen verwendet werden. AUCH NICHT IN EINEM NAMESPACE! WTF, wozu habe ich das in einen verfickten Namespace gepackt? Wozu soll der sonst da sein??? Amateure. Daher nun notgedrungen unbenannt in 'BaseObject'.