annotate .cms/lib/codemirror/src/model/selection.js @ 1:1d486627aa1e draft default tip

24.10
author Coffee CMS <info@coffee-cms.ru>
date Sat, 12 Oct 2024 02:51:39 +0000
parents 78edf6b517a0
children
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
rev   line source
0
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
1 import { cmp, copyPos, equalCursorPos, maxPos, minPos } from "../line/pos.js"
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
2 import { indexOf } from "../util/misc.js"
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
3
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
4 // Selection objects are immutable. A new one is created every time
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
5 // the selection changes. A selection is one or more non-overlapping
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
6 // (and non-touching) ranges, sorted, and an integer that indicates
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
7 // which one is the primary selection (the one that's scrolled into
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
8 // view, that getCursor returns, etc).
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
9 export class Selection {
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
10 constructor(ranges, primIndex) {
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
11 this.ranges = ranges
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
12 this.primIndex = primIndex
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
13 }
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
14
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
15 primary() { return this.ranges[this.primIndex] }
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
16
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
17 equals(other) {
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
18 if (other == this) return true
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
19 if (other.primIndex != this.primIndex || other.ranges.length != this.ranges.length) return false
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
20 for (let i = 0; i < this.ranges.length; i++) {
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
21 let here = this.ranges[i], there = other.ranges[i]
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
22 if (!equalCursorPos(here.anchor, there.anchor) || !equalCursorPos(here.head, there.head)) return false
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
23 }
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
24 return true
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
25 }
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
26
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
27 deepCopy() {
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
28 let out = []
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
29 for (let i = 0; i < this.ranges.length; i++)
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
30 out[i] = new Range(copyPos(this.ranges[i].anchor), copyPos(this.ranges[i].head))
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
31 return new Selection(out, this.primIndex)
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
32 }
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
33
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
34 somethingSelected() {
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
35 for (let i = 0; i < this.ranges.length; i++)
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
36 if (!this.ranges[i].empty()) return true
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
37 return false
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
38 }
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
39
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
40 contains(pos, end) {
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
41 if (!end) end = pos
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
42 for (let i = 0; i < this.ranges.length; i++) {
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
43 let range = this.ranges[i]
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
44 if (cmp(end, range.from()) >= 0 && cmp(pos, range.to()) <= 0)
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
45 return i
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
46 }
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
47 return -1
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
48 }
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
49 }
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
50
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
51 export class Range {
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
52 constructor(anchor, head) {
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
53 this.anchor = anchor; this.head = head
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
54 }
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
55
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
56 from() { return minPos(this.anchor, this.head) }
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
57 to() { return maxPos(this.anchor, this.head) }
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
58 empty() { return this.head.line == this.anchor.line && this.head.ch == this.anchor.ch }
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
59 }
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
60
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
61 // Take an unsorted, potentially overlapping set of ranges, and
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
62 // build a selection out of it. 'Consumes' ranges array (modifying
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
63 // it).
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
64 export function normalizeSelection(cm, ranges, primIndex) {
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
65 let mayTouch = cm && cm.options.selectionsMayTouch
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
66 let prim = ranges[primIndex]
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
67 ranges.sort((a, b) => cmp(a.from(), b.from()))
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
68 primIndex = indexOf(ranges, prim)
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
69 for (let i = 1; i < ranges.length; i++) {
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
70 let cur = ranges[i], prev = ranges[i - 1]
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
71 let diff = cmp(prev.to(), cur.from())
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
72 if (mayTouch && !cur.empty() ? diff > 0 : diff >= 0) {
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
73 let from = minPos(prev.from(), cur.from()), to = maxPos(prev.to(), cur.to())
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
74 let inv = prev.empty() ? cur.from() == cur.head : prev.from() == prev.head
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
75 if (i <= primIndex) --primIndex
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
76 ranges.splice(--i, 2, new Range(inv ? to : from, inv ? from : to))
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
77 }
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
78 }
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
79 return new Selection(ranges, primIndex)
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
80 }
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
81
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
82 export function simpleSelection(anchor, head) {
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
83 return new Selection([new Range(anchor, head || anchor)], 0)
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
84 }