ce924da6da9cfcb040a4fcf813bf2fa07f544672a483d94d86e959b2025883c20dc195da435886f8d4badd36748836332168e8c26a8bd8acac00afd4e502b6 2.2 KB

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