fix(fish): complete Bazel labels without query #5

Merged
alexion merged 2 commits from fish-bazel-completion into main 2026-09-02 11:42:28 -04:00
4 changed files with 149 additions and 2 deletions

2
.gitignore vendored
View File

@@ -4,8 +4,8 @@
# local environment overrides
.env
.env.*
.envrc
!.env.example
!.envrc
# editor and OS noise
.DS_Store

View File

@@ -0,0 +1,146 @@
set --query BAZEL_COMMAND_LIST; or set --global BAZEL_COMMAND_LIST analyze-profile aquery build canonicalize-flags clean coverage cquery dump fetch help info license mobile-install print_action query run shutdown test vendor version
function __bazel_seen_subcommand --description "Checks whether the command line contains a Bazel subcommand."
__fish_seen_subcommand_from $BAZEL_COMMAND_LIST
end
function __bazel_workspace_root --description "Prints the nearest Bazel workspace root."
set --local dir (pwd)
while test "$dir" != /
if test -e "$dir/MODULE.bazel"; or test -e "$dir/WORKSPACE"; or test -e "$dir/WORKSPACE.bazel"
printf '%s\n' "$dir"
return 0
end
set dir (dirname "$dir")
end
return 1
end
function __bazel_build_file --description "Prints the BUILD file for a package."
set --local root $argv[1]
set --local package $argv[2]
if test -f "$root/$package/BUILD.bazel"
printf '%s\n' "$root/$package/BUILD.bazel"
else if test -f "$root/$package/BUILD"
printf '%s\n' "$root/$package/BUILD"
end
end
function __bazel_complete_package --description "Completes Bazel package paths with BUILD-file scanning."
set --local root $argv[1]
set --local token $argv[2]
set --local absolute_prefix ''
set --local rel "$token"
if string match --quiet '//*' -- "$token"
set absolute_prefix '//'
set rel (string sub --start 3 -- "$token")
end
set --local parent (string replace --regex '[^/]*$' '' -- "$rel")
set --local prefix (string replace --regex '^.*/' '' -- "$rel")
set --local search_dir "$root/$parent"
test -d "$search_dir"; or return 0
if test -z "$rel"
set --local root_build_file (__bazel_build_file "$root" "")
if test -n "$root_build_file"
printf '%s:\tpackage\n' "$absolute_prefix"
end
end
for dir in (find "$search_dir" -mindepth 1 -maxdepth 1 -type d -name "$prefix*" 2>/dev/null)
set --local name (basename "$dir")
set --local package "$parent$name"
switch "$package"
case .direnv .git bazel-bin bazel-dev bazel-out bazel-testlogs target
continue
end
printf '%s%s/\tdirectory\n' "$absolute_prefix" "$package"
set --local package_build_file (__bazel_build_file "$root" "$package")
if test -n "$package_build_file"
printf '%s%s:\tpackage\n' "$absolute_prefix" "$package"
end
end
end
function __bazel_current_subcommand --description "Prints the active Bazel subcommand."
for token in (commandline --tokens-expanded)
if contains -- "$token" $BAZEL_COMMAND_LIST
printf '%s\n' "$token"
return 0
end
end
return 1
end
function __bazel_target_kind_pattern --description "Prints the target rule-kind pattern for the active subcommand."
switch (__bazel_current_subcommand)
case test coverage
printf '(^|_)test$|^test_suite$\n'
case run
printf '(_binary$|_test$|^test_suite$)\n'
case '*'
printf '.*\n'
end
end
function __bazel_complete_target --description "Completes targets from the selected package BUILD file."
set --local root $argv[1]
set --local token $argv[2]
set --local absolute_prefix ''
set --local rel "$token"
if string match --quiet '//*' -- "$token"
set absolute_prefix '//'
set rel (string sub --start 3 -- "$token")
end
set --local package (string replace --regex ':.*$' '' -- "$rel")
set --local target_prefix (string replace --regex '^.*:' '' -- "$rel")
set --local build_file (__bazel_build_file "$root" "$package")
set --local kind_pattern (__bazel_target_kind_pattern)
test -n "$build_file"; or return 0
awk -v prefix="$target_prefix" -v kind_pattern="$kind_pattern" '
match($0, /^[[:space:]]*([A-Za-z_][A-Za-z0-9_]*)[[:space:]]*\(/, rule) {
kind = rule[1]
}
match($0, /(^|[[:space:]])name[[:space:]]*=[[:space:]]*"([^"]+)"/, target) {
if (kind ~ kind_pattern && index(target[2], prefix) == 1) {
print target[2]
}
}
' "$build_file" | while read --local target
printf '%s%s:%s\ttarget\n' "$absolute_prefix" "$package" "$target"
end
end
function __bazel_complete_label --description "Completes local Bazel labels without running Bazel query."
set --local token (commandline --current-token)
string match --quiet -- '-*' "$token"; and return 0
string match --quiet -- '@*' "$token"; and return 0
set --local root (__bazel_workspace_root); or return 0
if string match --quiet '*:*' -- "$token"
__bazel_complete_target "$root" "$token"
else
__bazel_complete_package "$root" "$token"
end
end
complete -c bazel -e
complete -c bazel -f -n "not __bazel_seen_subcommand" -a "$BAZEL_COMMAND_LIST"
complete -c bazel -f -n "__fish_seen_subcommand_from build coverage fetch mobile-install print_action query run test" -a "(__bazel_complete_label)"

View File

@@ -37,6 +37,8 @@ in
fastfetch # the shell greeting
];
xdg.configFile."fish/completions/bazel.fish".source = ./completions/bazel.fish;
programs.fish = {
enable = true;

View File

@@ -1 +0,0 @@
use flake //#test