【Q】fd, channel, flush & buffer

Hello! Thanks to you guys’ support, I’m getting more and more comfortable with coding in OCaml!

I need to copy & paste text from raw PDF files for my homework; you might already know that when you do that, random newlines (\n) will be there in the string buffer. I wrote simple Python script to deal with this situation before, and now I’m moving to OCaml.

let () = print_endline "Removing NEWLINE from clipboard..."

(* *)
let run (cmd: string) =
    let fd = Unix.open_process_in cmd in
    let () = print_endline "running command" in
    let text = In_channel.input_all fd in
    let _ = Unix.close_process_in fd in
    text

let remove_newline str: string =
    str
    |> String.map
       @@ fun c -> if c = '\n' then ' ' else c

let () =
    let () = print_endline "initializing main" in
    let global_buffer: string ref = ref "(empty)" in
    while true do
        let () = Unix.sleep 1 in
        run "pbpaste"
        |> remove_newline
        |> fun str ->
                if str = !global_buffer then ()
                else let () = global_buffer := str in
                Printf.printf "<><><>New<><><>\n%s\n" !global_buffer
    done

Note the run cmd: string function; after opening a subprocess with Unix.open_process, I found that I have to add a print_endline to print something to the console, or the program seems to stuck and have 0 output.

I’m 66.66% sure that this is something related to buffer / tty / flush() but don’t exactly know the details and real reason behind it. Can some explain? Thanks :3 :3 :3

Indeed, you need to flush the standard output after printing there. You can do this by calling flush stdout, or indeed print_endline (which includes a flush) if you know that you want a newline anyway, or by using the %! format specifier in a printf format string (it takes no argument and just flushes), so in your code for example %s\n%! would do.

1 Like