src/lsp/enc.bend
bolt@1.27.0.0 · 208 lines · 26 definitions
1
2
3
4
5
6
7
8
9import Base
10import bolt@1.27.0.0/src/lazy/lazy.bend as Lazy
11import emerging-ezjson@1.2.0.0/main.bend as Ezjson
12import emerging-ezjson@1.2.0.0/src/value.bend as J
13
14
15type Enc is Data:
16 Utf16{}
17 Utf32{}
18
19
20def name(ee: Enc) -> String:
21 match ee:
22 case Utf16{}:
23 "utf-16"
24 case Utf32{}:
25 "utf-32"
26
27
28
29def offers(cells: J.Json) -> Bool:
30 match cells:
31 case J.JCons{h, t}:
32 +more = offers(t)
33 Bool.or(String.eq(Maybe.default(&2, String, Ezjson.as_str(h), ""), "utf-32"), more)
34 case _other:
35 False{}
36
37
38def cells(jj: J.Json) -> J.Json:
39 match jj:
40 case J.JArr{items}:
41 items
42 case _other:
43 J.JNil{}
44
45
46def chosen(yes: Bool) -> Enc:
47 match yes:
48 case True{}:
49 Utf32{}
50 case False{}:
51 Utf16{}
52
53
54
55def negotiate(params: J.Json) -> Enc:
56 chosen(offers(cells(Ezjson.get(Ezjson.get(Ezjson.get(params, "capabilities"), "general"), "positionEncodings"))))
57
58
59
60
61
62def wide(cc: Char) -> Bool:
63 U32.is_le(65536, Char.to_u32(cc))
64
65
66def units.step(isw: Bool, rest: Nat) -> Nat:
67 match isw:
68 case True{}:
69 2n+rest
70 case False{}:
71 1n+rest
72
73
74
75def units(cs: List<&2, Char>, nn: Nat) -> Nat:
76 match cs nn:
77 case Nil{} _:
78 nn
79 case Con{_c, _t} 0n:
80 0n
81 case Con{c, t} 1n+p:
82 units.step(wide(c), units(t, p))
83
84
85
86def points.skip(isw: Bool, pp: Nat) -> Nat:
87 match isw pp:
88 case True{} 0n:
89 0n
90 case True{} 1n+q:
91 q
92 case False{} _:
93 pp
94
95
96
97
98def points(cs: List<&2, Char>, uu: Nat) -> Nat:
99 match cs uu:
100 case Nil{} _:
101 uu
102 case Con{_c, _t} 0n:
103 0n
104 case Con{c, t} 1n+p:
105 1n+points(t, points.skip(wide(c), p))
106
107
108def out.of(ee: Enc, cs: List<&2, Char>, nn: Nat) -> Nat:
109 match ee:
110 case Utf16{}:
111 units(cs, nn)
112 case Utf32{}:
113 nn
114
115
116def into.of(ee: Enc, cs: List<&2, Char>, uu: Nat) -> Nat:
117 match ee:
118 case Utf16{}:
119 points(cs, uu)
120 case Utf32{}:
121 uu
122
123
124def wide_in(cs: List<&2, Char>) -> Bool:
125 match cs:
126 case Nil{}:
127 False{}
128 case Con{c, t}:
129 Lazy.or_else(wide(c), _u => wide_in(t))
130
131
132def wide_any(lines: List<&2, String>) -> Bool:
133 match lines:
134 case Nil{}:
135 False{}
136 case Con{l, t}:
137 Lazy.or_else(wide_in(String.to_list(l)), _u => wide_any(t))
138
139
140
141
142def narrowed(ee: Enc, wide: Bool) -> Enc:
143 match ee:
144 case Utf16{}:
145 Bool.pick(Enc, wide, Utf16{}, Utf32{})
146 case Utf32{}:
147 Utf32{}
148
149
150
151type Cols is Data:
152 Cols{enc: Enc, lines: List<&2, String>}
153
154
155def cols.of(ee: Enc, +lines: List<&2, String>) -> Cols:
156 Cols{narrowed(ee, wide_any(lines)), lines}
157
158
159def cols(ee: Enc, text: String) -> Cols:
160 cols.of(ee, String.lines(text))
161
162
163def chars(lines: List<&2, String>, line: U32) -> List<&2, Char>:
164 String.to_list(Maybe.default(&2, String, List.get(&2, String, lines, U32.to_nat(line)), ""))
165
166
167def out.col(ee: Enc, cs: List<&2, Char>, col: U32) -> U32:
168 match ee:
169 case Utf16{}:
170 U32.from_nat(out.of(Utf16{}, cs, U32.to_nat(col)))
171 case Utf32{}:
172 col
173
174
175
176def out.at(ee: Enc, lines: List<&2, String>, line: U32, col: U32) -> U32:
177 match ee:
178 case Utf16{}:
179 out.col(Utf16{}, chars(lines, line), col)
180 case Utf32{}:
181 col
182
183
184def out(cc: Cols, line: U32, col: U32) -> U32:
185 Cols{ee, lines} = cc
186 out.at(ee, lines, line, col)
187
188
189def into.col(ee: Enc, cs: List<&2, Char>, col: U32) -> U32:
190 match ee:
191 case Utf16{}:
192 U32.from_nat(into.of(Utf16{}, cs, U32.to_nat(col)))
193 case Utf32{}:
194 col
195
196
197
198def into.at(ee: Enc, lines: List<&2, String>, line: U32, col: U32) -> U32:
199 match ee:
200 case Utf16{}:
201 into.col(Utf16{}, chars(lines, line), col)
202 case Utf32{}:
203 col
204
205
206def into(cc: Cols, line: U32, col: U32) -> U32:
207 Cols{ee, lines} = cc
208 into.at(ee, lines, line, col)