package bonsai

  1. Overview
  2. Docs
Legend:
Page
Library
Module
Module type
Parameter
Class
Class type
Source

Source file focus_ring.ml

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
open! Core

type 'a t =
  { current_focus : 'a
  ; before_rev    : 'a list
  ; after         : 'a list
  }
[@@deriving fields, compare, equal, sexp]

let of_nonempty_list_exn full_list =
  { current_focus = List.hd_exn full_list
  ; before_rev    = []
  ; after         = List.tl_exn full_list
  }
;;

let next t =
  match t.after with
  | next :: rest ->
    { current_focus = next; before_rev = t.current_focus :: t.before_rev; after = rest }
  | [] ->
    let full_list = List.rev (t.current_focus :: t.before_rev) in
    { current_focus = List.hd_exn full_list
    ; before_rev    = []
    ; after         = List.tl_exn full_list
    }
;;

let prev t =
  match t.before_rev with
  | prev :: rest ->
    { current_focus = prev; before_rev = rest; after = t.current_focus :: t.after }
  | [] ->
    let full_list_rev = List.rev (t.current_focus :: t.after) in
    { current_focus = List.hd_exn full_list_rev
    ; before_rev    = List.tl_exn full_list_rev
    ; after         = []
    }
;;

let set t ~f =
  let full_list     = List.rev_append  t.before_rev (t.current_focus :: t.after) in
  let before, after = List.split_while full_list    ~f:(fun a -> not (f a))      in
  match after with
  | []             -> None
  | focus :: after -> Some { current_focus = focus; before_rev = List.rev before; after }
;;

let%expect_test _ =
  let t = ref (of_nonempty_list_exn [ 1; 2; 3; 4 ]) in
  let move f =
    t := f !t;
    print_s [%sexp (!t : int t)]
  in
  print_s [%sexp (!t : int t)];
  [%expect {| ((current_focus 1) (before_rev ()) (after (2 3 4))) |}];
  move next;
  [%expect {| ((current_focus 2) (before_rev (1)) (after (3 4))) |}];
  move next;
  [%expect {| ((current_focus 3) (before_rev (2 1)) (after (4))) |}];
  move next;
  [%expect {| ((current_focus 4) (before_rev (3 2 1)) (after ())) |}];
  move next;
  [%expect {| ((current_focus 1) (before_rev ()) (after (2 3 4))) |}];
  move next;
  [%expect {| ((current_focus 2) (before_rev (1)) (after (3 4))) |}];
  move prev;
  [%expect {| ((current_focus 1) (before_rev ()) (after (2 3 4))) |}];
  move prev;
  [%expect {| ((current_focus 4) (before_rev (3 2 1)) (after ())) |}];
  move prev;
  [%expect {| ((current_focus 3) (before_rev (2 1)) (after (4))) |}];
  move (fun t -> Option.value_exn (set t ~f:(fun a -> Int.equal a 1)));
  [%expect {| ((current_focus 1) (before_rev ()) (after (2 3 4))) |}];
  move (fun t -> Option.value_exn (set t ~f:(fun a -> Int.equal a 3)));
  [%expect {| ((current_focus 3) (before_rev (2 1)) (after (4))) |}]
;;
OCaml

Innovation. Community. Security.