How to trigger and handle a click event? - ocaml

In the following code, I try to handle a click event on a checkbox. I expect to see the word "hello" printed in the javascript console, but instead I see nothing. How can I modify the code to get the print statement to execute?
let checkGroupByRounds = Dom_html.createInput ~_type:(Js.string "checkbox") doc in
Lwt_js_events.clicks checkGroupByRounds (fun event event_loop ->
Lwt.return (Printf.printf "hello"));
Dom.appendChild container checkGroupByRounds;

You need to flush the standard output with a new line Printf.printf "hello\n" or an explicit flush flush stdout.

Related

In Vim, how to distinguish between a newline `\n` and an empty value returned by the input() function?

I'm writing a custom function within Vim and asking the user to input some info for use:
let x = input('Do input: ')
(update an entry with x)
However, I'd like to distinguish the two different cases:
the user enters an empty value so that the function will clear the previous value of the entry;
the user cancels the input process by pressing ESC.
Is it possible to do this?
If not using input(), what else I can do?
A similar question is here:
Detect when user cancels input field in Vim
But I need a more detailed control.
I tried a bit to experiment with input with the following code:
function! Foo()
let x = input('Do input: ')
execute "normal i".x
echo "Foo called with: ".x
endfunc
command -nargs=0 Foo call Foo()
Here are the following behaviours:
Pressing Return adds in the document the value typed by the user and prints the echo line,
Pressing Escape seems to have the same effect as typing nothing and pressing Return, nothing is added in the document and the echo line is printed, with no value for x,
Pressing C-c (Control C, similar to escape, but not quite. CF :help i_^c), the input and the function execution are cancelled, the echo line is not executed.
So I would say that you can consider escape (shortcut for emptying the input and pressing return) and an empty input as the same, and consider CTRL-c an the input being cancelled.
However, I am not sure that you can, while staying in the function, detect that the user cancelled the input or not, but hopefully someone will know better than me to confirm or correct this.

Why does a pipe to another process need to be closed plus set_close_on_exec to really close?

