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
open Base
let num_cursors = 5
type t =
{ offsets : int option array
; mutable selected : int
}
[@@deriving sexp]
let create () = { offsets = Array.init num_cursors ~f:(Fn.const None); selected = 0 }
let get_offset t = t.offsets.(t.selected)
let get_offset_as_string t = Option.value_map (get_offset t) ~default:"-" ~f:Int.to_string
let set_offset t offset = t.offsets.(t.selected) <- offset
let get_selected t = t.selected
let get_selected_as_string t = Int.to_string (get_selected t + 1)
let get_active_cursors t =
let rec f i =
if i = num_cursors
then []
else (
match t.offsets.(i) with
| Some offset -> offset :: f (i + 1)
| None -> f (i + 1))
in
let unique_cursors = f 0 |> List.dedup_and_sort ~compare:Int.compare in
match get_offset t with
| None -> List.map unique_cursors ~f:(fun c -> `Secondary c)
| Some offset ->
List.map unique_cursors ~f:(fun c -> if c = offset then `Primary c else `Secondary c)
;;
let set_selected t selected =
if selected < 0
then raise_s [%message "Cannot set negative cursor index" (selected : int)];
if selected >= num_cursors
then raise_s [%message "Cursor index out of range" (selected : int) (num_cursors : int)];
t.selected <- selected
;;
let with_selected t ~f =
let selected = get_selected t in
let result = f selected in
set_selected t selected;
result
;;