summaryrefslogtreecommitdiff
path: root/lib/editor.ml
diff options
context:
space:
mode:
authorFederico Igne <undyamon@disroot.org>2024-01-23 18:11:22 +0100
committerFederico Igne <undyamon@disroot.org>2024-01-23 18:11:22 +0100
commit5c3864986f844a31e0b6dbeec48543dc6376cff6 (patch)
treea6758e873c3a99d95e214b2fc989bc3d63d119fb /lib/editor.ml
parent482e8b80fa66e328e252567c915f5e96e727f7cf (diff)
downloadsandy-5c3864986f844a31e0b6dbeec48543dc6376cff6.tar.gz
sandy-5c3864986f844a31e0b6dbeec48543dc6376cff6.zip
feat: add partial chords to statusbar
Diffstat (limited to 'lib/editor.ml')
-rw-r--r--lib/editor.ml306
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
24type t = editor 24type 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
43let string_of_mode = function 43let 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
308let handle_normal_command = 318let 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
443let handle_next_command m e = 461let 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
455let handle_next_command = 473let handle_next_command =