Skip to content

Commit 70ee3c4

Browse files
berkegasche
authored andcommitted
Add #help to list available toplevel directives.
1 parent ae9cf67 commit 70ee3c4

4 files changed

Lines changed: 116 additions & 42 deletions

File tree

Changes

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -874,6 +874,8 @@ Compilers:
874874
Toplevel interactive system:
875875
- PR#5377: New "#show_*" directives
876876
(ygrek, Jacques Garrigue and Alain Frisch)
877+
- PR#6113: Add descriptions to directives, and display them via #help
878+
(Berke Durak)
877879

878880
Runtime system:
879881
- New configure option "-no-naked-pointers" to improve performance by

toplevel/topdirs.ml

Lines changed: 99 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,9 @@ let std_out = std_formatter
2727

2828
let dir_quit () = exit 0
2929

30-
let _ = Hashtbl.add directive_table "quit" (Directive_none dir_quit)
30+
let _ =
31+
add_directive "quit" "Exit the toplevel loop and terminate the ocaml command."
32+
(Directive_none dir_quit)
3133

3234
(* To add a directory to the load path *)
3335

@@ -36,7 +38,9 @@ let dir_directory s =
3638
Config.load_path := d :: !Config.load_path;
3739
Dll.add_path [d]
3840

39-
let _ = Hashtbl.add directive_table "directory" (Directive_string dir_directory)
41+
let _ = add_directive "directory"
42+
"Add <string> to search path for source and compiled files."
43+
(Directive_string dir_directory)
4044

4145
(* To remove a directory from the load path *)
4246
let dir_remove_directory s =
@@ -45,14 +49,16 @@ let dir_remove_directory s =
4549
Dll.remove_path [d]
4650

4751
let _ =
48-
Hashtbl.add directive_table "remove_directory"
52+
add_directive "remove_directory"
53+
"Remove <string> from the search path for source and compiled files."
4954
(Directive_string dir_remove_directory)
5055

5156
(* To change the current directory *)
5257

5358
let dir_cd s = Sys.chdir s
5459

55-
let _ = Hashtbl.add directive_table "cd" (Directive_string dir_cd)
60+
let _ = add_directive "cd" "Change the current working directory"
61+
(Directive_string dir_cd)
5662

5763
(* Load in-core a .cmo file *)
5864

@@ -173,12 +179,14 @@ and really_load_file recursive ppf name filename ic =
173179

174180
let dir_load ppf name = ignore (load_file false ppf name)
175181

176-
let _ = Hashtbl.add directive_table "load" (Directive_string (dir_load std_out))
182+
let _ = add_directive "load" "Load an object (.cmo) or a library (.cma) file"
183+
(Directive_string (dir_load std_out))
177184

178185
let dir_load_rec ppf name = ignore (load_file true ppf name)
179186

180-
let _ = Hashtbl.add directive_table "load_rec"
181-
(Directive_string (dir_load_rec std_out))
187+
let _ =
188+
add_directive "load_rec" "Like #load but recursively load missing modules"
189+
(Directive_string (dir_load_rec std_out))
182190

183191
let load_file = load_file false
184192

@@ -187,9 +195,14 @@ let load_file = load_file false
187195
let dir_use ppf name = ignore(Toploop.use_file ppf name)
188196
let dir_mod_use ppf name = ignore(Toploop.mod_use_file ppf name)
189197

190-
let _ = Hashtbl.add directive_table "use" (Directive_string (dir_use std_out))
191-
let _ = Hashtbl.add directive_table "mod_use"
192-
(Directive_string (dir_mod_use std_out))
198+
let _ =
199+
add_directive "use" "Read and execute source phrases from file <string>"
200+
(Directive_string (dir_use std_out))
201+
202+
let _ =
203+
add_directive "mod_use"
204+
"Like #use, but wraps code in a module named after <string>"
205+
(Directive_string (dir_mod_use std_out))
193206

194207
(* Install, remove a printer *)
195208

@@ -324,10 +337,13 @@ let dir_remove_printer ppf lid =
324337
end
325338
with Exit -> ()
326339

327-
let _ = Hashtbl.add directive_table "install_printer"
328-
(Directive_ident (dir_install_printer std_out))
329-
let _ = Hashtbl.add directive_table "remove_printer"
330-
(Directive_ident (dir_remove_printer std_out))
340+
let _ =
341+
add_directive "install_printer"
342+
"Register function <ident> as a printer for its argument type"
343+
(Directive_ident (dir_install_printer std_out))
344+
345+
let _ = add_directive "remove_printer" "Unregisters a printer"
346+
(Directive_ident (dir_remove_printer std_out))
331347

332348
(* The trace *)
333349

