containers / podman

Podman: A tool for managing OCI containers and pods.
https://podman.io
Apache License 2.0
23.44k stars 2.38k forks source link

podman completion is missing from podman help #14110

Closed IzhakJakov closed 2 years ago

IzhakJakov commented 2 years ago

I was able to find docs for podman completion here but I would expect it to be part of the Available Commands section when using podman help

vrothberg commented 2 years ago

Thanks for reaching out, @IzhakJakov.

I don't think we want to "support" this command as it is primarily used in the build system. I wonder why it's listed in the docs at all.

@containers/podman-maintainers WDYT?

Luap99 commented 2 years ago

There is exactly one reason why I did this.

If the command is hidden it will not be displayed in help and also not suggested via shell complation. Since podman completion is not a command that will be run often I decided to hide this. Most users should not care, the package manager will install the completion scripts for you.

If we show this, podman com[TAB] would not complete to commit but will suggest both completion and commit instead. I don't like this.

I added it to the docs because I had to document it somehwere and the man page is the best place IMO.

rhatdan commented 2 years ago

I think it should be totally hidden, just like some other commands. I don't believe we want users playing with it, so we should hide the fact it exists.

Luap99 commented 2 years ago

I disagree. We cannot guarantee that this will be installed via package manager. For example on windows you would need to manually load it into powershell. I think it is good to have this documented.

rhatdan commented 2 years ago

Huh? How does a man page about podman completion solve the powershell issue?

vrothberg commented 2 years ago

I think the man page causes confusion (as here in the issue). If we want to leave breadcrumbs, we could put an .md into the ./docs folder.

Luap99 commented 2 years ago

Huh? How does a man page about podman completion solve the powershell issue?

It doesn't solve issues. It is about having this documented so users know that this exists. Using ./docs will mean that it will not be shipped (for example in the windows.msi but also linux distros). If you take a look at the page it actually list an option you can use to customize the completion experience. I see no reason why users should not use this command if they wish too.

If the goal is to sync the man page with podman --help I would vote for making the command visible.

vrothberg commented 2 years ago

Let me rephrase the question: Is podman completion a command we support?

If we don't and only use it for packaging, I think it should not have a man page. If we do, we should list in the help message.

rhatdan commented 2 years ago

support is a tough word. The question is do we want user to be using it for reasons outside of the ways we use it, and would it be supported. I believe we do not. I believe this is an internal command and should not be documented.

Luap99 commented 2 years ago

Why wouldn't we support it? I have no problem with fixing bugs in it. The command only exposes the functions from github.com/spf13/cobra. I don't think there are problems with that, that are not already present in the generated script which we package.

rhatdan commented 2 years ago

If users use it in a way that we don't intend and we want to change the way it works, we could break their functionality. If it is only internal, then we control the API/CLI to do what we want.

There are several commands and options that we do not document for this reason. Remember that this stuff roles into RHEL and signs us up for support for years. I don't believe we should expose anything that is not core to the way we want Podman to run.

IzhakJakov commented 2 years ago

I don't know if you guys plan to support this or not but I hope you do as I find completion very useful both for command discovery and time saving.

BTW, the instructions in the document above are wrong:

 ❯ podman completion -f "${fpath[1]}/_podman zsh"
Error: accepts 1 arg(s), received 0

The instructions from podman help completion make more sense:

 ❯ podman completion zsh -f "${fpath[1]}/_podman"

 ❯ ll "${fpath[1]}/_podman"
lrwxr-xr-x    61 me 2022-05-04 08:51 /usr/local/share/zsh/site-functions/_podman -> ../../../Cellar/podman/4.0.3/share/zsh/site-functions/_podman

However this is not working either 😞

Luap99 commented 2 years ago

@IzhakJakov if you go to the latest page you will see the the incorrect example has been fixed in the docs.

Did you restart your shell? Otherwise the completion will not take effect.

IzhakJakov commented 2 years ago

@IzhakJakov if you go to the latest page you will see the the incorrect example has been fixed in the docs.

Confirmed fixed in latest. I will update my link in the description. Thank you!

Did you restart your shell? Otherwise the completion will not take effect.

Yes I did and even tried source <(podman completion zsh), which suppose to work even without restarting the shell.

Luap99 commented 2 years ago

Yes I did and even tried source <(podman completion zsh), which suppose to work even without restarting the shell.

