mt-lang 0.2.0 → 0.2.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (189) hide show
  1. checksums.yaml +4 -4
  2. data/docs/index.html +4 -3
  3. data/lib/milk_tea/base.rb +1 -1
  4. data/std/asset_pack.mt +267 -0
  5. data/std/async/libuv_runtime.mt +539 -0
  6. data/std/async/mailbox.mt +191 -0
  7. data/std/async/runtime.mt +87 -0
  8. data/std/async.mt +87 -0
  9. data/std/base64.mt +185 -0
  10. data/std/behavior_tree.mt +396 -0
  11. data/std/binary.mt +314 -0
  12. data/std/binary_heap.mt +157 -0
  13. data/std/bitset.mt +239 -0
  14. data/std/box2d.mt +535 -0
  15. data/std/bytes.mt +46 -0
  16. data/std/c/box2d.mt +1254 -0
  17. data/std/c/cgltf.mt +647 -0
  18. data/std/c/cjson.mt +106 -0
  19. data/std/c/crypto.mt +11 -0
  20. data/std/c/crypto_support.h +51 -0
  21. data/std/c/ctype.mt +19 -0
  22. data/std/c/ctype_bindgen.h +29 -0
  23. data/std/c/curl.mt +1223 -0
  24. data/std/c/enet.mt +473 -0
  25. data/std/c/errno.mt +41 -0
  26. data/std/c/errno_bindgen.h +53 -0
  27. data/std/c/flecs.mt +2945 -0
  28. data/std/c/fs.linux.mt +43 -0
  29. data/std/c/fs.windows.mt +43 -0
  30. data/std/c/fs_support.h +954 -0
  31. data/std/c/gl.mt +2065 -0
  32. data/std/c/gl_registry_helpers.h +10748 -0
  33. data/std/c/glfw.mt +499 -0
  34. data/std/c/libc.mt +167 -0
  35. data/std/c/libuv.mt +1491 -0
  36. data/std/c/math.mt +22 -0
  37. data/std/c/math_bindgen.h +31 -0
  38. data/std/c/miniaudio.mt +3420 -0
  39. data/std/c/pcre2.mt +735 -0
  40. data/std/c/process.mt +58 -0
  41. data/std/c/process_support.h +1147 -0
  42. data/std/c/raygui.mt +1602 -0
  43. data/std/c/raylib.mt +1245 -0
  44. data/std/c/raymath.mt +163 -0
  45. data/std/c/rlgl.mt +434 -0
  46. data/std/c/rpng.mt +60 -0
  47. data/std/c/rres.mt +187 -0
  48. data/std/c/sdl3.mt +4132 -0
  49. data/std/c/sqlite3.mt +951 -0
  50. data/std/c/stb_image.mt +52 -0
  51. data/std/c/stb_image_resize2.mt +128 -0
  52. data/std/c/stb_image_write.mt +19 -0
  53. data/std/c/stb_rect_pack.mt +38 -0
  54. data/std/c/stb_truetype.mt +175 -0
  55. data/std/c/stb_vorbis.mt +31 -0
  56. data/std/c/stdio.mt +90 -0
  57. data/std/c/steamworks.h +5769 -0
  58. data/std/c/steamworks.mt +4771 -0
  59. data/std/c/string.mt +16 -0
  60. data/std/c/string_bindgen.h +36 -0
  61. data/std/c/sync.mt +33 -0
  62. data/std/c/sync_support.h +219 -0
  63. data/std/c/terminal.mt +24 -0
  64. data/std/c/terminal_support.h +408 -0
  65. data/std/c/time.mt +26 -0
  66. data/std/c/tls.mt +24 -0
  67. data/std/c/tls_support.h +626 -0
  68. data/std/c/tracy.mt +53 -0
  69. data/std/c/zlib.mt +20 -0
  70. data/std/c/zlib_support.h +239 -0
  71. data/std/c/zstd.mt +231 -0
  72. data/std/cell.mt +60 -0
  73. data/std/cgltf.mt +115 -0
  74. data/std/cjson.mt +90 -0
  75. data/std/cli.mt +768 -0
  76. data/std/cookie.mt +198 -0
  77. data/std/counter.mt +160 -0
  78. data/std/crypto.mt +74 -0
  79. data/std/cstring.mt +13 -0
  80. data/std/ctype.mt +52 -0
  81. data/std/curl/runtime.mt +261 -0
  82. data/std/curl.mt +38 -0
  83. data/std/deque.mt +348 -0
  84. data/std/encoding.mt +93 -0
  85. data/std/enet.mt +133 -0
  86. data/std/env.mt +41 -0
  87. data/std/errno.mt +47 -0
  88. data/std/flecs.mt +978 -0
  89. data/std/fmt.mt +271 -0
  90. data/std/fs.linux.mt +696 -0
  91. data/std/fs.windows.mt +711 -0
  92. data/std/fsm.mt +267 -0
  93. data/std/gl.mt +2062 -0
  94. data/std/glfw.mt +471 -0
  95. data/std/goap.mt +342 -0
  96. data/std/graph.mt +521 -0
  97. data/std/gzip.mt +77 -0
  98. data/std/hash.mt +429 -0
  99. data/std/http/server.mt +810 -0
  100. data/std/http.mt +1227 -0
  101. data/std/intern.mt +53 -0
  102. data/std/jobs.mt +288 -0
  103. data/std/json.mt +627 -0
  104. data/std/libc.mt +34 -0
  105. data/std/libuv.mt +554 -0
  106. data/std/linear_algebra.mt +243 -0
  107. data/std/linked_map.mt +372 -0
  108. data/std/linked_map_view.mt +49 -0
  109. data/std/linked_set.mt +117 -0
  110. data/std/log.mt +69 -0
  111. data/std/map.mt +418 -0
  112. data/std/math.mt +24 -0
  113. data/std/mem/arena.mt +137 -0
  114. data/std/mem/endian.mt +51 -0
  115. data/std/mem/heap.mt +298 -0
  116. data/std/mem/pool.mt +164 -0
  117. data/std/mem/stack.mt +47 -0
  118. data/std/mem/tracking.mt +119 -0
  119. data/std/miniaudio.mt +1299 -0
  120. data/std/multiset.mt +191 -0
  121. data/std/net/channel.mt +727 -0
  122. data/std/net/clock.mt +237 -0
  123. data/std/net/discovery.mt +277 -0
  124. data/std/net/lobby.mt +813 -0
  125. data/std/net/manager.mt +539 -0
  126. data/std/net/mux.mt +839 -0
  127. data/std/net/nat.mt +122 -0
  128. data/std/net/packet.mt +219 -0
  129. data/std/net/punch.mt +162 -0
  130. data/std/net/rpc.mt +119 -0
  131. data/std/net/session.mt +1157 -0
  132. data/std/net/stun.mt +252 -0
  133. data/std/net/sync.mt +183 -0
  134. data/std/net/turn.mt +459 -0
  135. data/std/net.mt +2944 -0
  136. data/std/oauth2.mt +408 -0
  137. data/std/option.mt +51 -0
  138. data/std/ordered_map.mt +497 -0
  139. data/std/ordered_set.mt +348 -0
  140. data/std/path.mt +368 -0
  141. data/std/pcre2/runtime.mt +35 -0
  142. data/std/pcre2.mt +78 -0
  143. data/std/priority_queue.mt +55 -0
  144. data/std/process.mt +837 -0
  145. data/std/queue.mt +55 -0
  146. data/std/random.mt +146 -0
  147. data/std/raygui.mt +99 -0
  148. data/std/raylib/debug_console.mt +71 -0
  149. data/std/raylib/easing.mt +388 -0
  150. data/std/raylib/packed_assets.mt +255 -0
  151. data/std/raylib/runtime.mt +30 -0
  152. data/std/raylib/tracy_gpu.mt +37 -0
  153. data/std/raylib.mt +1510 -0
  154. data/std/raymath.mt +153 -0
  155. data/std/result.mt +89 -0
  156. data/std/rlgl.mt +268 -0
  157. data/std/rpng.mt +46 -0
  158. data/std/rres.mt +36 -0
  159. data/std/sdl3/runtime.mt +54 -0
  160. data/std/sdl3.mt +1731 -0
  161. data/std/serialize.mt +68 -0
  162. data/std/set.mt +124 -0
  163. data/std/spatial.mt +176 -0
  164. data/std/sqlite3.mt +151 -0
  165. data/std/stack.mt +55 -0
  166. data/std/stb_image.mt +47 -0
  167. data/std/stb_image_resize2.mt +41 -0
  168. data/std/stb_image_write.mt +17 -0
  169. data/std/stb_rect_pack.mt +15 -0
  170. data/std/stb_truetype.mt +77 -0
  171. data/std/stb_vorbis.mt +16 -0
  172. data/std/stdio.mt +88 -0
  173. data/std/steamworks.mt +1542 -0
  174. data/std/str.mt +293 -0
  175. data/std/string.mt +234 -0
  176. data/std/sync.mt +194 -0
  177. data/std/tar.mt +704 -0
  178. data/std/terminal.mt +1002 -0
  179. data/std/testing.mt +266 -0
  180. data/std/thread.mt +120 -0
  181. data/std/time.mt +105 -0
  182. data/std/tls.mt +616 -0
  183. data/std/toml.mt +1310 -0
  184. data/std/tracy.mt +42 -0
  185. data/std/uri.mt +118 -0
  186. data/std/url.mt +372 -0
  187. data/std/vec.mt +433 -0
  188. data/std/zstd.mt +94 -0
  189. metadata +187 -2
