working towards store editor features
This commit is contained in:
687
main.ml
687
main.ml
@ -411,12 +411,10 @@ module Display = struct
|
||||
(* the box2 here is cannonically the place the returner drew
|
||||
(the Wall.image extents) *)
|
||||
type image = box2 * Wall.image
|
||||
|
||||
let image_empty : image = (Box2.empty, Image.empty)
|
||||
|
||||
type pane = state -> state * image
|
||||
|
||||
let pane_empty s = (s, image_empty)
|
||||
let pane_empty s =
|
||||
(s, (Box2.of_pts (Box2.o s.box) (Box2.o s.box), Image.empty))
|
||||
|
||||
type frame =
|
||||
{ sdl_win: Sdl.window
|
||||
@ -485,7 +483,7 @@ module Display = struct
|
||||
else Sdl.Window.windowed )
|
||||
: _ result ) ) ;
|
||||
None
|
||||
| a -> Some a (*| a -> Some a*) )
|
||||
| a -> Some a )
|
||||
(get_events ()) in
|
||||
let width, height = Sdl.gl_get_drawable_size frame.sdl_win in
|
||||
if List.length events > 0 then last_pane := actor events ;
|
||||
@ -658,9 +656,7 @@ module Panel = struct
|
||||
type actor = Event.events -> Display.pane
|
||||
|
||||
let blank =
|
||||
{ act=
|
||||
(fun panel _events ->
|
||||
(panel, fun s -> (s, Display.image_empty)) )
|
||||
{ act= (fun panel _events -> (panel, Display.pane_empty))
|
||||
; subpanels= []
|
||||
; tag= "blank pane" }
|
||||
|
||||
@ -669,6 +665,16 @@ module Panel = struct
|
||||
; subpanels= []
|
||||
; tag= "draw-pane" }
|
||||
|
||||
let actor (panel : t) : Event.events -> Display.pane =
|
||||
let enclosure = ref panel in
|
||||
fun events ->
|
||||
let panel, pane = panel.act !enclosure events in
|
||||
enclosure := panel ;
|
||||
pane
|
||||
|
||||
let filter_events ef p =
|
||||
{p with act= (fun panel events -> p.act panel (ef events))}
|
||||
|
||||
(* draws subsequent items below *)
|
||||
let vbox subpanels =
|
||||
{ act=
|
||||
@ -796,174 +802,272 @@ module Panel = struct
|
||||
, ( Box2.of_pts (Box2.o s.box) (P2.v !max_x (Box2.maxy !box))
|
||||
, !node ) )
|
||||
|
||||
let textedit_bindings =
|
||||
let open Input.Bind in
|
||||
add [([], Code Left)] [Zed Prev_char]
|
||||
@@ add [([], Code Right)] [Zed Next_char]
|
||||
@@ add [([], Code Up)] [Zed Prev_line]
|
||||
@@ add [([], Code Down)] [Zed Next_line]
|
||||
@@ add [([], Code Home)] [Zed Goto_bol]
|
||||
@@ add [([], Code End)] [Zed Goto_eol]
|
||||
@@ add [([], Code Insert)] [Zed Switch_erase_mode]
|
||||
@@ add [([], Code Delete)] [Zed Delete_next_char]
|
||||
@@ add [([], Code Enter)] [Zed Newline]
|
||||
@@ add [([Ctrl], Char ' ')] [Zed Set_mark]
|
||||
@@ add [([Ctrl], Char 'a')] [Zed Goto_bol]
|
||||
@@ add [([Ctrl], Char 'e')] [Zed Goto_eol]
|
||||
@@ add [([Ctrl], Char 'd')] [Zed Delete_next_char]
|
||||
@@ add [([Ctrl], Char 'h')] [Zed Delete_prev_char]
|
||||
@@ add [([Ctrl], Char 'k')] [Zed Kill_next_line]
|
||||
@@ add [([Ctrl], Char 'u')] [Zed Kill_prev_line]
|
||||
@@ add [([Ctrl], Char 'n')] [Zed Next_line]
|
||||
@@ add [([Ctrl], Char 'p')] [Zed Prev_line]
|
||||
@@ add [([Ctrl], Char 'w')] [Zed Kill]
|
||||
@@ add [([Ctrl], Char 'y')] [Zed Yank]
|
||||
@@ add [([], Code Backspace)] [Zed Delete_prev_char]
|
||||
@@ add [([Meta], Char 'w')] [Zed Copy]
|
||||
@@ add [([Meta], Char 'c')] [Zed Capitalize_word]
|
||||
@@ add [([Meta], Char 'l')] [Zed Lowercase_word]
|
||||
@@ add [([Meta], Char 'u')] [Zed Uppercase_word]
|
||||
@@ add [([Meta], Char 'b')] [Zed Prev_word]
|
||||
@@ add [([Meta], Char 'f')] [Zed Next_word]
|
||||
@@ add [([Meta], Code Right)] [Zed Next_word]
|
||||
@@ add [([Meta], Code Left)] [Zed Prev_word]
|
||||
@@ add [([Ctrl], Code Right)] [Zed Next_word]
|
||||
@@ add [([Ctrl], Code Left)] [Zed Prev_word]
|
||||
@@ add [([Meta], Code Backspace)] [Zed Kill_prev_word]
|
||||
@@ add [([Meta], Code Delete)] [Zed Kill_prev_word]
|
||||
@@ add [([Ctrl], Code Delete)] [Zed Kill_next_word]
|
||||
@@ add [([Meta], Char 'd')] [Zed Kill_next_word]
|
||||
@@ add [([Ctrl], Char '/')] [Zed Undo]
|
||||
@@ add [([Ctrl], Char 'x'); ([], Char 'u')] [Zed Undo]
|
||||
@@ empty
|
||||
let format_symbolic_output_buffer (ppf : Format.formatter) buf =
|
||||
List.iter
|
||||
Format.(
|
||||
function
|
||||
| Output_flush -> F.pf ppf "@?"
|
||||
| Output_newline -> F.pf ppf "@."
|
||||
| Output_string s -> Format.pp_print_string ppf s
|
||||
| Output_spaces n | Output_indent n ->
|
||||
Format.pp_print_string ppf (String.make n ' '))
|
||||
buf
|
||||
|
||||
type textedit =
|
||||
{ mutable ze: unit Zed_edit.t
|
||||
; mutable zc: Zed_cursor.t
|
||||
; mutable keybind: Input.Bind.state }
|
||||
|
||||
let make_textedit ?(keybinds = textedit_bindings) () =
|
||||
let z = Zed_edit.create () in
|
||||
{ ze= z
|
||||
; zc= Zed_edit.new_cursor z
|
||||
; keybind= Input.Bind.init keybinds }
|
||||
|
||||
let clear_textedit ?(keybinds = textedit_bindings) te =
|
||||
te.ze <- Zed_edit.create () ;
|
||||
te.zc <- Zed_edit.new_cursor te.ze ;
|
||||
te.keybind <- Input.Bind.init keybinds
|
||||
|
||||
let str_of_textedit (te : textedit) =
|
||||
Zed_string.to_utf8 (Zed_rope.to_string (Zed_edit.text te.ze))
|
||||
|
||||
let textedit ?(_initialstring = "") ?(height = !g_text_height) te =
|
||||
{ act=
|
||||
(fun panel events ->
|
||||
let ctx = Zed_edit.context te.ze te.zc in
|
||||
(* collect events and update Zed context *)
|
||||
List.iter
|
||||
(function
|
||||
| `Key_down (k : Input.keystate) -> (
|
||||
let open Input.Bind in
|
||||
( match te.keybind.state with
|
||||
| Accepted _ | Rejected ->
|
||||
te.keybind.last_keyseq <- [] ;
|
||||
te.keybind.last_actions <- []
|
||||
| Continue _ -> () ) ;
|
||||
te.keybind.state <-
|
||||
resolve k
|
||||
(get_resolver te.keybind.state
|
||||
(default_resolver te.keybind.bindings) ) ;
|
||||
te.keybind.last_keyseq <-
|
||||
k :: te.keybind.last_keyseq ;
|
||||
match te.keybind.state with
|
||||
| Accepted a ->
|
||||
te.keybind.last_actions <- a ;
|
||||
List.iter
|
||||
(function
|
||||
| Input.Bind.Custom f -> f ()
|
||||
| Zed za -> Zed_edit.get_action za ctx )
|
||||
a
|
||||
| Continue _ -> ()
|
||||
| Rejected -> () )
|
||||
| `Key_up _ -> ()
|
||||
| `Text_input s ->
|
||||
Zed_edit.insert ctx
|
||||
(Zed_rope.of_string (Zed_string.of_utf8 s))
|
||||
| _ -> () )
|
||||
events ;
|
||||
let draw_textedit =
|
||||
draw_pp height (fun pp ->
|
||||
let zrb, zra =
|
||||
Zed_rope.break (Zed_edit.text te.ze)
|
||||
(Zed_cursor.get_position te.zc) in
|
||||
let before_cursor =
|
||||
Zed_string.to_utf8 (Zed_rope.to_string zrb) in
|
||||
let after_cursor =
|
||||
Zed_string.to_utf8 (Zed_rope.to_string zra) in
|
||||
Format.pp_open_hvbox pp 0 ;
|
||||
F.text pp before_cursor ;
|
||||
Format.pp_open_stag pp
|
||||
Display.(Cursor (Wall.Color.v 0.99 0.99 0.125 0.3)) ;
|
||||
F.pf pp "" ;
|
||||
Format.pp_close_stag pp () ;
|
||||
F.text pp after_cursor ;
|
||||
F.pf pp "@." ;
|
||||
Format.pp_close_box pp () ) in
|
||||
(panel, draw_textedit) )
|
||||
; subpanels= []
|
||||
; tag= "textedit" }
|
||||
|
||||
(* pane that displays last key binding match state *)
|
||||
let bindingstate ?(height = !g_text_height) (b : Input.Bind.state) =
|
||||
{ act=
|
||||
(fun panel _events ->
|
||||
( panel
|
||||
, draw_pp height (fun pp ->
|
||||
Format.pp_open_hbox pp () ;
|
||||
F.text pp
|
||||
(List.fold_left
|
||||
(fun s x -> Input.to_string_compact x ^ " " ^ s)
|
||||
"" b.last_keyseq ) ;
|
||||
F.text pp "-> " ;
|
||||
F.text pp
|
||||
( match b.state with
|
||||
| Accepted a ->
|
||||
"Accepted "
|
||||
^ List.fold_right
|
||||
(fun x s ->
|
||||
s
|
||||
^ Input.Bind.(
|
||||
match x with
|
||||
| Zed a -> Zed_edit.name_of_action a
|
||||
| Custom _ -> "Custom")
|
||||
^ "; " )
|
||||
a ""
|
||||
| Rejected -> "Rejected"
|
||||
| Continue _ -> "Continue" ) ;
|
||||
Format.pp_close_box pp () ;
|
||||
F.flush pp () ) ) )
|
||||
; subpanels= []
|
||||
; tag= "binding-state" }
|
||||
let out_funs_of_sob sob =
|
||||
Format.
|
||||
{ out_string=
|
||||
(fun s p n ->
|
||||
add_symbolic_output_item sob
|
||||
(Output_string (String.sub s p n)) )
|
||||
; out_flush=
|
||||
(fun () -> add_symbolic_output_item sob Output_flush)
|
||||
; out_indent=
|
||||
(fun n -> add_symbolic_output_item sob (Output_indent n))
|
||||
; out_newline=
|
||||
(fun () -> add_symbolic_output_item sob Output_newline)
|
||||
; out_spaces=
|
||||
(fun n -> add_symbolic_output_item sob (Output_spaces n)) }
|
||||
|
||||
let prettyprint ?(height = !g_text_height) fpp =
|
||||
{ act= (fun panel _events -> (panel, draw_pp height fpp))
|
||||
; subpanels= []
|
||||
; tag= "pretty-print" }
|
||||
|
||||
let actor (panel : t) : Event.events -> Display.pane =
|
||||
let enclosure = ref panel in
|
||||
fun events ->
|
||||
let panel, pane = panel.act !enclosure events in
|
||||
enclosure := panel ;
|
||||
pane
|
||||
module Textedit = struct
|
||||
let bindings =
|
||||
let open Input.Bind in
|
||||
add [([], Code Left)] [Zed Prev_char]
|
||||
@@ add [([], Code Right)] [Zed Next_char]
|
||||
@@ add [([], Code Up)] [Zed Prev_line]
|
||||
@@ add [([], Code Down)] [Zed Next_line]
|
||||
@@ add [([], Code Home)] [Zed Goto_bol]
|
||||
@@ add [([], Code End)] [Zed Goto_eol]
|
||||
@@ add [([], Code Insert)] [Zed Switch_erase_mode]
|
||||
@@ add [([], Code Delete)] [Zed Delete_next_char]
|
||||
@@ add [([], Code Enter)] [Zed Newline]
|
||||
@@ add [([Ctrl], Char ' ')] [Zed Set_mark]
|
||||
@@ add [([Ctrl], Char 'a')] [Zed Goto_bol]
|
||||
@@ add [([Ctrl], Char 'e')] [Zed Goto_eol]
|
||||
@@ add [([Ctrl], Char 'd')] [Zed Delete_next_char]
|
||||
@@ add [([Ctrl], Char 'h')] [Zed Delete_prev_char]
|
||||
@@ add [([Ctrl], Char 'k')] [Zed Kill_next_line]
|
||||
@@ add [([Ctrl], Char 'u')] [Zed Kill_prev_line]
|
||||
@@ add [([Ctrl], Char 'n')] [Zed Next_line]
|
||||
@@ add [([Ctrl], Char 'p')] [Zed Prev_line]
|
||||
@@ add [([Ctrl], Char 'w')] [Zed Kill]
|
||||
@@ add [([Ctrl], Char 'y')] [Zed Yank]
|
||||
@@ add [([], Code Backspace)] [Zed Delete_prev_char]
|
||||
@@ add [([Meta], Char 'w')] [Zed Copy]
|
||||
@@ add [([Meta], Char 'c')] [Zed Capitalize_word]
|
||||
@@ add [([Meta], Char 'l')] [Zed Lowercase_word]
|
||||
@@ add [([Meta], Char 'u')] [Zed Uppercase_word]
|
||||
@@ add [([Meta], Char 'b')] [Zed Prev_word]
|
||||
@@ add [([Meta], Char 'f')] [Zed Next_word]
|
||||
@@ add [([Meta], Code Right)] [Zed Next_word]
|
||||
@@ add [([Meta], Code Left)] [Zed Prev_word]
|
||||
@@ add [([Ctrl], Code Right)] [Zed Next_word]
|
||||
@@ add [([Ctrl], Code Left)] [Zed Prev_word]
|
||||
@@ add [([Meta], Code Backspace)] [Zed Kill_prev_word]
|
||||
@@ add [([Meta], Code Delete)] [Zed Kill_prev_word]
|
||||
@@ add [([Ctrl], Code Delete)] [Zed Kill_next_word]
|
||||
@@ add [([Meta], Char 'd')] [Zed Kill_next_word]
|
||||
@@ add [([Ctrl], Char '/')] [Zed Undo]
|
||||
@@ add [([Ctrl], Char 'x'); ([], Char 'u')] [Zed Undo]
|
||||
@@ empty
|
||||
|
||||
type t =
|
||||
{ mutable zed: unit Zed_edit.context
|
||||
; mutable keybind: Input.Bind.state }
|
||||
|
||||
let clear te =
|
||||
let ze = Zed_edit.create () in
|
||||
te.zed <- Zed_edit.context ze (Zed_edit.new_cursor ze)
|
||||
|
||||
let insert te text =
|
||||
Zed_edit.insert te.zed
|
||||
(Zed_rope.of_string (Zed_string.of_utf8 text))
|
||||
|
||||
let contents (te : t) =
|
||||
Zed_string.to_utf8
|
||||
(Zed_rope.to_string (Zed_edit.text (Zed_edit.edit te.zed)))
|
||||
|
||||
let make ?(keybinds = bindings) initialtext () =
|
||||
let ze = Zed_edit.create () in
|
||||
let te =
|
||||
{ zed= Zed_edit.context ze (Zed_edit.new_cursor ze)
|
||||
; keybind= Input.Bind.init keybinds } in
|
||||
insert te initialtext ; te
|
||||
|
||||
let panel ?(height = !g_text_height) te =
|
||||
{ act=
|
||||
(fun panel events ->
|
||||
(* collect events and update Zed context *)
|
||||
List.iter
|
||||
(function
|
||||
| `Key_down (k : Input.keystate) -> (
|
||||
let open Input.Bind in
|
||||
( match te.keybind.state with
|
||||
| Accepted _ | Rejected ->
|
||||
te.keybind.last_keyseq <- [] ;
|
||||
te.keybind.last_actions <- []
|
||||
| Continue _ -> () ) ;
|
||||
te.keybind.state <-
|
||||
resolve k
|
||||
(get_resolver te.keybind.state
|
||||
(default_resolver te.keybind.bindings) ) ;
|
||||
te.keybind.last_keyseq <-
|
||||
k :: te.keybind.last_keyseq ;
|
||||
match te.keybind.state with
|
||||
| Accepted a ->
|
||||
te.keybind.last_actions <- a ;
|
||||
List.iter
|
||||
(function
|
||||
| Input.Bind.Custom f -> f ()
|
||||
| Zed za -> Zed_edit.get_action za te.zed
|
||||
)
|
||||
a
|
||||
| Continue _ -> ()
|
||||
| Rejected -> () )
|
||||
| `Key_up _ -> ()
|
||||
| `Text_input s ->
|
||||
Zed_edit.insert te.zed
|
||||
(Zed_rope.of_string (Zed_string.of_utf8 s))
|
||||
| _ -> () )
|
||||
events ;
|
||||
let draw_textedit =
|
||||
draw_pp height (fun pp ->
|
||||
let zrb, zra =
|
||||
Zed_rope.break
|
||||
(Zed_edit.text (Zed_edit.edit te.zed))
|
||||
(Zed_cursor.get_position
|
||||
(Zed_edit.cursor te.zed) ) in
|
||||
let before_cursor =
|
||||
Zed_string.to_utf8 (Zed_rope.to_string zrb) in
|
||||
let after_cursor =
|
||||
Zed_string.to_utf8 (Zed_rope.to_string zra) in
|
||||
Format.pp_open_hvbox pp 0 ;
|
||||
F.text pp before_cursor ;
|
||||
Format.pp_open_stag pp
|
||||
Display.(
|
||||
Cursor (Wall.Color.v 0.99 0.99 0.125 0.3)) ;
|
||||
F.pf pp "" ;
|
||||
Format.pp_close_stag pp () ;
|
||||
F.text pp after_cursor ;
|
||||
F.pf pp "@." ;
|
||||
Format.pp_close_box pp () ) in
|
||||
(panel, draw_textedit) )
|
||||
; subpanels= []
|
||||
; tag= "textedit" }
|
||||
|
||||
(* pane that displays last key binding match state *)
|
||||
let bindingstate ?(height = !g_text_height) (b : Input.Bind.state)
|
||||
=
|
||||
{ act=
|
||||
(fun panel _events ->
|
||||
( panel
|
||||
, draw_pp height (fun pp ->
|
||||
Format.pp_open_hbox pp () ;
|
||||
F.text pp
|
||||
(List.fold_left
|
||||
(fun s x -> Input.to_string_compact x ^ " " ^ s)
|
||||
"" b.last_keyseq ) ;
|
||||
F.text pp "-> " ;
|
||||
F.text pp
|
||||
( match b.state with
|
||||
| Accepted a ->
|
||||
"Accepted "
|
||||
^ List.fold_right
|
||||
(fun x s ->
|
||||
s
|
||||
^ Input.Bind.(
|
||||
match x with
|
||||
| Zed a -> Zed_edit.name_of_action a
|
||||
| Custom _ -> "Custom")
|
||||
^ "; " )
|
||||
a ""
|
||||
| Rejected -> "Rejected"
|
||||
| Continue _ -> "Continue" ) ;
|
||||
Format.pp_close_box pp () ;
|
||||
F.flush pp () ) ) )
|
||||
; subpanels= []
|
||||
; tag= "binding-state" }
|
||||
end
|
||||
|
||||
module Modal = struct
|
||||
type t =
|
||||
{ te: Textedit.t
|
||||
; mutable input: string option
|
||||
; mutable handle: string -> unit
|
||||
; mutable prompt: string }
|
||||
|
||||
let make () =
|
||||
{ te= Textedit.make "" ()
|
||||
; input= None
|
||||
; handle= (fun _text -> ())
|
||||
; prompt= "" }
|
||||
|
||||
let panel ?(height = !g_text_height) me =
|
||||
let keybinds =
|
||||
let open Input.Bind in
|
||||
add [([], Code Enter)]
|
||||
[ Custom
|
||||
(fun () ->
|
||||
me.handle (Textedit.contents me.te) ;
|
||||
me.input <- None ) ]
|
||||
Textedit.bindings in
|
||||
me.te.keybind.bindings <- keybinds ;
|
||||
{ act=
|
||||
(fun panel events ->
|
||||
match me.input with
|
||||
| Some text ->
|
||||
Textedit.insert me.te text ;
|
||||
(hbox panel.subpanels).act panel events
|
||||
| None -> (panel, Display.pane_empty)
|
||||
(* don't draw anything if modal isn't active *) )
|
||||
; subpanels=
|
||||
[ prettyprint (fun pp -> F.text pp me.prompt)
|
||||
; Textedit.panel ~height me.te ]
|
||||
; tag= "modal-edit" }
|
||||
|
||||
let start me ?(prompt = "> ") text handler =
|
||||
me.input <- Some text ;
|
||||
Textedit.clear me.te ;
|
||||
Textedit.insert me.te text ;
|
||||
me.handle <- handler ;
|
||||
me.prompt <- prompt
|
||||
|
||||
let is_active me =
|
||||
match me.input with Some _ -> true | None -> false
|
||||
end
|
||||
end
|
||||
|
||||
open Wall
|
||||
open Gg
|
||||
module I = Image
|
||||
module P = Path
|
||||
module Text = Wall_text
|
||||
module Toplevel = struct
|
||||
type t =
|
||||
{mutable eval: Topinf.evalenv; res: Format.symbolic_output_buffer}
|
||||
|
||||
let init () =
|
||||
let sob = Format.make_symbolic_output_buffer () in
|
||||
let ppf = Format.formatter_of_symbolic_output_buffer sob in
|
||||
{eval= Topinf.init ppf; res= sob}
|
||||
|
||||
let eval t str =
|
||||
let ppf = Format.formatter_of_symbolic_output_buffer t.res in
|
||||
Topinf.ppf := ppf ;
|
||||
ignore (Format.flush_symbolic_output_buffer t.res) ;
|
||||
try
|
||||
t.eval ppf (str ^ ";;") ;
|
||||
(*HACK to prevent getting stuck in parser*)
|
||||
let b = Buffer.create 69 in
|
||||
Panel.format_symbolic_output_buffer
|
||||
(Format.formatter_of_buffer b)
|
||||
(Format.get_symbolic_output_buffer t.res)
|
||||
with e ->
|
||||
F.pf ppf "Exception in pane_top//eval@." ;
|
||||
Location.report_exception ppf e ;
|
||||
F.epr "Exception in pane_top//eval@."
|
||||
|
||||
let result_sob t = t.res
|
||||
end
|
||||
|
||||
module Store = struct
|
||||
module Istore = Irmin_unix.Git.FS.KV (Irmin.Contents.String)
|
||||
@ -991,6 +1095,38 @@ module Store = struct
|
||||
; selection= Istore.Key.v [fst (List.hd viewlist)]
|
||||
; editmode= false } )
|
||||
|
||||
let directives (top : Toplevel.t) sv =
|
||||
let dir_use_key key_lid =
|
||||
(* TODO: currently causes a segfault :( *)
|
||||
let key_obj =
|
||||
try
|
||||
match
|
||||
Env.find_value_by_name key_lid !Topinf.toplevel_env
|
||||
with
|
||||
| path, _desc ->
|
||||
Topinf.eval_value_path !Topinf.toplevel_env path
|
||||
| exception Not_found ->
|
||||
F.epr "Unbound value %a.@." Printtyp.longident key_lid ;
|
||||
raise Exit
|
||||
with Exit -> Obj.repr ["nofile"] in
|
||||
let key = Obj.obj key_obj in
|
||||
let contents =
|
||||
Lwt_main.run
|
||||
( Istore.kind sv.store key
|
||||
>>= function
|
||||
| Some a -> (
|
||||
match a with
|
||||
| `Contents -> Istore.get sv.store key
|
||||
| `Node ->
|
||||
Lwt.return "\"use_key on Node not implemented yet\"" )
|
||||
| None -> Lwt.return "Invalid Selection..." ) in
|
||||
Toplevel.eval top contents in
|
||||
Topinf.add_directive "use_key" (Directive_ident dir_use_key)
|
||||
{ section= "Console Store"
|
||||
; doc=
|
||||
"Read, compile and execute source phrases from the given \
|
||||
store key." }
|
||||
|
||||
let navigate sv action =
|
||||
let rec findi value = function
|
||||
| [] -> 0
|
||||
@ -1031,27 +1167,85 @@ module Store = struct
|
||||
|
||||
let editor ?(branch = "current") storepath : Panel.t =
|
||||
let sv = make_storeview storepath branch in
|
||||
let globalbinds =
|
||||
let open Input.Bind in
|
||||
add [([], Char 'e')]
|
||||
[Custom (fun () -> sv.editmode <- not sv.editmode)]
|
||||
empty in
|
||||
let te = Panel.Textedit.make "" () in
|
||||
let top = Toplevel.init () in
|
||||
let modalstate = Panel.Modal.make () in
|
||||
directives top sv ;
|
||||
let save store path content =
|
||||
Lwt_main.run
|
||||
(Istore.set_exn store
|
||||
~info:(Irmin_unix.info "editor-save")
|
||||
path content ) in
|
||||
let navbinds =
|
||||
let open Input.Bind in
|
||||
let new_contents name content =
|
||||
Lwt_main.run
|
||||
(let s =
|
||||
match Istore.Key.rdecons sv.selection with
|
||||
| Some (t, _) -> t
|
||||
| None -> Istore.Key.empty in
|
||||
Istore.get_tree sv.store (sv.view @ s)
|
||||
>>= fun tree ->
|
||||
Istore.Tree.add tree name content
|
||||
>>= fun newtree ->
|
||||
Istore.set_tree_exn
|
||||
~info:(Irmin_unix.info "new Contents")
|
||||
sv.store sv.view newtree ) in
|
||||
add [([], Char 'n')] [Custom (navigate sv `Next)]
|
||||
@@ add [([], Char 'p')] [Custom (navigate sv `Prev)]
|
||||
@@ add [([], Char 'w')] [Custom (navigate sv `Prev)]
|
||||
@@ add [([], Char 's')] [Custom (navigate sv `Next)]
|
||||
@@ add [([], Char 'd')] [Custom (navigate sv `Sub)]
|
||||
@@ add [([], Char 'a')] [Custom (navigate sv `Sup)] globalbinds
|
||||
in
|
||||
@@ add [([], Char 'a')] [Custom (navigate sv `Sup)]
|
||||
@@ add [([], Char 'e')]
|
||||
[Custom (fun () -> sv.editmode <- not sv.editmode)]
|
||||
@@ add
|
||||
[([], Char 'f')] (* find: enter path in modal *)
|
||||
[Custom (fun () -> ())]
|
||||
@@ add
|
||||
[([], Char 'c')] (* contents: create new contents node *)
|
||||
[ Custom
|
||||
(fun () ->
|
||||
Panel.Modal.start ~prompt:"Contents name > "
|
||||
modalstate "" (fun name ->
|
||||
new_contents (Istore.Key.v [name]) "" ) ) ]
|
||||
@@ add [([], Char 't')]
|
||||
[ Custom
|
||||
(fun () ->
|
||||
Panel.Modal.start ~prompt:"Node name := " modalstate
|
||||
"" (fun nodename ->
|
||||
Panel.Modal.start
|
||||
~prompt:"Initial Contents name > " modalstate
|
||||
"" (fun contentsname ->
|
||||
new_contents
|
||||
(Istore.Key.v [nodename; contentsname])
|
||||
"" ) ) ) ]
|
||||
(* tree: create new subtree *)
|
||||
empty in
|
||||
let editbinds =
|
||||
let open Input.Bind in
|
||||
add [([], Char 'e')]
|
||||
[Custom (fun () -> sv.editmode <- not sv.editmode)]
|
||||
Panel.textedit_bindings in
|
||||
add
|
||||
[([Ctrl], Char 'c')]
|
||||
[ Custom
|
||||
(fun () ->
|
||||
sv.editmode <- not sv.editmode ;
|
||||
save sv.store
|
||||
(sv.view @ sv.selection)
|
||||
(Panel.Textedit.contents te) ) ]
|
||||
@@ add
|
||||
[([Ctrl], Char 's')]
|
||||
[ Custom
|
||||
(fun () ->
|
||||
save sv.store
|
||||
(sv.view @ sv.selection)
|
||||
(Panel.Textedit.contents te) ) ]
|
||||
@@ add
|
||||
[([Ctrl], Char 'x'); ([], Char 'x')]
|
||||
[ Custom
|
||||
(fun () ->
|
||||
Toplevel.eval top (Panel.Textedit.contents te) ) ]
|
||||
Panel.Textedit.bindings in
|
||||
let bindstate = Input.Bind.init navbinds in
|
||||
let te = Panel.make_textedit () in
|
||||
{ act=
|
||||
(fun panel events ->
|
||||
if sv.editmode then bindstate.bindings <- editbinds
|
||||
@ -1071,93 +1265,73 @@ module Store = struct
|
||||
| `Contents -> Istore.Tree.get t sv.selection
|
||||
| `Node -> Lwt.return "Node..." )
|
||||
| None -> Lwt.return "Invalid Selection..." ) in
|
||||
Panel.clear_textedit te ;
|
||||
let zctx = Zed_edit.context te.ze te.zc in
|
||||
Zed_edit.insert zctx
|
||||
(Zed_rope.of_string (Zed_string.of_utf8 contents)) ) ;
|
||||
(Panel.vbox panel.subpanels).act panel
|
||||
(if sv.editmode then events else []) )
|
||||
Panel.Textedit.clear te ;
|
||||
Panel.Textedit.insert te contents ) ;
|
||||
(Panel.vbox panel.subpanels).act panel events )
|
||||
; subpanels=
|
||||
[ Panel.hbox
|
||||
[ Panel.filter_events
|
||||
(fun ev ->
|
||||
if Panel.Modal.is_active modalstate then ev else [] )
|
||||
(Panel.Modal.panel modalstate)
|
||||
; Panel.hbox
|
||||
[ Panel.prettyprint (fun pp ->
|
||||
let indent = ref 0 in
|
||||
let rec draw_levels (tree : Istore.tree)
|
||||
(sel : Istore.key) =
|
||||
let rec draw_levels ?(indent = 0)
|
||||
(tree : Istore.tree) (sel : Istore.key) =
|
||||
List.iteri
|
||||
(fun _i (step, node) ->
|
||||
Format.pp_open_vbox pp 0 ;
|
||||
Format.pp_open_hbox pp () ;
|
||||
for _ = 1 to !indent do
|
||||
Format.pp_print_space pp ()
|
||||
done ;
|
||||
if sel = [step] then
|
||||
Format.pp_open_hovbox pp indent ;
|
||||
if sel = [step] then (
|
||||
Format.pp_open_stag pp
|
||||
Display.(
|
||||
Panel.Cursor
|
||||
(Wall.Color.v 0.99 0.99 0.125 0.3)) ;
|
||||
Format.fprintf pp "%s@." step ;
|
||||
if sel = [step] then
|
||||
Format.pp_close_stag pp () ;
|
||||
Format.pp_close_box pp () ;
|
||||
let subsel =
|
||||
match Istore.Key.decons sel with
|
||||
| Some (_tstep, subkey) -> subkey
|
||||
| None -> [] in
|
||||
indent := succ !indent ;
|
||||
draw_levels node subsel ;
|
||||
indent := pred !indent ;
|
||||
F.pf pp "@," ;
|
||||
Format.pp_close_stag pp () ) ;
|
||||
( match
|
||||
Lwt_main.run (Istore.Tree.kind node [])
|
||||
with
|
||||
| Some `Contents -> F.pf pp "- %s@." step
|
||||
| Some `Node ->
|
||||
F.pf pp "> %s@." step ;
|
||||
let subsel =
|
||||
match Istore.Key.decons sel with
|
||||
| Some (_tstep, subkey) -> subkey
|
||||
| None -> [] in
|
||||
Format.pp_open_vbox pp 0 ;
|
||||
draw_levels ~indent:(indent + 1) node
|
||||
subsel ;
|
||||
Format.pp_close_box pp ()
|
||||
| None -> F.pf pp "ERROR: None" ) ;
|
||||
Format.pp_close_box pp () )
|
||||
(Lwt_main.run (Istore.Tree.list tree [])) in
|
||||
let root =
|
||||
Lwt_main.run (Istore.get_tree sv.store sv.view)
|
||||
in
|
||||
draw_levels root sv.selection ); Panel.textedit te
|
||||
(*; Panel.prettyprint (fun pp ->
|
||||
let contents =
|
||||
Lwt_main.run
|
||||
( Istore.get_tree sv.store sv.view
|
||||
>>= fun t ->
|
||||
Istore.Tree.kind t sv.selection
|
||||
>>= function
|
||||
| Some a -> (
|
||||
match a with
|
||||
| `Contents -> Istore.Tree.get t sv.selection
|
||||
| `Node -> Lwt.return "Node..." )
|
||||
| None -> Lwt.return "Invalid Selection..." )
|
||||
in Format.fprintf pp "%s @." contents ) *) ]
|
||||
; Panel.bindingstate bindstate
|
||||
draw_levels root sv.selection )
|
||||
; Panel.filter_events
|
||||
(fun ev -> if sv.editmode then ev else [])
|
||||
(Panel.Textedit.panel te)
|
||||
; Panel.prettyprint (fun pp ->
|
||||
Format.pp_open_hovbox pp 0 ;
|
||||
Panel.format_symbolic_output_buffer pp
|
||||
(Format.get_symbolic_output_buffer
|
||||
(Toplevel.result_sob top) ) ;
|
||||
Format.pp_close_box pp () ;
|
||||
F.flush pp () ) ]
|
||||
; Panel.Textedit.bindingstate bindstate
|
||||
; Panel.prettyprint (fun pp ->
|
||||
Format.fprintf pp "sv.editmode = %b @." sv.editmode ) ]
|
||||
; tag= "store-editor" }
|
||||
end
|
||||
|
||||
let format_symbolic_output_buffer (ppf : Format.formatter) buf =
|
||||
List.iter
|
||||
Format.(
|
||||
function
|
||||
| Output_flush -> F.pf ppf "@?"
|
||||
| Output_newline -> F.pf ppf "@."
|
||||
| Output_string s -> Format.pp_print_string ppf s
|
||||
| Output_spaces n | Output_indent n ->
|
||||
Format.pp_print_string ppf (String.make n ' '))
|
||||
buf
|
||||
|
||||
let out_funs_of_sob sob =
|
||||
Format.
|
||||
{ out_string=
|
||||
(fun s p n ->
|
||||
add_symbolic_output_item sob
|
||||
(Output_string (String.sub s p n)) )
|
||||
; out_flush= (fun () -> add_symbolic_output_item sob Output_flush)
|
||||
; out_indent=
|
||||
(fun n -> add_symbolic_output_item sob (Output_indent n))
|
||||
; out_newline=
|
||||
(fun () -> add_symbolic_output_item sob Output_newline)
|
||||
; out_spaces=
|
||||
(fun n -> add_symbolic_output_item sob (Output_spaces n)) }
|
||||
open Wall
|
||||
open Gg
|
||||
module I = Image
|
||||
module P = Path
|
||||
module Text = Wall_text
|
||||
|
||||
type top =
|
||||
{ te: Panel.textedit
|
||||
{ te: Panel.Textedit.t
|
||||
; res: Format.symbolic_output_buffer
|
||||
; mutable eval: Topinf.evalenv option
|
||||
; mutable path: string list
|
||||
@ -1166,7 +1340,7 @@ type top =
|
||||
|
||||
let make_top storepath ?(branch = "current") () =
|
||||
let t =
|
||||
{ te= Panel.make_textedit ()
|
||||
{ te= Panel.Textedit.make "" ()
|
||||
; res= Format.make_symbolic_output_buffer ()
|
||||
; eval= None
|
||||
; path= ["init"]
|
||||
@ -1175,11 +1349,8 @@ let make_top storepath ?(branch = "current") () =
|
||||
Topinf.ppf := Format.formatter_of_symbolic_output_buffer t.res ;
|
||||
(* Format.pp_set_formatter_out_functions Format.std_formatter
|
||||
(out_funs_of_sob t.res) ;*)
|
||||
let zctx = Zed_edit.context t.te.ze t.te.zc in
|
||||
Zed_edit.insert zctx
|
||||
(Zed_rope.of_string
|
||||
(Zed_string.of_utf8
|
||||
(Lwt_main.run (Store.Istore.get t.storeview.store t.path)) ) ) ;
|
||||
Panel.Textedit.insert t.te
|
||||
(Lwt_main.run (Store.Istore.get t.storeview.store t.path)) ;
|
||||
t
|
||||
|
||||
let top_panel (t : top) =
|
||||
@ -1204,12 +1375,12 @@ let top_panel (t : top) =
|
||||
>>= fun tree ->
|
||||
Store.Istore.Tree.add tree
|
||||
(t.histpath @ ["input"])
|
||||
(Panel.str_of_textedit t.te) ) ) ;
|
||||
(Panel.Textedit.contents t.te) ) ) ;
|
||||
ignore (Format.flush_symbolic_output_buffer t.res) ;
|
||||
eval ppf (Panel.str_of_textedit t.te ^ ";;") ;
|
||||
eval ppf (Panel.Textedit.contents t.te ^ ";;") ;
|
||||
(*HACK to prevent getting stuck in parser*)
|
||||
let b = Buffer.create 69 in
|
||||
format_symbolic_output_buffer
|
||||
Panel.format_symbolic_output_buffer
|
||||
(Format.formatter_of_buffer b)
|
||||
(Format.get_symbolic_output_buffer t.res) ;
|
||||
ignore
|
||||
@ -1224,8 +1395,8 @@ let top_panel (t : top) =
|
||||
(Store.Istore.set_exn t.storeview.store
|
||||
~info:(Irmin_unix.info "history")
|
||||
t.path
|
||||
(Panel.str_of_textedit t.te) ) ) ;
|
||||
Zed_edit.clear_data t.te.ze
|
||||
(Panel.Textedit.contents t.te) ) ) ;
|
||||
Panel.Textedit.clear t.te
|
||||
with e ->
|
||||
F.pf ppf "Exception in pane_top//eval@." ;
|
||||
Location.report_exception ppf e ;
|
||||
@ -1238,7 +1409,7 @@ let top_panel (t : top) =
|
||||
t.te.keybind.bindings) ;
|
||||
Panel.(
|
||||
vbox
|
||||
[ textedit t.te
|
||||
[ Textedit.panel t.te
|
||||
; prettyprint (fun pp ->
|
||||
Format.pp_open_hovbox pp 0 ;
|
||||
format_symbolic_output_buffer pp
|
||||
@ -1254,7 +1425,7 @@ let () =
|
||||
(Panel.obox
|
||||
[ Panel.draw (fun (s : Display.state) ->
|
||||
(s, Display.fill_box (Display.gray 0.125) s.box) )
|
||||
; Store.editor "../rootstore" (*top_panel top_1*) ] ) in
|
||||
; Store.editor "../rootstore" ] ) in
|
||||
Display.(run (make_frame ~title:"hi" ~w:1440 ~h:900 ()) actor) ()
|
||||
|
||||
(* Implement the "window management" as just toplevel defined functions that manipulate the window tree *)
|
||||
|
||||
Reference in New Issue
Block a user