blob: 6077f21105e2450b604795457a98a9c97e3da4d7 (
plain) (
blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
|
(* Module [Zipper]: functional linear zippers *)
open Base
type !+'a zipper = { pos : int; before : 'a Sequence.t; after : 'a Sequence.t }
type !+'a t = 'a zipper
let empty = { pos = 0; before = Sequence.empty; after = Sequence.empty }
let before z = z.before
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 ?(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
let length z = left_length z + right_length z
let left z =
match Sequence.next z.before with
| None -> z
| Some (h, t) ->
{ pos = z.pos - 1; before = t; after = Sequence.shift_right z.after h }
let rec left_while f z =
if (not (is_far_left z)) && Option.(focus z |> map ~f |> value ~default:false)
then left z |> left_while f
else z
let rec far_left z = if is_far_left z then z else z |> left |> far_left
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 ?(by_one = false) f z =
if
(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 ?(by_one = false) z =
if is_far_right ~by_one z then z else z |> right |> far_right ~by_one
let goto ?(by_one = false) n z =
let n = n - z.pos 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 =
let a, b = Sequence.split_n z.after n in
(Sequence.of_list a, { z with after = b })
let pop_before ?(n = 1) =
let rec aux m z =
if m < n && not (is_far_left z) then aux (m + 1) (left z) else pop ~n:m z
in
aux 0
let pop_after ?(n = 1) z =
if right_length z < 2 then (Sequence.empty, z)
else
let a, b = right z |> pop ~n in
(a, left b)
let push x z = { z with after = Sequence.shift_right z.after x }
let push_seq s z = { z with after = Sequence.append s z.after }
let push_after x z = right z |> push x |> left
let push_after_seq s z = right z |> push_seq s |> left
let push_before x z =
{ z with pos = z.pos + 1; before = Sequence.shift_right z.before x }
let push_before_seq s z =
let f a e = Sequence.shift_right a e in
{
z with
pos = z.pos + Sequence.length s;
before = Sequence.fold ~init:z.before ~f s;
}
let split z =
( { z with after = Sequence.empty },
{ z with pos = 0; before = Sequence.empty } )
let join z1 ~z2 =
let z1 = far_right z1 and z2 = far_left z2 in
{ z1 with after = z2.after }
let iter_left f z = Sequence.iter ~f z.before
let iter_right f z = Sequence.iter ~f z.after
let iter f z =
iter_left f z;
iter_right f z
let for_all f z = Sequence.(for_all ~f z.before && for_all ~f z.after)
let exists f z = Sequence.(exists ~f z.before || exists ~f z.after)
let find_left f z = Sequence.find ~f z.before
let find_right f z = Sequence.find ~f z.after
let apply_focus f z = Option.map ~f (focus z)
let apply_focus_or ~default f z = Option.value ~default (apply_focus f z)
let map_left f z = { z with before = Sequence.map ~f z.before }
let map_right f z = { z with after = Sequence.map ~f z.after }
let map_focus f z =
match Sequence.next z.after with
| None -> z
| Some (h, t) -> { z with after = Sequence.shift_right t (f h) }
let map_focus_or ~default f z =
match Sequence.next z.after with
| None -> { z with after = Sequence.singleton default }
| Some (h, t) -> { z with after = Sequence.shift_right t (f h) }
let map f z =
{ z with before = Sequence.map ~f z.before; after = Sequence.map ~f z.after }
let mapi_left f z = { z with before = Sequence.mapi ~f z.before }
let mapi_right f z = { z with after = Sequence.mapi ~f z.after }
let mapi f z =
{
z with
before = Sequence.mapi ~f z.before;
after = Sequence.mapi ~f z.after;
}
let filter_left f z = { z with before = Sequence.filter ~f z.before }
let filter_right f z = { z with after = Sequence.filter ~f z.after }
let filter p z = z |> filter_left p |> filter_right p
let context_left n z = { z with before = Sequence.take z.before n }
let context_right n z = { z with after = Sequence.take z.after n }
let context ~l ?(r = l) z = z |> context_left l |> context_right r
let swap_focus a = map_focus_or ~default:a (Fn.const a)
let of_seq s = { empty with after = s }
let to_seq z = z |> far_left |> after
let window ~from ~len z = goto from z |> context_right len |> after
|