@@ -422,6 +438,39 @@ let trim_signature = function
422438
sg)
423439
| mty -> mty
424440

441+
let dir_help ppf () =
442+
pp_open_tbox ppf ();
443+
fprintf ppf "Directive ";
444+
pp_set_tab ppf ();
445+
fprintf ppf "Argument(s) ";
446+
pp_set_tab ppf ();
447+
fprintf ppf "Description@\n@\n";
448+
let directives =
449+
List.sort
450+
(fun (key1,_) (key2,_) -> compare key1 key2)
451+
(Hashtbl.fold (fun key x res -> (key, x) :: res) directive_table [])
452+
in
453+
List.iter
454+
(fun (key, (kind, desc)) ->
455+
let kind_desc =
456+
match kind with
457+
| Directive_ident _ -> "<ident>"
458+
| Directive_none _ -> " "
459+
| Directive_int _ -> "<int>"
460+
| Directive_bool _ -> "<bool>"
461+
| Directive_string _ -> "<string>"
462+
in
463+
fprintf ppf "#%s" key;
464+
pp_print_tbreak ppf 0 0;
465+
fprintf ppf "%s" kind_desc;
466+
pp_print_tbreak ppf 0 0;
467+
fprintf ppf "%s@\n" desc;
468+
)
469+
directives;
470+
pp_close_tbox ppf ();
471+
fprintf ppf "@."
472+
[@@warning "-3"] (* Tabulation boxes are deprecated in 4.03+dev *)
473+
425474
let show_prim to_sig ppf lid =
426475
let env = !Toploop.toplevel_env in
427476
let loc = Location.none in
@@ -445,26 +494,30 @@ let show_prim to_sig ppf lid =
445494

446495
let all_show_funs = ref []
447496

448-
let reg_show_prim name to_sig =
497+
let reg_show_prim name ~help to_sig =
449498
all_show_funs := to_sig :: !all_show_funs;
450-
Hashtbl.add directive_table name (Directive_ident (show_prim to_sig std_out))
499+
add_directive "show"
500+
(Printf.sprintf
501+
"Describe the %s with this name if it exists in the environment."
502+
help)
503+
(Directive_ident (show_prim to_sig std_out))
451504

452505
let () =
453-
reg_show_prim "show_val"
506+
reg_show_prim "show_val" ~help:"value"
454507
(fun env loc id lid ->
455508
let path, desc = Typetexp.find_value env loc lid in
456509
[ Sig_value (id, desc) ]
457510
)
458511

459512
let () =
460-
reg_show_prim "show_type"
513+
reg_show_prim "show_type" ~help:"type"
461514
(fun env loc id lid ->
462515
let path, desc = Typetexp.find_type env loc lid in
463516
[ Sig_type (id, desc, Trec_not) ]
464517
)
465518

466519
let () =
467-
reg_show_prim "show_exception"
520+
reg_show_prim "show_exception" ~help:"exception"
468521
(fun env loc id lid ->
469522
let desc = Typetexp.find_constructor env loc lid in
470523
if not (Ctype.equal env true [desc.cstr_res] [Predef.type_exn]) then
@@ -486,29 +539,29 @@ let () =
486539
)
487540

488541
let () =
489-
reg_show_prim "show_module"
542+
reg_show_prim "show_module" ~help:"module"
490543
(fun env loc id lid ->
491544
let path, md = Typetexp.find_module env loc lid in
492545
[ Sig_module (id, {md with md_type = trim_signature md.md_type},
493546
Trec_not) ]
494547
)
495548

496549
let () =
497-
reg_show_prim "show_module_type"
550+
reg_show_prim "show_module_type" ~help:"module type"
498551
(fun env loc id lid ->
499552
let path, desc = Typetexp.find_modtype env loc lid in
500553
[ Sig_modtype (id, desc) ]
501554
)
502555

503556
let () =
504-
reg_show_prim "show_class"
557+
reg_show_prim "show_class" ~help:"class"
505558
(fun env loc id lid ->
506559
let path, desc = Typetexp.find_class env loc lid in
507560
[ Sig_class (id, desc, Trec_not) ]
508561
)
509562

