aboutsummaryrefslogtreecommitdiffstats
path: root/bin/repl.ml
blob: 092c50327e570e8453f92d97c980ac87dfb5594b (about) (plain) (blame)
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
40
41
42
43
44
45
46
47
48
49
50
51
52
open Core
open Option.Let_syntax

let ok = ref true
let opts = Settings.opts

let rec user_input cb =
  let prompt = (if !ok then "[okay]" else "[fail]") ^ " (mini)nix> " in
  try
    match LNoise.linenoise prompt with
    | None -> ()
    | Some v ->
        cb v;
        user_input cb
  with Sys_unix.Break ->
    printf "\n%!";
    user_input cb

let split_cmd_prefix cmd =
  let%bind cmd = String.chop_prefix ~prefix:":" cmd in
  let cmd' = Repl_cmd.lstrip_space cmd in
  let space = String.chop_suffix_exn cmd ~suffix:cmd' in
  return (":" ^ space, cmd')

let handle_cmd cmd =
  let cmd = Repl_cmd.strip_space cmd in
  (match split_cmd_prefix cmd with
  | Some (_, cmd) -> ok := Repl_cmd.invoke cmd
  | None ->
      if String.(strip cmd <> "") then
        ok := Run.eval_expr cmd ~origin:Interactive);
  printf "\n%!"

let run () =
  LNoise.set_multiline true;
  LNoise.history_load ~filename:"mininix_history" |> ignore;
  LNoise.history_set ~max_length:500 |> ignore;
  LNoise.set_hints_callback (fun line ->
      let%bind _, cmd = split_cmd_prefix line in
      let%bind hint = Repl_cmd.hint cmd in
      return (hint, LNoise.Yellow, true));
  LNoise.set_completion_callback (fun line_so_far completions ->
      match split_cmd_prefix line_so_far with
      | Some (prefix, cmd_so_far) ->
          Repl_cmd.complete cmd_so_far
          |> List.map ~f:(String.append prefix)
          |> List.iter ~f:(LNoise.add_completion completions)
      | None -> ());
  user_input (fun from_user ->
      LNoise.history_add from_user |> ignore;
      LNoise.history_save ~filename:"mininix_history" |> ignore;
      handle_cmd from_user)