Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Bash completion Ubuntu 20.04 #25

Open
semseysandor opened this issue Sep 4, 2021 · 10 comments
Open

Bash completion Ubuntu 20.04 #25

semseysandor opened this issue Sep 4, 2021 · 10 comments

Comments

@semseysandor
Copy link

After installing from the apt repository on Ubuntu 20.04, completion for bash was not working.

  • pass update 2.1
  • pass v1.7.3
  • GNU bash, version 5.0.17(1)-release

If I:

  • source /usr/share/bash-completion/completions/pass-update sourced manually the file (or in .bashrc),
  • or moved that to: sudo mv /usr/share/bash-completion/completions/pass-update /etc/bash_completion.d/
    then it was working.

In my understanding, completion scripts are loaded by /usr/share/bash-completion/bash_completion only if the completion script has the same name as the invoked command, which is pass in our case. The completion script for pass (/usr/share/bash-completion/completions/pass) will not source the pass-update script. If the completion function (__password_store_extension_complete_update) isn't defined yet it won't be called.
However completion scripts in /etc/bash_completion.d/ are sourced by /usr/share/bash-completion/bash_completion automatically.

So it seems on Ubuntu 20.04 /etc/bash_completion.d/ is the good place for this script:
8721eb0#diff-76ed074a9305c04054cdebb9e9aad2d818052b07091de1f20cad0bbac34ffb52

@so-rose
Copy link

so-rose commented May 29, 2022

I'm experiencing the exact same problem on Debian 11 (bullseye). With the exact same workaround of sourceing it in .bashrc.

@anarcat
Copy link

anarcat commented Feb 14, 2024

i'm working on an official debian package for this which has the patch built in, you can track the progress in #31 or in the Debian bug tracker. alternatively, this git repo "just" needs a new release to ship that patch, so I filed #32 about that.

@roddhjav
Copy link
Owner

roddhjav commented Feb 14, 2024

Wait, so Ubuntu needs /etc/bash_completion.d/ while Debian is looking for /usr/share/bash-completion/bash_completion/completions ? That does not look right.

@anarcat
Copy link

anarcat commented Feb 15, 2024

uh. now that i reread the original post here, i'm confused as well.

when i built the debian package here, lintian warned about the file in /etc, i assumed that was the issue. i assume the proper location is in /usr, no idea what's up with Ubuntu, but i would assume it's the same.

@semseysandor
Copy link
Author

I understand the issue now. The problem is not the directory, /usr/share/bash-completion/completions is the future-proof place (/etc/bash_completion.d is deprecated) for completions in Debian and Ubuntu also.

The issue is that completion scripts in /usr/share/bash-completion/completions are dynamically sourced if the completion script name complies with the naming conventions: it should be $cmd, $cmd.bash or _$cmd where $cmd is the invoked command name, which is pass in our case. So the script should be called pass, pass.bash or _pass, but these names are used by upstream pass, not one of it's extensions... /etc/bash_completion.d/ works as all scripts in this dir get sourced statically.

Though pass supports completion functions for extensions - __password_store_extension_complete_update here, but /usr/share/bash-completion/completions/pass-update is never sourced by bash, so the function is not defined and therefore not called by pass.

So this function could be moved to other file which are sourced (update.bash maybe) or source completion/pass-update.bash manually by update.bash.

@anarcat
Copy link

anarcat commented Feb 27, 2024

yeah, so i can confirm that issue as well. the problem is the auto-loading. i wonder how other extensions / software handle this. surely (e.g.) git has some tricks to fix this?

@roddhjav
Copy link
Owner

After a few tests, I can confirm the issue too. My other extensions have the same issue (they all install completion under /usr/share)

In pass-otp, it works because the file is installed in /etc/bash_completion.d (see https://github.com/tadfisher/pass-otp/blob/develop/Makefile)

@anarcat
Copy link

anarcat commented Feb 27, 2024

Hm. I don't know. here the git-annex completion (to give another example) works both with git-annex and git annex, even though the completion file is /usr/share/bash-completion/completions/git-annex.

here's the complete file, in case that matters:

# Use git-annex's built-in bash completion
# This is the same code output by git-annex --bash-completion-script git-annex
# This covers all commands, all options, and will never go out of date!
_git-annex()
{
    local CMDLINE
    local IFS=$'\n'
    CMDLINE=(--bash-completion-index $COMP_CWORD)

    for arg in ${COMP_WORDS[@]}; do
        CMDLINE=(${CMDLINE[@]} --bash-completion-word $arg)
    done

    COMPREPLY=( $(git-annex "${CMDLINE[@]}") )
}

complete -o bashdefault -o default -o filenames -F _git-annex git-annex

# Called by git's bash completion script when completing "git annex"
# Translate to the "git-annex" completion above.
_git_annex() {
    local CMDLINE
    CMDLINE=(--bash-completion-index $(($COMP_CWORD - 1)))

    local seen_git
    local seen_annex
    for arg in ${COMP_WORDS[@]}; do
        if [ "$arg" = git ] && [ -z "$seen_git" ]; then
		seen_git=1
		CMDLINE=(${CMDLINE[@]} --bash-completion-word git-annex)
	elif [ "$arg" = annex ] && [ -z "$seen_annex" ]; then
		seen_annex=1
	else
		CMDLINE=(${CMDLINE[@]} --bash-completion-word $arg)
	fi
    done

    # This is the same as __gitcomp_file_direct in git-completion.bash;
    local IFS=$'\n'
    COMPREPLY=( $(git-annex "${CMDLINE[@]}") )
    compopt -o filenames +o nospace ||
    compgen -f /non-existing-dir/ >/dev/null ||
    true
}

one thing I find interesting is this comment:

# Called by git's bash completion script when completing "git annex"

I think this is something in the git completion mechanism itself that allows sub-commands to define their own completion and auto-load them. And, lo-and-behold, here's this chunk in git's source:

__git_complete_command () {
	local command="$1"
	local completion_func="_git_${command//-/_}"
	if ! __git_have_func $completion_func &&
		__git_have_func _completion_loader
	then
		_completion_loader "git-$command"
	fi
	if __git_have_func $completion_func
	then
		$completion_func
		return 0
	elif __git_support_parseopt_helper "$command"
	then
		__git_complete_common "$command"
		return 0
	else
		return 1
	fi
}

So I think that's the key thing here: the pass completion mechanism needs a hook like this to delegate to extensions if they're available. Reading that source now there's some shim for PASSWORD_STORE_EXTENSION_COMMANDS but not if the extension is globally available.

So I think to fix this properly, one must patch pass directly.

@anarcat
Copy link

anarcat commented Feb 27, 2024

Interestingly, the pass completion also does not properly delegate the git the way it should be; it only hardcodes a few commands:

			git)
				COMPREPLY+=($(compgen -W "init push pull config log reflog rebase" -- ${cur}))
				;;

... so that's something that could be improved over there as well, but it's getting out of scope here.

@semseysandor
Copy link
Author

Turns out this is a long-known issue with the possible solution also (patch upstream pass):
tadfisher/pass-otp#28
tadfisher/pass-otp#137

Now I've submitted a patch on the mailing list:
https://lists.zx2c4.com/pipermail/password-store/2024-June/004860.html

Hopefully it will get merged.
Maybe you could push there, as patches are merged very rarely, there were only 2 commits accepted in 2023, and none (so far) in this year...

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging a pull request may close this issue.

4 participants