change_measurement.js (2221B)
1 import { cmp, Pos } from "../line/pos.js" 2 import { lst } from "../util/misc.js" 3 4 import { normalizeSelection, Range, Selection } from "./selection.js" 5 6 // Compute the position of the end of a change (its 'to' property 7 // refers to the pre-change end). 8 export function changeEnd(change) { 9 if (!change.text) return change.to 10 return Pos(change.from.line + change.text.length - 1, 11 lst(change.text).length + (change.text.length == 1 ? change.from.ch : 0)) 12 } 13 14 // Adjust a position to refer to the post-change position of the 15 // same text, or the end of the change if the change covers it. 16 function adjustForChange(pos, change) { 17 if (cmp(pos, change.from) < 0) return pos 18 if (cmp(pos, change.to) <= 0) return changeEnd(change) 19 20 let line = pos.line + change.text.length - (change.to.line - change.from.line) - 1, ch = pos.ch 21 if (pos.line == change.to.line) ch += changeEnd(change).ch - change.to.ch 22 return Pos(line, ch) 23 } 24 25 export function computeSelAfterChange(doc, change) { 26 let out = [] 27 for (let i = 0; i < doc.sel.ranges.length; i++) { 28 let range = doc.sel.ranges[i] 29 out.push(new Range(adjustForChange(range.anchor, change), 30 adjustForChange(range.head, change))) 31 } 32 return normalizeSelection(out, doc.sel.primIndex) 33 } 34 35 function offsetPos(pos, old, nw) { 36 if (pos.line == old.line) 37 return Pos(nw.line, pos.ch - old.ch + nw.ch) 38 else 39 return Pos(nw.line + (pos.line - old.line), pos.ch) 40 } 41 42 // Used by replaceSelections to allow moving the selection to the 43 // start or around the replaced test. Hint may be "start" or "around". 44 export function computeReplacedSel(doc, changes, hint) { 45 let out = [] 46 let oldPrev = Pos(doc.first, 0), newPrev = oldPrev 47 for (let i = 0; i < changes.length; i++) { 48 let change = changes[i] 49 let from = offsetPos(change.from, oldPrev, newPrev) 50 let to = offsetPos(changeEnd(change), oldPrev, newPrev) 51 oldPrev = change.to 52 newPrev = to 53 if (hint == "around") { 54 let range = doc.sel.ranges[i], inv = cmp(range.head, range.anchor) < 0 55 out[i] = new Range(inv ? to : from, inv ? from : to) 56 } else { 57 out[i] = new Range(from, from) 58 } 59 } 60 return new Selection(out, doc.sel.primIndex) 61 }