package miaou-core

  1. Overview
  2. Docs
Miaou core/widgets (no drivers, no SDL)

Install

dune-project
 Dependency

Authors

Maintainers

Sources

v0.5.2.tar.gz
md5=60a3b9f181f24572a06a9492532bfdda
sha512=fcc35a275066be2900e6201782faf47503076fa4640f08cf78067835a6f447b74613009e55b2ac799adb7ca46f1bffa261fc5971753f2cc3c6bef327511c7ef6

doc/src/miaou-core.core/tui_capture.ml.html

Source file tui_capture.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
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
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
(*****************************************************************************)
(*                                                                           *)
(* SPDX-License-Identifier: MIT                                              *)
(* Copyright (c) 2025 Nomadic Labs <contact@nomadic-labs.com>                *)
(*                                                                           *)
(*****************************************************************************)

open Printf

let truthy value =
  let normalized = String.lowercase_ascii (String.trim value) in
  match normalized with "" | "0" | "false" | "off" | "no" -> false | _ -> true

let default_capture_dir () =
  match Sys.getenv_opt "MIAOU_DEBUG_CAPTURE_DIR" with
  | Some dir when String.trim dir <> "" -> dir
  | _ -> ( try Sys.getcwd () with _ -> Filename.get_temp_dir_name ())

let timestamp_suffix () =
  let tm = Unix.localtime (Unix.time ()) in
  sprintf
    "%04d%02d%02d-%02d%02d%02d"
    (tm.Unix.tm_year + 1900)
    (tm.Unix.tm_mon + 1)
    tm.Unix.tm_mday
    tm.Unix.tm_hour
    tm.Unix.tm_min
    tm.Unix.tm_sec

let rec ensure_dir path =
  if path = "" || path = "." then ()
  else if Sys.file_exists path then ()
  else
    let parent = Filename.dirname path in
    if parent = path then ()
    else (
      ensure_dir parent ;
      try Unix.mkdir path 0o755 with
      | Unix.Unix_error (Unix.EEXIST, _, _) -> ()
      | _ -> ())

type writer = {oc : out_channel}

type writer_state = Uninitialized | Active of writer | Disabled

let keystroke_writer : writer_state ref = ref Uninitialized

let frame_writer : writer_state ref = ref Uninitialized

let writer_mutex = Mutex.create ()

let close_writer_opt slot =
  Mutex.lock writer_mutex ;
  (match !slot with
  | Active w ->
      (try close_out w.oc with _ -> ()) ;
      slot := Uninitialized
  | _ -> ()) ;
  Mutex.unlock writer_mutex

let () =
  at_exit (fun () ->
      close_writer_opt keystroke_writer ;
      close_writer_opt frame_writer)

let open_writer kind path =
  try
    let dir = Filename.dirname path in
    if dir <> path && dir <> "" then ensure_dir dir ;
    let oc =
      open_out_gen [Open_wronly; Open_creat; Open_append; Open_text] 0o644 path
    in
    fprintf stderr "[miaou][capture] %s -> %s\n%!" kind path ;
    Some {oc}
  with exn ->
    fprintf
      stderr
      "[miaou][capture] failed to open %s (%s): %s\n%!"
      kind
      path
      (Printexc.to_string exn) ;
    None

let resolve_path kind path_env =
  match Sys.getenv_opt path_env with
  | Some path when String.trim path <> "" -> path
  | _ ->
      let dir = default_capture_dir () in
      Filename.concat
        dir
        (sprintf "miaou_tui_%s_%s.jsonl" kind (timestamp_suffix ()))

let writer_enabled flag_env path_env =
  match (Sys.getenv_opt flag_env, Sys.getenv_opt path_env) with
  | None, None -> false
  | Some flag, _ -> truthy flag
  | None, Some path -> String.trim path <> ""

let create_writer ~kind ~flag_env ~path_env =
  if writer_enabled flag_env path_env then
    let path = resolve_path kind path_env in
    open_writer kind path
  else None

let ensure_writer slot create =
  match !slot with
  | Active w -> Some w
  | Disabled -> None
  | Uninitialized -> (
      Mutex.lock writer_mutex ;
      match !slot with
      | Active w ->
          Mutex.unlock writer_mutex ;
          Some w
      | Disabled ->
          Mutex.unlock writer_mutex ;
          None
      | Uninitialized -> (
          match create () with
          | Some w ->
              slot := Active w ;
              Mutex.unlock writer_mutex ;
              Some w
          | None ->
              slot := Disabled ;
              Mutex.unlock writer_mutex ;
              None))

let record_keystroke key =
  match
    ensure_writer keystroke_writer (fun () ->
        create_writer
          ~kind:"keystrokes"
          ~flag_env:"MIAOU_DEBUG_KEYSTROKE_CAPTURE"
          ~path_env:"MIAOU_DEBUG_KEYSTROKE_CAPTURE_PATH")
  with
  | None -> ()
  | Some w -> (
      try
        fprintf
          w.oc
          "{\"timestamp\": %.6f, \"key\": %S}\n"
          (Unix.gettimeofday ())
          key ;
        flush w.oc
      with _ -> ())

let record_frame ~rows ~cols frame =
  match
    ensure_writer frame_writer (fun () ->
        create_writer
          ~kind:"frames"
          ~flag_env:"MIAOU_DEBUG_FRAME_CAPTURE"
          ~path_env:"MIAOU_DEBUG_FRAME_CAPTURE_PATH")
  with
  | None -> ()
  | Some w -> (
      try
        fprintf
          w.oc
          "{\"timestamp\": %.6f, \"size\": {\"rows\": %d, \"cols\": %d}, \
           \"frame\": %S}\n"
          (Unix.gettimeofday ())
          rows
          cols
          frame ;
        flush w.oc
      with _ -> ())

let reset_for_tests () =
  close_writer_opt keystroke_writer ;
  close_writer_opt frame_writer