From af0cd851fec5038faff5a8133cadad6c65568374 Mon Sep 17 00:00:00 2001 From: Federico Igne Date: Wed, 24 Jan 2024 21:14:11 +0100 Subject: feat: add ability to paste text from a register Register are simplier than Vim register, in particular no register is local to buffers. --- lib/editorBuffer.ml | 55 ++++++++++++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 52 insertions(+), 3 deletions(-) (limited to 'lib/editorBuffer.ml') diff --git a/lib/editorBuffer.ml b/lib/editorBuffer.ml index c492b8b..295e6e7 100644 --- a/lib/editorBuffer.ml +++ b/lib/editorBuffer.ml @@ -61,12 +61,22 @@ module Action = struct (* let on_content_stored ?(register = '"') ?(append = false) f b = ... *) - let update_render_at_cursor b = + let update_render ?(before = false) ~n b = match b.content with | Error _ -> b | Ok c -> - let l = apply_focus_or ~default:Sequence.empty (to_seq &> render) c in - { b with rendered = swap_focus l b.rendered } + let step = if before then left else right in + let rec aux i r c = + if i = 0 then r + else + let default = Sequence.empty in + let l = apply_focus_or ~default (to_seq &> render) c in + let c' = step c and r' = swap_focus l r |> step in + aux (i - 1) r' c' + in + { b with rendered = aux n b.rendered c |> goto (left_length c) } + + let update_render_at_cursor = update_render ~n:1 let move_up ?(n = 1) = let change_content = @@ -218,6 +228,45 @@ module Action = struct in change_content &> change_rendered &> update_render_at_cursor + let paste ?(before = false) ?(linewise = false) ?(n = 1) s = + let change_content = + if linewise then + let push = if before then push_before_seq else push_after_seq in + push (Sequence.map ~f:of_seq s) |> on_content + else + let aux z = + match Sequence.next s with + | None -> z + | Some (h, t) -> + let init = + let default = Zipper.(of_seq h |> far_right) in + map_focus_or ~default (push_before_seq h) z + and f z l = + let default = (Zipper.empty, Zipper.empty) in + let z1, z2 = apply_focus_or ~default split z in + z |> push_before z1 |> swap_focus z2 + |> map_focus (push_before_seq l) + in + let folded = Sequence.fold ~init ~f t in + if before then folded + else + folded + |> Fn.apply_n_times ~n:(Sequence.length t) left + |> map_focus (Fn.apply_n_times ~n:(Sequence.length h) left) + in + on_content aux + and change_rendered = + if linewise then + let push = if before then push_before_seq else push_after_seq in + push (Sequence.map ~f:render s) |> on_rendered + else + let len = Sequence.length s in + let push = if before then push_before else push in + let aux z = Fn.apply_n_times ~n:(len - 1) (push Sequence.empty) z in + on_rendered aux &> update_render ~before ~n:len + in + Fn.apply_n_times ~n (change_content &> change_rendered) + (* let save_history_to ?(clear = true) r = () *) end -- cgit v1.2.3