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:
130
human.ml
130
human.ml
@ -1335,7 +1335,7 @@ module Nottui = struct
|
||||
|
||||
let pp_may_handle ppf = function
|
||||
| `Unhandled -> F.pf ppf "`Unhandled"
|
||||
| `Handled -> F.pf ppf "`Unhandled"
|
||||
| `Handled -> F.pf ppf "`Handled"
|
||||
|
||||
type mouse_handler =
|
||||
x:float ->
|
||||
@ -2628,8 +2628,8 @@ module Nottui_widgets = struct
|
||||
let 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)
|
||||
?(on_submit = ignore) state =
|
||||
let edit_field ?(focus = Focus.make ()) ?(on_change = Fun.id) state
|
||||
=
|
||||
let on_change a = Lwd.set state (on_change a) in
|
||||
let update focus_h focus (text, pos) =
|
||||
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 " " ]
|
||||
else
|
||||
[
|
||||
I.string ~attr (sub' text 0 pos);
|
||||
I.string ~attr:attr_cursor (sub' text pos 1);
|
||||
I.string ~attr (sub' text (pos + 1) (len - pos - 1));
|
||||
I.string ~attr (String.sub text 0 pos);
|
||||
I.string ~attr:attr_cursor (String.sub text pos 1);
|
||||
I.string ~attr
|
||||
(String.sub text (pos + 1) (len - pos - 1));
|
||||
]
|
||||
else [ I.string (if text = "" then " " else text) ]
|
||||
in
|
||||
@ -2667,23 +2668,23 @@ module Nottui_widgets = struct
|
||||
in
|
||||
on_change (text, pos + 1);
|
||||
`Handled
|
||||
| `Backspace, _ ->
|
||||
let text =
|
||||
if pos > 0 then
|
||||
| `Backspace, [] ->
|
||||
if pos > 0 then (
|
||||
let text =
|
||||
if pos < String.length text then
|
||||
String.sub text 0 (pos - 1)
|
||||
^ String.sub text pos (String.length text - pos)
|
||||
else if String.length text > 0 then
|
||||
String.sub text 0 (String.length text - 1)
|
||||
else text
|
||||
else text
|
||||
in
|
||||
let pos = max 0 (pos - 1) in
|
||||
on_change (text, pos);
|
||||
`Handled
|
||||
| `Enter, _ ->
|
||||
in
|
||||
let pos = max 0 (pos - 1) in
|
||||
on_change (text, pos);
|
||||
`Handled)
|
||||
else `Unhandled
|
||||
(* | `Enter, _ ->
|
||||
on_submit (text, pos);
|
||||
`Handled
|
||||
`Handled *)
|
||||
| `Arrow `Left, [] ->
|
||||
let pos = min (String.length text) pos in
|
||||
if pos > 0 then (
|
||||
@ -2727,7 +2728,6 @@ module Nottui_widgets = struct
|
||||
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 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
|
||||
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
|
||||
(f : line Lwd_table.row -> line Lwd_table.row option) =
|
||||
match Lwd.peek cursor with
|
||||
@ -2754,19 +2764,14 @@ module Nottui_widgets = struct
|
||||
| None -> `Unhandled)
|
||||
| None -> `Unhandled
|
||||
|
||||
let line_append ?(table = Lwd_table.make ()) str =
|
||||
let focus = Focus.make () in
|
||||
let line_make ?(focus = Focus.make ()) str =
|
||||
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
|
||||
Lwd_table.set row
|
||||
{
|
||||
focus;
|
||||
state;
|
||||
ui =
|
||||
edit_field ~focus
|
||||
~on_change:(_line_on_change table row)
|
||||
state;
|
||||
}
|
||||
Lwd_table.set row (line_make ~focus str)
|
||||
|
||||
let line_table_of_string ?(table = Lwd_table.make ())
|
||||
?(focus = Focus.make ()) (s : string) : Ui.t Lwd.t =
|
||||
@ -2788,26 +2793,55 @@ module Nottui_widgets = struct
|
||||
|> Lwd.join
|
||||
|> Lwd.map2
|
||||
~f:(fun focus ->
|
||||
Ui.keyboard_area ~focus (function
|
||||
| `Uchar u, [ `Ctrl ] when eq_uc_c u 'n' ->
|
||||
cursor_move cursor (fun c -> Lwd_table.next c)
|
||||
| `Arrow `Down, _ ->
|
||||
cursor_move cursor (fun c -> Lwd_table.next c)
|
||||
| `Uchar u, [ `Ctrl ] when eq_uc_c u 'p' ->
|
||||
cursor_move cursor (fun c -> Lwd_table.prev c)
|
||||
| `Arrow `Up, _ ->
|
||||
cursor_move cursor (fun c -> Lwd_table.prev c)
|
||||
| `Uchar u, [ `Meta ] when eq_uc_c u '<' ->
|
||||
cursor_move cursor (fun _ -> Lwd_table.first table)
|
||||
| `Uchar u, [ `Meta ] when eq_uc_c u '>' ->
|
||||
cursor_move cursor (fun _ -> Lwd_table.last table)
|
||||
(* | `Enter, [] -> (
|
||||
let row = Lwd.peek cursor in
|
||||
match Lwd_table.get row with
|
||||
| Some line ->
|
||||
Lwd_table.after row ~set:Lwd.set cursor
|
||||
| None -> `Unhandled) *)
|
||||
| _ -> `Unhandled))
|
||||
Ui.keyboard_area ~focus (fun k ->
|
||||
Log.debug (fun m ->
|
||||
m "line_table handler %a" Ui.pp_key k);
|
||||
match k with
|
||||
| `Uchar u, [ `Ctrl ] when eq_uc_c u 'n' ->
|
||||
cursor_move cursor (fun c -> Lwd_table.next c)
|
||||
| `Arrow `Down, _ ->
|
||||
cursor_move cursor (fun c -> Lwd_table.next c)
|
||||
| `Uchar u, [ `Ctrl ] when eq_uc_c u 'p' ->
|
||||
cursor_move cursor (fun c -> Lwd_table.prev c)
|
||||
| `Arrow `Up, _ ->
|
||||
cursor_move cursor (fun c -> Lwd_table.prev c)
|
||||
| `Uchar u, [ `Meta ] when eq_uc_c u '<' ->
|
||||
cursor_move cursor (fun _ -> Lwd_table.first table)
|
||||
| `Uchar u, [ `Meta ] when eq_uc_c u '>' ->
|
||||
cursor_move cursor (fun _ -> Lwd_table.last table)
|
||||
| `Enter, [] ->
|
||||
line_of_cursor cursor (fun old_row old_line ->
|
||||
let str, pos = Lwd.peek old_line.state in
|
||||
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)
|
||||
|
||||
(** Tab view, where exactly one element of [l] is shown at a time. *)
|
||||
|
||||
Reference in New Issue
Block a user