`Unix.sleep` on windows box?

Testing the ANSITerminal library and trying to build a progress bar, I am trying to slow down a bit the progression of the bar in order to emulate an heavy process with the sleep command. It does not work at all. Compilation is ok but launching the executable results in nothing happening. Without the sleep command my test runs though, but way too fast (I can see the progress bar at the end). Is the sleep function of the Unix module available on windows setup ?

I have ocaml version 4.14.0 on windows 10

Any help/hint would be welcome

open ANSITerminal

let rec bar n = 
  if n < 1 then "" 
  else "\u{258A}" ^ (bar (n-1)) 

let progress n percent = 
  let taille = int_of_float (percent *. (float_of_int n)) in 
  bar taille


let () = 
  for i = 1 to 100 do
    ANSITerminal.erase Above;
    ANSITerminal.printf [yellow] "%s" (progress 50 ((float_of_int i) /. 100.0));
    Unix.sleep 1
  done

Yes, Unix.sleep works under Windows.

Naïve question/suggestion: have you tried flushing after every printf?

Cheers,
Nicolas

Looks good because when I remove the ANSITerminal.erase above the sleep works.
But flushing after every printf did not work:

ANSITerminal.printf [yellow] "%s\n" (progress 50 ((float_of_int i) /. 100.0));
ANSITerminal.printf [yellow] "%s%!" (progress 50 ((float_of_int i) /. 100.0));
ANSITerminal.printf [yellow] "%s" (progress 50 ((float_of_int i) /. 100.0));flush stdout;

none of these worked.

What happens if you run this:

let () =
  Unix.sleep 10;
  print_endline "Slept for 10s"

Just this by itself, not as part of any project.

It sleeps for 10 seconds and print “Slept for 10s” …If I copy and paste it within my project. Though in utop it says "Reference to undefined global ‘Unix’

The sleep function works well if I remove the erase Above part. I suspect an issue with flushing not at the right time but I am also surprised by the speed of the program (it ends immediatly) without outputing anything whereas I was at least expecting 100 seconds before ending.

You have to start utop with utop -require unix

The code is segfaulting in ANSITerminal.erase (which is why it exits immediately). A quick glance at the source of ANSITerminal revealed the problem, a NULL pointer was being passed to the system call GetConsoleScreenBufferInfo. The following diff should be enough to fix the problem:

diff --git a/src/ANSITerminal_win_stubs.c b/src/ANSITerminal_win_stubs.c
index dd34e61..8ad3247 100644
--- a/src/ANSITerminal_win_stubs.c
+++ b/src/ANSITerminal_win_stubs.c
@@ -99,6 +99,7 @@ void exn_of_error(char *fname, BOOL cond)
 
 #define SET_CSBI(fname)                                               \
   if (! csbiInfo) {                                                   \
+    csbiInfo = caml_stat_alloc(sizeof(CONSOLE_SCREEN_BUFFER_INFO));   \
     hStdout = GetStdHandle(STD_OUTPUT_HANDLE);                        \
     if (hStdout == INVALID_HANDLE_VALUE) {                            \
       raise_error(fname, "Invalid stdout handle");                    \

cc @Chris00

Cheers,
Nicolas

1 Like

Thanks for checking. I use “\r” in the mean time.