510563
let () =
511-
reg_show_prim "show_class_type"
564+
reg_show_prim "show_class_type" ~help:"class type"
512565
(fun env loc id lid ->
513566
let path, desc = Typetexp.find_class_type env loc lid in
514567
[ Sig_class_type (id, desc, Trec_not) ]
@@ -524,39 +577,47 @@ let show env loc id lid =
524577
if sg = [] then raise Not_found else sg
525578

526579
let () =
527-
Hashtbl.add directive_table "show" (Directive_ident (show_prim show std_out))
580+
add_directive "show"
581+
"Describe this name if it exists in the environment;\
582+
see also #show_val, #show_type, #show_module etc."
583+
(Directive_ident (show_prim show std_out))
528584

529585
let _ =
530-
Hashtbl.add directive_table "trace" (Directive_ident (dir_trace std_out));
531-
Hashtbl.add directive_table "untrace" (Directive_ident (dir_untrace std_out));
532-
Hashtbl.add directive_table
533-
"untrace_all" (Directive_none (dir_untrace_all std_out));
586+
add_directive "trace" "Trace calls to function <ident>"
587+
(Directive_ident (dir_trace std_out));
588+
add_directive "untrace" "Stop tracing function <ident>"
589+
(Directive_ident (dir_untrace std_out));
590+
add_directive "untrace_all" "Stop all function traces"
591+
(Directive_none (dir_untrace_all std_out));
534592

535593
(* Control the printing of values *)
536594

537-
Hashtbl.add directive_table "print_depth"
538-
(Directive_int(fun n -> max_printer_depth := n));
539-
Hashtbl.add directive_table "print_length"
540-
(Directive_int(fun n -> max_printer_steps := n));
595+
add_directive "print_depth" "Limit the depth of printed values to <int>"
596+
(Directive_int(fun n -> max_printer_depth := n));
597+
add_directive "print_length" "Limit the number of values printed to <int>"
598+
(Directive_int(fun n -> max_printer_steps := n));
541599

542600
(* Set various compiler flags *)
543601

544-
Hashtbl.add directive_table "labels"
602+
add_directive "labels" "Ignore labels in function types (if true)"
545603
(Directive_bool(fun b -> Clflags.classic := not b));
546604

547-
Hashtbl.add directive_table "principal"
605+
add_directive "principal" "Ensure that inferred types are principal (if true)"
548606
(Directive_bool(fun b -> Clflags.principal := b));
549607

550-
Hashtbl.add directive_table "rectypes"
608+
add_directive "rectypes" "Allow arbitrary recursive types"
551609
(Directive_none(fun () -> Clflags.recursive_types := true));
552610

553-
Hashtbl.add directive_table "ppx"
611+
add_directive "ppx" "Pass input phrases through a ppx preprocessor"
554612
(Directive_string(fun s -> Clflags.all_ppx := s :: !Clflags.all_ppx));
555613

556-
Hashtbl.add directive_table "warnings"
614+
add_directive "warnings" "Apply the warning filter <string>"
557615
(Directive_string (parse_warnings std_out false));
558616

559-
Hashtbl.add directive_table "warn_error"
617+
add_directive "warn_error" "Swap listed items between warning and error"
560618
(Directive_string (parse_warnings std_out true));
561619

620+
add_directive "help" "This help screen"
621+
(Directive_none (dir_help std_out));
622+
562623
()

toplevel/toploop.ml

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -224,7 +224,15 @@ let print_exception_outcome ppf exn =
224224
(* The table of toplevel directives.
225225
Filled by functions from module topdirs. *)
226226

227-
let directive_table = (Hashtbl.create 13 : (string, directive_fun) Hashtbl.t)
227+
let directive_table =
228+
(Hashtbl.create 13 : (string, directive_fun * string) Hashtbl.t)
229+
230+
let add_directive dir_name dir_descr dir_arg =
231+
Hashtbl.add directive_table dir_name (dir_arg, dir_descr)
232+
233+
let find_directive dir_name =
234+
let (f, _) = Hashtbl.find directive_table dir_name in
235+
f
228236

229237
(* Execute a toplevel phrase *)
230238

@@ -294,7 +302,7 @@ let execute_phrase print_outcome ppf phr =
294302
end
295303
| Ptop_dir(dir_name, dir_arg) ->
296304
let d =
297-
try Some (Hashtbl.find directive_table dir_name)
305+
try Some (find_directive dir_name)
298306
with Not_found -> None
299307
in
300308
begin match d with

toplevel/toploop.mli

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -40,8 +40,11 @@ type directive_fun =
4040
| Directive_ident of (Longident.t -> unit)
4141
| Directive_bool of (bool -> unit)
4242

43-
val directive_table : (string, directive_fun) Hashtbl.t
44-
(* Table of known directives, with their execution function *)
43+
val directive_table : (string, directive_fun * string) Hashtbl.t
44+
(* Table of known directives, with their execution function and
45+
description *)
46+
val add_directive : string -> string -> directive_fun -> unit
47+
(* Add a directive to the table with a short description *)
4548
val toplevel_env : Env.t ref
4649
(* Typing environment for the toplevel *)
4750
val initialize_toplevel_env : unit -> unit

0 commit comments

Comments
 (0)