So, I was trying to use OCaml to communicate with a Python process. I wanted to pipe the Python program to the Python interpreter's stdin, and then read the Python program's output back in the OCaml process.
I was able to solve it like this:
let py_program = {|
import time
while True:
print('hi from Python', flush=True)
time.sleep(0.25)
|}
let exec_py_program () =
let cmd = "", [|"python3"; "-"|] in
let pipe_out_fd, pipe_out_fd_unix = Lwt_unix.pipe_out () in
(* Close the 1st time *)
let () = Lwt_unix.set_close_on_exec pipe_out_fd_unix in
let redir = `FD_move pipe_out_fd in
let py_stream = Lwt_process.pread_lines ~stdin:redir cmd in
let%lwt n = Lwt_unix.write_string pipe_out_fd_unix py_program 0 (String.length py_program) in
if n < String.length py_program then failwith "Failed to write python to pipe" else
let rec read_back () =
match%lwt Lwt_stream.get py_stream with
| Some str ->
let%lwt () = Lwt_io.printl ## "Got: " ^ str in
read_back ()
| None -> Lwt.return ()
in
(* Close the 2nd time *)
let%lwt () = Lwt_unix.close pipe_out_fd_unix in
read_back ()
I use "set_close_on_exec" to close the file descriptor corresponding to the pipe mapped to the Python process's stdin near the comment "Close the 1st time", and close the pipe again after sending over the Python program again ("Close the 2nd time"). "set_close_on_exec" supposedly closes the file descriptor "when the process calls exec on another process".
If I leave either of these lines out, the Python process indefinitely keeps reading from its stdin and never begins executing, so "hi from Python" is never received. So my question is, why are these both necessary? It was mostly a guess on my part.
Starting a program on a POSIX operating system (like Linux) is done in two steps. First, the process launching the program is forked, which creates a copy of the running process. Then, the new process is replaced by the new program using a call to exec. When the process is forked both resulting processes inherit all open file descriptors. Hence, to actually close a file descriptor it must be closed in both processes.
Setting the close-on-exec flag, causes the process to close the corresponding file descriptor as soon as exec is called. Hence, when you set this flag, only the old process has the open file descriptor after the program was started.
See also this question.

Ocaml lwt read stdout from other process

I'm trying to build a new frontend in Ocaml for a terminal based application. The main idea is the spawn a new process with Lwt:
let cmd = shell "./otherterminalapp" in
let p = open_process_full cmd;
And then later write stuff to the process' stdin, to execute commands in the external app.
Lwt_io.write_line p#stdin "some command" >>= (fun _ -> Lwt_io.flush p#stdin)
When I read the result from the command back in with Lwt_io.read_line_opt. How do I read till there aren't any lines left?
The problem I'm encountering is that my program just hangs at a certain point. When I read with read_line_opt, while I reached the end it seems like it's just waiting for the process to redirect new output.
How can I approach this?
A concrete example of what I'm trying to do:
(The terminal based application is ocamldebug)
Program source code:
open Lwt
open Lwt_unix
open Lwt_process
let () =
let run () =
let cmd = shell "ocamldebug test.d.byte" in
let dbgr = open_process_full cmd in
(((((((Lwt_io.write_line dbgr#stdin "info modules") >>=
(fun _ -> Lwt_io.flush dbgr#stdin))
>>= (fun _ -> Lwt_io.read_line_opt dbgr#stdout))
>>=
(fun s ->
(match s with
| Some l -> print_endline l
| None -> print_endline "nothing here! ");
Lwt_io.read_line_opt dbgr#stdout))
>>=
(fun s ->
(match s with
| Some l -> print_endline l
| None -> print_endline "nothing here! ");
Lwt_io.read_line_opt dbgr#stdout))
>>=
(fun s ->
(match s with
| Some l -> print_endline l
| None -> print_endline "nothing here! ");
Lwt_io.read_line_opt dbgr#stdout))
>>=
(fun s ->
(match s with
| Some l -> print_endline l
| None -> print_endline "nothing here! ");
Lwt_io.read_line_opt dbgr#stdout))
>>=
(fun s ->
(match s with
| Some l -> print_endline l
| None -> print_endline "nothing here! ");
Lwt.return ()) in
Lwt_main.run (run ())
If you would normally run ocamldebug with test.d.byte, you get the
following in your terminal:
OCaml Debugger version 4.03.0
(ocd) info modules
Loading program... done.
Used modules:
Std_exit Test Pervasives CamlinternalFormatBasics
(ocd)
When I execute the above program, I get the following printed:
OCaml Debugger version 4.03.0
(ocd) Loading program... Used modules:
Std_exit Test Pervasives CamlinternalFormatBasics
And here it just hangs..., my program doesn't exit. Even when I do
Ctrl-c/Ctrl-c in my terminal, there's an active ocamlrun process. The terminal however becomes responsive though.
I am missing something obvious here?
A call to Lwt.read_line_opt returns a deferred value, that will be determined in the future as Some data once the channel reads a newline-terminated string, or with None if the channel was closed. The channel will be closed if there was an end-of-file condition. For the regular files, the end-of-file condition occurs when the file pointer reaches the end of the file. For the pipes, that are used to communicate with the subprocess, the end-of-file condition occurs when the opposite side closes the file descriptor associated with the pipe.
The ocamldebug program doesn't close its inputs or outputs. It is an interactive program, that is ready to interact with a user for the infinite amount of time, or until a user closes the program, by either hitting Ctrl-D or using the quit command.
In your scenario, you wrote the info modules command into the channel's input. The process responded with the three lines (where each line is a piece of data terminated with the newline). Then the subprocess started to wait for the next input. You're not seeing the (ocd) prompt, because it is not terminated by the newline character. The program didn't hang-up. It is still waiting for the output from the subprocess, and the subprocess is waiting for the input from you (a dead lock).
If you really need to distinguish outputs from different commands, then you need to track the prompt in the subprocess output. Since the prompt is not terminated by the newline, you can't rely on the read_line* family of functions, since they are line buffered. You need to read all available characters and find the prompt in them manually.
On the other hand, if you do not really need to distinguish between the outputs of different commands, then you can ignore the prompt (actually, you may even filter it out, for the nicer output). In that case, you will have two concurrent subroutines - one would be responsible for feeding input, and another will read all the output, and dump it, without actually carrying about the contents of the data.

DBMS_OUTPUT.PUT_LINE doesn't print with output and pooling turned on

DBMS_OUTPUT.PUT_LINE( ) doesn't print output however output and spooling are turned on. "Procedure is completed successfully" message is displayed without any output. When run in SQLPLUS it throws errors.
Do you have any idea to check? I tried the DBMS_OUTPUT.ENABLE() etc.
Make sure you "execute as a script" by pressing F5. Make sure the editor window has this line before calling your procedure:
set serveroutput on size unlimited;
Here is an example calling a homegrown function that returns an element from a list (in this case the 6th element, "mirror") where the delimiter is a space. Note you can view output on the "DBMS Output" tab too (click the "turn output on" button first).
Click on the image to view full size
i found this little tricky button in jetBrains Datagrip, it turns on dbms_output without any dbms_output.enable or set serveron etc.

How to Read a Line from File in Ocaml?

I am in trouble with OCaml, because I want to read the lines from a text file, and I'm using this code to do the job:
let parse3ac() =
let lines = ref "" in
let chan = open_in "3ac" in
try
while true do
lines := input_line chan;
print_string(!lines);
done;
with End_of_file -> close_in chan;print_string("End Of File");;
But it only prints in the console "End Of File", but the lines from the file, doesn't appears.
What is wrong with this code guys?
Thks 4 all!!!
Edited:
Actually I have discovered the reason it isn't working.
It is very simple, the code above works very well, but the file "3ac" that I had created previously using OCaml, wasn't properly closed, and then it would be impossible to read the file.
Thanks everybody, and like I said before the code works so everyone can use that.
Thanks .
This code works, I tested it and it writes the lines of the file 3ac (without newlines as you don't print them) and then "End Of File". Are you sure the file 3ac is not empty ?