cli11, bsd manual
This commit is contained in:
parent
9c7c528a0c
commit
18c97eacd0
7 changed files with 534 additions and 117 deletions
|
|
@ -1,5 +1,9 @@
|
|||
open Parser
|
||||
|
||||
module SSet = Set.Make(String)
|
||||
module SMap = Map.Make(String)
|
||||
module CSet = Set.Make(Char)
|
||||
|
||||
(* Nushell built-in commands and keywords *)
|
||||
let nushell_builtins = [
|
||||
"alias"; "all"; "ansi"; "any"; "append"; "ast"; "attr";
|
||||
|
|
@ -40,13 +44,10 @@ let nushell_builtins = [
|
|||
"zip";
|
||||
]
|
||||
|
||||
let builtin_set = lazy (
|
||||
let tbl = Hashtbl.create (List.length nushell_builtins) in
|
||||
List.iter (fun s -> Hashtbl.replace tbl s true) nushell_builtins;
|
||||
tbl)
|
||||
let builtin_set = lazy (SSet.of_list nushell_builtins)
|
||||
|
||||
let is_nushell_builtin cmd =
|
||||
Hashtbl.mem (Lazy.force builtin_set) cmd
|
||||
SSet.mem cmd (Lazy.force builtin_set)
|
||||
|
||||
let dedup_entries entries =
|
||||
let key_of entry =
|
||||
|
|
@ -60,30 +61,24 @@ let dedup_entries entries =
|
|||
let d = min 5 (String.length entry.desc / 10) in
|
||||
sw + p + d
|
||||
in
|
||||
let best = Hashtbl.create 64 in
|
||||
List.iter (fun e ->
|
||||
let best = List.fold_left (fun acc e ->
|
||||
let k = key_of e in
|
||||
match Hashtbl.find_opt best k with
|
||||
| Some prev when score prev >= score e -> ()
|
||||
| _ -> Hashtbl.replace best k e
|
||||
) entries;
|
||||
let covered_shorts = Hashtbl.create 16 in
|
||||
Hashtbl.iter (fun _ e ->
|
||||
match SMap.find_opt k acc with
|
||||
| Some prev when score prev >= score e -> acc
|
||||
| _ -> SMap.add k e acc
|
||||
) SMap.empty entries in
|
||||
let covered = SMap.fold (fun _ e acc ->
|
||||
match e.switch with
|
||||
| Both (c, _) -> Hashtbl.replace covered_shorts c true
|
||||
| _ -> ()
|
||||
) best;
|
||||
let seen = Hashtbl.create 64 in
|
||||
List.filter_map (fun e ->
|
||||
| Both (c, _) -> CSet.add c acc
|
||||
| _ -> acc
|
||||
) best CSet.empty in
|
||||
List.fold_left (fun (seen, acc) e ->
|
||||
let k = key_of e in
|
||||
if Hashtbl.mem seen k then None
|
||||
else
|
||||
match e.switch with
|
||||
| Short c when Hashtbl.mem covered_shorts c -> None
|
||||
| _ ->
|
||||
Hashtbl.add seen k true;
|
||||
Hashtbl.find_opt best k
|
||||
) entries
|
||||
if SSet.mem k seen then (seen, acc)
|
||||
else match e.switch with
|
||||
| Short c when CSet.mem c covered -> (seen, acc)
|
||||
| _ -> (SSet.add k seen, SMap.find k best :: acc)
|
||||
) (SSet.empty, []) entries |> snd |> List.rev
|
||||
|
||||
let nushell_type_of_param = function
|
||||
| "FILE" | "file" | "PATH" | "path" | "DIR" | "dir" | "DIRECTORY"
|
||||
|
|
@ -120,22 +115,26 @@ let format_flag entry =
|
|||
let pad_len = max 1 (40 - String.length flag) in
|
||||
flag ^ String.make pad_len ' ' ^ "# " ^ entry.desc
|
||||
|
||||
let write_extern buf cmd_name result =
|
||||
let entries = dedup_entries result.entries in
|
||||
Printf.bprintf buf "export extern \"%s\" [\n" (escape_nu cmd_name);
|
||||
List.iter (fun e ->
|
||||
Buffer.add_string buf (format_flag e); Buffer.add_char buf '\n'
|
||||
) entries;
|
||||
Buffer.add_string buf "]\n";
|
||||
List.iter (fun (sc : subcommand) ->
|
||||
Printf.bprintf buf "\nexport extern \"%s %s\" [ # %s\n]\n"
|
||||
(escape_nu cmd_name) (escape_nu sc.name) (escape_nu sc.desc)
|
||||
) result.subcommands
|
||||
let format_positional p =
|
||||
let name = String.map (function '-' -> '_' | c -> c) p.pos_name in
|
||||
let prefix = if p.variadic then "..." else "" in
|
||||
let suffix = if p.optional && not p.variadic then "?" else "" in
|
||||
let typ = nushell_type_of_param (String.uppercase_ascii p.pos_name) in
|
||||
Printf.sprintf " %s%s%s: %s" prefix name suffix typ
|
||||
|
||||
let generate_extern cmd_name result =
|
||||
let buf = Buffer.create 1024 in
|
||||
write_extern buf cmd_name result;
|
||||
Buffer.contents buf
|
||||
let extern_of cmd_name result =
|
||||
let entries = dedup_entries result.entries in
|
||||
let cmd = escape_nu cmd_name in
|
||||
let pos_lines = List.map (fun p -> format_positional p ^ "\n") result.positionals in
|
||||
let flags = List.map (fun e -> format_flag e ^ "\n") entries in
|
||||
let main = Printf.sprintf "export extern \"%s\" [\n%s%s]\n" cmd (String.concat "" pos_lines) (String.concat "" flags) in
|
||||
let subs = List.map (fun (sc : subcommand) ->
|
||||
Printf.sprintf "\nexport extern \"%s %s\" [ # %s\n]\n"
|
||||
cmd (escape_nu sc.name) (escape_nu sc.desc)
|
||||
) result.subcommands in
|
||||
String.concat "" (main :: subs)
|
||||
|
||||
let generate_extern = extern_of
|
||||
|
||||
let module_name_of cmd_name =
|
||||
let s = String.map (function
|
||||
|
|
@ -144,11 +143,7 @@ let module_name_of cmd_name =
|
|||
|
||||
let generate_module cmd_name result =
|
||||
let m = module_name_of cmd_name in
|
||||
let buf = Buffer.create 1024 in
|
||||
Printf.bprintf buf "module %s {\n" m;
|
||||
write_extern buf cmd_name result;
|
||||
Printf.bprintf buf "}\n\nuse %s *\n" m;
|
||||
Buffer.contents buf
|
||||
Printf.sprintf "module %s {\n%s}\n\nuse %s *\n" m (extern_of cmd_name result) m
|
||||
|
||||
let generate_extern_from_entries cmd_name entries =
|
||||
generate_extern cmd_name { entries; subcommands = [] }
|
||||
generate_extern cmd_name { entries; subcommands = []; positionals = [] }
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue