summaryrefslogtreecommitdiff
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
parent482e8b80fa66e328e252567c915f5e96e727f7cf (diff)
downloadsandy-5c3864986f844a31e0b6dbeec48543dc6376cff6.tar.gz
sandy-5c3864986f844a31e0b6dbeec48543dc6376cff6.zip
feat: add partial chords to statusbar
-rw-r--r--lib/command.ml47
-rw-r--r--lib/editor.ml306
-rw-r--r--lib/key.ml19
-rw-r--r--lib/text.ml9
4 files changed, 213 insertions, 168 deletions
diff --git a/lib/command.ml b/lib/command.ml
index 31e2ca2..74b616a 100644
--- a/lib/command.ml
+++ b/lib/command.ml
@@ -18,6 +18,7 @@ type operation =
18type scope = Line | To_bol | To_eol | Down | Left | Right | Up 18type scope = Line | To_bol | To_eol | Down | Left | Right | Up
19 19
20type command = 20type command =
21 | Reset
21 | Type of char 22 | Type of char
22 | Simple of Key.t 23 | Simple of Key.t
23 | Partial of Key.t 24 | Partial of Key.t
@@ -89,59 +90,57 @@ let is_instant_operation k = List.mem ~equal:Poly.equal instant_operation k
89 90
90let n_stream = 91let n_stream =
91 let step s k = 92 let step s k =
92 let open Sequence.Step in
93 match (s, k) with 93 match (s, k) with
94 | `start, Key '"' -> Yield { value = Partial k; state = `chord_reg_pre } 94 | `start, Key '"' -> (`chord_reg_pre, Partial k)
95 (* Register *) 95 (* Register *)
96 | `chord_reg_pre, Key c -> Yield { value = Partial k; state = `chord_reg c } 96 | `chord_reg_pre, Key c -> (`chord_reg c, Partial k)
97 (* Count (first) *) 97 (* Count (first) *)
98 | `start, Key n when Char.('1' <= n && n <= '9') -> 98 | `start, Key n when Char.('1' <= n && n <= '9') ->
99 let n = Char.to_int n - 48 in 99 let n = Char.to_int n - 48 in
100 Yield { value = Partial k; state = `chord_fst_n (None, n) } 100 (`chord_fst_n (None, n), Partial k)
101 | `chord_reg r, Key n when Char.('1' <= n && n <= '9') -> 101 | `chord_reg r, Key n when Char.('1' <= n && n <= '9') ->
102 let n = Char.to_int n - 48 in 102 let n = Char.to_int n - 48 in
103 Yield { value = Partial k; state = `chord_fst_n (Some r, n) } 103 (`chord_fst_n (Some r, n), Partial k)
104 | `chord_fst_n (r, m), Key n when Char.('0' <= n && n <= '9') -> 104 | `chord_fst_n (r, m), Key n when Char.('0' <= n && n <= '9') ->
105 let n = (10 * m) + Char.to_int n - 48 in 105 let n = (10 * m) + Char.to_int n - 48 in
106 Yield { value = Partial k; state = `chord_fst_n (r, n) } 106 (`chord_fst_n (r, n), Partial k)
107 (* Instant operations *) 107 (* Instant operations *)
108 | `start, k when is_instant_operation k -> 108 | `start, k when is_instant_operation k -> (`start, shortcut (to_op k))
109 Yield { value = shortcut (to_op k); state = `start }
110 | `chord_reg r, k when is_instant_operation k -> 109 | `chord_reg r, k when is_instant_operation k ->
111 Yield { value = shortcut ~r (to_op k); state = `start } 110 (`start, shortcut ~r (to_op k))
112 | `chord_fst_n (r, n), k when is_instant_operation k -> 111 | `chord_fst_n (r, n), k when is_instant_operation k ->
113 Yield { value = shortcut ?r ~n (to_op k); state = `start } 112 (`start, shortcut ?r ~n (to_op k))
114 (* Chord operation (first) *) 113 (* Chord operation (first) *)
115 | `start, k when is_chord_operation k -> 114 | `start, k when is_chord_operation k ->
116 Yield { value = Partial k; state = `chord_cmd (None, None, to_op k) } 115 (`chord_cmd (None, None, to_op k), Partial k)
117 | `chord_reg r, k when is_chord_operation k -> 116 | `chord_reg r, k when is_chord_operation k ->
118 Yield { value = Partial k; state = `chord_cmd (Some r, None, to_op k) } 117 (`chord_cmd (Some r, None, to_op k), Partial k)
119 | `chord_fst_n (r, n), k when is_chord_operation k -> 118 | `chord_fst_n (r, n), k when is_chord_operation k ->
120 Yield { value = Partial k; state = `chord_cmd (r, Some n, to_op k) } 119 (`chord_cmd (r, Some n, to_op k), Partial k)
121 (* Count (second) *) 120 (* Count (second) *)
122 | `chord_cmd (r, n1, c), Key n when Char.('1' <= n && n <= '9') -> 121 | `chord_cmd (r, n1, c), Key n when Char.('1' <= n && n <= '9') ->
123 let n = Char.to_int n - 48 in 122 let n = Char.to_int n - 48 in
124 Yield { value = Partial k; state = `chord_snd_n (r, n1, c, n) } 123 (`chord_snd_n (r, n1, c, n), Partial k)
125 | `chord_snd_n (r, n1, c, n2), Key n when Char.('0' <= n && n <= '9') -> 124 | `chord_snd_n (r, n1, c, n2), Key n when Char.('0' <= n && n <= '9') ->
126 let n2 = (10 * n2) + Char.to_int n - 48 in 125 let n2 = (10 * n2) + Char.to_int n - 48 in
127 Yield { value = Partial k; state = `chord_snd_n (r, n1, c, n2) } 126 (`chord_snd_n (r, n1, c, n2), Partial k)
128 (* Chord operation (second) *) 127 (* Chord operation (second) *)
129 | `chord_cmd (r, n, c), k when is_chord_operation k && Poly.(c = to_op k) -> 128 | `chord_cmd (r, n, c), k when is_chord_operation k && Poly.(c = to_op k) ->
130 Yield { value = chord ?r ?n1:n c Line; state = `start } 129 (`start, chord ?r ?n1:n c Line)
131 | `chord_snd_n (r, n1, c, n2), k 130 | `chord_snd_n (r, n1, c, n2), k
132 when is_chord_operation k && Poly.(c = to_op k) -> 131 when is_chord_operation k && Poly.(c = to_op k) ->
133 Yield { value = chord ?r ?n1 c ~n2 Line; state = `start } 132 (`start, chord ?r ?n1 c ~n2 Line)
134 (* Movement *) 133 (* Movement *)
135 | (`start | `chord_reg _), k when is_simple_movement k -> 134 | (`start | `chord_reg _), k when is_simple_movement k ->
136 Yield { value = chord Noop (to_scope k); state = `start } 135 (`start, chord Noop (to_scope k))
137 | `chord_fst_n (_, n), k when is_simple_movement k -> 136 | `chord_fst_n (_, n), k when is_simple_movement k ->
138 Yield { value = chord ~n1:n Noop (to_scope k); state = `start } 137 (`start, chord ~n1:n Noop (to_scope k))
139 | `chord_cmd (r, n, c), k when is_simple_movement k -> 138 | `chord_cmd (r, n, c), k when is_simple_movement k ->
140 Yield { value = chord ?r ?n1:n c (to_scope k); state = `start } 139 (`start, chord ?r ?n1:n c (to_scope k))
141 | `chord_snd_n (r, n1, c, n2), k when is_simple_movement k -> 140 | `chord_snd_n (r, n1, c, n2), k when is_simple_movement k ->
142 Yield { value = chord ?r ?n1 c ~n2 (to_scope k); state = `start } 141 (`start, chord ?r ?n1 c ~n2 (to_scope k))
143 (* Catch-all rules *) 142 (* Catch-all rules *)
144 | `start, _ -> Yield { value = Simple k; state = `start } 143 | `start, _ -> (`start, Simple k)
145 | _, _ -> Skip { state = `start } 144 | _, _ -> (`start, Reset)
146 in 145 in
147 Sequence.unfold_with ~init:`start ~f:step Key.stream 146 Sequence.folding_map ~init:`start ~f:step Key.stream
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 =
diff --git a/lib/key.ml b/lib/key.ml
index d6656c5..22338f4 100644
--- a/lib/key.ml
+++ b/lib/key.ml
@@ -32,6 +32,25 @@ let of_char = function
32 | c when Char.(c < ' ') -> Char.to_int c + 64 |> Char.of_int_exn |> ctrl 32 | c when Char.(c < ' ') -> Char.to_int c + 64 |> Char.of_int_exn |> ctrl
33 | c -> Key c 33 | c -> Key c
34 34
35let to_string = function
36 | Arrow_down -> "<down>"
37 | Arrow_left -> "<left>"
38 | Arrow_right -> "<right>"
39 | Arrow_up -> "<up>"
40 | Backspace -> "<backspace>"
41 | Ctrl c -> Printf.sprintf "<c-%c>" c
42 | Delete -> "<delete>"
43 | End -> "<end>"
44 | Enter -> "<cr>"
45 | Esc -> "<esc>"
46 | Home -> "<home>"
47 | Key ' ' -> "<space>"
48 | Key c -> String.of_char c
49 | Nul -> "<nil>"
50 | Page_down -> "<pgdown>"
51 | Page_up -> "<pgup>"
52 | Tab -> "<tab>"
53
35let stream = 54let stream =
36 let step s c = 55 let step s c =
37 let open Sequence.Step in 56 let open Sequence.Step in
diff --git a/lib/text.ml b/lib/text.ml
index ff1f727..218f5e1 100644
--- a/lib/text.ml
+++ b/lib/text.ml
@@ -8,3 +8,12 @@ let center ~fill n text =
8 take (take padding len_p @ text @ padding) n 8 take (take padding len_p @ text @ padding) n
9 9
10let extend ~fill n text = take (text @ repeat fill) n 10let extend ~fill n text = take (text @ repeat fill) n
11
12let spread ?(l = empty) ?(lsize = length l) ?(c = empty) ?(csize = length c)
13 ?(r = empty) ?(rsize = length r) ~fill w =
14 let lpad = take (repeat fill) ((w / 2) - lsize - (csize / 2) - 1) in
15 let rpad = take (repeat fill) ((w / 2) - rsize - (csize / 2)) in
16 l @ lpad @ c @ rpad @ r
17
18let invert text = Terminal.(fmt_inverted_on @ text @ fmt_inverted_off)
19let bold text = Terminal.(fmt_bold_on @ text @ fmt_bold_off)