use relative /share path to look for manuals when resolving on-the-fly
This commit is contained in:
parent
cadc5f98d4
commit
9dd1261a46
1 changed files with 43 additions and 4 deletions
47
bin/main.ml
47
bin/main.ml
|
|
@ -1087,15 +1087,27 @@ let cmd_complete spans user_dir system_dirs mandirs =
|
|||
match lookup dirs try_name with
|
||||
| Some r -> Some (try_name, r, List.length prefix)
|
||||
| None -> None) in
|
||||
let all_tokens = cmd_name :: rest in
|
||||
(* strip flag tokens (--user, -a, etc.) from intermediate positions.
|
||||
* flags are not part of the subcommand path and should not affect
|
||||
* lookup. e.g. "systemctl --user start" should look up "systemctl start".
|
||||
* the last token (partial) is NOT stripped — it may be a flag the
|
||||
* user is typing (e.g. "--u") which needs fuzzy matching. *)
|
||||
let strip_intermediate_flags tokens =
|
||||
match List.rev tokens with
|
||||
| last :: rev_rest ->
|
||||
List.filter (fun t ->
|
||||
String.length t = 0 || t.[0] <> '-') (List.rev rev_rest)
|
||||
@ [last]
|
||||
| [] -> [] in
|
||||
let all_tokens = strip_intermediate_flags (cmd_name :: rest) in
|
||||
let last_token = match rest with
|
||||
| [] -> "" | _ -> List.nth rest (List.length rest - 1) in
|
||||
(* only treat the last token as a completed subcommand when nushell
|
||||
* sends a trailing empty token (cursor is after a space).
|
||||
* otherwise the user is still typing and we treat it as partial. *)
|
||||
let lookup_tokens = if last_token = "" then all_tokens
|
||||
else match rest with
|
||||
| _ :: _ -> cmd_name :: List.rev (List.tl (List.rev rest))
|
||||
else match all_tokens with
|
||||
| _ :: _ -> List.rev (List.tl (List.rev all_tokens))
|
||||
| _ -> [cmd_name] in
|
||||
let resolve tokens partial =
|
||||
match find_result tokens with
|
||||
|
|
@ -1112,7 +1124,34 @@ let cmd_complete spans user_dir system_dirs mandirs =
|
|||
(* no match, or only a parent matched — try on-the-fly resolution *)
|
||||
(match find_in_path cmd_name with
|
||||
| Some path ->
|
||||
(match resolve_and_cache ~dir:user_dir ~mandirs cmd_name path with
|
||||
(* derive sibling share/man from the binary's location.
|
||||
* e.g. /nix/store/.../bin/foo → /nix/store/.../share/man
|
||||
* this lets on-the-fly resolution find manpages for commands
|
||||
* not in the indexed prefixes. also resolves through nix
|
||||
* wrappers to find the real binary's manpage location. *)
|
||||
let mandir_of_bin p =
|
||||
let bindir = Filename.dirname p in
|
||||
let prefix = Filename.dirname bindir in
|
||||
Filename.concat (Filename.concat prefix "share") "man" in
|
||||
let bin_mandirs =
|
||||
let direct = mandir_of_bin path in
|
||||
(* also check the canonical path after resolving symlinks.
|
||||
* e.g. /run/current-system/sw/bin/foo is a symlink to
|
||||
* /nix/store/xxx/bin/foo — check /nix/store/xxx/share/man *)
|
||||
let via_realpath =
|
||||
try let real = Unix.realpath path in
|
||||
if real <> path then [mandir_of_bin real] else []
|
||||
with Unix.Unix_error _ -> [] in
|
||||
let via_wrapper =
|
||||
match nix_script_wrapper_target path with
|
||||
| Some target -> [mandir_of_bin target]
|
||||
| None ->
|
||||
match nix_wrapper_target path with
|
||||
| Some target -> [mandir_of_bin target]
|
||||
| None -> [] in
|
||||
List.filter is_dir (direct :: via_realpath @ via_wrapper) in
|
||||
let all_mandirs = bin_mandirs @ mandirs in
|
||||
(match resolve_and_cache ~dir:user_dir ~mandirs:all_mandirs cmd_name path with
|
||||
| Some _pairs -> resolve lookup_tokens last_token
|
||||
| None -> (found, partial))
|
||||
| None -> (found, partial)) in
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue