summaryrefslogtreecommitdiff
path: root/lib/editorBuffer.ml
diff options
context:
space:
mode:
authorFederico Igne <undyamon@disroot.org>2024-01-28 01:22:52 +0100
committerFederico Igne <undyamon@disroot.org>2024-01-28 01:22:52 +0100
commit53916fc3f7dcbefd90e3d0340a2a8f32bf331d1d (patch)
treebaf9b5d6bdfdc77d0338e230adf64f7f52aefa4e /lib/editorBuffer.ml
parent722a3d4d2d0d0630f57cfbfdddc229dee341505b (diff)
downloadsandy-53916fc3f7dcbefd90e3d0340a2a8f32bf331d1d.tar.gz
sandy-53916fc3f7dcbefd90e3d0340a2a8f32bf331d1d.zip
feat: add plain search functionality (with history)
Diffstat (limited to 'lib/editorBuffer.ml')
-rw-r--r--lib/editorBuffer.ml60
1 files changed, 58 insertions, 2 deletions
diff --git a/lib/editorBuffer.ml b/lib/editorBuffer.ml
index 52b1115..1f363ef 100644
--- a/lib/editorBuffer.ml
+++ b/lib/editorBuffer.ml
@@ -88,8 +88,10 @@ module Action = struct
88 let ( let+ ) b f = map b ~f 88 let ( let+ ) b f = map b ~f
89 let get b = (b, b) 89 let get b = (b, b)
90 let put b _ = ((), b) 90 let put b _ = ((), b)
91 let modify ~f = get >>= (put &> f) 91 let modify ~f = get >>| f >>= put
92 let on_content f b = ((), { b with content = Result.map ~f b.content }) 92 let get_content b = (b.content, b)
93 let set_content c b = ((), { b with content = c })
94 let on_content f = get_content >>| Result.map ~f >>= set_content
93 95
94 let on_content_with_output ~default f b = 96 let on_content_with_output ~default f b =
95 match b.content with 97 match b.content with
@@ -143,6 +145,11 @@ module Action = struct
143 in 145 in
144 (horizontal left, horizontal right) 146 (horizontal left, horizontal right)
145 147
148 let goto r c =
149 let change_content = Zipper.(goto r &> map_focus (goto c)) |> on_content
150 and change_rendered = Zipper.goto r |> on_rendered in
151 change_content *> change_rendered
152
146 let bol ?(n = 0) = move_down ~n *> (map_focus far_left |> on_content) 153 let bol ?(n = 0) = move_down ~n *> (map_focus far_left |> on_content)
147 let eol ?(n = 0) = move_down ~n *> (map_focus far_right |> on_content) 154 let eol ?(n = 0) = move_down ~n *> (map_focus far_right |> on_content)
148 155
@@ -374,6 +381,55 @@ module Action = struct
374 in 381 in
375 bind_n_times ~n (change_content *> change_rendered) 382 bind_n_times ~n (change_content *> change_rendered)
376 383
384 let search forward word =
385 let rec tails s =
386 match Sequence.next s with
387 | None -> Sequence.empty
388 | Some (_, t) -> Sequence.shift_right (tails t) s
389 and prefix p l =
390 match Sequence.(next p, next l) with
391 | Some (ph, pt), Some (lh, lt) when Char.(ph = lh) -> prefix pt lt
392 | None, _ -> true
393 | _ -> false
394 in
395 let search_line w l =
396 Sequence.findi ~f:(fun _ -> prefix w) (tails l) |> Option.map ~f:fst
397 in
398 let* b = get in
399 let cr, cc = cursor ~rendered:false b in
400 let* c = get_content in
401 match c with
402 | Error _ -> return None
403 | Ok c -> (
404 if forward then
405 match Sequence.next (Zipper.after c) with
406 | None -> return None
407 | Some (h, t) -> (
408 match Zipper.(h |> right |> after) |> search_line word with
409 | Some i -> return (Some (cr, cc + i + 1))
410 | None ->
411 let f r z =
412 z |> to_seq |> search_line word
413 |> Option.map ~f:(fun c -> (cr + r + 1, c))
414 in
415 return (Sequence.find_mapi t ~f))
416 else
417 let word = Sequence.(word |> to_list_rev |> of_list) in
418 let wlen = Sequence.length word in
419 match Zipper.(c |> right |> before) |> Sequence.next with
420 | None -> return None
421 | Some (h, t) -> (
422 match h |> Zipper.before |> search_line word with
423 | Some i -> return (Some (cr, cc - wlen - i))
424 | None ->
425 let f r z =
426 let z = z |> far_right in
427 let len = left_length z in
428 z |> before |> search_line word
429 |> Option.map ~f:(fun c -> (cr - r - 1, len - wlen - c))
430 in
431 return (Sequence.find_mapi t ~f)))
432
377 (* let save_history_to ?(clear = true) r = () *) 433 (* let save_history_to ?(clear = true) r = () *)
378end 434end
379 435