annotate .cms/lib/codemirror/src/util/misc.js @ 0:78edf6b517a0 draft

24.10
author Coffee CMS <info@coffee-cms.ru>
date Fri, 11 Oct 2024 22:40:23 +0000
parents
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 export function bind(f) {
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
2 let args = Array.prototype.slice.call(arguments, 1)
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
3 return function(){return f.apply(null, args)}
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
4 }
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
5
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
6 export function copyObj(obj, target, overwrite) {
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
7 if (!target) target = {}
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
8 for (let prop in obj)
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
9 if (obj.hasOwnProperty(prop) && (overwrite !== false || !target.hasOwnProperty(prop)))
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
10 target[prop] = obj[prop]
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
11 return target
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
12 }
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
13
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
14 // Counts the column offset in a string, taking tabs into account.
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
15 // Used mostly to find indentation.
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
16 export function countColumn(string, end, tabSize, startIndex, startValue) {
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
17 if (end == null) {
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
18 end = string.search(/[^\s\u00a0]/)
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
19 if (end == -1) end = string.length
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
20 }
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
21 for (let i = startIndex || 0, n = startValue || 0;;) {
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
22 let nextTab = string.indexOf("\t", i)
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
23 if (nextTab < 0 || nextTab >= end)
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
24 return n + (end - i)
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
25 n += nextTab - i
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
26 n += tabSize - (n % tabSize)
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
27 i = nextTab + 1
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
28 }
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
29 }
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
30
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
31 export class Delayed {
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
32 constructor() {
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
33 this.id = null
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
34 this.f = null
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
35 this.time = 0
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
36 this.handler = bind(this.onTimeout, this)
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
37 }
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
38 onTimeout(self) {
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
39 self.id = 0
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
40 if (self.time <= +new Date) {
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
41 self.f()
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
42 } else {
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
43 setTimeout(self.handler, self.time - +new Date)
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
44 }
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
45 }
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
46 set(ms, f) {
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
47 this.f = f
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
48 const time = +new Date + ms
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
49 if (!this.id || time < this.time) {
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
50 clearTimeout(this.id)
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
51 this.id = setTimeout(this.handler, ms)
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
52 this.time = time
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
53 }
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
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
57 export function indexOf(array, elt) {
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
58 for (let i = 0; i < array.length; ++i)
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
59 if (array[i] == elt) return i
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
60 return -1
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
61 }
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
62
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
63 // Number of pixels added to scroller and sizer to hide scrollbar
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
64 export let scrollerGap = 50
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
65
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
66 // Returned or thrown by various protocols to signal 'I'm not
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
67 // handling this'.
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
68 export let Pass = {toString: function(){return "CodeMirror.Pass"}}
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
69
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
70 // Reused option objects for setSelection & friends
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
71 export let sel_dontScroll = {scroll: false}, sel_mouse = {origin: "*mouse"}, sel_move = {origin: "+move"}
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
72
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
73 // The inverse of countColumn -- find the offset that corresponds to
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
74 // a particular column.
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
75 export function findColumn(string, goal, tabSize) {
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
76 for (let pos = 0, col = 0;;) {
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
77 let nextTab = string.indexOf("\t", pos)
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
78 if (nextTab == -1) nextTab = string.length
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
79 let skipped = nextTab - pos
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
80 if (nextTab == string.length || col + skipped >= goal)
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
81 return pos + Math.min(skipped, goal - col)
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
82 col += nextTab - pos
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
83 col += tabSize - (col % tabSize)
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
84 pos = nextTab + 1
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
85 if (col >= goal) return pos
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
86 }
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
87 }
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
88
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
89 let spaceStrs = [""]
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
90 export function spaceStr(n) {
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
91 while (spaceStrs.length <= n)
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
92 spaceStrs.push(lst(spaceStrs) + " ")
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
93 return spaceStrs[n]
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
94 }
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
95
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
96 export function lst(arr) { return arr[arr.length-1] }
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
97
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
98 export function map(array, f) {
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
99 let out = []
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
100 for (let i = 0; i < array.length; i++) out[i] = f(array[i], i)
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
101 return out
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
102 }
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
103
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
104 export function insertSorted(array, value, score) {
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
105 let pos = 0, priority = score(value)
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
106 while (pos < array.length && score(array[pos]) <= priority) pos++
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
107 array.splice(pos, 0, value)
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
108 }
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
109
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
110 function nothing() {}
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
111
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
112 export function createObj(base, props) {
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
113 let inst
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
114 if (Object.create) {
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
115 inst = Object.create(base)
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
116 } else {
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
117 nothing.prototype = base
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
118 inst = new nothing()
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
119 }
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
120 if (props) copyObj(props, inst)
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
121 return inst
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
122 }
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
123
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
124 let nonASCIISingleCaseWordChar = /[\u00df\u0587\u0590-\u05f4\u0600-\u06ff\u3040-\u309f\u30a0-\u30ff\u3400-\u4db5\u4e00-\u9fcc\uac00-\ud7af]/
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
125 export function isWordCharBasic(ch) {
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
126 return /\w/.test(ch) || ch > "\x80" &&
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
127 (ch.toUpperCase() != ch.toLowerCase() || nonASCIISingleCaseWordChar.test(ch))
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
128 }
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
129 export function isWordChar(ch, helper) {
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
130 if (!helper) return isWordCharBasic(ch)
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
131 if (helper.source.indexOf("\\w") > -1 && isWordCharBasic(ch)) return true
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
132 return helper.test(ch)
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
133 }
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
134
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
135 export function isEmpty(obj) {
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
136 for (let n in obj) if (obj.hasOwnProperty(n) && obj[n]) return false
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
137 return true
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
138 }
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
139
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
140 // Extending unicode characters. A series of a non-extending char +
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
141 // any number of extending chars is treated as a single unit as far
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
142 // as editing and measuring is concerned. This is not fully correct,
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
143 // since some scripts/fonts/browsers also treat other configurations
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
144 // of code points as a group.
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
145 let extendingChars = /[\u0300-\u036f\u0483-\u0489\u0591-\u05bd\u05bf\u05c1\u05c2\u05c4\u05c5\u05c7\u0610-\u061a\u064b-\u065e\u0670\u06d6-\u06dc\u06de-\u06e4\u06e7\u06e8\u06ea-\u06ed\u0711\u0730-\u074a\u07a6-\u07b0\u07eb-\u07f3\u0816-\u0819\u081b-\u0823\u0825-\u0827\u0829-\u082d\u0900-\u0902\u093c\u0941-\u0948\u094d\u0951-\u0955\u0962\u0963\u0981\u09bc\u09be\u09c1-\u09c4\u09cd\u09d7\u09e2\u09e3\u0a01\u0a02\u0a3c\u0a41\u0a42\u0a47\u0a48\u0a4b-\u0a4d\u0a51\u0a70\u0a71\u0a75\u0a81\u0a82\u0abc\u0ac1-\u0ac5\u0ac7\u0ac8\u0acd\u0ae2\u0ae3\u0b01\u0b3c\u0b3e\u0b3f\u0b41-\u0b44\u0b4d\u0b56\u0b57\u0b62\u0b63\u0b82\u0bbe\u0bc0\u0bcd\u0bd7\u0c3e-\u0c40\u0c46-\u0c48\u0c4a-\u0c4d\u0c55\u0c56\u0c62\u0c63\u0cbc\u0cbf\u0cc2\u0cc6\u0ccc\u0ccd\u0cd5\u0cd6\u0ce2\u0ce3\u0d3e\u0d41-\u0d44\u0d4d\u0d57\u0d62\u0d63\u0dca\u0dcf\u0dd2-\u0dd4\u0dd6\u0ddf\u0e31\u0e34-\u0e3a\u0e47-\u0e4e\u0eb1\u0eb4-\u0eb9\u0ebb\u0ebc\u0ec8-\u0ecd\u0f18\u0f19\u0f35\u0f37\u0f39\u0f71-\u0f7e\u0f80-\u0f84\u0f86\u0f87\u0f90-\u0f97\u0f99-\u0fbc\u0fc6\u102d-\u1030\u1032-\u1037\u1039\u103a\u103d\u103e\u1058\u1059\u105e-\u1060\u1071-\u1074\u1082\u1085\u1086\u108d\u109d\u135f\u1712-\u1714\u1732-\u1734\u1752\u1753\u1772\u1773\u17b7-\u17bd\u17c6\u17c9-\u17d3\u17dd\u180b-\u180d\u18a9\u1920-\u1922\u1927\u1928\u1932\u1939-\u193b\u1a17\u1a18\u1a56\u1a58-\u1a5e\u1a60\u1a62\u1a65-\u1a6c\u1a73-\u1a7c\u1a7f\u1b00-\u1b03\u1b34\u1b36-\u1b3a\u1b3c\u1b42\u1b6b-\u1b73\u1b80\u1b81\u1ba2-\u1ba5\u1ba8\u1ba9\u1c2c-\u1c33\u1c36\u1c37\u1cd0-\u1cd2\u1cd4-\u1ce0\u1ce2-\u1ce8\u1ced\u1dc0-\u1de6\u1dfd-\u1dff\u200c\u200d\u20d0-\u20f0\u2cef-\u2cf1\u2de0-\u2dff\u302a-\u302f\u3099\u309a\ua66f-\ua672\ua67c\ua67d\ua6f0\ua6f1\ua802\ua806\ua80b\ua825\ua826\ua8c4\ua8e0-\ua8f1\ua926-\ua92d\ua947-\ua951\ua980-\ua982\ua9b3\ua9b6-\ua9b9\ua9bc\uaa29-\uaa2e\uaa31\uaa32\uaa35\uaa36\uaa43\uaa4c\uaab0\uaab2-\uaab4\uaab7\uaab8\uaabe\uaabf\uaac1\uabe5\uabe8\uabed\udc00-\udfff\ufb1e\ufe00-\ufe0f\ufe20-\ufe26\uff9e\uff9f]/
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
146 export function isExtendingChar(ch) { return ch.charCodeAt(0) >= 768 && extendingChars.test(ch) }
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
147
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
148 // Returns a number from the range [`0`; `str.length`] unless `pos` is outside that range.
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
149 export function skipExtendingChars(str, pos, dir) {
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
150 while ((dir < 0 ? pos > 0 : pos < str.length) && isExtendingChar(str.charAt(pos))) pos += dir
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
151 return pos
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
152 }
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
153
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
154 // Returns the value from the range [`from`; `to`] that satisfies
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
155 // `pred` and is closest to `from`. Assumes that at least `to`
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
156 // satisfies `pred`. Supports `from` being greater than `to`.
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
157 export function findFirst(pred, from, to) {
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
158 // At any point we are certain `to` satisfies `pred`, don't know
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
159 // whether `from` does.
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
160 let dir = from > to ? -1 : 1
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
161 for (;;) {
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
162 if (from == to) return from
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
163 let midF = (from + to) / 2, mid = dir < 0 ? Math.ceil(midF) : Math.floor(midF)
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
164 if (mid == from) return pred(mid) ? from : to
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
165 if (pred(mid)) to = mid
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
166 else from = mid + dir
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
167 }
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
168 }