Hi Kenichi,
It is possible to do this kind of thing. If you only want to change the character for the prompt, you can set the Toploop.read_interactive_input function. Then to create a custom toplevel, you need to call [Topmain.main] and link your program with the compiler-libs.toplevel library. Here is a complete example where I copied and adapted the default [read_interactive_input] function from the compiler libraries, and used dune to build a custom toplevel:
$ cat
mytop.mllet read_input prompt buffer len =
let prompt =
if prompt <> "" && prompt.[0] = '#' then
String.mapi (fun i c -> if i = 0 then '%' else c) prompt
else
prompt
in
output_string stdout prompt; flush stdout;
let i = ref 0 in
try
while true do
if !i >= len then raise Exit;
let c = input_char stdin in
Bytes.set buffer !i c;
Option.iter (fun b -> Buffer.add_char b c) !Location.input_phrase_buffer;
incr i;
if c = '\n' then raise Exit;
done;
(!i, false)
with
| End_of_file ->
(!i, true)
| Exit ->
(!i, false)
let () =
Toploop.read_interactive_input := read_input;
Topmain.main ()
$ cat dune
(executable
(name mytop)
(libraries compiler-libs.toplevel)
(link_flags :standard -linkall)
(modes byte))
$ dune exec ./mytop.exe
OCaml version 4.11.1
% 1 + 1;;
- : int = 2
FTR, the compiler invocation to build myutop.exe is:
$ ocamlc -linkall -I +compiler-libs ocamlcommon.cma ocamlbytecomp.cma ocamltoplevel.cma
mytop.ml -o mytop.exe
$ ./mytop.exe
OCaml version 4.11.1
% 1 + 1;;
- : int = 2
If you want to go further, there are few projects that add line edition support to the toplevel, colors etc, using similar methods:
Finally, if you'd like to improve the toplevel API so that doing this kind of thing is easier in the future, a PR is always welcome :)
Happy hacking,
Jeremie