I’ve been using pass to manage passwords, and the pass-otp extension to handle one-time-password tokens.
{ config, pkgs, ... }:
{
environment.systemPackages = [
(pkgs.pass.withExtensions (exts: [exts.pass-otp]))
];
# ...
}
Problem
Bash completion for pass
worked out of the box,
pass show foo<Tab> #=> "pass show foobar"
but not so for pass otp,
pass ot<Tab> # no completion
pass otp show foo<Tab> # no completion
I was perplexed by this, because both packages provide completion scripts.
And both completion scripts were installed:
for dir in ${XDG_DATA_DIRS//:/ }
do
ls "$dir"/bash-completion/completions/pass* 2>/dev/null
done
/run/current-system/sw/share/bash-completion/completions/pass
/run/current-system/sw/share/bash-completion/completions/pass-otp
Solution
Poking around in /etc/bashrc
, I noticed this comment:
Bash loads completions in all $XDG_DATA_DIRS/bash-completion/completions/ on demand…
The pass
completion function is written in a way that allows extensions to register their additional completion functions, and the pass-otp completion script will indeed register it’s completion function when loaded. We just need to ensure that script actually gets loaded. We can’t rely on bash to load it on demand, since that strategy discovers the main command being completed (pass
), not the subcommands provided by an extension.
To get it working, I added the following to my nixos config:
programs.bash.interactiveShellInit = ''
. ${pkgs.pass.extensions.pass-otp}/share/bash-completion/completions/pass-otp
'';
By loading the pass-otp
completion script upfront, when we eventually trigger completion of a pass
command, the extension completion will already be registered, and thus visible to the pass
completion function as well.