From f787f4bfa50306bcabed11e92fc73fd3e137c693 Mon Sep 17 00:00:00 2001 From: Thomas Waldmann Date: Wed, 19 Nov 2025 04:25:38 +0100 Subject: [PATCH] completion: complete tags with already present ones in repo --- src/borg/archiver/completion_cmd.py | 128 ++++++++++++++++++++++++---- 1 file changed, 111 insertions(+), 17 deletions(-) diff --git a/src/borg/archiver/completion_cmd.py b/src/borg/archiver/completion_cmd.py index 8255f2cf1..237500bbd 100644 --- a/src/borg/archiver/completion_cmd.py +++ b/src/borg/archiver/completion_cmd.py @@ -1,14 +1,3 @@ -import argparse - -import shtab - -from ._common import process_epilog -from ..constants import * # NOQA -from ..helpers import archivename_validator, SortBySpec, FilesCacheMode, PathSpec, ChunkerParams -from ..compress import CompressionSpec -from ..helpers.parseformat import partial_format -from ..manifest import AI_HUMAN_SORT_KEYS - """ Shell completion support for Borg commands. @@ -18,6 +7,7 @@ and extends it with custom dynamic completions for Borg-specific argument types. Dynamic Completions ------------------- + The following argument types have intelligent, context-aware completion: 1. Archive names/IDs (archivename_validator): @@ -46,15 +36,20 @@ The following argument types have intelligent, context-aware completion: 7. Help topics: - Completes help command topics and subcommand names -Implementation Details ----------------------- -- Custom shell functions are injected via shtab's preamble mechanism -- Archive completion calls `borg repo-list --format ...` to fetch data dynamically -- All dynamic completions are non-interactive and suppress prompts/errors -- Bash and zsh have separate preamble templates with shell-specific syntax +8. Tags (tag_validator): + - Completes existing tags from the repository """ +import argparse +import shtab + +from ._common import process_epilog +from ..constants import * # NOQA +from ..helpers import archivename_validator, SortBySpec, FilesCacheMode, PathSpec, ChunkerParams, tag_validator +from ..compress import CompressionSpec +from ..helpers.parseformat import partial_format +from ..manifest import AI_HUMAN_SORT_KEYS # Global bash preamble that is prepended to the generated completion script. # It aggregates only what we need: @@ -139,6 +134,52 @@ _borg_complete_chunker_params() { compgen -W "${choices}" -- "$1" } +# Complete tags from repository +_borg_complete_tags() { + local cur="${COMP_WORDS[COMP_CWORD]}" + + # derive repo context from words: --repo=V, --repo V, -r=V, -rV, or -r V + local repo_arg=() + local i w + for (( i=0; i<${#COMP_WORDS[@]}; i++ )); do + w="${COMP_WORDS[i]}" + if [[ "$w" == --repo=* ]]; then repo_arg=( --repo "${w#--repo=}" ); break + elif [[ "$w" == -r=* ]]; then repo_arg=( -r "${w#-r=}" ); break + elif [[ "$w" == -r* && "$w" != "-r" ]]; then repo_arg=( -r "${w#-r}" ); break + elif [[ "$w" == "--repo" || "$w" == "-r" ]]; then + if (( i+1 < ${#COMP_WORDS[@]} )); then repo_arg=( "$w" "${COMP_WORDS[i+1]}" ); fi + break + fi + done + + # ask borg for tags; avoid prompts and suppress stderr + local out + if [[ -n "${repo_arg[*]}" ]]; then + out=$( borg repo-list "${repo_arg[@]}" --format '{tags}{NL}' 2>/dev/null /dev/null 0 )); then + out=$( borg repo-list "${repo_arg[@]}" --format '{tags}{NL}' 2>/dev/null /dev/null