summaryrefslogtreecommitdiff
path: root/lib/zipper.ml
diff options
context:
space:
mode:
Diffstat (limited to 'lib/zipper.ml')
-rw-r--r--lib/zipper.ml96
1 files changed, 42 insertions, 54 deletions
diff --git a/lib/zipper.ml b/lib/zipper.ml
index 9313518..202f6d4 100644
--- a/lib/zipper.ml
+++ b/lib/zipper.ml
@@ -2,28 +2,14 @@
2 2
3open Base 3open Base
4 4
5type !+'a zipper = { 5type !+'a zipper = { pos : int; before : 'a Sequence.t; after : 'a Sequence.t }
6 pos : int;
7 popped : 'a Sequence.t;
8 before : 'a Sequence.t;
9 after : 'a Sequence.t;
10}
11
12type !+'a t = 'a zipper 6type !+'a t = 'a zipper
13 7
14let empty = 8let empty = { pos = 0; before = Sequence.empty; after = Sequence.empty }
15 {
16 pos = 0;
17 popped = Sequence.empty;
18 before = Sequence.empty;
19 after = Sequence.empty;
20 }
21
22let before z = z.before 9let before z = z.before
23let after z = z.after 10let after z = z.after
24let focus z = after z |> Sequence.next |> Option.map ~f:fst 11let focus z = after z |> Sequence.next |> Option.map ~f:fst
25let focus_or z ~default = Option.value ~default (focus z) 12let focus_or ~default z = Option.value ~default (focus z)
26let history z = z.popped
27let is_far_left z = before z |> Sequence.is_empty 13let is_far_left z = before z |> Sequence.is_empty
28let is_far_right z = after z |> Sequence.is_empty 14let is_far_right z = after z |> Sequence.is_empty
29let is_empty z = is_far_left z && is_far_right z 15let is_empty z = is_far_left z && is_far_right z
@@ -35,12 +21,7 @@ let left z =
35 match Sequence.next z.before with 21 match Sequence.next z.before with
36 | None -> z 22 | None -> z
37 | Some (h, t) -> 23 | Some (h, t) ->
38 { 24 { pos = z.pos - 1; before = t; after = Sequence.shift_right z.after h }
39 z with
40 pos = z.pos - 1;
41 before = t;
42 after = Sequence.shift_right z.after h;
43 }
44 25
45let rec left_while f z = 26let rec left_while f z =
46 if (not (is_far_left z)) && Option.(focus z |> map ~f |> value ~default:false) 27 if (not (is_far_left z)) && Option.(focus z |> map ~f |> value ~default:false)
@@ -53,12 +34,7 @@ let right z =
53 match Sequence.next z.after with 34 match Sequence.next z.after with
54 | None -> z 35 | None -> z
55 | Some (h, t) -> 36 | Some (h, t) ->
56 { 37 { pos = z.pos + 1; before = Sequence.shift_right z.before h; after = t }
57 z with
58 pos = z.pos + 1;
59 before = Sequence.shift_right z.before h;
60 after = t;
61 }
62 38
63let rec right_while f z = 39let rec right_while f z =
64 if 40 if
@@ -73,34 +49,46 @@ let goto n z =
73 let step = if n < 0 then left else right in 49 let step = if n < 0 then left else right in
74 Fn.apply_n_times ~n:(abs n) step z 50 Fn.apply_n_times ~n:(abs n) step z
75 51
76let pop_after z = { z with after = Sequence.drop_eagerly z.after 1 } 52let pop ?(n = 1) z = { z with after = Sequence.drop_eagerly z.after n }
77let pop_before z = if is_far_left z then z else z |> left |> pop_after 53
78let pop = pop_before 54let pop_before ?(n = 1) =
79let push_after x z = { z with after = Sequence.shift_right z.after x } 55 let rec aux m z =
56 if m < n && not (is_far_left z) then aux (m + 1) (left z) else pop ~n:m z
57 in
58 aux 0
59
60let pop_after ?(n = 1) z =
61 if right_length z < 2 then z else right z |> pop ~n |> left
62
63let push x z = { z with after = Sequence.shift_right z.after x }
64let push_after x z = right z |> push x |> left
80 65
81let push_before x z = 66let push_before x z =
82 { z with pos = z.pos + 1; before = Sequence.shift_right z.before x } 67 { z with pos = z.pos + 1; before = Sequence.shift_right z.before x }
83 68
84let push = push_before
85
86let split z = 69let split z =
87 ( { z with after = Sequence.empty }, 70 ( { z with after = Sequence.empty },
88 { z with pos = 0; before = Sequence.empty } ) 71 { z with pos = 0; before = Sequence.empty } )
89 72
90let join z1 z2 = { z1 with after = z2.after } 73let join z1 ~z2 =
91let iter_before f z = Sequence.iter ~f z.before 74 let z1 = far_right z1 and z2 = far_left z2 in
92let iter_after f z = Sequence.iter ~f z.after 75 { z1 with after = z2.after }
76
77let iter_left f z = Sequence.iter ~f z.before
78let iter_right f z = Sequence.iter ~f z.after
93 79
94let iter f z = 80let iter f z =
95 iter_before f z; 81 iter_left f z;
96 iter_after f z 82 iter_right f z
97 83
98let for_all f z = Sequence.(for_all ~f z.before && for_all ~f z.after) 84let for_all f z = Sequence.(for_all ~f z.before && for_all ~f z.after)
99let exists f z = Sequence.(exists ~f z.before || exists ~f z.after) 85let exists f z = Sequence.(exists ~f z.before || exists ~f z.after)
100let find_before f z = Sequence.find ~f z.before 86let find_left f z = Sequence.find ~f z.before
101let find_after f z = Sequence.find ~f z.after 87let find_right f z = Sequence.find ~f z.after
102let map_before f z = { z with before = Sequence.map ~f z.before } 88let apply_focus f z = Option.map ~f (focus z)
103let map_after f z = { z with after = Sequence.map ~f z.after } 89let apply_focus_or ~default f z = Option.value ~default (apply_focus f z)
90let map_left f z = { z with before = Sequence.map ~f z.before }
91let map_right f z = { z with after = Sequence.map ~f z.after }
104 92
105let map_focus f z = 93let map_focus f z =
106 match Sequence.next z.after with 94 match Sequence.next z.after with
@@ -115,8 +103,8 @@ let map_focus_or ~default f z =
115let map f z = 103let map f z =
116 { z with before = Sequence.map ~f z.before; after = Sequence.map ~f z.after } 104 { z with before = Sequence.map ~f z.before; after = Sequence.map ~f z.after }
117 105
118let mapi_before f z = { z with before = Sequence.mapi ~f z.before } 106let mapi_left f z = { z with before = Sequence.mapi ~f z.before }
119let mapi_after f z = { z with after = Sequence.mapi ~f z.after } 107let mapi_right f z = { z with after = Sequence.mapi ~f z.after }
120 108
121let mapi f z = 109let mapi f z =
122 { 110 {
@@ -125,13 +113,13 @@ let mapi f z =
125 after = Sequence.mapi ~f z.after; 113 after = Sequence.mapi ~f z.after;
126 } 114 }
127 115
128let filter_before f z = { z with before = Sequence.filter ~f z.before } 116let filter_left f z = { z with before = Sequence.filter ~f z.before }
129let filter_after f z = { z with after = Sequence.filter ~f z.after } 117let filter_right f z = { z with after = Sequence.filter ~f z.after }
130let filter p z = z |> filter_before p |> filter_after p 118let filter p z = z |> filter_left p |> filter_right p
131let context_before n z = { z with before = Sequence.take z.before n } 119let context_left n z = { z with before = Sequence.take z.before n }
132let context_after n z = { z with after = Sequence.take z.after n } 120let context_right n z = { z with after = Sequence.take z.after n }
133let context ~b ?(a = b) z = z |> context_before b |> context_after a 121let context ~l ?(r = l) z = z |> context_left l |> context_right r
134let clear_history z = { z with popped = Sequence.empty } 122let swap_focus a = map_focus (Fn.const a)
135let of_seq s = { empty with after = s } 123let of_seq s = { empty with after = s }
136let to_seq z = z |> far_left |> after 124let to_seq z = z |> far_left |> after
137let window ~from ~len z = goto from z |> context_after len |> after 125let window ~from ~len z = goto from z |> context_right len |> after