diff options
author | Federico Igne <undyamon@disroot.org> | 2024-01-23 18:11:22 +0100 |
---|---|---|
committer | Federico Igne <undyamon@disroot.org> | 2024-01-23 18:11:22 +0100 |
commit | 5c3864986f844a31e0b6dbeec48543dc6376cff6 (patch) | |
tree | a6758e873c3a99d95e214b2fc989bc3d63d119fb /lib/editor.ml | |
parent | 482e8b80fa66e328e252567c915f5e96e727f7cf (diff) | |
download | sandy-5c3864986f844a31e0b6dbeec48543dc6376cff6.tar.gz sandy-5c3864986f844a31e0b6dbeec48543dc6376cff6.zip |
feat: add partial chords to statusbar
Diffstat (limited to 'lib/editor.ml')
-rw-r--r-- | lib/editor.ml | 306 |
1 files changed, 162 insertions, 144 deletions
diff --git a/lib/editor.ml b/lib/editor.ml index c34d558..230f13a 100644 --- a/lib/editor.ml +++ b/lib/editor.ml | |||
@@ -12,13 +12,13 @@ type editor = { | |||
12 | cursor : cursor; | 12 | cursor : cursor; |
13 | buffer : Buffer.t option; | 13 | buffer : Buffer.t option; |
14 | rendered : bool; | 14 | rendered : bool; |
15 | pending : Key.t Sequence.t; | 15 | istream : Command.t Sequence.t; |
16 | i_pending : Command.t Sequence.t; | 16 | nstream : Command.t Sequence.t; |
17 | n_pending : Command.t Sequence.t; | ||
18 | status_size : int; | 17 | status_size : int; |
19 | message : string option; | 18 | message : string option; |
20 | message_timestamp : float; | 19 | message_timestamp : float; |
21 | message_duration : float; | 20 | message_duration : float; |
21 | pending_command : string; | ||
22 | } | 22 | } |
23 | 23 | ||
24 | type t = editor | 24 | type t = editor |
@@ -31,13 +31,13 @@ let init (c : Config.t) : editor = | |||
31 | cursor = (1, 1); | 31 | cursor = (1, 1); |
32 | buffer = List.hd c.files |> Option.map ~f:Buffer.from_file; | 32 | buffer = List.hd c.files |> Option.map ~f:Buffer.from_file; |
33 | rendered = true; | 33 | rendered = true; |
34 | pending = Key.stream; | 34 | istream = Command.i_stream; |
35 | i_pending = Command.i_stream; | 35 | nstream = Command.n_stream; |
36 | n_pending = Command.n_stream; | ||
37 | status_size = 2; | 36 | status_size = 2; |
38 | message = Some "Hello, control line!"; | 37 | message = Some "Hello, control line!"; |
39 | message_timestamp = Unix.time (); | 38 | message_timestamp = Unix.time (); |
40 | message_duration = 5.; | 39 | message_duration = 5.; |
40 | pending_command = ""; | ||
41 | } | 41 | } |
42 | 42 | ||
43 | let string_of_mode = function | 43 | let string_of_mode = function |
@@ -80,8 +80,9 @@ let statusbar e = | |||
80 | ~fill:' ' w | 80 | ~fill:' ' w |
81 | |> invert | 81 | |> invert |
82 | and control = | 82 | and control = |
83 | let msg = Option.value ~default:"" e.message |> sequence_of_string in | 83 | let msg = Option.value ~default:"" e.message |> sequence_of_string |
84 | spread ~l:msg ~fill:' ' w | 84 | and cmd = e.pending_command |> sequence_of_string in |
85 | spread ~l:msg ~r:cmd ~fill:' ' w | ||
85 | in | 86 | in |
86 | Sequence.(take (of_list [ status; control ]) e.status_size) | 87 | Sequence.(take (of_list [ status; control ]) e.status_size) |
87 | 88 | ||
@@ -187,6 +188,14 @@ module Action = struct | |||
187 | let set_message m e = | 188 | let set_message m e = |
188 | ((), { e with message = m; message_timestamp = Unix.time () }) | 189 | ((), { e with message = m; message_timestamp = Unix.time () }) |
189 | 190 | ||
191 | let get_pending_command e = (e.pending_command, e) | ||
192 | let set_pending_command p e = ((), { e with pending_command = p }) | ||
193 | |||
194 | let append_pending_command k = | ||
195 | let aux p = p ^ Key.to_string k in | ||
196 | get_pending_command >>| aux >>= set_pending_command | ||
197 | |||
198 | let clear_pending_command = set_pending_command "" | ||
190 | 199 | ||
191 | let tick = | 200 | let tick = |
192 | let check_message_timestamp e = | 201 | let check_message_timestamp e = |
@@ -285,6 +294,7 @@ let handle_insert_command = | |||
285 | (Buffer.Action.move_left |> on_focused_buffer) *> set_mode Normal | 294 | (Buffer.Action.move_left |> on_focused_buffer) *> set_mode Normal |
286 | | Simple Page_down | Simple (Ctrl 'F') -> | 295 | | Simple Page_down | Simple (Ctrl 'F') -> |
287 | fun e -> | 296 | fun e -> |
297 | (* TODO consider using the buffer window size (i.e., subtract status_size) *) | ||
288 | let (n, _), e = get_terminal_size e in | 298 | let (n, _), e = get_terminal_size e in |
289 | on_focused_buffer (Buffer.Action.move_down ~n) e | 299 | on_focused_buffer (Buffer.Action.move_down ~n) e |
290 | | Simple Page_up | Simple (Ctrl 'B') -> | 300 | | Simple Page_up | Simple (Ctrl 'B') -> |
@@ -305,151 +315,159 @@ let handle_insert_command = | |||
305 | | Type k -> Buffer.Action.insert k |> on_focused_buffer | 315 | | Type k -> Buffer.Action.insert k |> on_focused_buffer |
306 | | _ -> noop | 316 | | _ -> noop |
307 | 317 | ||
308 | let handle_normal_command = | 318 | let handle_normal_command c = |
309 | let open Command in | 319 | let open Command in |
310 | let open Action in | 320 | let open Action in |
311 | function | 321 | let update_command_cue = |
312 | (* Movements *) | 322 | match c with |
313 | | Chord (_, n, Noop, _, Down) -> | 323 | | Partial k -> append_pending_command k |
314 | Buffer.Action.move_down ?n |> on_focused_buffer | 324 | | _ -> clear_pending_command |
315 | | Chord (_, n, Noop, _, Left) -> | 325 | and compute_action = |
316 | Buffer.Action.move_left ?n |> on_focused_buffer | 326 | match c with |
317 | | Chord (_, n, Noop, _, Right) -> | 327 | (* Movements *) |
318 | Buffer.Action.move_right ?n |> on_focused_buffer | 328 | | Chord (_, n, Noop, _, Down) -> |
319 | | Chord (_, n, Noop, _, Up) -> Buffer.Action.move_up ?n |> on_focused_buffer | 329 | Buffer.Action.move_down ?n |> on_focused_buffer |
320 | | Chord (_, n, Noop, _, To_bol) -> | 330 | | Chord (_, n, Noop, _, Left) -> |
321 | let n = Option.value ~default:1 n - 1 in | 331 | Buffer.Action.move_left ?n |> on_focused_buffer |
322 | Buffer.Action.(move_down ~n &> bol) |> on_focused_buffer | 332 | | Chord (_, n, Noop, _, Right) -> |
323 | | Chord (_, n, Noop, _, To_eol) -> | 333 | Buffer.Action.move_right ?n |> on_focused_buffer |
324 | let n = Option.value ~default:1 n - 1 in | 334 | | Chord (_, n, Noop, _, Up) -> Buffer.Action.move_up ?n |> on_focused_buffer |
325 | Buffer.Action.(move_down ~n &> eol) |> on_focused_buffer | 335 | | Chord (_, n, Noop, _, To_bol) -> |
326 | | Simple Page_down | Simple (Ctrl 'F') -> | 336 | let n = Option.value ~default:1 n - 1 in |
327 | fun e -> | 337 | Buffer.Action.(move_down ~n &> bol) |> on_focused_buffer |
328 | let (n, _), e = get_terminal_size e in | 338 | | Chord (_, n, Noop, _, To_eol) -> |
329 | on_focused_buffer (Buffer.Action.move_down ~n) e | 339 | let n = Option.value ~default:1 n - 1 in |
330 | | Simple Page_up | Simple (Ctrl 'B') -> | 340 | Buffer.Action.(move_down ~n &> eol) |> on_focused_buffer |
331 | fun e -> | 341 | | Simple Page_down | Simple (Ctrl 'F') -> |
332 | let (n, _), e = get_terminal_size e in | 342 | fun e -> |
333 | on_focused_buffer (Buffer.Action.move_up ~n) e | 343 | let (n, _), e = get_terminal_size e in |
334 | | Simple (Ctrl 'D') -> | 344 | on_focused_buffer (Buffer.Action.move_down ~n) e |
335 | fun e -> | 345 | | Simple Page_up | Simple (Ctrl 'B') -> |
336 | let (r, _), e = get_terminal_size e in | 346 | fun e -> |
337 | on_focused_buffer (Buffer.Action.move_down ~n:(r / 2)) e | 347 | let (n, _), e = get_terminal_size e in |
338 | | Simple (Ctrl 'U') -> | 348 | on_focused_buffer (Buffer.Action.move_up ~n) e |
339 | fun e -> | 349 | | Simple (Ctrl 'D') -> |
340 | let (r, _), e = get_terminal_size e in | 350 | fun e -> |
341 | on_focused_buffer (Buffer.Action.move_up ~n:(r / 2)) e | 351 | let (r, _), e = get_terminal_size e in |
342 | (* Change *) | 352 | on_focused_buffer (Buffer.Action.move_down ~n:(r / 2)) e |
343 | | Shortcut (_, n, Change) -> | 353 | | Simple (Ctrl 'U') -> |
344 | let n = Option.value ~default:1 n - 1 in | 354 | fun e -> |
345 | (Buffer.Action.( | 355 | let (r, _), e = get_terminal_size e in |
346 | delete_to_eol &> move_down &> delete_lines ~n &> move_up &> eol) | 356 | on_focused_buffer (Buffer.Action.move_up ~n:(r / 2)) e |
347 | |> on_focused_buffer_or_new) | 357 | (* Change *) |
348 | *> set_mode Insert | 358 | | Shortcut (_, n, Change) -> |
349 | | Chord (_, n1, Change, n2, Line) -> | 359 | let n = Option.value ~default:1 n - 1 in |
350 | let n = Option.((value ~default:1 n1 * value ~default:1 n2) - 1) in | 360 | (Buffer.Action.( |
351 | (Buffer.Action.(delete_lines ~n &> bol &> delete_to_eol) | 361 | delete_to_eol &> move_down &> delete_lines ~n &> move_up &> eol) |
352 | |> on_focused_buffer_or_new) | 362 | |> on_focused_buffer_or_new) |
353 | *> set_mode Insert | 363 | *> set_mode Insert |
354 | | Chord (_, n1, Change, n2, Down) -> | 364 | | Chord (_, n1, Change, n2, Line) -> |
355 | let n = Option.(value ~default:1 n1 * value ~default:1 n2) in | 365 | let n = Option.((value ~default:1 n1 * value ~default:1 n2) - 1) in |
356 | (Buffer.Action.(delete_lines ~n &> bol &> delete_to_eol) | 366 | (Buffer.Action.(delete_lines ~n &> bol &> delete_to_eol) |
357 | |> on_focused_buffer_or_new) | 367 | |> on_focused_buffer_or_new) |
358 | *> set_mode Insert | 368 | *> set_mode Insert |
359 | | Chord (_, n1, Change, n2, Left) -> | 369 | | Chord (_, n1, Change, n2, Down) -> |
360 | let n = Option.(value ~default:1 n1 * value ~default:1 n2) in | 370 | let n = Option.(value ~default:1 n1 * value ~default:1 n2) in |
361 | (Buffer.Action.delete_before ~n |> on_focused_buffer_or_new) | 371 | (Buffer.Action.(delete_lines ~n &> bol &> delete_to_eol) |
362 | *> set_mode Insert | 372 | |> on_focused_buffer_or_new) |
363 | | Chord (_, n1, Change, n2, Right) -> | 373 | *> set_mode Insert |
364 | let n = Option.(value ~default:1 n1 * value ~default:1 n2) in | 374 | | Chord (_, n1, Change, n2, Left) -> |
365 | (Buffer.Action.delete_after ~n |> on_focused_buffer_or_new) | 375 | let n = Option.(value ~default:1 n1 * value ~default:1 n2) in |
366 | *> set_mode Insert | 376 | (Buffer.Action.delete_before ~n |> on_focused_buffer_or_new) |
367 | | Chord (_, n1, Change, n2, Up) -> | 377 | *> set_mode Insert |
368 | let n = Option.(value ~default:1 n1 * value ~default:1 n2) in | 378 | | Chord (_, n1, Change, n2, Right) -> |
369 | (Buffer.Action.(bol &> delete_to_eol &> delete_lines_before ~n) | 379 | let n = Option.(value ~default:1 n1 * value ~default:1 n2) in |
370 | |> on_focused_buffer_or_new) | 380 | (Buffer.Action.delete_after ~n |> on_focused_buffer_or_new) |
371 | *> set_mode Insert | 381 | *> set_mode Insert |
372 | | Chord (_, n1, Change, n2, To_bol) -> | 382 | | Chord (_, n1, Change, n2, Up) -> |
373 | let n = Option.((value ~default:1 n1 * value ~default:1 n2) - 1) in | 383 | let n = Option.(value ~default:1 n1 * value ~default:1 n2) in |
374 | (Buffer.Action.( | 384 | (Buffer.Action.(bol &> delete_to_eol &> delete_lines_before ~n) |
375 | delete_to_bol &> move_down &> delete_lines ~n &> move_up &> bol) | 385 | |> on_focused_buffer_or_new) |
376 | |> on_focused_buffer_or_new) | 386 | *> set_mode Insert |
377 | *> set_mode Insert | 387 | | Chord (_, n1, Change, n2, To_bol) -> |
378 | | Chord (_, n1, Change, n2, To_eol) -> | 388 | let n = Option.((value ~default:1 n1 * value ~default:1 n2) - 1) in |
379 | let n = Option.((value ~default:1 n1 * value ~default:1 n2) - 1) in | 389 | (Buffer.Action.( |
380 | (Buffer.Action.( | 390 | delete_to_bol &> move_down &> delete_lines ~n &> move_up &> bol) |
381 | delete_to_eol &> move_down &> delete_lines ~n &> move_up &> eol) | 391 | |> on_focused_buffer_or_new) |
382 | |> on_focused_buffer_or_new) | 392 | *> set_mode Insert |
383 | *> set_mode Insert | 393 | | Chord (_, n1, Change, n2, To_eol) -> |
384 | (* Delete *) | 394 | let n = Option.((value ~default:1 n1 * value ~default:1 n2) - 1) in |
385 | | Shortcut (_, n, Delete) -> | 395 | (Buffer.Action.( |
386 | let n = Option.value ~default:1 n - 1 in | 396 | delete_to_eol &> move_down &> delete_lines ~n &> move_up &> eol) |
387 | Buffer.Action.( | 397 | |> on_focused_buffer_or_new) |
388 | delete_to_eol &> move_down &> delete_lines ~n &> move_up &> eol) | 398 | *> set_mode Insert |
389 | |> on_focused_buffer_or_new | 399 | (* Delete *) |
390 | | Chord (_, n1, Delete, n2, Line) -> | 400 | | Shortcut (_, n, Delete) -> |
391 | let n = Option.(value ~default:1 n1 * value ~default:1 n2) in | 401 | let n = Option.value ~default:1 n - 1 in |
392 | Buffer.Action.delete_lines ~n |> on_focused_buffer_or_new | 402 | Buffer.Action.( |
393 | | Chord (_, n1, Delete, n2, Down) -> | 403 | delete_to_eol &> move_down &> delete_lines ~n &> move_up &> eol) |
394 | let n = Option.((value ~default:1 n1 * value ~default:1 n2) + 1) in | 404 | |> on_focused_buffer_or_new |
395 | Buffer.Action.delete_lines ~n |> on_focused_buffer_or_new | 405 | | Chord (_, n1, Delete, n2, Line) -> |
396 | | Chord (_, n1, Delete, n2, Left) -> | 406 | let n = Option.(value ~default:1 n1 * value ~default:1 n2) in |
397 | let n = Option.(value ~default:1 n1 * value ~default:1 n2) in | 407 | Buffer.Action.delete_lines ~n |> on_focused_buffer_or_new |
398 | Buffer.Action.delete_before ~n |> on_focused_buffer_or_new | 408 | | Chord (_, n1, Delete, n2, Down) -> |
399 | | Shortcut (_, n, Erase_before) -> | 409 | let n = Option.((value ~default:1 n1 * value ~default:1 n2) + 1) in |
400 | let n = Option.(value ~default:1 n) in | 410 | Buffer.Action.delete_lines ~n |> on_focused_buffer_or_new |
401 | Buffer.Action.delete_before ~n |> on_focused_buffer_or_new | 411 | | Chord (_, n1, Delete, n2, Left) -> |
402 | | Chord (_, n1, Delete, n2, Right) -> | 412 | let n = Option.(value ~default:1 n1 * value ~default:1 n2) in |
403 | let n = Option.(value ~default:1 n1 * value ~default:1 n2) in | 413 | Buffer.Action.delete_before ~n |> on_focused_buffer_or_new |
404 | Buffer.Action.delete_after ~n |> on_focused_buffer_or_new | 414 | | Shortcut (_, n, Erase_before) -> |
405 | | Shortcut (_, n, Erase_after) -> | 415 | let n = Option.(value ~default:1 n) in |
406 | let n = Option.(value ~default:1 n) in | 416 | Buffer.Action.delete_before ~n |> on_focused_buffer_or_new |
407 | Buffer.Action.delete_after ~n |> on_focused_buffer_or_new | 417 | | Chord (_, n1, Delete, n2, Right) -> |
408 | | Chord (_, n1, Delete, n2, Up) -> | 418 | let n = Option.(value ~default:1 n1 * value ~default:1 n2) in |
409 | let n = Option.(value ~default:1 n1 * value ~default:1 n2) in | 419 | Buffer.Action.delete_after ~n |> on_focused_buffer_or_new |
410 | Buffer.Action.(delete_lines ~n:1 &> delete_lines_before ~n) | 420 | | Shortcut (_, n, Erase_after) -> |
411 | |> on_focused_buffer_or_new | 421 | let n = Option.(value ~default:1 n) in |
412 | | Chord (_, n1, Delete, n2, To_bol) -> | 422 | Buffer.Action.delete_after ~n |> on_focused_buffer_or_new |
413 | let n = Option.((value ~default:1 n1 * value ~default:1 n2) - 1) in | 423 | | Chord (_, n1, Delete, n2, Up) -> |
414 | Buffer.Action.( | 424 | let n = Option.(value ~default:1 n1 * value ~default:1 n2) in |
415 | delete_to_bol &> move_down &> delete_lines ~n &> move_up &> bol) | 425 | Buffer.Action.(delete_lines ~n:1 &> delete_lines_before ~n) |
416 | |> on_focused_buffer_or_new | 426 | |> on_focused_buffer_or_new |
417 | | Chord (_, n1, Delete, n2, To_eol) -> | 427 | | Chord (_, n1, Delete, n2, To_bol) -> |
418 | let n = Option.((value ~default:1 n1 * value ~default:1 n2) - 1) in | 428 | let n = Option.((value ~default:1 n1 * value ~default:1 n2) - 1) in |
419 | Buffer.Action.( | 429 | Buffer.Action.( |
420 | delete_to_eol &> move_down &> delete_lines ~n &> move_up &> eol) | 430 | delete_to_bol &> move_down &> delete_lines ~n &> move_up &> bol) |
421 | |> on_focused_buffer_or_new | 431 | |> on_focused_buffer_or_new |
422 | (* Join *) | 432 | | Chord (_, n1, Delete, n2, To_eol) -> |
423 | | Shortcut (_, n, Join) -> | 433 | let n = Option.((value ~default:1 n1 * value ~default:1 n2) - 1) in |
424 | let n = Option.(value ~default:1 n) in | 434 | Buffer.Action.( |
425 | Buffer.Action.join_lines ~n |> on_focused_buffer_or_new | 435 | delete_to_eol &> move_down &> delete_lines ~n &> move_up &> eol) |
426 | (* Quit *) | 436 | |> on_focused_buffer_or_new |
427 | | Simple (Ctrl 'Q') -> quit 0 | 437 | (* Join *) |
428 | (* Misc *) | 438 | | Shortcut (_, n, Join) -> |
429 | | Simple (Key 'A') -> | 439 | let n = Option.(value ~default:1 n) in |
430 | (Buffer.Action.eol |> on_focused_buffer_or_new) *> set_mode Insert | 440 | Buffer.Action.join_lines ~n |> on_focused_buffer_or_new |
431 | | Simple (Key 'a') -> | 441 | (* Quit *) |
432 | (Buffer.Action.move_right |> on_focused_buffer_or_new) *> set_mode Insert | 442 | | Simple (Ctrl 'Q') -> quit 0 |
433 | (* | Key 'G' -> Buffer.Action.eof |> on_focused_buffer_or_new *) | 443 | (* Misc *) |
434 | (* | Key 'I' -> noop *) | 444 | | Simple (Key 'A') -> |
435 | | Simple (Key 'i') -> (Fn.id |> on_focused_buffer_or_new) *> set_mode Insert | 445 | (Buffer.Action.eol |> on_focused_buffer_or_new) *> set_mode Insert |
436 | (* | Key 's' -> *) | 446 | | Simple (Key 'a') -> |
437 | (* (Buffer.Action.delete_after |> on_focused_buffer_or_new) *) | 447 | (Buffer.Action.move_right |> on_focused_buffer_or_new) |
438 | (* *> set_mode Insert *) | 448 | *> set_mode Insert |
439 | (* Debug *) | 449 | (* | Key 'G' -> Buffer.Action.eof |> on_focused_buffer_or_new *) |
440 | | Simple (Ctrl 'R') -> toggle_rendered | 450 | (* | Key 'I' -> noop *) |
441 | | _ -> noop | 451 | | Simple (Key 'i') -> (Fn.id |> on_focused_buffer_or_new) *> set_mode Insert |
452 | (* | Key 's' -> *) | ||
453 | (* (Buffer.Action.delete_after |> on_focused_buffer_or_new) *) | ||
454 | (* *> set_mode Insert *) | ||
455 | (* Debug *) | ||
456 | | Simple (Ctrl 'R') -> toggle_rendered | ||
457 | | _ -> noop | ||
458 | in | ||
459 | compute_action *> update_command_cue | ||
442 | 460 | ||
443 | let handle_next_command m e = | 461 | let handle_next_command m e = |
444 | match m with | 462 | match m with |
445 | | Insert -> ( | 463 | | Insert -> ( |
446 | match Sequence.next e.i_pending with | 464 | match Sequence.next e.istream with |
447 | | None -> ((), e) | 465 | | None -> ((), e) |
448 | | Some (h, t) -> handle_insert_command h { e with i_pending = t }) | 466 | | Some (h, t) -> handle_insert_command h { e with istream = t }) |
449 | | Normal -> ( | 467 | | Normal -> ( |
450 | match Sequence.next e.n_pending with | 468 | match Sequence.next e.nstream with |
451 | | None -> ((), e) | 469 | | None -> ((), e) |
452 | | Some (h, t) -> handle_normal_command h { e with n_pending = t }) | 470 | | Some (h, t) -> handle_normal_command h { e with nstream = t }) |
453 | | Control -> failwith "unimplemented" | 471 | | Control -> failwith "unimplemented" |
454 | 472 | ||
455 | let handle_next_command = | 473 | let handle_next_command = |