Backspace but there's a subtle/unusual issue with enter/backspace and the text insertion occuring on the wrong line after unknown sequence.

This commit is contained in:
cqc
2022-12-14 13:23:16 -06:00
parent 5c10f3860a
commit a12db025e0
2 changed files with 573275 additions and 48 deletions

573193
_build/default/boot_js.bc.js Normal file

File diff suppressed because one or more lines are too long

130
human.ml
View File

@ -1335,7 +1335,7 @@ module Nottui = struct
let pp_may_handle ppf = function let pp_may_handle ppf = function
| `Unhandled -> F.pf ppf "`Unhandled" | `Unhandled -> F.pf ppf "`Unhandled"
| `Handled -> F.pf ppf "`Unhandled" | `Handled -> F.pf ppf "`Handled"
type mouse_handler = type mouse_handler =
x:float -> x:float ->
@ -2628,8 +2628,8 @@ module Nottui_widgets = struct
let sub' str p l = let sub' str p l =
if p = 0 && l = String.length str then str else String.sub str p l if p = 0 && l = String.length str then str else String.sub str p l
let edit_field ?(focus = Focus.make ()) ?(on_change = Fun.id) let edit_field ?(focus = Focus.make ()) ?(on_change = Fun.id) state
?(on_submit = ignore) state = =
let on_change a = Lwd.set state (on_change a) in let on_change a = Lwd.set state (on_change a) in
let update focus_h focus (text, pos) = let update focus_h focus (text, pos) =
let pos = min (max 0 pos) (String.length text) in let pos = min (max 0 pos) (String.length text) in
@ -2643,9 +2643,10 @@ module Nottui_widgets = struct
[ I.string ~attr text; I.string ~attr:attr_cursor " " ] [ I.string ~attr text; I.string ~attr:attr_cursor " " ]
else else
[ [
I.string ~attr (sub' text 0 pos); I.string ~attr (String.sub text 0 pos);
I.string ~attr:attr_cursor (sub' text pos 1); I.string ~attr:attr_cursor (String.sub text pos 1);
I.string ~attr (sub' text (pos + 1) (len - pos - 1)); I.string ~attr
(String.sub text (pos + 1) (len - pos - 1));
] ]
else [ I.string (if text = "" then " " else text) ] else [ I.string (if text = "" then " " else text) ]
in in
@ -2667,23 +2668,23 @@ module Nottui_widgets = struct
in in
on_change (text, pos + 1); on_change (text, pos + 1);
`Handled `Handled
| `Backspace, _ -> | `Backspace, [] ->
let text = if pos > 0 then (
if pos > 0 then let text =
if pos < String.length text then if pos < String.length text then
String.sub text 0 (pos - 1) String.sub text 0 (pos - 1)
^ String.sub text pos (String.length text - pos) ^ String.sub text pos (String.length text - pos)
else if String.length text > 0 then else if String.length text > 0 then
String.sub text 0 (String.length text - 1) String.sub text 0 (String.length text - 1)
else text else text
else text in
in let pos = max 0 (pos - 1) in
let pos = max 0 (pos - 1) in on_change (text, pos);
on_change (text, pos); `Handled)
`Handled else `Unhandled
| `Enter, _ -> (* | `Enter, _ ->
on_submit (text, pos); on_submit (text, pos);
`Handled `Handled *)
| `Arrow `Left, [] -> | `Arrow `Left, [] ->
let pos = min (String.length text) pos in let pos = min (String.length text) pos in
if pos > 0 then ( if pos > 0 then (
@ -2727,7 +2728,6 @@ module Nottui_widgets = struct
ui : Ui.t Lwd.t; ui : Ui.t Lwd.t;
} }
let _line_on_change _table _row (s, i) = (s, i)
let eq_uc_c uc c = Uchar.(equal uc (of_char c)) let eq_uc_c uc c = Uchar.(equal uc (of_char c))
let copy_line_cursor (x : line) (y : line) = let copy_line_cursor (x : line) (y : line) =
@ -2736,6 +2736,16 @@ module Nottui_widgets = struct
let yi = Int.max 0 (Int.min xi (String.length ys)) in let yi = Int.max 0 (Int.min xi (String.length ys)) in
Lwd.set y.state (ys, yi) Lwd.set y.state (ys, yi)
let line_of_cursor cursor
(f : line Lwd_table.row -> line -> Ui.may_handle) :
Ui.may_handle =
match Lwd.peek cursor with
| Some row -> (
match Lwd_table.get row with
| Some line -> f row line
| None -> `Unhandled)
| None -> `Unhandled
let cursor_move cursor let cursor_move cursor
(f : line Lwd_table.row -> line Lwd_table.row option) = (f : line Lwd_table.row -> line Lwd_table.row option) =
match Lwd.peek cursor with match Lwd.peek cursor with
@ -2754,19 +2764,14 @@ module Nottui_widgets = struct
| None -> `Unhandled) | None -> `Unhandled)
| None -> `Unhandled | None -> `Unhandled
let line_append ?(table = Lwd_table.make ()) str = let line_make ?(focus = Focus.make ()) str =
let focus = Focus.make () in
let state = Lwd.var (str, 0) in let state = Lwd.var (str, 0) in
{ focus; state; ui = edit_field ~focus state }
let line_append ?(table = Lwd_table.make ())
?(focus = Focus.make ()) str =
let row = Lwd_table.append table in let row = Lwd_table.append table in
Lwd_table.set row Lwd_table.set row (line_make ~focus str)
{
focus;
state;
ui =
edit_field ~focus
~on_change:(_line_on_change table row)
state;
}
let line_table_of_string ?(table = Lwd_table.make ()) let line_table_of_string ?(table = Lwd_table.make ())
?(focus = Focus.make ()) (s : string) : Ui.t Lwd.t = ?(focus = Focus.make ()) (s : string) : Ui.t Lwd.t =
@ -2788,26 +2793,55 @@ module Nottui_widgets = struct
|> Lwd.join |> Lwd.join
|> Lwd.map2 |> Lwd.map2
~f:(fun focus -> ~f:(fun focus ->
Ui.keyboard_area ~focus (function Ui.keyboard_area ~focus (fun k ->
| `Uchar u, [ `Ctrl ] when eq_uc_c u 'n' -> Log.debug (fun m ->
cursor_move cursor (fun c -> Lwd_table.next c) m "line_table handler %a" Ui.pp_key k);
| `Arrow `Down, _ -> match k with
cursor_move cursor (fun c -> Lwd_table.next c) | `Uchar u, [ `Ctrl ] when eq_uc_c u 'n' ->
| `Uchar u, [ `Ctrl ] when eq_uc_c u 'p' -> cursor_move cursor (fun c -> Lwd_table.next c)
cursor_move cursor (fun c -> Lwd_table.prev c) | `Arrow `Down, _ ->
| `Arrow `Up, _ -> cursor_move cursor (fun c -> Lwd_table.next c)
cursor_move cursor (fun c -> Lwd_table.prev c) | `Uchar u, [ `Ctrl ] when eq_uc_c u 'p' ->
| `Uchar u, [ `Meta ] when eq_uc_c u '<' -> cursor_move cursor (fun c -> Lwd_table.prev c)
cursor_move cursor (fun _ -> Lwd_table.first table) | `Arrow `Up, _ ->
| `Uchar u, [ `Meta ] when eq_uc_c u '>' -> cursor_move cursor (fun c -> Lwd_table.prev c)
cursor_move cursor (fun _ -> Lwd_table.last table) | `Uchar u, [ `Meta ] when eq_uc_c u '<' ->
(* | `Enter, [] -> ( cursor_move cursor (fun _ -> Lwd_table.first table)
let row = Lwd.peek cursor in | `Uchar u, [ `Meta ] when eq_uc_c u '>' ->
match Lwd_table.get row with cursor_move cursor (fun _ -> Lwd_table.last table)
| Some line -> | `Enter, [] ->
Lwd_table.after row ~set:Lwd.set cursor line_of_cursor cursor (fun old_row old_line ->
| None -> `Unhandled) *) let str, pos = Lwd.peek old_line.state in
| _ -> `Unhandled)) let o_str = String.sub str 0 pos in
let n_str =
String.(sub str pos (length str - pos))
in
Lwd.set old_line.state (o_str, pos);
let new_line = line_make n_str in
Focus.request new_line.focus;
Lwd.set cursor
(Some (Lwd_table.after old_row ~set:new_line));
`Handled)
| `Backspace, [] ->
line_of_cursor cursor (fun row line ->
let str, pos = Lwd.peek line.state in
match Lwd_table.prev row with
| Some row_prev when pos = 0 -> (
match Lwd_table.get row_prev with
| Some line_prev ->
let str_prev, _ =
Lwd.peek line_prev.state
in
Lwd.set line_prev.state
( str_prev ^ str,
String.length str_prev );
Focus.request line_prev.focus;
Lwd_table.remove row;
Lwd.set cursor (Some row_prev);
`Handled
| None -> `Unhandled)
| _ -> `Unhandled)
| _ -> `Unhandled))
(Focus.status focus) (Focus.status focus)
(** Tab view, where exactly one element of [l] is shown at a time. *) (** Tab view, where exactly one element of [l] is shown at a time. *)