data/std/terminal.mt ADDED
@@ -0,0 +1,1002 @@
1
+ import std.c.terminal as c
2
+ import std.fmt as fmt
3
+ import std.string as string
4
+ import std.vec as vec
5
+
6
+ public struct Size:
7
+ width: int
8
+ height: int
9
+
10
+ public struct Error:
11
+ code: int
12
+ message: string.String
13
+
14
+ public enum Color: int
15
+ black = 0
16
+ red = 1
17
+ green = 2
18
+ yellow = 3
19
+ blue = 4
20
+ magenta = 5
21
+ cyan = 6
22
+ white = 7
23
+ bright_black = 8
24
+ bright_red = 9
25
+ bright_green = 10
26
+ bright_yellow = 11
27
+ bright_blue = 12
28
+ bright_magenta = 13
29
+ bright_cyan = 14
30
+ bright_white = 15
31
+
32
+ public enum KeyCode: int
33
+ none = 0
34
+ character = 1
35
+ enter = 2
36
+ escape = 3
37
+ backspace = 4
38
+ tab = 5
39
+ shift_tab = 6
40
+ up = 7
41
+ down = 8
42
+ left = 9
43
+ right = 10
44
+ home = 11
45
+ end = 12
46
+ page_up = 13
47
+ page_down = 14
48
+ insert = 15
49
+ delete = 16
50
+ function_1 = 17
51
+ function_2 = 18
52
+ function_3 = 19
53
+ function_4 = 20
54
+ unknown = 21
55
+
56
+ public enum MouseAction: int
57
+ none = 0
58
+ press = 1
59
+ release = 2
60
+ move = 3
61
+ scroll_up = 4
62
+ scroll_down = 5
63
+
64
+ public enum MouseButton: int
65
+ none = 0
66
+ left = 1
67
+ middle = 2
68
+ right = 3
69
+
70
+ public enum EventKind: int
71
+ none = 0
72
+ key = 1
73
+ mouse = 2
74
+ resize = 3
75
+
76
+ public struct KeyEvent:
77
+ code: KeyCode
78
+ input_byte: ubyte
79
+ has_byte: bool
80
+ ctrl: bool
81
+ alt: bool
82
+ shifted: bool
83
+
84
+ public struct MouseEvent:
85
+ action: MouseAction
86
+ button: MouseButton
87
+ column: int
88
+ row: int
89
+ ctrl: bool
90
+ alt: bool
91
+ shifted: bool
92
+
93
+ public struct Event:
94
+ kind: EventKind
95
+ key: KeyEvent
96
+ mouse: MouseEvent
97
+ size: Size
98
+
99
+ struct ParsedDecimal:
100
+ value: int
101
+ next_index: ptr_uint
102
+
103
+ public struct Terminal:
104
+ input: vec.Vec[ubyte]
105
+ size: Size
106
+ raw_mode: bool
107
+ alternate_screen: bool
108
+ cursor_hidden: bool
109
+ mouse_enabled: bool
110
+
111
+
112
+ function take_owned_string(data: ptr[char]?, len: ptr_uint) -> string.String:
113
+ if data == null:
114
+ if len != 0:
115
+ fatal(c"terminal.take_owned_string missing storage")
116
+
117
+ return string.String.create()
118
+
119
+ return unsafe: string.String(data = ptr[ubyte]<-data, len = len, capacity = len, owns_storage = true)
120
+
121
+
122
+ function take_error(raw: c.mt_terminal_error, fallback: str) -> Error:
123
+ if raw.message_data == null and raw.message_len == 0:
124
+ return Error(code = raw.code, message = string.String.from_str(fallback))
125
+
126
+ return Error(code = raw.code, message = take_owned_string(raw.message_data, raw.message_len))
127
+
128
+
129
+ function default_key_event() -> KeyEvent:
130
+ return KeyEvent(code = KeyCode.none, input_byte = 0, has_byte = false, ctrl = false, alt = false, shifted = false)
131
+
132
+
133
+ function default_mouse_event() -> MouseEvent:
134
+ return MouseEvent(
135
+ action = MouseAction.none,
136
+ button = MouseButton.none,
137
+ column = 0,
138
+ row = 0,
139
+ ctrl = false,
140
+ alt = false,
141
+ shifted = false
142
+ )
143
+
144
+
145
+ function key_event(code: KeyCode, input_value: ubyte, has_byte: bool, ctrl: bool, alt: bool, shifted: bool) -> Event:
146
+ return Event(
147
+ kind = EventKind.key,
148
+ key = KeyEvent(
149
+ code = code,
150
+ input_byte = input_value,
151
+ has_byte = has_byte,
152
+ ctrl = ctrl,
153
+ alt = alt,
154
+ shifted = shifted
155
+ ),
156
+ mouse = default_mouse_event(),
157
+ size = Size(width = 0, height = 0)
158
+ )
159
+
160
+
161
+ function mouse_event(
162
+ action: MouseAction,
163
+ button: MouseButton,
164
+ column: int,
165
+ row: int,
166
+ ctrl: bool,
167
+ alt: bool,
168
+ shifted: bool
169
+ ) -> Event:
170
+ return Event(
171
+ kind = EventKind.mouse,
172
+ key = default_key_event(),
173
+ mouse = MouseEvent(
174
+ action = action,
175
+ button = button,
176
+ column = column,
177
+ row = row,
178
+ ctrl = ctrl,
179
+ alt = alt,
180
+ shifted = shifted
181
+ ),
182
+ size = Size(width = 0, height = 0)
183
+ )
184
+
185
+
186
+ function resize_event(current: Size) -> Event:
187
+ return Event(kind = EventKind.resize, key = default_key_event(), mouse = default_mouse_event(), size = current)
188
+
189
+
190
+ function clamp_cursor_position_1based(value: int) -> int:
191
+ if value < 1:
192
+ return 1
193
+
194
+ return value
195
+
196
+
197
+ function clamp_color_channel(value: int) -> int:
198
+ if value < 0:
199
+ return 0
200
+ if value > 255:
201
+ return 255
202
+
203
+ return value
204
+
205
+
206
+ function append_escape(output: ref[string.String]) -> void:
207
+ output.push_byte(27)
208
+
209
+
210
+ function append_csi(output: ref[string.String], suffix: str) -> void:
211
+ append_escape(output)
212
+ output.append("[")
213
+ output.append(suffix)
214
+
215
+
216
+ function write_stdout_bytes(data: const_ptr[ubyte]?, len: ptr_uint, fallback: str) -> Result[ptr_uint, Error]:
217
+ var written: ptr_uint = 0
218
+ var raw_error = zero[c.mt_terminal_error]
219
+ let status = c.mt_terminal_write_stdout(data, len, written, raw_error)
220
+ if status != 0:
221
+ return Result[ptr_uint, Error].failure(error= take_error(raw_error, fallback))
222
+
223
+ return Result[ptr_uint, Error].success(value= written)
224
+
225
+
226
+ function write_stderr_bytes(data: const_ptr[ubyte]?, len: ptr_uint, fallback: str) -> Result[ptr_uint, Error]:
227
+ var written: ptr_uint = 0
228
+ var raw_error = zero[c.mt_terminal_error]
229
+ let status = c.mt_terminal_write_stderr(data, len, written, raw_error)
230
+ if status != 0:
231
+ return Result[ptr_uint, Error].failure(error= take_error(raw_error, fallback))
232
+
233
+ return Result[ptr_uint, Error].success(value= written)
234
+
235
+
236
+ function write_stdout_sequence(sequence: string.String, fallback: str) -> Result[bool, Error]:
237
+ var data: const_ptr[ubyte]? = null
238
+ if sequence.len != 0:
239
+ data = unsafe: const_ptr[ubyte]<-sequence.data
240
+
241
+ write_stdout_bytes(data, sequence.len, fallback)?
242
+ return Result[bool, Error].success(value= true)
243
+
244
+
245
+ function flush_stdout_internal() -> Result[bool, Error]:
246
+ var raw_error = zero[c.mt_terminal_error]
247
+ let status = c.mt_terminal_flush_stdout(raw_error)
248
+ if status != 0:
249
+ return Result[bool, Error].failure(error= take_error(raw_error, "terminal flush failed"))
250
+
251
+ return Result[bool, Error].success(value= true)
252
+
253
+
254
+ function flush_stderr_internal() -> Result[bool, Error]:
255
+ var raw_error = zero[c.mt_terminal_error]
256
+ let status = c.mt_terminal_flush_stderr(raw_error)
257
+ if status != 0:
258
+ return Result[bool, Error].failure(error= take_error(raw_error, "terminal flush failed"))
259
+
260
+ return Result[bool, Error].success(value= true)
261
+
262
+
263
+ function raw_mode_enter() -> Result[bool, Error]:
264
+ var raw_error = zero[c.mt_terminal_error]
265
+ let status = c.mt_terminal_enter_raw_mode(raw_error)
266
+ if status != 0:
267
+ return Result[bool, Error].failure(error= take_error(raw_error, "terminal raw mode failed"))
268
+
269
+ return Result[bool, Error].success(value= true)
270
+
271
+
272
+ function raw_mode_leave() -> Result[bool, Error]:
273
+ var raw_error = zero[c.mt_terminal_error]
274
+ let status = c.mt_terminal_leave_raw_mode(raw_error)
275
+ if status != 0:
276
+ return Result[bool, Error].failure(error= take_error(raw_error, "terminal raw mode restore failed"))
277
+
278
+ return Result[bool, Error].success(value= true)
279
+
280
+
281
+ function read_stdin(timeout_ms: int) -> Result[vec.Vec[ubyte], Error]:
282
+ var buffer = zero[array[ubyte, 128]]
283
+ var read_count: ptr_uint = 0
284
+ var raw_error = zero[c.mt_terminal_error]
285
+ let status = c.mt_terminal_read_stdin(ptr_of(buffer[0]), 128, timeout_ms, read_count, raw_error)
286
+ if status != 0:
287
+ return Result[vec.Vec[ubyte], Error].failure(error= take_error(raw_error, "terminal read failed"))
288
+
289
+ var result = vec.Vec[ubyte].with_capacity(read_count)
290
+ if read_count != 0:
291
+ unsafe:
292
+ let read_span = span[ubyte](data = ptr_of(buffer[0]), len = read_count)
293
+ result.append_span(read_span)
294
+
295
+ return Result[vec.Vec[ubyte], Error].success(value= result)
296
+
297
+
298
+ function get_size_internal() -> Result[Size, Error]:
299
+ var raw_size = zero[c.mt_terminal_size]
300
+ var raw_error = zero[c.mt_terminal_error]
301
+ let status = c.mt_terminal_get_size(raw_size, raw_error)
302
+ if status != 0:
303
+ return Result[Size, Error].failure(error= take_error(raw_error, "terminal size query failed"))
304
+
305
+ return Result[Size, Error].success(value= Size(width = raw_size.width, height = raw_size.height))
306
+
307
+
308
+ function append_color_code(output: ref[string.String], color: Color, background: bool) -> void:
309
+ let code = int<-color
310
+ var base = 30
311
+ var bright_base = 90
312
+ if background:
313
+ base = 40
314
+ bright_base = 100
315
+ if code < 8:
316
+ fmt.append_int(output, base + code)
317
+ return
318
+
319
+ fmt.append_int(output, bright_base + (code - 8))
320
+
321
+
322
+ function apply_modifier(key: ref[KeyEvent], modifier: int) -> void:
323
+ if modifier <= 1:
324
+ return
325
+
326
+ let modifier_bits = modifier - 1
327
+ unsafe:
328
+ read(key).shifted = (modifier_bits & 1) != 0
329
+ read(key).alt = (modifier_bits & 2) != 0
330
+ read(key).ctrl = (modifier_bits & 4) != 0
331
+
332
+
333
+ function get_byte(buffer: vec.Vec[ubyte], index: ptr_uint) -> Option[ubyte]:
334
+ let value = buffer.get(index) else:
335
+ return Option[ubyte].none
336
+
337
+ return Option[ubyte].some(value = unsafe: read(value))
338
+
339
+
340
+ function get_ref_byte(buffer: ref[vec.Vec[ubyte]], index: ptr_uint) -> Option[ubyte]:
341
+ return get_byte(read(buffer), index)
342
+
343
+
344
+ function consume_bytes(buffer: ref[vec.Vec[ubyte]], count: ptr_uint) -> void:
345
+ var remaining = count
346
+ while remaining > 0 and not buffer.is_empty():
347
+ match buffer.remove(0):
348
+ Option.some:
349
+ pass
350
+ Option.none:
351
+ break
352
+ remaining -= 1
353
+
354
+
355
+ function parse_decimal(buffer: vec.Vec[ubyte], start: ptr_uint) -> Option[ParsedDecimal]:
356
+ var value = 0
357
+ var next_index = start
358
+
359
+ var parsed = false
360
+ while next_index < buffer.len():
361
+ match get_byte(buffer, next_index):
362
+ Option.some as payload:
363
+ let current_byte = payload.value
364
+ if current_byte < 48 or current_byte > 57:
365
+ break
366
+
367
+ parsed = true
368
+ value *= 10
369
+ value += int<-(current_byte - 48)
370
+ next_index += 1
371
+ Option.none:
372
+ break
373
+
374
+ if not parsed:
375
+ return Option[ParsedDecimal].none
376
+
377
+ return Option[ParsedDecimal].some(value = ParsedDecimal(value = value, next_index = next_index))
378
+
379
+
380
+ function parse_simple_key(input_value: ubyte, alt: bool) -> Event:
381
+ if input_value == 13 or input_value == 10:
382
+ return key_event(KeyCode.enter, 0, false, false, alt, false)
383
+ if input_value == 9:
384
+ return key_event(KeyCode.tab, 0, false, false, alt, false)
385
+ if input_value == 8 or input_value == 127:
386
+ return key_event(KeyCode.backspace, 0, false, false, alt, false)
387
+ if input_value == 27:
388
+ return key_event(KeyCode.escape, 0, false, false, alt, false)
389
+ if input_value < 32:
390
+ if input_value >= 1 and input_value <= 26:
391
+ let ascii_code = int<-input_value
392
+ return key_event(KeyCode.character, ubyte<-(96 + ascii_code), true, true, alt, false)
393
+ if input_value >= 28 and input_value <= 31:
394
+ let ascii_code = int<-input_value
395
+ return key_event(KeyCode.character, ubyte<-(64 + ascii_code), true, true, alt, false)
396
+ return key_event(KeyCode.unknown, input_value, true, true, alt, false)
397
+
398
+ return key_event(KeyCode.character, input_value, true, false, alt, false)
399
+
400
+
401
+ function parse_ss3_event(buffer: ref[vec.Vec[ubyte]]) -> Option[Event]:
402
+ match get_ref_byte(buffer, 2):
403
+ Option.some as payload:
404
+ consume_bytes(buffer, 3)
405
+ match payload.value:
406
+ 80:
407
+ return Option[Event].some(value = key_event(KeyCode.function_1, 0, false, false, false, false))
408
+ 81:
409
+ return Option[Event].some(value = key_event(KeyCode.function_2, 0, false, false, false, false))
410
+ 82:
411
+ return Option[Event].some(value = key_event(KeyCode.function_3, 0, false, false, false, false))
412
+ 83:
413
+ return Option[Event].some(value = key_event(KeyCode.function_4, 0, false, false, false, false))
414
+ 72:
415
+ return Option[Event].some(value = key_event(KeyCode.home, 0, false, false, false, false))
416
+ 70:
417
+ return Option[Event].some(value = key_event(KeyCode.end, 0, false, false, false, false))
418
+ _:
419
+ return Option[Event].some(value = key_event(KeyCode.unknown, 0, false, false, false, false))
420
+ Option.none:
421
+ return Option[Event].none
422
+
423
+
424
+ function decode_mouse_button(code: int) -> MouseButton:
425
+ match code & 3:
426
+ 0:
427
+ return MouseButton.left
428
+ 1:
429
+ return MouseButton.middle
430
+ 2:
431
+ return MouseButton.right
432
+ _:
433
+ return MouseButton.none
434
+
435
+
436
+ function parse_mouse_event(buffer: ref[vec.Vec[ubyte]]) -> Option[Event]:
437
+ let button_code_payload = parse_decimal(read(buffer), 3) else:
438
+ return Option[Event].none
439
+
440
+ let button_code = button_code_payload.value
441
+ var next_index = button_code_payload.next_index
442
+
443
+ match get_ref_byte(buffer, next_index):
444
+ Option.some as separator_payload:
445
+ if separator_payload.value != 59:
446
+ consume_bytes(buffer, next_index + 1)
447
+ return Option[Event].some(value = key_event(KeyCode.unknown, 0, false, false, false, false))
448
+ Option.none:
449
+ return Option[Event].none
450
+
451
+ next_index += 1
452
+ let column_payload = parse_decimal(read(buffer), next_index) else:
453
+ return Option[Event].none
454
+
455
+ let column = column_payload.value
456
+ next_index = column_payload.next_index
457
+
458
+ match get_ref_byte(buffer, next_index):
459
+ Option.some as separator_payload:
460
+ if separator_payload.value != 59:
461
+ consume_bytes(buffer, next_index + 1)
462
+ return Option[Event].some(value = key_event(KeyCode.unknown, 0, false, false, false, false))
463
+ Option.none:
464
+ return Option[Event].none
465
+
466
+ next_index += 1
467
+ let row_payload = parse_decimal(read(buffer), next_index) else:
468
+ return Option[Event].none
469
+
470
+ let row = row_payload.value
471
+ next_index = row_payload.next_index
472
+
473
+ match get_ref_byte(buffer, next_index):
474
+ Option.some as payload:
475
+ consume_bytes(buffer, next_index + 1)
476
+ let final_byte = payload.value
477
+ let shifted = (button_code & 4) != 0
478
+ let alt = (button_code & 8) != 0
479
+ let ctrl = (button_code & 16) != 0
480
+
481
+ if (button_code & 64) != 0:
482
+ if (button_code & 1) != 0:
483
+ return Option[Event].some(value = mouse_event(
484
+ MouseAction.scroll_down,
485
+ MouseButton.none,
486
+ column,
487
+ row,
488
+ ctrl,
489
+ alt,
490
+ shifted
491
+ ))
492
+ return Option[Event].some(value = mouse_event(
493
+ MouseAction.scroll_up,
494
+ MouseButton.none,
495
+ column,
496
+ row,
497
+ ctrl,
498
+ alt,
499
+ shifted
500
+ ))
501
+
502
+ if final_byte == 109:
503
+ return Option[Event].some(value = mouse_event(
504
+ MouseAction.release,
505
+ decode_mouse_button(button_code),
506
+ column,
507
+ row,
508
+ ctrl,
509
+ alt,
510
+ shifted
511
+ ))
512
+
513
+ if (button_code & 32) != 0:
514
+ return Option[Event].some(value = mouse_event(
515
+ MouseAction.move,
516
+ decode_mouse_button(button_code),
517
+ column,
518
+ row,
519
+ ctrl,
520
+ alt,
521
+ shifted
522
+ ))
523
+
524
+ return Option[Event].some(value = mouse_event(
525
+ MouseAction.press,
526
+ decode_mouse_button(button_code),
527
+ column,
528
+ row,
529
+ ctrl,
530
+ alt,
531
+ shifted
532
+ ))
533
+ Option.none:
534
+ return Option[Event].none
535
+
536
+
537
+ function parse_csi_letter(buffer: ref[vec.Vec[ubyte]], final_byte: ubyte, modifier: int) -> Event:
538
+ var event_ = key_event(KeyCode.unknown, 0, false, false, false, false)
539
+ if final_byte == 65:
540
+ event_ = key_event(KeyCode.up, 0, false, false, false, false)
541
+ else if final_byte == 66:
542
+ event_ = key_event(KeyCode.down, 0, false, false, false, false)
543
+ else if final_byte == 67:
544
+ event_ = key_event(KeyCode.right, 0, false, false, false, false)
545
+ else if final_byte == 68:
546
+ event_ = key_event(KeyCode.left, 0, false, false, false, false)
547
+ else if final_byte == 72:
548
+ event_ = key_event(KeyCode.home, 0, false, false, false, false)
549
+ else if final_byte == 70:
550
+ event_ = key_event(KeyCode.end, 0, false, false, false, false)
551
+ else if final_byte == 90:
552
+ event_ = key_event(KeyCode.shift_tab, 0, false, false, false, true)
553
+
554
+ apply_modifier(ref_of(event_.key), modifier)
555
+ return event_
556
+
557
+
558
+ function parse_csi_event(buffer: ref[vec.Vec[ubyte]]) -> Option[Event]:
559
+ match get_ref_byte(buffer, 2):
560
+ Option.some as payload:
561
+ let first = payload.value
562
+ if first == 65 or first == 66 or first == 67 or first == 68 or first == 72 or first == 70 or first == 90:
563
+ consume_bytes(buffer, 3)
564
+ return Option[Event].some(value = parse_csi_letter(buffer, first, 1))
565
+
566
+ if first == 60:
567
+ return parse_mouse_event(buffer)
568
+
569
+ if first < 48 or first > 57:
570
+ consume_bytes(buffer, 3)
571
+ return Option[Event].some(value = key_event(KeyCode.unknown, 0, false, false, false, false))
572
+
573
+ var modifier = 1
574
+ let first_param_payload = parse_decimal(read(buffer), 2) else:
575
+ return Option[Event].none
576
+
577
+ let first_param = first_param_payload.value
578
+ var next_index = first_param_payload.next_index
579
+
580
+ match get_ref_byte(buffer, next_index):
581
+ Option.some as separator_payload:
582
+ if separator_payload.value == 59:
583
+ next_index += 1
584
+ let modifier_payload = parse_decimal(read(buffer), next_index) else:
585
+ return Option[Event].none
586
+
587
+ modifier = modifier_payload.value
588
+ next_index = modifier_payload.next_index
589
+
590
+ match get_ref_byte(buffer, next_index):
591
+ Option.some as final_payload:
592
+ let final_byte = final_payload.value
593
+ consume_bytes(buffer, next_index + 1)
594
+ if final_byte == 126:
595
+ var event_ = key_event(KeyCode.unknown, 0, false, false, false, false)
596
+ if first_param == 1:
597
+ event_ = key_event(KeyCode.home, 0, false, false, false, false)
598
+ else if first_param == 2:
599
+ event_ = key_event(KeyCode.insert, 0, false, false, false, false)
600
+ else if first_param == 3:
601
+ event_ = key_event(KeyCode.delete, 0, false, false, false, false)
602
+ else if first_param == 4:
603
+ event_ = key_event(KeyCode.end, 0, false, false, false, false)
604
+ else if first_param == 5:
605
+ event_ = key_event(KeyCode.page_up, 0, false, false, false, false)
606
+ else if first_param == 6:
607
+ event_ = key_event(KeyCode.page_down, 0, false, false, false, false)
608
+
609
+ apply_modifier(ref_of(event_.key), modifier)
610
+ return Option[Event].some(value = event_)
611
+
612
+ if (
613
+ final_byte == 65
614
+ or final_byte == 66
615
+ or final_byte == 67
616
+ or final_byte == 68
617
+ or final_byte == 72
618
+ or final_byte == 70
619
+ ):
620
+ return Option[Event].some(value = parse_csi_letter(buffer, final_byte, modifier))
621
+
622
+ return Option[Event].some(value = key_event(KeyCode.unknown, 0, false, false, false, false))
623
+ Option.none:
624
+ return Option[Event].none
625
+ Option.none:
626
+ return Option[Event].none
627
+ Option.none:
628
+ return Option[Event].none
629
+
630
+
631
+ function parse_event(buffer: ref[vec.Vec[ubyte]]) -> Option[Event]:
632
+ match get_byte(read(buffer), 0):
633
+ Option.some as payload:
634
+ let first = payload.value
635
+ if first != 27:
636
+ consume_bytes(buffer, 1)
637
+ return Option[Event].some(value = parse_simple_key(first, false))
638
+
639
+ match get_byte(read(buffer), 1):
640
+ Option.some as next_payload:
641
+ let second = next_payload.value
642
+ if second == 91:
643
+ return parse_csi_event(buffer)
644
+ if second == 79:
645
+ return parse_ss3_event(buffer)
646
+
647
+ consume_bytes(buffer, 2)
648
+ return Option[Event].some(value = parse_simple_key(second, true))
649
+ Option.none:
650
+ consume_bytes(buffer, 1)
651
+ return Option[Event].some(value = key_event(KeyCode.escape, 0, false, false, false, false))
652
+ Option.none:
653
+ return Option[Event].none
654
+
655
+
656
+ public function stdin_is_tty() -> bool:
657
+ return c.mt_terminal_stdin_is_tty()
658
+
659
+
660
+ public function stdout_is_tty() -> bool:
661
+ return c.mt_terminal_stdout_is_tty()
662
+
663
+
664
+ public function stderr_is_tty() -> bool:
665
+ return c.mt_terminal_stderr_is_tty()
666
+
667
+
668
+ public function size() -> Result[Size, Error]:
669
+ return get_size_internal()
670
+
671
+
672
+ public function write_stdout(text: str) -> Result[ptr_uint, Error]:
673
+ var data: const_ptr[ubyte]? = null
674
+ if text.len != 0:
675
+ data = unsafe: const_ptr[ubyte]<-text.data
676
+
677
+ return write_stdout_bytes(data, text.len, "terminal write failed")
678
+
679
+
680
+ public function write_stderr(text: str) -> Result[ptr_uint, Error]:
681
+ var data: const_ptr[ubyte]? = null
682
+ if text.len != 0:
683
+ data = unsafe: const_ptr[ubyte]<-text.data
684
+
685
+ return write_stderr_bytes(data, text.len, "terminal write failed")
686
+
687
+
688
+ public function flush_stdout() -> Result[bool, Error]:
689
+ return flush_stdout_internal()
690
+
691
+
692
+ public function flush_stderr() -> Result[bool, Error]:
693
+ return flush_stderr_internal()
694
+
695
+
696
+ public function clear_screen() -> Result[bool, Error]:
697
+ var sequence = string.String.with_capacity(8)
698
+ defer sequence.release()
699
+ append_csi(ref_of(sequence), "2J")
700
+ append_csi(ref_of(sequence), "H")
701
+ return write_stdout_sequence(sequence, "terminal clear screen failed")
702
+
703
+
704
+ public function clear_line() -> Result[bool, Error]:
705
+ var sequence = string.String.with_capacity(5)
706
+ defer sequence.release()
707
+ append_csi(ref_of(sequence), "2K")
708
+ return write_stdout_sequence(sequence, "terminal clear line failed")
709
+
710
+
711
+ public function cursor_home() -> Result[bool, Error]:
712
+ var sequence = string.String.with_capacity(4)
713
+ defer sequence.release()
714
+ append_csi(ref_of(sequence), "H")
715
+ return write_stdout_sequence(sequence, "terminal cursor home failed")
716
+
717
+
718
+ public function move_cursor(row: int, column: int) -> Result[bool, Error]:
719
+ var sequence = string.String.with_capacity(24)
720
+ defer sequence.release()
721
+ append_escape(ref_of(sequence))
722
+ sequence.append_format(f"[#{clamp_cursor_position_1based(row)};#{clamp_cursor_position_1based(column)}H")
723
+ return write_stdout_sequence(sequence, "terminal move cursor failed")
724
+
725
+
726
+ public function hide_cursor() -> Result[bool, Error]:
727
+ var sequence = string.String.with_capacity(8)
728
+ defer sequence.release()
729
+ append_csi(ref_of(sequence), "?25l")
730
+ return write_stdout_sequence(sequence, "terminal hide cursor failed")
731
+
732
+
733
+ public function show_cursor() -> Result[bool, Error]:
734
+ var sequence = string.String.with_capacity(8)
735
+ defer sequence.release()
736
+ append_csi(ref_of(sequence), "?25h")
737
+ return write_stdout_sequence(sequence, "terminal show cursor failed")
738
+
739
+
740
+ public function enter_alternate_screen() -> Result[bool, Error]:
741
+ var sequence = string.String.with_capacity(10)
742
+ defer sequence.release()
743
+ append_csi(ref_of(sequence), "?1049h")
744
+ return write_stdout_sequence(sequence, "terminal alternate screen failed")
745
+
746
+
747
+ public function leave_alternate_screen() -> Result[bool, Error]:
748
+ var sequence = string.String.with_capacity(10)
749
+ defer sequence.release()
750
+ append_csi(ref_of(sequence), "?1049l")
751
+ return write_stdout_sequence(sequence, "terminal alternate screen failed")
752
+
753
+
754
+ public function enable_mouse() -> Result[bool, Error]:
755
+ var sequence = string.String.with_capacity(24)
756
+ defer sequence.release()
757
+ append_csi(ref_of(sequence), "?1000h")
758
+ append_csi(ref_of(sequence), "?1002h")
759
+ append_csi(ref_of(sequence), "?1006h")
760
+ return write_stdout_sequence(sequence, "terminal mouse enable failed")
761
+
762
+
763
+ public function disable_mouse() -> Result[bool, Error]:
764
+ var sequence = string.String.with_capacity(24)
765
+ defer sequence.release()
766
+ append_csi(ref_of(sequence), "?1006l")
767
+ append_csi(ref_of(sequence), "?1002l")
768
+ append_csi(ref_of(sequence), "?1000l")
769
+ return write_stdout_sequence(sequence, "terminal mouse disable failed")
770
+
771
+
772
+ public function set_foreground(color: Color) -> Result[bool, Error]:
773
+ var sequence = string.String.with_capacity(10)
774
+ defer sequence.release()
775
+ append_escape(ref_of(sequence))
776
+ sequence.append("[")
777
+ append_color_code(ref_of(sequence), color, false)
778
+ sequence.append("m")
779
+ return write_stdout_sequence(sequence, "terminal foreground color failed")
780
+
781
+
782
+ public function set_background(color: Color) -> Result[bool, Error]:
783
+ var sequence = string.String.with_capacity(10)
784
+ defer sequence.release()
785
+ append_escape(ref_of(sequence))
786
+ sequence.append("[")
787
+ append_color_code(ref_of(sequence), color, true)
788
+ sequence.append("m")
789
+ return write_stdout_sequence(sequence, "terminal background color failed")
790
+
791
+
792
+ public function set_rgb_foreground(red: int, green: int, blue: int) -> Result[bool, Error]:
793
+ var sequence = string.String.with_capacity(24)
794
+ defer sequence.release()
795
+ append_escape(ref_of(sequence))
796
+ sequence.append_format(
797
+ f"[38;2;#{clamp_color_channel(red)};#{clamp_color_channel(green)};#{clamp_color_channel(blue)}m"
798
+ )
799
+ return write_stdout_sequence(sequence, "terminal foreground color failed")
800
+
801
+
802
+ public function set_rgb_background(red: int, green: int, blue: int) -> Result[bool, Error]:
803
+ var sequence = string.String.with_capacity(24)
804
+ defer sequence.release()
805
+ append_escape(ref_of(sequence))
806
+ sequence.append_format(
807
+ f"[48;2;#{clamp_color_channel(red)};#{clamp_color_channel(green)};#{clamp_color_channel(blue)}m"
808
+ )
809
+ return write_stdout_sequence(sequence, "terminal background color failed")
810
+
811
+
812
+ public function set_bold(enabled: bool) -> Result[bool, Error]:
813
+ var sequence = string.String.with_capacity(6)
814
+ defer sequence.release()
815
+ if enabled:
816
+ append_csi(ref_of(sequence), "1m")
817
+ else:
818
+ append_csi(ref_of(sequence), "22m")
819
+ return write_stdout_sequence(sequence, "terminal bold styling failed")
820
+
821
+
822
+ public function set_underline(enabled: bool) -> Result[bool, Error]:
823
+ var sequence = string.String.with_capacity(6)
824
+ defer sequence.release()
825
+ if enabled:
826
+ append_csi(ref_of(sequence), "4m")
827
+ else:
828
+ append_csi(ref_of(sequence), "24m")
829
+ return write_stdout_sequence(sequence, "terminal underline styling failed")
830
+
831
+
832
+ public function reset_style() -> Result[bool, Error]:
833
+ var sequence = string.String.with_capacity(5)
834
+ defer sequence.release()
835
+ append_csi(ref_of(sequence), "0m")
836
+ return write_stdout_sequence(sequence, "terminal style reset failed")
837
+
838
+
839
+ extending Terminal:
840
+ public static function create() -> Terminal:
841
+ return Terminal(
842
+ input = vec.Vec[ubyte].with_capacity(64),
843
+ size = Size(width = 0, height = 0),
844
+ raw_mode = false,
845
+ alternate_screen = false,
846
+ cursor_hidden = false,
847
+ mouse_enabled = false
848
+ )
849
+
850
+
851
+ public editable function refresh_size() -> Result[Size, Error]:
852
+ let size = get_size_internal()?
853
+ this.size = size
854
+ return Result[Size, Error].success(value= this.size)
855
+
856
+
857
+ public function current_size() -> Size:
858
+ return this.size
859
+
860
+
861
+ public function write(text: str) -> Result[ptr_uint, Error]:
862
+ return write_stdout(text)
863
+
864
+
865
+ public function write_error(text: str) -> Result[ptr_uint, Error]:
866
+ return write_stderr(text)
867
+
868
+
869
+ public function flush() -> Result[bool, Error]:
870
+ return flush_stdout_internal()
871
+
872
+
873
+ public function flush_error() -> Result[bool, Error]:
874
+ return flush_stderr_internal()
875
+
876
+
877
+ public editable function enter_raw_mode() -> Result[bool, Error]:
878
+ if this.raw_mode:
879
+ return Result[bool, Error].success(value= true)
880
+
881
+ let value = raw_mode_enter()?
882
+ this.raw_mode = value
883
+ return Result[bool, Error].success(value= true)
884
+
885
+
886
+ public editable function leave_raw_mode() -> Result[bool, Error]:
887
+ if not this.raw_mode:
888
+ return Result[bool, Error].success(value= true)
889
+
890
+ let value = raw_mode_leave()?
891
+ this.raw_mode = false
892
+ return Result[bool, Error].success(value= value)
893
+
894
+
895
+ public editable function enter_alternate_screen() -> Result[bool, Error]:
896
+ if this.alternate_screen:
897
+ return Result[bool, Error].success(value= true)
898
+
899
+ let value = enter_alternate_screen()?
900
+ this.alternate_screen = value
901
+ return Result[bool, Error].success(value= true)
902
+
903
+
904
+ public editable function leave_alternate_screen() -> Result[bool, Error]:
905
+ if not this.alternate_screen:
906
+ return Result[bool, Error].success(value= true)
907
+
908
+ let value = leave_alternate_screen()?
909
+ this.alternate_screen = false
910
+ return Result[bool, Error].success(value= value)
911
+
912
+
913
+ public editable function hide_cursor() -> Result[bool, Error]:
914
+ if this.cursor_hidden:
915
+ return Result[bool, Error].success(value= true)
916
+
917
+ let value = hide_cursor()?
918
+ this.cursor_hidden = value
919
+ return Result[bool, Error].success(value= true)
920
+
921
+
922
+ public editable function show_cursor() -> Result[bool, Error]:
923
+ if not this.cursor_hidden:
924
+ return Result[bool, Error].success(value= true)
925
+
926
+ let value = show_cursor()?
927
+ this.cursor_hidden = false
928
+ return Result[bool, Error].success(value= value)
929
+
930
+
931
+ public editable function enable_mouse() -> Result[bool, Error]:
932
+ if this.mouse_enabled:
933
+ return Result[bool, Error].success(value= true)
934
+
935
+ let value = enable_mouse()?
936
+ this.mouse_enabled = value
937
+ return Result[bool, Error].success(value= true)
938
+
939
+
940
+ public editable function disable_mouse() -> Result[bool, Error]:
941
+ if not this.mouse_enabled:
942
+ return Result[bool, Error].success(value= true)
943
+
944
+ let value = disable_mouse()?
945
+ this.mouse_enabled = false
946
+ return Result[bool, Error].success(value= value)
947
+
948
+
949
+ public editable function poll_event(timeout_ms: int) -> Result[Option[Event], Error]:
950
+ if stdin_is_tty():
951
+ let current = get_size_internal()?
952
+ if current.width != this.size.width or current.height != this.size.height:
953
+ this.size = current
954
+ return Result[Option[Event], Error].success(value= Option[Event].some(value = resize_event(current)))
955
+
956
+ let ev = parse_event(ref_of(this.input))
957
+ if ev.is_some():
958
+ return Result[Option[Event], Error].success(value= Option[Event].some(value= ev.unwrap()))
959
+
960
+ var bytes = read_stdin(timeout_ms)?
961
+ defer bytes.release()
962
+ if not bytes.is_empty():
963
+ this.input.append_span(bytes.as_span())
964
+
965
+ return Result[Option[Event], Error].success(value= parse_event(ref_of(this.input)))
966
+
967
+
968
+ public editable function release() -> void:
969
+ if this.mouse_enabled:
970
+ let res = disable_mouse()
971
+ if res.is_failure():
972
+ var err = res.unwrap_error()
973
+ err.release()
974
+ this.mouse_enabled = false
975
+
976
+ if this.cursor_hidden:
977
+ let res = show_cursor()
978
+ if res.is_failure():
979
+ var err = res.unwrap_error()
980
+ err.release()
981
+ this.cursor_hidden = false
982
+
983
+ if this.alternate_screen:
984
+ let res = leave_alternate_screen()
985
+ if res.is_failure():
986
+ var err = res.unwrap_error()
987
+ err.release()
988
+ this.alternate_screen = false
989
+
990
+ if this.raw_mode:
991
+ let res = raw_mode_leave()
992
+ if res.is_failure():
993
+ var err = res.unwrap_error()
994
+ err.release()
995
+ this.raw_mode = false
996
+
997
+ this.input.release()
998
+
999
+
1000
+ extending Error:
1001
+ public editable function release() -> void:
1002
+ this.message.release()