Source file private_mode.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
open! Core

type action =
  | Set
  | Reset
[@@deriving compare ~localize, equal ~localize, quickcheck, sexp]

type t =
  { modes : int list
  ; action : action
  }
[@@deriving compare ~localize, equal ~localize, quickcheck, sexp]

let quickcheck_generator =
  let open Base_quickcheck.Generator.Let_syntax in
  let%bind modes = List.quickcheck_generator (Int.gen_incl 1 9999) in
  let modes = if List.is_empty modes then [ 1 ] else modes in
  let%bind action = [%quickcheck.generator: action] in
  return { modes; action }
;;

let of_csi_params params ~terminal =
  let action =
    match terminal with
    | 'h' -> Some Set
    | 'l' -> Some Reset
    | _ -> None
  in
  let modes = List.filter_opt params in
  match action with
  | Some action when not (List.is_empty modes) -> Some { modes; action }
  | _ -> None
;;

let alternate_screen_modes = [ 47; 1049 ]

let is_alternate_screen t =
  List.exists t.modes ~f:(fun mode ->
    List.mem alternate_screen_modes mode ~equal:Int.equal)
;;

let to_string { modes; action } =
  let modes_str = List.map modes ~f:Int.to_string |> String.concat ~sep:";" in
  let action_char =
    match action with
    | Set -> 'h'
    | Reset -> 'l'
  in
  sprintf "\027[?%s%c" modes_str action_char
;;

let to_string_hum { modes; action } =
  let modes_str = List.map modes ~f:Int.to_string |> String.concat ~sep:";" in
  let action_str =
    match action with
    | Set -> "set"
    | Reset -> "reset"
  in
  sprintf "(PrivateMode:%s:%s)" action_str modes_str
;;