Skip to content

add tcsh completion support - #9503

Open
ThomasWaldmann wants to merge 1 commit into
borgbackup:masterfrom
ThomasWaldmann:tcsh-completions
Open

add tcsh completion support#9503
ThomasWaldmann wants to merge 1 commit into
borgbackup:masterfrom
ThomasWaldmann:tcsh-completions

Conversation

@ThomasWaldmann

@ThomasWaldmann ThomasWaldmann commented Mar 18, 2026

Copy link
Copy Markdown
Member

borg completion tcsh now generates a usable completion script.

Since the original version of this PR, all the generator fixes it used to carry as a local
monkeypatch of shtab.complete_tcsh have landed upstream in shtab
1.9.3
, which we already require — positional completion
under subcommands at any depth, no out-of-range $cmd indexing, custom .complete patterns in
multi-requirement rules, --opt= completion and rule deduplication. That monkeypatch (132 lines)
is therefore gone: with shtab 1.9.3 it produced exactly the same script as stock shtab.

What is left here:

  • a tcsh preamble providing the dynamic completion helpers as aliases (tcsh has no functions),
    and the tcsh patterns for sort keys, files-cache mode, compression specs, chunker params,
    relative times, timestamps, file sizes and help topics
  • completion of archive names, archive IDs (for tokens starting with aid:) and tags. tcsh can
    neither define functions nor use backquotes in these helpers (the completion rule invoking them
    is backquoted already), so both run one POSIX sh script that parses $COMMAND_LINE for
    --repo/-r and queries borg repo-list
  • _tcsh_anchor_positional_patterns(), a temporary ~30-line backport of
    tqdm/shtab#241 (merged upstream, not released yet)

Why the backport is needed

A completion pattern (f, d, ...) for a positional of a subcommand ends up inside that
positional's p@N@ rule. tcsh runs the clauses in such a rule as commands and completes from
their output, so a pattern there does nothing at all: without this, borg umount <TAB> offers no
mountpoint and borg key export <TAB> no path. The fix is to express them as n/<subcommand>/
rules instead, which tcsh does apply as patterns.

The rewrite produces byte-identical output to what a shtab containing #241 generates on its own,
and it is a no-op with such a shtab — so it can simply be deleted once we require the release that
contains it. That is noted as a TODO in its docstring.

Not covered

  • tcsh has no completion descriptions, so archive completion is a plain candidate list there,
    unlike in zsh and fish
  • tcsh matches completions for positional arguments by word position, so options preceding an
    archive name shift it out of place and it is not completed - the command's epilog points tcsh
    users at BORG_REPO for this. tqdm/shtab#247 fixes
    this for options before the subcommand (borg -r REPO list <TAB>)
  • options are mingled across subcommands in shtab's tcsh backend, so e.g. --compression is
    offered for every subcommand

Testing

Tests pass against both shtab 1.9.3 and current shtab main (21 passed, 1 skipped), and the
generated script was verified by driving a real interactive tcsh 6.21.00: borg <TAB>,
borg key <TAB>, borg key change-location <TAB>, borg help <TAB>, borg umount <TAB>,
borg key export <TAB>, borg create --compression=z<TAB> and borg list --sort-by=<TAB> all
complete as expected. Against a real repository (two archives, two tags), borg list <TAB> gives
the archive names, borg list aid:<TAB> gives aid: + 8 hex digits per archive, and
borg tag --add=<TAB> gives the tags.

Checklist

  • PR is against master (or maintenance branch if only applicable there)
  • New code has tests and docs where appropriate
  • Tests pass (run tox or the relevant test subset)
  • Commit messages are clean and reference related issues

@ThomasWaldmann

Copy link
Copy Markdown
Member Author

This was created with AI assistance (Gemini Flash/Pro) and likely needs more work:

  • that monkeypatching of shtab isn't pretty. IF there are bugs / missing features in shtab tcsh support, they should be fixed there.
  • archivename / aid completion is missing. The AI tried to write that, but ran into severe troubles. To at least have something simpler to begin with, I decided to skip that for the initial commit.

@codecov

codecov Bot commented Mar 18, 2026

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 86.21%. Comparing base (3a8431c) to head (bfb0f5c).
⚠️ Report is 10 commits behind head on master.
✅ All tests successful. No failed tests found.

Additional details and impacted files
@@            Coverage Diff             @@
##           master    #9503      +/-   ##
==========================================
+ Coverage   86.18%   86.21%   +0.03%     
==========================================
  Files          96       96              
  Lines       17434    17462      +28     
  Branches     2665     2672       +7     
==========================================
+ Hits        15025    15055      +30     
+ Misses       1668     1667       -1     
+ Partials      741      740       -1     

☔ View full report in Codecov by Harness.
📢 Have feedback on the report? Share it here.

@ThomasWaldmann

Copy link
Copy Markdown
Member Author

@simaoafonso-pwt Could you have a look at that monkeypatch please?

@simaoafonso-pwt

Copy link
Copy Markdown

