allow explicit help-only

This commit is contained in:
atagen 2026-03-23 15:18:10 +11:00
parent a2f207272a
commit 4e41fcda6d
2 changed files with 32 additions and 13 deletions

View file

@ -10,10 +10,12 @@ let usage () =
{|inshellah - nushell completions engine
Usage:
inshellah index PREFIX... [--dir PATH]
inshellah index PREFIX... [--dir PATH] [--ignore FILE] [--help-only FILE]
Index completions into a directory of JSON/nu files.
PREFIX is a directory containing bin/ and share/man/.
Default dir: $XDG_CACHE_HOME/inshellah
--ignore FILE skip listed commands entirely
--help-only FILE skip manpages for listed commands, use --help instead
inshellah complete CMD [ARGS...] [--dir PATH] [--system-dir PATH]
Nushell custom completer. Outputs JSON completion candidates.
Falls back to --help resolution if command is not indexed.
@ -396,7 +398,7 @@ let help_resolve_par ?(timeout=200) cmd rest name =
Each child handles one binary completely (including subcommand resolution)
and marshals results back via pipe. Children use help_resolve_par
which forks per subcommand for parallelism. *)
let cmd_index bindirs mandirs ignorelist dir =
let cmd_index bindirs mandirs ignorelist help_only dir =
ensure_dir dir;
let done_cmds = ref SSet.empty in
let n_results = ref 0 in
@ -410,7 +412,9 @@ let cmd_index bindirs mandirs ignorelist dir =
then manpaged_commands mandir else SSet.empty in
let max_jobs = num_cores () in
let classified = Array.map (fun name ->
if SSet.mem name manpaged || SSet.mem name ignorelist then (name, Skip)
if SSet.mem name ignorelist then (name, Skip)
else if SSet.mem name help_only then (name, classify_binary bindir name)
else if SSet.mem name manpaged then (name, Skip)
else (name, classify_binary bindir name)
) bins in
let pending = ref [] in
@ -505,7 +509,9 @@ let cmd_index bindirs mandirs ignorelist dir =
let files = Sys.readdir subdir in
Array.sort String.compare files;
Array.iter (fun file ->
match process_manpage (Filename.concat subdir file) with
let base_cmd = cmd_name_of_manpage file in
if SSet.mem base_cmd help_only then ()
else match process_manpage (Filename.concat subdir file) with
| None -> ()
| Some (cmd, result, subs) ->
if not (SSet.mem cmd !done_cmds) then begin
@ -665,12 +671,13 @@ let load_ignorelist path =
with _ -> SSet.empty
let parse_index_args args =
let rec go prefixes dir ignore = function
| [] -> (List.rev prefixes, dir, ignore)
| "--dir" :: path :: rest -> go prefixes path ignore rest
| "--ignore" :: path :: rest -> go prefixes dir (SSet.union ignore (load_ignorelist path)) rest
| prefix :: rest -> go (prefix :: prefixes) dir ignore rest in
go [] (default_store_path ()) SSet.empty args
let rec go prefixes dir ignore help_only = function
| [] -> (List.rev prefixes, dir, ignore, help_only)
| "--dir" :: path :: rest -> go prefixes path ignore help_only rest
| "--ignore" :: path :: rest -> go prefixes dir (SSet.union ignore (load_ignorelist path)) help_only rest
| "--help-only" :: path :: rest -> go prefixes dir ignore (SSet.union help_only (load_ignorelist path)) rest
| prefix :: rest -> go (prefix :: prefixes) dir ignore help_only rest in
go [] (default_store_path ()) SSet.empty SSet.empty args
let parse_dir_args args =
let rec go user_dir system_dirs rest_args = function
@ -683,11 +690,11 @@ let parse_dir_args args =
let () =
match Array.to_list Sys.argv |> List.tl with
| "index" :: rest ->
let (prefixes, dir, ignorelist) = parse_index_args rest in
let (prefixes, dir, ignorelist, help_only) = parse_index_args rest in
if prefixes = [] then (Printf.eprintf "error: index requires at least one prefix dir\n"; exit 1);
let bindirs = List.map (fun p -> Filename.concat p "bin") prefixes in
let mandirs = List.map (fun p -> Filename.concat p "share/man") prefixes in
cmd_index bindirs mandirs ignorelist dir
cmd_index bindirs mandirs ignorelist help_only dir
| "complete" :: rest ->
let (user_dir, system_dirs, spans) = parse_dir_args rest in
cmd_complete spans user_dir system_dirs

View file

@ -51,6 +51,16 @@ in
'';
};
helpOnlyCommands = lib.mkOption {
type = lib.types.listOf lib.types.str;
default = [ ];
example = [ "nix" ];
description = ''
list of command names to skip manpage parsing for,
using --help scraping instead
'';
};
snippet = lib.mkOption {
type = lib.types.str;
readOnly = true;
@ -65,12 +75,14 @@ in
destDir = "$out${cfg.completionsPath}";
ignoreFile = pkgs.writeText "inshellah-ignore" (lib.concatStringsSep "\n" cfg.ignoreCommands);
ignoreFlag = lib.optionalString (cfg.ignoreCommands != [ ]) " --ignore ${ignoreFile}";
helpOnlyFile = pkgs.writeText "inshellah-help-only" (lib.concatStringsSep "\n" cfg.helpOnlyCommands);
helpOnlyFlag = lib.optionalString (cfg.helpOnlyCommands != [ ]) " --help-only ${helpOnlyFile}";
in
''
mkdir -p ${destDir}
if [ -d "$out/bin" ] && [ -d "$out/share/man" ]; then
${inshellah} index "$out" --dir ${destDir}${ignoreFlag} \
${inshellah} index "$out" --dir ${destDir}${ignoreFlag}${helpOnlyFlag} \
2>/dev/null || true
fi