No source <(podman completion zsh) should not work, there plenty of upstream issues but allowing this to work cause performance issues. Please the cobra docs for this, https://github.com/spf13/cobra/blob/master/shell_completions.md.

This is very likely an issue with your shell config. Does other shell completion work for you?

IzhakJakov commented 2 years ago

Yes everything else I am using is working. and source <(podman completion zsh) should work though it would not last beyond the session it was called in. I am not saying it is the best solution (generating the completion function every time is not the most efficient way) but it should work. Cobra's document only shows how to permanent install the completion but it does not mean that sourcing it every time would not work.

IzhakJakov commented 2 years ago

Here is the result of my podman completion zsh:

#compdef _podman podman

# zsh completion for podman                               -*- shell-script -*-

__podman_debug()
{
    local file="$BASH_COMP_DEBUG_FILE"
    if [[ -n ${file} ]]; then
        echo "$*" >> "${file}"
    fi
}

_podman()
{
    local shellCompDirectiveError=1
    local shellCompDirectiveNoSpace=2
    local shellCompDirectiveNoFileComp=4
    local shellCompDirectiveFilterFileExt=8
    local shellCompDirectiveFilterDirs=16

    local lastParam lastChar flagPrefix requestComp out directive comp lastComp noSpace
    local -a completions

    __podman_debug "\n========= starting completion logic =========="
    __podman_debug "CURRENT: ${CURRENT}, words[*]: ${words[*]}"

    # The user could have moved the cursor backwards on the command-line.
    # We need to trigger completion from the $CURRENT location, so we need
    # to truncate the command-line ($words) up to the $CURRENT location.
    # (We cannot use $CURSOR as its value does not work when a command is an alias.)
    words=("${=words[1,CURRENT]}")
    __podman_debug "Truncated words[*]: ${words[*]},"

    lastParam=${words[-1]}
    lastChar=${lastParam[-1]}
    __podman_debug "lastParam: ${lastParam}, lastChar: ${lastChar}"

    # For zsh, when completing a flag with an = (e.g., podman -n=<TAB>)
    # completions must be prefixed with the flag
    setopt local_options BASH_REMATCH
    if [[ "${lastParam}" =~ '-.*=' ]]; then
        # We are dealing with a flag with an =
        flagPrefix="-P ${BASH_REMATCH}"
    fi

    # Prepare the command to obtain completions
    requestComp="${words[1]} __complete ${words[2,-1]}"
    if [ "${lastChar}" = "" ]; then
        # If the last parameter is complete (there is a space following it)
        # We add an extra empty parameter so we can indicate this to the go completion code.
        __podman_debug "Adding extra empty parameter"
        requestComp="${requestComp} \"\""
    fi

    __podman_debug "About to call: eval ${requestComp}"

    # Use eval to handle any environment variables and such
    out=$(eval ${requestComp} 2>/dev/null)
    __podman_debug "completion output: ${out}"

    # Extract the directive integer following a : from the last line
    local lastLine
    while IFS='\n' read -r line; do
        lastLine=${line}
    done < <(printf "%s\n" "${out[@]}")
    __podman_debug "last line: ${lastLine}"

    if [ "${lastLine[1]}" = : ]; then
        directive=${lastLine[2,-1]}
        # Remove the directive including the : and the newline
        local suffix
        (( suffix=${#lastLine}+2))
        out=${out[1,-$suffix]}
    else
        # There is no directive specified.  Leave $out as is.
        __podman_debug "No directive found.  Setting do default"
        directive=0
    fi

    __podman_debug "directive: ${directive}"
    __podman_debug "completions: ${out}"
    __podman_debug "flagPrefix: ${flagPrefix}"

    if [ $((directive & shellCompDirectiveError)) -ne 0 ]; then
        __podman_debug "Completion received error. Ignoring completions."
        return
    fi

    while IFS='\n' read -r comp; do
        if [ -n "$comp" ]; then
            # If requested, completions are returned with a description.
            # The description is preceded by a TAB character.
            # For zsh's _describe, we need to use a : instead of a TAB.
            # We first need to escape any : as part of the completion itself.
            comp=${comp//:/\\:}

            local tab=$(printf '\t')
            comp=${comp//$tab/:}

            __podman_debug "Adding completion: ${comp}"
            completions+=${comp}
            lastComp=$comp
        fi
    done < <(printf "%s\n" "${out[@]}")

    if [ $((directive & shellCompDirectiveNoSpace)) -ne 0 ]; then
        __podman_debug "Activating nospace."
        noSpace="-S ''"
    fi

    if [ $((directive & shellCompDirectiveFilterFileExt)) -ne 0 ]; then
        # File extension filtering
        local filteringCmd
        filteringCmd='_files'
        for filter in ${completions[@]}; do
            if [ ${filter[1]} != '*' ]; then
                # zsh requires a glob pattern to do file filtering
                filter="\*.$filter"
            fi
            filteringCmd+=" -g $filter"
        done
        filteringCmd+=" ${flagPrefix}"

        __podman_debug "File filtering command: $filteringCmd"
        _arguments '*:filename:'"$filteringCmd"
    elif [ $((directive & shellCompDirectiveFilterDirs)) -ne 0 ]; then
        # File completion for directories only
        local subdir
        subdir="${completions[1]}"
        if [ -n "$subdir" ]; then
            __podman_debug "Listing directories in $subdir"
            pushd "${subdir}" >/dev/null 2>&1
        else
            __podman_debug "Listing directories in ."
        fi

        local result
        _arguments '*:dirname:_files -/'" ${flagPrefix}"
        result=$?
        if [ -n "$subdir" ]; then
            popd >/dev/null 2>&1
        fi
        return $result
    else
        __podman_debug "Calling _describe"
        if eval _describe "completions" completions $flagPrefix $noSpace; then
            __podman_debug "_describe found some completions"

            # Return the success of having called _describe
            return 0
        else
            __podman_debug "_describe did not find completions."
            __podman_debug "Checking if we should do file completion."
            if [ $((directive & shellCompDirectiveNoFileComp)) -ne 0 ]; then
                __podman_debug "deactivating file completion"

                # We must return an error code here to let zsh know that there were no
                # completions found by _describe; this is what will trigger other
                # matching algorithms to attempt to find completions.
                # For example zsh can match letters in the middle of words.
                return 1
            else
                # Perform file completion
                __podman_debug "Activating file completion"

                # We must return the result of this command, so it must be the
                # last command, or else we must store its result to return it.
                _arguments '*:filename:_files'" ${flagPrefix}"
            fi
        fi
    fi
}

# don't run the completion function when being source-ed or eval-ed
if [ "$funcstack[1]" = "_podman" ]; then
    _podman
fi

# This file is generated with "podman completion"; see: podman-completion(1)

@Luap99 If podman's completion works for you on zsh. Would you mind sharing the content of podman completion zsh?

Luap99 commented 2 years ago

source <(podman completion zsh) should work though

No this does not work with the script! Just look at the last lines of the script, you need to do this: https://github.com/spf13/cobra/pull/1608/files

I have exactly the same generated completion script and it works for me. I know that this also works for other people who are using zsh. I do not use zsh so I am not aware of all the settings you need but there is something which cause it to not work.

You can export BASH_COMP_DEBUG_FILE=somefile, then if you press podman [tab] the completion script should print some debug information to this file.

IzhakJakov commented 2 years ago

No this does not work with the script! Just look at the last lines of the script, you need to do this: https://github.com/spf13/cobra/pull/1608/files

Right! I learned something new :)

Thank you my podman completion working now if I add:

source <(podman completion zsh) && compdef _podman podman

Not sure why the autoload from /usr/local/share/zsh/site-functions/_podman is ignored but at least there's a workaround 😊

Luap99 commented 2 years ago

@IzhakJakov Maybe related: https://github.com/spf13/cobra/issues/1529

Anyway the point of the issue is that completion is not in --help but listed in the docs. I peronally think this is fine but others seem to disagree. I am fine with making the command visible in --help but I strongly disagree in removing the documentation and/or not supporting this command. The completion command is not something I invented. It is a common thing in applications who use the cobra library. In recent versions this command is even added automatically and application have to actively opt out. You will find this in many applications, e.g. kubectl

github-actions[bot] commented 2 years ago

A friendly reminder that this issue had no activity for 30 days.

cdoern commented 2 years ago

@Luap99 didn't you merge something for this?

Luap99 commented 2 years ago

No I still do not have clear answer. We hide this command in skopeo as well so I see no reason to show it in podman.

rhatdan commented 2 years ago

Keep it hidden. It is not supposed to be used by general users.