@simaoafonso-pwt Could you have a look at that monkeypatch please?

Thanks for tagging me, I know that tcsh support is not fully featured, but it was the best I could do.

I see that monkey patching is changing a single function, can you please create a diff between that new function, and the one on shtab itself, so that it's easier to review the changes?

@ThomasWaldmann

ThomasWaldmann commented Mar 23, 2026

Copy link
Copy Markdown
Member Author

@simaoafonso-pwt I added a draft PR there:

tqdm/shtab#213

@simaoafonso-pwt

Copy link
Copy Markdown

@simaoafonso-pwt I added a draft PR there:

iterative/shtab#213

Thanks, I'll review that.

@ThomasWaldmann
ThomasWaldmann force-pushed the tcsh-completions branch 6 times, most recently from d09f173 to f059162 Compare August 5, 2026 09:19
@ThomasWaldmann
ThomasWaldmann marked this pull request as ready for review August 5, 2026 09:20
@ThomasWaldmann ThomasWaldmann changed the title fix: improve tcsh completion support add tcsh completion support Aug 5, 2026
@ThomasWaldmann

Copy link
Copy Markdown
Member Author

Rebased onto current master and reworked.

  • shtab #213 is merged and released in shtab 1.9.3,
    which borg already requires, so the local monkeypatch of shtab.complete_tcsh (132 lines) is
    removed: its generated script was identical to stock 1.9.3's apart from the header comment.
  • What remains of the generator work is _tcsh_anchor_positional_patterns(), a temporary backport
    of tqdm/shtab#241 (merged, unreleased) so that
    borg umount <TAB> / borg key export <TAB> complete a mountpoint / path at all. Its output is
    byte-identical to what a shtab with possible loss of backup archives when following example in documentations with prune command #241 generates, and it is a verified no-op with such a
    shtab, so it can be dropped once we require that release.
  • Rebasing over the fish-completion work meant adopting master's for_all_shells() helper; tcsh is
    now folded into it (tcsh=False for the archive and tags helpers, which have no tcsh
    implementation).
  • New test asserts the anchored rules exist and, more generally, that no p@N@ clause action is a
    bare completion pattern.

Diff is down from +192/−8 to +122/−7. Title and description updated to match.

`borg completion tcsh` now generates a usable completion script:

- add a tcsh preamble with the dynamic completion helpers (as aliases, since tcsh has no
  functions) and wire the tcsh patterns up for sort keys, files-cache mode, compression specs,
  chunker params, relative times, timestamps, file sizes and help topics.
- complete archive names, archive IDs (when the token starts with "aid:") and tags. tcsh can
  neither define functions nor use backquotes there (the completion rule calling the helper is
  backquoted already), so both helpers run one POSIX sh script that parses $COMMAND_LINE for
  --repo/-r and queries `borg repo-list`. tcsh has no completion descriptions, so unlike zsh
  and fish these are plain candidate lists.

The generator fixes this needed are all upstream in shtab now (tqdm/shtab#213, released in
1.9.3, which we already require): positional completion under subcommands at any depth, no
out-of-range `$cmd` indexing, custom `.complete` patterns in multi-requirement rules, `--opt=`
completion, and rule deduplication.

One upstream fix is merged but not yet released (tqdm/shtab#241): completion patterns (`f`,
`d`, ...) for a positional of a subcommand end up inside a `p@N@` rule, where tcsh runs the
clauses as commands and only uses their output, so they do nothing - e.g. `borg umount <TAB>`
would not complete a mountpoint. `_tcsh_anchor_positional_patterns` rewrites those into `n/`
rules keyed off the preceding (sub)command word, producing exactly what a shtab with borgbackup#241
generates. It is a no-op with such a shtab and can then be removed.

Note that tcsh matches completions for positional arguments by word position, so options
before an archive name shift it out of place and it is not completed - the `borg completion`
epilog points at BORG_REPO for this.
@ThomasWaldmann

Copy link
Copy Markdown
Member Author

Added archive name, aid: and tag completion for tcsh, which this PR previously left out.

tcsh has no functions, and these helpers cannot use backquotes because the completion rule
invoking them is backquoted already. So both aliases run one POSIX sh script (kept in a csh
variable) that parses $COMMAND_LINE for --repo/-r and queries borg repo-list. Verified
against a real repository by driving an interactive tcsh:

borg list <TAB>        ->  arch-one arch-two
borg list aid:<TAB>    ->  aid:2f4b2c84 aid:a428b2b4
borg tag --add=<TAB>   ->  important nightly

Caveat, now noted in the command's epilog: tcsh matches positional completions by word position,
so borg list --repo REPO <TAB> shifts the archive out of place and completes nothing — with
BORG_REPO set it works. tqdm/shtab#247 fixes the
options-before-the-subcommand half of that upstream (borg -r REPO list <TAB>); with that shtab,
borg --repo REPO info <TAB> completes archive names here.

Tests are up to 21 passed / 1 skipped against both shtab 1.9.3 and shtab main.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants