Shells in OCaml

Program completion

Basic program completion in interactive mode.

+19 -5
+19 -5
src/lib/interactive.ml
··· 29 29 (Fpath.normalize @@ S.cwd state |> subst_tilde |> Fpath.to_string); 30 30 Format.flush_str_formatter () 31 31 32 + let resolve_programs name = 33 + if not (String.contains name '/') then begin 34 + Eunix.find_env "PATH" 35 + |> Option.value ~default:"/bin:/usr/bin" 36 + |> String.split_on_char ':' 37 + |> List.concat_map (fun dir -> 38 + let files = try Sys.readdir dir |> Array.to_list with _ -> [] in 39 + List.filter (fun f -> String.starts_with ~prefix:name f) files) 40 + end 41 + else if Sys.file_exists name then [ name ] 42 + else [] 43 + 32 44 let complete path = 33 45 let rest, last_arg = 34 46 String.split_on_char ' ' path |> List.rev |> function 35 - | [] -> ([], None) 36 - | x :: rest -> (List.rev rest, Some x) 47 + | [] -> ([], `None) 48 + | [ prog ] -> ([], `Prog prog) 49 + | x :: rest -> (List.rev rest, `Path x) 37 50 in 38 51 let completions from_path basename = 39 52 match (Unix.stat from_path).st_kind with ··· 53 66 | exception Unix.Unix_error (Unix.ENOENT, _, _) -> [] 54 67 in 55 68 match last_arg with 56 - | None -> [] 57 - | Some path -> ( 69 + | `None -> [] 70 + | `Prog prog -> resolve_programs prog 71 + | `Path path -> ( 58 72 match Unix.(stat path).st_kind with 59 73 | exception Unix.Unix_error (Unix.ENOENT, _, _) -> 60 74 let dirname = Filename.dirname path in ··· 87 101 match 88 102 Bruit.bruit 89 103 ~history:(fun command -> H.history ~command !h |> H.commands) 90 - ~complete "" 104 + ~complete "% " 91 105 with 92 106 | String None -> 93 107 Fmt.pr "exit\n%!";