Compare commits
4 Commits
686d868a94
...
graphv_egu
| Author | SHA1 | Date | |
|---|---|---|---|
| 73d6e2233b | |||
| c604345886 | |||
| f8525ac35f | |||
| 7ed07061aa |
639
ogui.ml
639
ogui.ml
@ -440,7 +440,6 @@ module Event = struct
|
||||
|
||||
let pp_event : event F.t =
|
||||
fun ppf e ->
|
||||
let open Glfw_types in
|
||||
match e with
|
||||
| Key (a, k, m) ->
|
||||
F.pf ppf "%a %a %a" pp_key_action a pp_key k pp_mods m
|
||||
@ -723,7 +722,7 @@ module Ui = struct
|
||||
enabled : bool;
|
||||
gv : Gv.t;
|
||||
glfw_window : GLFW.window option;
|
||||
bindings : (int * action list Event.t) Lwd.var;
|
||||
mutable bindings : action list Event.resolver Lwd.t;
|
||||
}
|
||||
|
||||
and action = Custom of string * (unit -> unit Lwt.t)
|
||||
@ -740,8 +739,7 @@ module Ui = struct
|
||||
enabled = true;
|
||||
gv;
|
||||
glfw_window = window;
|
||||
bindings =
|
||||
Lwd.var ~eq:(fun (a, _) (b, _) -> a = b) (0, Event.empty);
|
||||
bindings = Lwd.pure Event.[ pack Fun.id empty ];
|
||||
}
|
||||
|
||||
let pp_action : action F.t =
|
||||
@ -760,17 +758,35 @@ module Ui = struct
|
||||
|> ignore)
|
||||
p ()
|
||||
|
||||
let pp_pack : action list Event.pack F.t =
|
||||
fun ppf p ->
|
||||
let open Event in
|
||||
let rec iter (prev : Event.event list)
|
||||
(p : action list Event.pack) : unit =
|
||||
let module Pack = (val p) in
|
||||
match EventMap.bindings Pack.set with
|
||||
| (event, node) :: rest ->
|
||||
(match node with
|
||||
| Set set -> iter (prev @ [ event ]) (pack Pack.map set)
|
||||
| Val action ->
|
||||
F.pf ppf "%a: %a@."
|
||||
F.(list pp_action)
|
||||
(Pack.map action)
|
||||
F.(brackets @@ list ~sep:semi pp_event)
|
||||
(prev @ [ event ]));
|
||||
iter prev (pack Pack.map (EventMap.of_list rest))
|
||||
| [] -> ()
|
||||
in
|
||||
|
||||
iter [] p
|
||||
|
||||
let process_key t (resolver : action list Event.result)
|
||||
(state : Event.key_action) (key : Event.key)
|
||||
(mods : Event.key_mod list) : action list Event.result Lwt.t =
|
||||
let res =
|
||||
match resolver with
|
||||
| Event.Rejected | Event.Accepted _ ->
|
||||
[
|
||||
t.bindings |> Lwd.peek
|
||||
(*Lwd.get |> Lwd.observe |> Lwd.quick_sample *) |> snd
|
||||
|> Event.pack Fun.id;
|
||||
]
|
||||
t.bindings |> Lwd.observe |> Lwd.quick_sample
|
||||
| Event.Continue r -> r
|
||||
in
|
||||
let res = Event.resolve (Key (state, key, mods)) res in
|
||||
@ -785,11 +801,9 @@ module Ui = struct
|
||||
| Event.Continue _ | Event.Rejected -> Lwt.return_unit)
|
||||
>>= fun () -> Lwt.return res
|
||||
|
||||
let update_bindings ui
|
||||
(f : action list Event.t -> action list Event.t) =
|
||||
Lwd.set ui.bindings
|
||||
( Lwd.peek ui.bindings |> fst |> Int.add 1,
|
||||
f (Lwd.peek ui.bindings |> snd) )
|
||||
let append_bindings ui (b : action list Event.resolver Lwd.t) : unit
|
||||
=
|
||||
ui.bindings <- Lwd.map2 ~f:List.append ui.bindings b
|
||||
|
||||
let chrcallback_ref : (Uchar.t -> unit Lwt.t) ref =
|
||||
ref (fun _c ->
|
||||
@ -814,11 +828,11 @@ module Ui = struct
|
||||
| Accepted _ -> "Accepted"
|
||||
| Continue _ -> "Continue"
|
||||
| Rejected -> "Rejected"));
|
||||
|
||||
(* junk the `Char that is sent with a `Key that has no mods *)
|
||||
(match res with
|
||||
| Accepted _ when mods = [] || mods == [ Shift ] -> (
|
||||
(* junk the `Char that is sent with a `Key that has no mods *)
|
||||
Lwt_stream.peek events
|
||||
>>= function
|
||||
Lwt_stream.peek events >>= function
|
||||
| Some (`Char _) ->
|
||||
F.epr "process_events: junking next event@.";
|
||||
Lwt_stream.junk events
|
||||
@ -830,7 +844,6 @@ module Ui = struct
|
||||
(Uchar.of_int char);
|
||||
process_char char >>= fun () -> proc (Event.Accepted [])
|
||||
in
|
||||
|
||||
proc Event.Rejected >>= fun _ -> Lwt.return_unit)
|
||||
|
||||
module Style = struct
|
||||
@ -962,235 +975,210 @@ module TextEdit = struct
|
||||
let cursor_set (t : t) (index : int) : unit Lwt.t =
|
||||
cursor_update t (Fun.const index)
|
||||
|
||||
let default_bindings (t : t) (ui : Ui.t) : unit =
|
||||
let default_bindings (t : t) : Ui.action list Event.pack =
|
||||
let open GLFW in
|
||||
let open Event in
|
||||
let open Ui in
|
||||
Ui.update_bindings ui (fun a ->
|
||||
a
|
||||
|> adds
|
||||
[
|
||||
[ Key (Press, F, [ Control ]) ];
|
||||
[ Key (Repeat, F, [ Control ]) ];
|
||||
[ Key (Press, Right, []) ];
|
||||
[ Key (Repeat, Right, []) ];
|
||||
]
|
||||
[ Custom ("char_forward", fun () -> cursor_move t 1) ]
|
||||
|> adds
|
||||
[
|
||||
[ Key (Press, B, [ Control ]) ];
|
||||
[ Key (Repeat, B, [ Control ]) ];
|
||||
[ Key (Press, Left, []) ];
|
||||
[ Key (Repeat, Left, []) ];
|
||||
]
|
||||
[
|
||||
Custom ("char_backward", fun () -> cursor_move t (-1));
|
||||
]
|
||||
|> adds
|
||||
[
|
||||
[ Key (Press, N, [ Control ]) ];
|
||||
[ Key (Repeat, N, [ Control ]) ];
|
||||
[ Key (Press, Down, []) ];
|
||||
[ Key (Repeat, Down, []) ];
|
||||
]
|
||||
[
|
||||
Custom
|
||||
( "forward_line",
|
||||
fun () ->
|
||||
TextBuffer.fold_string t.text (fun s ->
|
||||
let sn = String.length s in
|
||||
let seol =
|
||||
Str.search_forward (Str.regexp "$")
|
||||
in
|
||||
let next_bol =
|
||||
min sn
|
||||
(seol s (Lwd.peek t.cursor).index + 1)
|
||||
in
|
||||
let next_line_len =
|
||||
seol s next_bol - next_bol
|
||||
in
|
||||
next_bol
|
||||
+
|
||||
if
|
||||
(Lwd.peek t.cursor).last_col
|
||||
> next_line_len
|
||||
then next_line_len
|
||||
else
|
||||
min next_line_len
|
||||
(Lwd.peek t.cursor).last_col)
|
||||
>>= cursor_set t );
|
||||
]
|
||||
|> adds
|
||||
[
|
||||
[ Key (Press, P, [ Control ]) ];
|
||||
[ Key (Repeat, P, [ Control ]) ];
|
||||
[ Key (Press, Up, []) ];
|
||||
[ Key (Repeat, Up, []) ];
|
||||
]
|
||||
[
|
||||
Custom
|
||||
( "line_backward",
|
||||
fun () ->
|
||||
TextBuffer.fold_string t.text (fun s ->
|
||||
let sbol =
|
||||
Str.search_backward (Str.regexp "^") s
|
||||
in
|
||||
let bol = sbol (Lwd.peek t.cursor).index in
|
||||
if bol > 0 then
|
||||
let prev_bol = sbol (max 0 (bol - 1)) in
|
||||
let prev_line_len = bol - 1 - prev_bol in
|
||||
(Ui.chrcallback_ref :=
|
||||
fun c ->
|
||||
TextBuffer.insert_uchar t.text (Lwd.peek t.cursor).index c
|
||||
>>= fun _ -> cursor_move t 1);
|
||||
empty
|
||||
|> adds
|
||||
[
|
||||
[ Key (Press, F, [ Control ]) ];
|
||||
[ Key (Repeat, F, [ Control ]) ];
|
||||
[ Key (Press, Right, []) ];
|
||||
[ Key (Repeat, Right, []) ];
|
||||
]
|
||||
[ Custom ("char_forward", fun () -> cursor_move t 1) ]
|
||||
|> adds
|
||||
[
|
||||
[ Key (Press, B, [ Control ]) ];
|
||||
[ Key (Repeat, B, [ Control ]) ];
|
||||
[ Key (Press, Left, []) ];
|
||||
[ Key (Repeat, Left, []) ];
|
||||
]
|
||||
[ Custom ("char_backward", fun () -> cursor_move t (-1)) ]
|
||||
|> adds
|
||||
[
|
||||
[ Key (Press, N, [ Control ]) ];
|
||||
[ Key (Repeat, N, [ Control ]) ];
|
||||
[ Key (Press, Down, []) ];
|
||||
[ Key (Repeat, Down, []) ];
|
||||
]
|
||||
[
|
||||
Custom
|
||||
( "forward_line",
|
||||
fun () ->
|
||||
TextBuffer.fold_string t.text (fun s ->
|
||||
let sn = String.length s in
|
||||
let seol = Str.search_forward (Str.regexp "$") in
|
||||
let next_bol =
|
||||
min sn (seol s (Lwd.peek t.cursor).index + 1)
|
||||
in
|
||||
let next_line_len = seol s next_bol - next_bol in
|
||||
next_bol
|
||||
+
|
||||
if (Lwd.peek t.cursor).last_col > next_line_len
|
||||
then next_line_len
|
||||
else
|
||||
min next_line_len (Lwd.peek t.cursor).last_col)
|
||||
>>= cursor_set t );
|
||||
]
|
||||
|> adds
|
||||
[
|
||||
[ Key (Press, P, [ Control ]) ];
|
||||
[ Key (Repeat, P, [ Control ]) ];
|
||||
[ Key (Press, Up, []) ];
|
||||
[ Key (Repeat, Up, []) ];
|
||||
]
|
||||
[
|
||||
Custom
|
||||
( "line_backward",
|
||||
fun () ->
|
||||
TextBuffer.fold_string t.text (fun s ->
|
||||
let sbol =
|
||||
Str.search_backward (Str.regexp "^") s
|
||||
in
|
||||
let bol = sbol (Lwd.peek t.cursor).index in
|
||||
if bol > 0 then
|
||||
let prev_bol = sbol (max 0 (bol - 1)) in
|
||||
let prev_line_len = bol - 1 - prev_bol in
|
||||
|
||||
(*F.epr
|
||||
"up: index=%d bol=%d prev_bol=%d \
|
||||
prev_line_len=%d @."
|
||||
t.cursor.index bol prev_bol prev_line_len; *)
|
||||
prev_bol
|
||||
+
|
||||
if
|
||||
(Lwd.peek t.cursor).last_col
|
||||
> prev_line_len
|
||||
then prev_line_len
|
||||
else
|
||||
min prev_line_len
|
||||
(Lwd.peek t.cursor).last_col
|
||||
else (Lwd.peek t.cursor).index)
|
||||
>>= cursor_set t );
|
||||
]
|
||||
|> adds (* EOL *)
|
||||
[
|
||||
[ Key (Press, E, [ Control ]) ];
|
||||
[ Key (Press, End, []) ];
|
||||
]
|
||||
[
|
||||
Custom
|
||||
( "end_of_line",
|
||||
fun () ->
|
||||
TextBuffer.fold_string t.text (fun s ->
|
||||
let bol =
|
||||
Str.search_backward (Str.regexp "^") s
|
||||
(Lwd.peek t.cursor).index
|
||||
in
|
||||
(*F.epr
|
||||
"up: index=%d bol=%d prev_bol=%d \
|
||||
prev_line_len=%d @."
|
||||
t.cursor.index bol prev_bol prev_line_len; *)
|
||||
prev_bol
|
||||
+
|
||||
if (Lwd.peek t.cursor).last_col > prev_line_len
|
||||
then prev_line_len
|
||||
else
|
||||
min prev_line_len
|
||||
(Lwd.peek t.cursor).last_col
|
||||
else (Lwd.peek t.cursor).index)
|
||||
>>= cursor_set t );
|
||||
]
|
||||
|> adds (* EOL *)
|
||||
[ [ Key (Press, E, [ Control ]) ]; [ Key (Press, End, []) ] ]
|
||||
[
|
||||
Custom
|
||||
( "end_of_line",
|
||||
fun () ->
|
||||
TextBuffer.fold_string t.text (fun s ->
|
||||
let bol =
|
||||
Str.search_backward (Str.regexp "^") s
|
||||
(Lwd.peek t.cursor).index
|
||||
in
|
||||
let eol =
|
||||
Str.search_forward (Str.regexp "$") s
|
||||
(Lwd.peek t.cursor).index
|
||||
in
|
||||
Lwd.set t.cursor
|
||||
@@ TextLayout.cursor ~last_col:(eol - bol) eol)
|
||||
);
|
||||
]
|
||||
|> adds (* BOL *)
|
||||
[
|
||||
[ Key (Press, A, [ Control ]) ]; [ Key (Press, Home, []) ];
|
||||
]
|
||||
[
|
||||
Custom
|
||||
( "beginning_of_line",
|
||||
fun () ->
|
||||
TextBuffer.fold_string t.text (fun s ->
|
||||
Lwd.set t.cursor
|
||||
@@ TextLayout.cursor ~last_col:0
|
||||
(Str.search_backward (Str.regexp "^") s
|
||||
(Lwd.peek t.cursor).index)) );
|
||||
]
|
||||
|> adds
|
||||
[
|
||||
[ Key (Press, Backspace, []) ];
|
||||
[ Key (Repeat, Backspace, []) ];
|
||||
]
|
||||
[
|
||||
Custom
|
||||
( "delete_char_backward",
|
||||
fun () ->
|
||||
match Lwd.peek t.mark with
|
||||
| Some mark ->
|
||||
TextBuffer.remove t.text
|
||||
(mark, (Lwd.peek t.cursor).index)
|
||||
>>= fun _ ->
|
||||
Lwd.set t.mark None;
|
||||
cursor_set t (min mark (Lwd.peek t.cursor).index)
|
||||
| None ->
|
||||
if (Lwd.peek t.cursor).index > 0 then
|
||||
TextBuffer.remove_uchar t.text
|
||||
((Lwd.peek t.cursor).index - 1)
|
||||
>>= fun _ -> cursor_move t (-1)
|
||||
else Lwt.return_unit );
|
||||
]
|
||||
|> adds
|
||||
[ [ Key (Press, K, [ Control ]) ] ]
|
||||
[
|
||||
Custom
|
||||
( "line_kill",
|
||||
fun () ->
|
||||
TextBuffer.fold_string t.text (fun s ->
|
||||
TextBuffer.remove t.text
|
||||
( (Lwd.peek t.cursor).index,
|
||||
let eol =
|
||||
Str.search_forward (Str.regexp "$") s
|
||||
(Lwd.peek t.cursor).index
|
||||
in
|
||||
Lwd.set t.cursor
|
||||
@@ TextLayout.cursor ~last_col:(eol - bol)
|
||||
eol) );
|
||||
]
|
||||
|> adds (* BOL *)
|
||||
[
|
||||
[ Key (Press, A, [ Control ]) ];
|
||||
[ Key (Press, Home, []) ];
|
||||
]
|
||||
[
|
||||
Custom
|
||||
( "beginning_of_line",
|
||||
fun () ->
|
||||
TextBuffer.fold_string t.text (fun s ->
|
||||
Lwd.set t.cursor
|
||||
@@ TextLayout.cursor ~last_col:0
|
||||
(Str.search_backward (Str.regexp "^") s
|
||||
(Lwd.peek t.cursor).index)) );
|
||||
]
|
||||
|> adds
|
||||
[
|
||||
[ Key (Press, Backspace, []) ];
|
||||
[ Key (Repeat, Backspace, []) ];
|
||||
]
|
||||
[
|
||||
Custom
|
||||
( "delete_char_backward",
|
||||
fun () ->
|
||||
match Lwd.peek t.mark with
|
||||
| Some mark ->
|
||||
TextBuffer.remove t.text
|
||||
(mark, (Lwd.peek t.cursor).index)
|
||||
>>= fun _ ->
|
||||
Lwd.set t.mark None;
|
||||
cursor_set t
|
||||
(min mark (Lwd.peek t.cursor).index)
|
||||
| None ->
|
||||
if (Lwd.peek t.cursor).index > 0 then
|
||||
TextBuffer.remove_uchar t.text
|
||||
((Lwd.peek t.cursor).index - 1)
|
||||
>>= fun _ -> cursor_move t (-1)
|
||||
else Lwt.return_unit );
|
||||
]
|
||||
|> adds
|
||||
[ [ Key (Press, K, [ Control ]) ] ]
|
||||
[
|
||||
Custom
|
||||
( "line_kill",
|
||||
fun () ->
|
||||
TextBuffer.fold_string t.text (fun s ->
|
||||
TextBuffer.remove t.text
|
||||
( (Lwd.peek t.cursor).index,
|
||||
let eol =
|
||||
Str.search_forward (Str.regexp "$") s
|
||||
(Lwd.peek t.cursor).index
|
||||
in
|
||||
if
|
||||
eol == (Lwd.peek t.cursor).index
|
||||
&& String.length s > eol
|
||||
then eol + 1
|
||||
else eol )
|
||||
>>= fun _ ->
|
||||
Lwd.set t.mark None;
|
||||
cursor_set t (Lwd.peek t.cursor).index)
|
||||
>>= fun u -> u );
|
||||
]
|
||||
|> adds
|
||||
[
|
||||
[ Key (Press, Enter, []) ]; [ Key (Repeat, Enter, []) ];
|
||||
]
|
||||
[
|
||||
Custom
|
||||
( "new_line",
|
||||
fun () ->
|
||||
TextBuffer.insert_uchar t.text
|
||||
(Lwd.peek t.cursor).index (Uchar.of_char '\n')
|
||||
>>= fun _ -> cursor_move t 1 );
|
||||
]
|
||||
|> adds
|
||||
[ [ Key (Press, Space, [ Control ]) ] ] (* Mark set *)
|
||||
[
|
||||
Custom
|
||||
( "mark_toggle",
|
||||
fun () ->
|
||||
Lwd.set t.mark
|
||||
(match Lwd.peek t.mark with
|
||||
| Some _ -> None
|
||||
| None -> Some (Lwd.peek t.cursor).index);
|
||||
Lwt.return_unit );
|
||||
]
|
||||
|> adds
|
||||
[ [ Key (Press, G, [ Control ]) ] ] (* Exit / Clear *)
|
||||
[
|
||||
Custom
|
||||
( "command_clear",
|
||||
fun () ->
|
||||
if
|
||||
eol == (Lwd.peek t.cursor).index
|
||||
&& String.length s > eol
|
||||
then eol + 1
|
||||
else eol )
|
||||
>>= fun _ ->
|
||||
Lwd.set t.mark None;
|
||||
Lwt.return_unit );
|
||||
]
|
||||
|> adds
|
||||
[
|
||||
[
|
||||
Key (Press, X, [ Control ]);
|
||||
Key (Press, S, [ Control ]);
|
||||
];
|
||||
]
|
||||
(* Save *)
|
||||
[
|
||||
Custom ("save_buffer", fun () -> TextBuffer.save t.text);
|
||||
]);
|
||||
|
||||
Ui.chrcallback_ref :=
|
||||
fun c ->
|
||||
TextBuffer.insert_uchar t.text (Lwd.peek t.cursor).index c
|
||||
>>= fun _ -> cursor_move t 1
|
||||
(* This creates a giant stack of calls lol
|
||||
>>= fun () -> !Ui.chrcallback_ref c *)
|
||||
cursor_set t (Lwd.peek t.cursor).index)
|
||||
>>= fun u -> u );
|
||||
]
|
||||
|> adds
|
||||
[ [ Key (Press, Enter, []) ]; [ Key (Repeat, Enter, []) ] ]
|
||||
[
|
||||
Custom
|
||||
( "new_line",
|
||||
fun () ->
|
||||
TextBuffer.insert_uchar t.text
|
||||
(Lwd.peek t.cursor).index (Uchar.of_char '\n')
|
||||
>>= fun _ -> cursor_move t 1 );
|
||||
]
|
||||
|> adds
|
||||
[ [ Key (Press, Space, [ Control ]) ] ] (* Mark set *)
|
||||
[
|
||||
Custom
|
||||
( "mark_toggle",
|
||||
fun () ->
|
||||
Lwd.set t.mark
|
||||
(match Lwd.peek t.mark with
|
||||
| Some _ -> None
|
||||
| None -> Some (Lwd.peek t.cursor).index);
|
||||
Lwt.return_unit );
|
||||
]
|
||||
|> adds
|
||||
[ [ Key (Press, G, [ Control ]) ] ] (* Exit / Clear *)
|
||||
[
|
||||
Custom
|
||||
( "command_clear",
|
||||
fun () ->
|
||||
Lwd.set t.mark None;
|
||||
Lwt.return_unit );
|
||||
]
|
||||
|> adds
|
||||
[
|
||||
[
|
||||
Key (Press, X, [ Control ]); Key (Press, S, [ Control ]);
|
||||
];
|
||||
]
|
||||
(* Save *)
|
||||
[ Custom ("save_buffer", fun () -> TextBuffer.save t.text) ]
|
||||
|> Event.pack Fun.id
|
||||
|
||||
let multiline ui ?(text_format = TextLayout.format_default)
|
||||
(text : TextBuffer.t) : t =
|
||||
@ -1218,7 +1206,7 @@ module TextEdit = struct
|
||||
(* return_key = keyboard_shortcut; *)
|
||||
}
|
||||
in
|
||||
default_bindings t ui;
|
||||
Ui.append_bindings ui (Lwd.pure [ default_bindings t ]);
|
||||
t
|
||||
end
|
||||
|
||||
@ -1355,16 +1343,31 @@ end
|
||||
module WindowManager = struct
|
||||
open Layout
|
||||
|
||||
type t =
|
||||
[ `T of dir * (t * dim) list
|
||||
| `TextEdit of TextEdit.t
|
||||
| `Frame of frame ]
|
||||
type content = [ `TextEdit of TextEdit.t | `Frame of frame ]
|
||||
type bindings = Event.event Event.resolver
|
||||
|
||||
type t = [ `T of dir * tt list | content ]
|
||||
and tt = { t : t; dim : dim; bindings : bindings }
|
||||
|
||||
let rec length : t -> int = function
|
||||
| `T (_, tl) ->
|
||||
List.fold_left (fun a (t', _) -> a + length t') 0 tl
|
||||
List.fold_left (fun a { t; _ } -> a + length t) 0 tl
|
||||
| _ -> 1
|
||||
|
||||
let rec nth (n : int) : t -> content option = function
|
||||
| `T (_, tl) ->
|
||||
let rec nl n' : tt list -> content option = function
|
||||
| { t; _ } :: tl' -> (
|
||||
match nth n' t with
|
||||
| Some t -> Some t
|
||||
| None -> nl (n - 1) tl')
|
||||
| [] -> None
|
||||
in
|
||||
nl n tl
|
||||
| (`TextEdit _ | `Frame _) as t ->
|
||||
F.epr "nth: %d@." n;
|
||||
if n == 0 then Some t else None
|
||||
|
||||
let rec fold_left ?(dir = `X)
|
||||
~(f :
|
||||
dir ->
|
||||
@ -1416,73 +1419,93 @@ module WindowManager = struct
|
||||
~size:(`Ratio 1.0, `Pixels 30.)
|
||||
(F.str "window/%d" n, status_format (n == cursor))))
|
||||
|
||||
let frame_default_bindings _ui _f = Event.empty |> Event.pack Fun.id
|
||||
|
||||
let default_bindings ui = function
|
||||
| `TextEdit t -> [ TextEdit.default_bindings t ]
|
||||
| `Frame f -> [ frame_default_bindings ui f ]
|
||||
|
||||
let make ui ?(style = textedit_style)
|
||||
?(_mode : [ `Tiling | `FullScreen | `Floating ] = `Tiling)
|
||||
(telist : t Lwd.var) =
|
||||
(t : t Lwd.var) =
|
||||
let cursor = Lwd.var 0 in
|
||||
Ui.update_bindings ui (fun a ->
|
||||
a
|
||||
|> Event.adds
|
||||
[ [ Key (Press, X, [ Control ]); Key (Press, O, []) ] ]
|
||||
[
|
||||
Ui.Custom
|
||||
( "window_next",
|
||||
fun () ->
|
||||
Lwd.set cursor
|
||||
(if
|
||||
Lwd.peek cursor
|
||||
< (Lwd.peek telist |> length) - 1
|
||||
then Lwd.peek cursor + 1
|
||||
else 0);
|
||||
(*TextEdit.default_bindings
|
||||
(List.nth (Lwd.peek telist) (Lwd.peek cursor))
|
||||
ui; *)
|
||||
Lwt.return_unit );
|
||||
]
|
||||
|> Event.adds
|
||||
[ [ Key (Press, X, [ Control ]); Key (Press, P, []) ] ]
|
||||
[
|
||||
Ui.Custom
|
||||
( "window_previous",
|
||||
fun () ->
|
||||
Lwd.set cursor
|
||||
(if Lwd.peek cursor > 0 then
|
||||
Lwd.peek cursor - 1
|
||||
else (Lwd.peek telist |> length) - 1);
|
||||
(*TextEdit.default_bindings
|
||||
(List.nth (Lwd.peek telist) (Lwd.peek cursor))
|
||||
ui;*)
|
||||
Lwt.return_unit );
|
||||
]);
|
||||
|
||||
Lwd.map_s (Lwd.get telist) ~f:(fun (tl : t) ->
|
||||
let rec fold dir dim : t -> Layout.frame Lwd.t Lwt.t =
|
||||
(* add the bindings of the currently selected window *)
|
||||
Ui.append_bindings ui
|
||||
(Lwd.map2 (Lwd.get cursor) (Lwd.get t) ~f:nth
|
||||
|> Lwd.map ~f:(function
|
||||
| Some v -> default_bindings ui v
|
||||
| None -> []));
|
||||
Ui.append_bindings ui
|
||||
(Lwd.return
|
||||
Event.
|
||||
[
|
||||
empty
|
||||
|> adds
|
||||
[
|
||||
[
|
||||
Key (Press, X, [ Control ]); Key (Press, O, []);
|
||||
];
|
||||
]
|
||||
Lwd.
|
||||
[
|
||||
Ui.Custom
|
||||
( "window_next",
|
||||
fun () ->
|
||||
set cursor
|
||||
(if peek cursor < (peek t |> length) - 1
|
||||
then peek cursor + 1
|
||||
else 0);
|
||||
Lwt.return_unit );
|
||||
]
|
||||
|> adds
|
||||
[
|
||||
[
|
||||
Key (Press, X, [ Control ]); Key (Press, P, []);
|
||||
];
|
||||
]
|
||||
Lwd.
|
||||
[
|
||||
Ui.Custom
|
||||
( "window_previous",
|
||||
fun () ->
|
||||
set cursor
|
||||
(if peek cursor > 0 then peek cursor - 1
|
||||
else (peek t |> length) - 1);
|
||||
Lwt.return_unit );
|
||||
]
|
||||
|> pack Fun.id;
|
||||
]);
|
||||
let i = ref 0 in
|
||||
Lwd.map_s (Lwd.get t) ~f:(fun (t : t) ->
|
||||
let rec fold dir (t : tt) : Layout.frame Lwd.t Lwt.t =
|
||||
let size =
|
||||
match dir with
|
||||
| `X -> (dim, `Ratio 1.)
|
||||
| `Y -> (`Ratio 1., dim)
|
||||
| `Z -> (dim, dim)
|
||||
| `X -> (t.dim, `Ratio 1.)
|
||||
| `Y -> (`Ratio 1., t.dim)
|
||||
| `Z -> (t.dim, t.dim)
|
||||
in
|
||||
function
|
||||
| `T ((dir', (t0, dim0) :: trest) as tl) ->
|
||||
fold dir' dim0 t0 >>= fun fst ->
|
||||
match t.t with
|
||||
| `T (dir', t0 :: trest) ->
|
||||
fold dir' t0 >>= fun fst ->
|
||||
Lwt_list.fold_left_s
|
||||
(fun f (t, dim) ->
|
||||
fold dir' dim t >>= fun newf ->
|
||||
(fun f t ->
|
||||
fold dir' t >>= fun newf ->
|
||||
Lwd.map2 f newf ~f:(join ~size dir') |> Lwt.return)
|
||||
fst trest
|
||||
| `T (_, []) -> Layout.none |> Lwd.return |> Lwt.return
|
||||
| `Frame f' ->
|
||||
frame_of_window 314 cursor style size (Lwd.return f')
|
||||
i := !i + 1;
|
||||
frame_of_window !i cursor style size (Lwd.return f')
|
||||
|> Lwt.return
|
||||
| `TextEdit t' ->
|
||||
Layout.textedit
|
||||
~size:(`Ratio 1.0, `Fun (fun b -> Gg.Box2.h b -. 30.))
|
||||
t'
|
||||
>>= fun tt ->
|
||||
frame_of_window 314 cursor style size tt |> Lwt.return
|
||||
i := !i + 1;
|
||||
frame_of_window !i cursor style size tt |> Lwt.return
|
||||
in
|
||||
fold `X (`Ratio 1.) tl)
|
||||
fold `X { t; dim = `Ratio 1.; bindings = [] })
|
||||
>>= fun d -> Lwd.join d |> Lwt.return
|
||||
end
|
||||
|
||||
@ -1520,7 +1543,7 @@ module Painter = struct
|
||||
let string ?(style = Style.default) (t : Gv.t) (rect : box2)
|
||||
((contents, format) : string * TextLayout.format) : box2 Lwt.t =
|
||||
(* draw_box t ~box:rect ~style; *)
|
||||
F.epr "string";
|
||||
(* F.epr "string"; *)
|
||||
set_text_format t format;
|
||||
let rect' = Margin.inner style.margin rect in
|
||||
V2.v
|
||||
@ -1615,13 +1638,13 @@ module Painter = struct
|
||||
| `Fun f -> f box))
|
||||
in
|
||||
let box' = Margin.inner style.margin box in
|
||||
F.epr "@[<hv 3>%a " pp_box2 box;
|
||||
(* F.epr "@[<hv 3>%a " pp_box2 box; *)
|
||||
draw_box ui.gv ~box ~style;
|
||||
(match t with
|
||||
| `Join (dir, (a, b)) ->
|
||||
F.epr "`Join %a @,(@[<hv>" pp_dir dir;
|
||||
(* F.epr "`Join %a @,(@[<hv>" pp_dir dir; *)
|
||||
layout box' ui a >>= fun ra ->
|
||||
F.epr ",@ ";
|
||||
(* F.epr ",@ "; *)
|
||||
let c' =
|
||||
Box2.(
|
||||
match dir with
|
||||
@ -1630,35 +1653,29 @@ module Painter = struct
|
||||
| `Z -> box')
|
||||
in
|
||||
layout c' ui b >>= fun rb ->
|
||||
F.epr "@])";
|
||||
(* F.epr "@])"; *)
|
||||
Gg.Box2.union ra rb |> Lwt.return
|
||||
| `TextEdit tt ->
|
||||
F.epr "`TextEdit";
|
||||
text_layout ui.gv box' tt
|
||||
(* F.epr "`TextEdit"; *)
|
||||
text_layout ui.gv box' tt >>= fun _ -> Lwt.return box'
|
||||
| `None ->
|
||||
F.epr "`None";
|
||||
(* F.epr "`None"; *)
|
||||
Lwt.return Gg.Box2.(v (o box') Gg.V2.zero)
|
||||
| `String s -> string ui.gv box' s
|
||||
| _ ->
|
||||
F.epr "_ !!Unimplemented!!";
|
||||
Lwt.return Gg.Box2.zero)
|
||||
>>= fun r ->
|
||||
F.epr "@]";
|
||||
|
||||
let r' =
|
||||
(*Box2.add_pt r
|
||||
V2.(Box2.max r + v style.margin.right style.margin.bottom)
|
||||
|> *)
|
||||
Margin.outer style.margin r
|
||||
in
|
||||
(* F.epr "@]"; *)
|
||||
let r' = Margin.outer style.margin r in
|
||||
|
||||
(*F.epr "layout: box=%a box'=%a r=%a r'=%a@." Gg.Box2.pp box
|
||||
Gg.Box2.pp box' Gg.Box2.pp r Gg.Box2.pp r'; *)
|
||||
Lwt.return r'
|
||||
|
||||
let layout box ui frame =
|
||||
F.epr "layout:@ @[%a@]@.as:@.@[<hv>" Layout.pp_frame_rec frame;
|
||||
(* F.epr "layout:@ @[%a@]@.as:@.@[<hv>" Layout.pp_frame_rec frame; *)
|
||||
let r = layout box ui frame in
|
||||
F.epr "@]@.";
|
||||
(* F.epr "@]@."; *)
|
||||
r
|
||||
end
|
||||
|
||||
275
opam_switch
Normal file
275
opam_switch
Normal file
@ -0,0 +1,275 @@
|
||||
opam-version: "2.0"
|
||||
compiler: ["ocaml-variants.5.1.1+options"]
|
||||
roots: [
|
||||
"camlp5.8.03.00"
|
||||
"gg.1.0.0"
|
||||
"glfw-ocaml.3.3.1-2"
|
||||
"graphv_gles2_native.0.1.1"
|
||||
"irmin-git.3.9.0"
|
||||
"lablgtk3.3.1.4"
|
||||
"lablgtk3-sourceview3.3.1.4"
|
||||
"lwd.0.3"
|
||||
"lwt_glib.1.1.1"
|
||||
"memtrace.0.2.3"
|
||||
"merlin.4.14-501"
|
||||
"ocamlformat.0.26.2"
|
||||
"odig.0.0.9"
|
||||
"stb_image.0.5"
|
||||
"tgls.0.8.6"
|
||||
"tuareg.3.0.1"
|
||||
"user-setup.0.7"
|
||||
"utop.2.14.0"
|
||||
]
|
||||
installed: [
|
||||
"angstrom.0.16.0"
|
||||
"arp.3.1.1"
|
||||
"asn1-combinators.0.2.6"
|
||||
"astring.0.8.5"
|
||||
"awa.0.3.0"
|
||||
"awa-mirage.0.3.0"
|
||||
"b0.0.0.5"
|
||||
"base.v0.16.3"
|
||||
"base-bigarray.base"
|
||||
"base-bytes.base"
|
||||
"base-domains.base"
|
||||
"base-nnp.base"
|
||||
"base-threads.base"
|
||||
"base-unix.base"
|
||||
"base64.3.5.1"
|
||||
"bheap.2.0.0"
|
||||
"bigarray-compat.1.1.0"
|
||||
"bigstringaf.0.9.1"
|
||||
"biniou.1.2.2"
|
||||
"bos.0.2.1"
|
||||
"ca-certs.0.2.3"
|
||||
"ca-certs-nss.3.98"
|
||||
"cairo2.0.6.4"
|
||||
"camlp-streams.5.0.1"
|
||||
"camlp5.8.03.00"
|
||||
"camlp5-buildscripts.0.03"
|
||||
"carton.0.7.1"
|
||||
"carton-git.0.7.1"
|
||||
"carton-lwt.0.7.1"
|
||||
"cf.0.5.0"
|
||||
"cf-lwt.0.5.0"
|
||||
"checkseum.0.5.2"
|
||||
"cmdliner.1.2.0"
|
||||
"cohttp.5.3.1"
|
||||
"cohttp-lwt.5.3.0"
|
||||
"cohttp-lwt-unix.5.3.0"
|
||||
"conduit.6.2.2"
|
||||
"conduit-lwt.6.2.2"
|
||||
"conduit-lwt-unix.6.2.2"
|
||||
"conf-bash.1"
|
||||
"conf-cairo.1"
|
||||
"conf-emacs.1"
|
||||
"conf-gles2.1"
|
||||
"conf-glfw3.2"
|
||||
"conf-glib-2.1"
|
||||
"conf-gmp.4"
|
||||
"conf-gmp-powm-sec.3"
|
||||
"conf-gtk3.18"
|
||||
"conf-gtksourceview3.0+2"
|
||||
"conf-libffi.2.0.0"
|
||||
"conf-m4.1"
|
||||
"conf-perl.2"
|
||||
"conf-pkg-config.3"
|
||||
"conf-which.1"
|
||||
"cppo.1.6.9"
|
||||
"crunch.3.3.1"
|
||||
"csexp.1.5.2"
|
||||
"cstruct.6.2.0"
|
||||
"cstruct-lwt.6.2.0"
|
||||
"cstruct-unix.6.2.0"
|
||||
"ctypes.0.20.2"
|
||||
"ctypes-foreign.0.18.0"
|
||||
"decompress.1.5.3"
|
||||
"digestif.1.2.0"
|
||||
"dispatch.0.5.0"
|
||||
"dns.7.0.3"
|
||||
"dns-client.7.0.3"
|
||||
"dns-client-lwt.7.0.3"
|
||||
"dns-client-mirage.7.0.3"
|
||||
"domain-name.0.4.0"
|
||||
"dot-merlin-reader.4.9"
|
||||
"duff.0.5"
|
||||
"dune.3.15.2"
|
||||
"dune-build-info.3.15.2"
|
||||
"dune-configurator.3.15.2"
|
||||
"duration.0.2.1"
|
||||
"easy-format.1.3.4"
|
||||
"either.1.0.0"
|
||||
"emile.1.1"
|
||||
"encore.0.8"
|
||||
"eqaf.0.9"
|
||||
"ethernet.3.2.0"
|
||||
"faraday.0.8.2"
|
||||
"fix.20230505"
|
||||
"fmt.0.9.0"
|
||||
"fpath.0.7.3"
|
||||
"fsevents.0.3.0"
|
||||
"fsevents-lwt.0.3.0"
|
||||
"functoria-runtime.4.4.2"
|
||||
"gg.1.0.0"
|
||||
"git.3.15.0"
|
||||
"git-mirage.3.15.0"
|
||||
"git-paf.3.15.0"
|
||||
"git-unix.3.15.0"
|
||||
"glfw-ocaml.3.3.1-2"
|
||||
"gmap.0.3.0"
|
||||
"graphql.0.14.0"
|
||||
"graphql-cohttp.0.14.0"
|
||||
"graphql-lwt.0.14.0"
|
||||
"graphql_parser.0.14.0"
|
||||
"graphv_core.0.1.1"
|
||||
"graphv_core_lib.0.1.1"
|
||||
"graphv_font.0.1.1"
|
||||
"graphv_font_stb_truetype.0.1.1"
|
||||
"graphv_gles2.0.1.1"
|
||||
"graphv_gles2_native.0.1.1"
|
||||
"graphv_gles2_native_impl.0.1.1"
|
||||
"h2.0.11.0"
|
||||
"happy-eyeballs.0.6.0"
|
||||
"happy-eyeballs-lwt.0.6.0"
|
||||
"happy-eyeballs-mirage.0.6.0"
|
||||
"hashcons.1.4.0"
|
||||
"hex.1.5.0"
|
||||
"hkdf.1.0.4"
|
||||
"hpack.0.11.0"
|
||||
"httpaf.0.7.1"
|
||||
"hxd.0.3.2"
|
||||
"index.1.6.2"
|
||||
"inotify.2.5"
|
||||
"integers.0.7.0"
|
||||
"ipaddr.5.5.0"
|
||||
"ipaddr-cstruct.5.5.0"
|
||||
"ipaddr-sexp.5.5.0"
|
||||
"irmin.3.9.0"
|
||||
"irmin-fs.3.9.0"
|
||||
"irmin-git.3.9.0"
|
||||
"irmin-graphql.3.9.0"
|
||||
"irmin-pack.3.9.0"
|
||||
"irmin-tezos.3.9.0"
|
||||
"irmin-watcher.0.5.0"
|
||||
"jsonm.1.0.2"
|
||||
"ke.0.6"
|
||||
"lablgtk3.3.1.4"
|
||||
"lablgtk3-sourceview3.3.1.4"
|
||||
"lambda-term.3.3.2"
|
||||
"logs.0.7.0"
|
||||
"lru.0.3.1"
|
||||
"lwd.0.3"
|
||||
"lwt.5.7.0"
|
||||
"lwt-dllist.1.0.1"
|
||||
"lwt_glib.1.1.1"
|
||||
"lwt_react.1.2.0"
|
||||
"macaddr.5.5.0"
|
||||
"macaddr-cstruct.5.5.0"
|
||||
"magic-mime.1.3.1"
|
||||
"memtrace.0.2.3"
|
||||
"menhir.20231231"
|
||||
"menhirCST.20231231"
|
||||
"menhirLib.20231231"
|
||||
"menhirSdk.20231231"
|
||||
"merlin.4.14-501"
|
||||
"merlin-lib.4.14-501"
|
||||
"metrics.0.4.1"
|
||||
"metrics-lwt.0.4.1"
|
||||
"mew.0.1.0"
|
||||
"mew_vi.0.5.0"
|
||||
"mimic.0.0.6"
|
||||
"mimic-happy-eyeballs.0.0.6"
|
||||
"mirage-clock.4.2.0"
|
||||
"mirage-clock-unix.4.2.0"
|
||||
"mirage-crypto.0.11.3"
|
||||
"mirage-crypto-ec.0.11.3"
|
||||
"mirage-crypto-pk.0.11.3"
|
||||
"mirage-crypto-rng.0.11.3"
|
||||
"mirage-crypto-rng-lwt.0.11.3"
|
||||
"mirage-device.2.0.0"
|
||||
"mirage-flow.3.0.0"
|
||||
"mirage-kv.6.1.1"
|
||||
"mirage-net.4.0.0"
|
||||
"mirage-no-solo5.1"
|
||||
"mirage-random.3.0.0"
|
||||
"mirage-runtime.4.5.1"
|
||||
"mirage-time.3.0.0"
|
||||
"mirage-unix.5.0.1"
|
||||
"mtime.2.0.0"
|
||||
"not-ocamlfind.0.13"
|
||||
"num.1.5"
|
||||
"ocaml.5.1.1"
|
||||
"ocaml-compiler-libs.v0.12.4"
|
||||
"ocaml-config.3"
|
||||
"ocaml-syntax-shims.1.0.0"
|
||||
"ocaml-variants.5.1.1+options"
|
||||
"ocaml-version.3.6.7"
|
||||
"ocamlbuild.0.14.3"
|
||||
"ocamlfind.1.9.6"
|
||||
"ocamlformat.0.26.2"
|
||||
"ocamlformat-lib.0.26.2"
|
||||
"ocamlgraph.2.1.0"
|
||||
"ocp-indent.1.8.1"
|
||||
"ocplib-endian.1.2"
|
||||
"odig.0.0.9"
|
||||
"odoc.2.4.2"
|
||||
"odoc-parser.2.4.2"
|
||||
"optint.0.3.0"
|
||||
"paf.0.5.0"
|
||||
"parsexp.v0.16.0"
|
||||
"pbkdf.1.2.0"
|
||||
"pecu.0.7"
|
||||
"ppx_derivers.1.2.1"
|
||||
"ppx_deriving.5.2.1"
|
||||
"ppx_enumerate.v0.16.0"
|
||||
"ppx_irmin.3.9.0"
|
||||
"ppx_repr.0.7.0"
|
||||
"ppx_sexp_conv.v0.16.0"
|
||||
"ppxlib.0.32.1"
|
||||
"progress.0.4.0"
|
||||
"psq.0.2.1"
|
||||
"ptime.1.1.0"
|
||||
"randomconv.0.1.3"
|
||||
"re.1.11.0"
|
||||
"react.1.2.2"
|
||||
"repr.0.7.0"
|
||||
"result.1.5"
|
||||
"rresult.0.7.0"
|
||||
"rusage.1.0.0"
|
||||
"semaphore-compat.1.0.1"
|
||||
"seq.base"
|
||||
"sexplib.v0.16.0"
|
||||
"sexplib0.v0.16.0"
|
||||
"stb_image.0.5"
|
||||
"stb_truetype.0.7"
|
||||
"stdio.v0.16.0"
|
||||
"stdlib-shims.0.3.0"
|
||||
"stringext.1.6.0"
|
||||
"tcpip.8.0.0"
|
||||
"terminal.0.4.0"
|
||||
"tezos-base58.1.0.0"
|
||||
"tgls.0.8.6"
|
||||
"tls.0.17.3"
|
||||
"tls-lwt.0.17.3"
|
||||
"tls-mirage.0.17.3"
|
||||
"topkg.1.0.7"
|
||||
"trie.1.0.0"
|
||||
"tuareg.3.0.1"
|
||||
"tyxml.4.6.0"
|
||||
"uchar.0.0.2"
|
||||
"uri.4.4.0"
|
||||
"uri-sexp.4.4.0"
|
||||
"user-setup.0.7"
|
||||
"utop.2.14.0"
|
||||
"uucp.15.1.0"
|
||||
"uuseg.15.1.0"
|
||||
"uutf.1.0.3"
|
||||
"vector.1.0.0"
|
||||
"webmachine.0.7.0"
|
||||
"x509.0.16.5"
|
||||
"xdg.3.15.2"
|
||||
"yaml.3.2.0"
|
||||
"yojson.2.1.2"
|
||||
"zarith.1.13"
|
||||
"zed.3.2.3"
|
||||
]
|
||||
76
oplevel.ml
76
oplevel.ml
@ -64,9 +64,6 @@ let main =
|
||||
let min_fps = ref Float.max_float in
|
||||
let max_fps = ref Float.min_float in
|
||||
|
||||
(* Thread which is woken up when the main window is closed. *)
|
||||
let _waiter, _wakener = Lwt.wait () in
|
||||
|
||||
let rootrepo =
|
||||
Store.init_default
|
||||
(F.str "%s/console/rootstore.git" Secrets.giturl)
|
||||
@ -152,43 +149,58 @@ let main =
|
||||
(String "#use \"topfind\";;\n#list;;#require \"lwt\";;")); *)
|
||||
(* toplevel execution binding *)
|
||||
Ui.(
|
||||
update_bindings ui
|
||||
Event.(
|
||||
fun a ->
|
||||
a
|
||||
|> adds
|
||||
[
|
||||
[
|
||||
Key (Press, X, [ Control ]);
|
||||
Key (Press, E, [ Control ]);
|
||||
];
|
||||
]
|
||||
[
|
||||
Custom
|
||||
( "toplevel_execute",
|
||||
fun () ->
|
||||
TextBuffer.peek tb_init >>= fun _str ->
|
||||
(*Toploop.use_input out_ppf (String str)
|
||||
|> F.epr "Toploop.use_input=%b@."; *)
|
||||
Lwt.return_unit );
|
||||
]));
|
||||
append_bindings ui
|
||||
(Lwd.return
|
||||
Event.
|
||||
[
|
||||
pack Fun.id
|
||||
(empty
|
||||
|> adds
|
||||
[
|
||||
[
|
||||
Key (Press, X, [ Control ]);
|
||||
Key (Press, E, [ Control ]);
|
||||
];
|
||||
]
|
||||
[
|
||||
Custom
|
||||
( "toplevel_execute",
|
||||
fun () ->
|
||||
TextBuffer.peek tb_init >>= fun _str ->
|
||||
(*Toploop.use_input out_ppf (String str)
|
||||
|> F.epr "Toploop.use_input=%b@."; *)
|
||||
Lwt.return_unit );
|
||||
]);
|
||||
]));
|
||||
|
||||
WindowManager.make ui
|
||||
(Lwd.var
|
||||
(`T
|
||||
( `Y,
|
||||
[
|
||||
(`TextEdit (TextEdit.multiline ui to_init), `Ratio 0.333);
|
||||
(`TextEdit (TextEdit.multiline ui tb_init), `Ratio 0.5);
|
||||
(`TextEdit (TextEdit.multiline ui to_init), `Ratio 1.0);
|
||||
] )))
|
||||
WindowManager.
|
||||
[
|
||||
{
|
||||
t = `TextEdit (TextEdit.multiline ui to_init);
|
||||
dim = `Ratio 0.333;
|
||||
bindings = [];
|
||||
};
|
||||
{
|
||||
t = `TextEdit (TextEdit.multiline ui tb_init);
|
||||
dim = `Ratio 0.5;
|
||||
bindings = [];
|
||||
};
|
||||
{
|
||||
t = `TextEdit (TextEdit.multiline ui to_init);
|
||||
dim = `Ratio 1.0;
|
||||
bindings = [];
|
||||
};
|
||||
] )))
|
||||
>>= fun page ->
|
||||
let page_root = Lwd.observe page in
|
||||
|
||||
let bindings =
|
||||
ui.bindings |> Lwd.get |> Lwd.observe |> Lwd.quick_sample |> snd
|
||||
in
|
||||
F.epr "Bindings:@.%a" Ui.pp_bindings bindings;
|
||||
let bindings = ui.bindings |> Lwd.observe |> Lwd.quick_sample in
|
||||
F.epr "Bindings:@.";
|
||||
List.iter (fun bs -> F.epr "%a" Ui.pp_pack bs) bindings;
|
||||
|
||||
F.pr "oplevel.ml: entering drawing loop@.";
|
||||
let period_min = 1.0 /. 30. in
|
||||
|
||||
Reference in New Issue
Block a user