diff --git a/bin/main.ml b/bin/main.ml index 2221cf4..dd66912 100644 --- a/bin/main.ml +++ b/bin/main.ml @@ -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 diff --git a/nix/module.nix b/nix/module.nix index 8d41026..8e538b2 100644 --- a/nix/module.nix +++ b/nix/module.nix @@ -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