This commit is contained in:
atagen 2026-03-23 16:24:00 +11:00
parent 4e41fcda6d
commit 144d72b223
5 changed files with 188 additions and 258 deletions

View file

@ -266,125 +266,101 @@ let write_native ~dir command data =
let path = Filename.concat dir (filename_of_command command ^ ".nu") in
write_file path data
let is_dir path = Sys.file_exists path && Sys.is_directory path
let find_file dirs command =
let base = filename_of_command command in
let rec go = function
| [] -> None
| dir :: rest ->
let json_path = Filename.concat dir (base ^ ".json") in
if Sys.file_exists json_path then Some json_path
else
let nu_path = Filename.concat dir (base ^ ".nu") in
if Sys.file_exists nu_path then Some nu_path
else go rest in
go dirs
List.find_map (fun dir ->
let json_path = Filename.concat dir (base ^ ".json") in
if Sys.file_exists json_path then Some json_path
else
let nu_path = Filename.concat dir (base ^ ".nu") in
if Sys.file_exists nu_path then Some nu_path
else None
) dirs
let lookup dirs command =
let base = filename_of_command command in
let rec go = function
| [] -> None
| dir :: rest ->
let path = Filename.concat dir (base ^ ".json") in
(match read_file path with
| Some data ->
(try Some (help_result_of_json (parse_json data))
with _ -> None)
| None -> go rest) in
go dirs
List.find_map (fun dir ->
let path = Filename.concat dir (base ^ ".json") in
match read_file path with
| Some data ->
(try Some (help_result_of_json (parse_json data))
with _ -> None)
| None -> None
) dirs
let lookup_raw dirs command =
let base = filename_of_command command in
let rec go = function
| [] -> None
| dir :: rest ->
let json_path = Filename.concat dir (base ^ ".json") in
(match read_file json_path with
| Some _ as r -> r
| None ->
let nu_path = Filename.concat dir (base ^ ".nu") in
match read_file nu_path with
| Some _ as r -> r
| None -> go rest) in
go dirs
List.find_map (fun dir ->
let json_path = Filename.concat dir (base ^ ".json") in
match read_file json_path with
| Some _ as r -> r
| None ->
let nu_path = Filename.concat dir (base ^ ".nu") in
read_file nu_path
) dirs
let has_command dirs command =
find_file dirs command <> None
let chop_extension f =
if Filename.check_suffix f ".json" then Some (Filename.chop_suffix f ".json")
else if Filename.check_suffix f ".nu" then Some (Filename.chop_suffix f ".nu")
else None
let subcommands_of dirs command =
let prefix = filename_of_command command ^ "_" in
let plen = String.length prefix in
let module SMap = Map.Make(String) in
let subs = ref SMap.empty in
List.iter (fun dir ->
if Sys.file_exists dir && Sys.is_directory dir then
Array.iter (fun f ->
if String.starts_with ~prefix f then
let subs = List.fold_left (fun subs dir ->
if is_dir dir then
Array.fold_left (fun subs f ->
if not (String.starts_with ~prefix f) then subs
else
let is_json = Filename.check_suffix f ".json" in
let base =
if is_json then Some (Filename.chop_suffix f ".json")
else if Filename.check_suffix f ".nu" then
Some (Filename.chop_suffix f ".nu")
else None in
match base with
match chop_extension f with
| None -> subs
| Some b ->
let rest = String.sub b plen (String.length b - plen) in
(* Only direct children: no further underscores *)
if not (String.contains rest '_') && String.length rest > 0 then
let name = rest in
if not (SMap.mem name !subs) then
let desc = if is_json then
match read_file (Filename.concat dir f) with
| Some data ->
(try json_to_string (json_get "description" (parse_json data))
with _ -> "")
| None -> ""
else "" in
subs := SMap.add name { name; desc } !subs
| None -> ()
) (Sys.readdir dir)
) dirs;
SMap.fold (fun _ sc acc -> sc :: acc) !subs [] |> List.rev
if String.contains rest '_' || String.length rest = 0 then subs
else if SMap.mem rest subs then subs
else
let desc = if is_json then
match read_file (Filename.concat dir f) with
| Some data ->
(try json_to_string (json_get "description" (parse_json data))
with _ -> "")
| None -> ""
else "" in
SMap.add rest { name = rest; desc } subs
) subs (Sys.readdir dir)
else subs
) SMap.empty dirs in
SMap.fold (fun _ sc acc -> sc :: acc) subs [] |> List.rev
let all_commands dirs =
let module SSet = Set.Make(String) in
let cmds = ref SSet.empty in
List.iter (fun dir ->
if Sys.file_exists dir && Sys.is_directory dir then
Array.iter (fun f ->
let base =
if Filename.check_suffix f ".json" then
Some (Filename.chop_suffix f ".json")
else if Filename.check_suffix f ".nu" then
Some (Filename.chop_suffix f ".nu")
else None in
match base with
| Some b -> cmds := SSet.add (command_of_filename b) !cmds
| None -> ()
) (Sys.readdir dir)
) dirs;
SSet.elements !cmds
let delete ~dir command =
let base = filename_of_command command in
let json_path = Filename.concat dir (base ^ ".json") in
let nu_path = Filename.concat dir (base ^ ".nu") in
(try Sys.remove json_path with Sys_error _ -> ());
(try Sys.remove nu_path with Sys_error _ -> ())
List.fold_left (fun cmds dir ->
if is_dir dir then
Array.fold_left (fun cmds f ->
match chop_extension f with
| Some b -> SSet.add (command_of_filename b) cmds
| None -> cmds
) cmds (Sys.readdir dir)
else cmds
) SSet.empty dirs
|> SSet.elements
let file_type_of dirs command =
let base = filename_of_command command in
let rec go = function
| [] -> None
| dir :: rest ->
let json_path = Filename.concat dir (base ^ ".json") in
if Sys.file_exists json_path then
(match read_file json_path with
| Some data ->
(try Some (json_to_string (json_get "source" (parse_json data)))
with _ -> Some "json")
| None -> Some "json")
else
let nu_path = Filename.concat dir (base ^ ".nu") in
if Sys.file_exists nu_path then Some "native"
else go rest in
go dirs
List.find_map (fun dir ->
let json_path = Filename.concat dir (base ^ ".json") in
if Sys.file_exists json_path then
(match read_file json_path with
| Some data ->
(try Some (json_to_string (json_get "source" (parse_json data)))
with _ -> Some "json")
| None -> Some "json")
else
let nu_path = Filename.concat dir (base ^ ".nu") in
if Sys.file_exists nu_path then Some "native"
else None
) dirs