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
let stdin_fd = Unix.descr_of_in_channel stdin
let decoder = Uutf.decoder ~encoding:`UTF_8 `Manual
let set_raw_mode () =
let termios = Unix.tcgetattr stdin_fd in
let new_termios =
Unix.
{ termios with c_icanon = false; c_echo = false; c_vmin = 1; c_vtime = 0 }
in
Unix.tcsetattr stdin_fd TCSANOW new_termios;
termios
let restore_mode termios = Unix.tcsetattr stdin_fd TCSANOW termios
let try_read () =
let bytes = Bytes.create 8 in
match Unix.read stdin_fd bytes 0 8 with
| exception Unix.(Unix_error ((EINTR | EAGAIN | EWOULDBLOCK), _, _)) -> ()
| len -> Uutf.Manual.src decoder bytes 0 len
let uchar_to_str u =
let buf = Buffer.create 8 in
Uutf.Buffer.add_utf_8 buf u;
Buffer.contents buf
let read_utf8 () =
match Uutf.decode decoder with
| `Uchar u -> `Read (uchar_to_str u)
| `End -> `End
| `Await ->
try_read ();
`Retry
| `Malformed err -> `Malformed err
let setup () =
Unix.set_nonblock stdin_fd;
set_raw_mode ()
let shutdown termios = restore_mode termios