diff options
Diffstat (limited to 'lib/zipper.ml')
-rw-r--r-- | lib/zipper.ml | 96 |
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 | ||
3 | open Base | 3 | open Base |
4 | 4 | ||
5 | type !+'a zipper = { | 5 | type !+'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 | |||
12 | type !+'a t = 'a zipper | 6 | type !+'a t = 'a zipper |
13 | 7 | ||
14 | let empty = | 8 | let 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 | |||
22 | let before z = z.before | 9 | let before z = z.before |
23 | let after z = z.after | 10 | let after z = z.after |
24 | let focus z = after z |> Sequence.next |> Option.map ~f:fst | 11 | let focus z = after z |> Sequence.next |> Option.map ~f:fst |
25 | let focus_or z ~default = Option.value ~default (focus z) | 12 | let focus_or ~default z = Option.value ~default (focus z) |
26 | let history z = z.popped | ||
27 | let is_far_left z = before z |> Sequence.is_empty | 13 | let is_far_left z = before z |> Sequence.is_empty |
28 | let is_far_right z = after z |> Sequence.is_empty | 14 | let is_far_right z = after z |> Sequence.is_empty |
29 | let is_empty z = is_far_left z && is_far_right z | 15 | let 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 | ||
45 | let rec left_while f z = | 26 | let 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 | ||
63 | let rec right_while f z = | 39 | let 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 | ||
76 | let pop_after z = { z with after = Sequence.drop_eagerly z.after 1 } | 52 | let pop ?(n = 1) z = { z with after = Sequence.drop_eagerly z.after n } |
77 | let pop_before z = if is_far_left z then z else z |> left |> pop_after | 53 | |
78 | let pop = pop_before | 54 | let pop_before ?(n = 1) = |
79 | let 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 | |||
60 | let pop_after ?(n = 1) z = | ||
61 | if right_length z < 2 then z else right z |> pop ~n |> left | ||
62 | |||
63 | let push x z = { z with after = Sequence.shift_right z.after x } | ||
64 | let push_after x z = right z |> push x |> left | ||
80 | 65 | ||
81 | let push_before x z = | 66 | let 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 | ||
84 | let push = push_before | ||
85 | |||
86 | let split z = | 69 | let 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 | ||
90 | let join z1 z2 = { z1 with after = z2.after } | 73 | let join z1 ~z2 = |
91 | let iter_before f z = Sequence.iter ~f z.before | 74 | let z1 = far_right z1 and z2 = far_left z2 in |
92 | let iter_after f z = Sequence.iter ~f z.after | 75 | { z1 with after = z2.after } |
76 | |||
77 | let iter_left f z = Sequence.iter ~f z.before | ||
78 | let iter_right f z = Sequence.iter ~f z.after | ||
93 | 79 | ||
94 | let iter f z = | 80 | let 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 | ||
98 | let for_all f z = Sequence.(for_all ~f z.before && for_all ~f z.after) | 84 | let for_all f z = Sequence.(for_all ~f z.before && for_all ~f z.after) |
99 | let exists f z = Sequence.(exists ~f z.before || exists ~f z.after) | 85 | let exists f z = Sequence.(exists ~f z.before || exists ~f z.after) |
100 | let find_before f z = Sequence.find ~f z.before | 86 | let find_left f z = Sequence.find ~f z.before |
101 | let find_after f z = Sequence.find ~f z.after | 87 | let find_right f z = Sequence.find ~f z.after |
102 | let map_before f z = { z with before = Sequence.map ~f z.before } | 88 | let apply_focus f z = Option.map ~f (focus z) |
103 | let map_after f z = { z with after = Sequence.map ~f z.after } | 89 | let apply_focus_or ~default f z = Option.value ~default (apply_focus f z) |
90 | let map_left f z = { z with before = Sequence.map ~f z.before } | ||
91 | let map_right f z = { z with after = Sequence.map ~f z.after } | ||
104 | 92 | ||
105 | let map_focus f z = | 93 | let 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 = | |||
115 | let map f z = | 103 | let 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 | ||
118 | let mapi_before f z = { z with before = Sequence.mapi ~f z.before } | 106 | let mapi_left f z = { z with before = Sequence.mapi ~f z.before } |
119 | let mapi_after f z = { z with after = Sequence.mapi ~f z.after } | 107 | let mapi_right f z = { z with after = Sequence.mapi ~f z.after } |
120 | 108 | ||
121 | let mapi f z = | 109 | let 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 | ||
128 | let filter_before f z = { z with before = Sequence.filter ~f z.before } | 116 | let filter_left f z = { z with before = Sequence.filter ~f z.before } |
129 | let filter_after f z = { z with after = Sequence.filter ~f z.after } | 117 | let filter_right f z = { z with after = Sequence.filter ~f z.after } |
130 | let filter p z = z |> filter_before p |> filter_after p | 118 | let filter p z = z |> filter_left p |> filter_right p |
131 | let context_before n z = { z with before = Sequence.take z.before n } | 119 | let context_left n z = { z with before = Sequence.take z.before n } |
132 | let context_after n z = { z with after = Sequence.take z.after n } | 120 | let context_right n z = { z with after = Sequence.take z.after n } |
133 | let context ~b ?(a = b) z = z |> context_before b |> context_after a | 121 | let context ~l ?(r = l) z = z |> context_left l |> context_right r |
134 | let clear_history z = { z with popped = Sequence.empty } | 122 | let swap_focus a = map_focus (Fn.const a) |
135 | let of_seq s = { empty with after = s } | 123 | let of_seq s = { empty with after = s } |
136 | let to_seq z = z |> far_left |> after | 124 | let to_seq z = z |> far_left |> after |
137 | let window ~from ~len z = goto from z |> context_after len |> after | 125 | let window ~from ~len z = goto from z |> context_right len |> after |