From 05e1cc51b2fb0824580925b55319377305105c44 Mon Sep 17 00:00:00 2001 From: Federico Igne Date: Sun, 28 Jan 2024 23:40:30 +0100 Subject: feat(zipper): add option to not move past last element when moving right --- lib/zipper.ml | 24 +++++++++++++++--------- 1 file changed, 15 insertions(+), 9 deletions(-) (limited to 'lib/zipper.ml') diff --git a/lib/zipper.ml b/lib/zipper.ml index 5f3b37a..6077f21 100644 --- a/lib/zipper.ml +++ b/lib/zipper.ml @@ -1,4 +1,4 @@ -(* Module [Zipper]: functional zippers *) +(* Module [Zipper]: functional linear zippers *) open Base @@ -11,7 +11,10 @@ let after z = z.after let focus z = after z |> Sequence.next |> Option.map ~f:fst let focus_or ~default z = Option.value ~default (focus z) let is_far_left z = before z |> Sequence.is_empty -let is_far_right z = after z |> Sequence.is_empty + +let is_far_right ?(by_one = false) z = + after z |> Sequence.length_is_bounded_by ~max:(if by_one then 1 else 0) + let is_empty z = is_far_left z && is_far_right z let left_length z = z.pos let right_length z = after z |> Sequence.length @@ -30,23 +33,26 @@ let rec left_while f z = let rec far_left z = if is_far_left z then z else z |> left |> far_left -let right z = +let right ?(by_one = false) z = match Sequence.next z.after with | None -> z + | Some (_, t) when by_one && Sequence.is_empty t -> z | Some (h, t) -> { pos = z.pos + 1; before = Sequence.shift_right z.before h; after = t } -let rec right_while f z = +let rec right_while ?(by_one = false) f z = if - (not (is_far_right z)) && Option.(focus z |> map ~f |> value ~default:false) - then right z |> right_while f + (not (is_far_right ~by_one z)) + && Option.(focus z |> map ~f |> value ~default:false) + then right z |> right_while ~by_one f else z -let rec far_right z = if is_far_right z then z else z |> right |> far_right +let rec far_right ?(by_one = false) z = + if is_far_right ~by_one z then z else z |> right |> far_right ~by_one -let goto n z = +let goto ?(by_one = false) n z = let n = n - z.pos in - let step = if n < 0 then left else right in + let step = if n < 0 then left else right ~by_one in Fn.apply_n_times ~n:(abs n) step z let pop ?(n = 1) z = -- cgit v1.2.3