aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPaul Holzinger <paul.holzinger@web.de>2021-02-10 17:57:11 +0100
committerPaul Holzinger <paul.holzinger@web.de>2021-03-29 15:00:09 +0200
commit6a78fcaa0a5451e8b9839c689b01c9264e391401 (patch)
treeaaf09ea076b9a531526d7836fd0709a98a8e606b
parent259004f0a9cc18018127baec0bfcf8bc091dabb6 (diff)
downloadpodman-6a78fcaa0a5451e8b9839c689b01c9264e391401.tar.gz
podman-6a78fcaa0a5451e8b9839c689b01c9264e391401.tar.bz2
podman-6a78fcaa0a5451e8b9839c689b01c9264e391401.zip
Add powershell completions
Add support for generating powershell completion files. This is especially useful for people using the podman remote client on windows. [NO TESTS NEEDED] Signed-off-by: Paul Holzinger <paul.holzinger@web.de>
-rw-r--r--Makefile3
-rw-r--r--cmd/podman/completion/completion.go8
-rw-r--r--cmd/podman/root.go4
-rw-r--r--completions/powershell/podman-remote.ps1227
-rw-r--r--completions/powershell/podman.ps1227
-rw-r--r--docs/source/markdown/podman-completion.1.md25
6 files changed, 481 insertions, 13 deletions
diff --git a/Makefile b/Makefile
index 14e428397..49250f2fd 100644
--- a/Makefile
+++ b/Makefile
@@ -536,6 +536,7 @@ install.completions:
install ${SELINUXOPT} -d -m 755 ${DESTDIR}${FISHINSTALLDIR}
install ${SELINUXOPT} -m 644 completions/fish/podman.fish ${DESTDIR}${FISHINSTALLDIR}
install ${SELINUXOPT} -m 644 completions/fish/podman-remote.fish ${DESTDIR}${FISHINSTALLDIR}
+ # There is no common location for powershell files so do not install them. Users have to source the file from their powershell profile.
.PHONY: install.cni
install.cni:
@@ -658,7 +659,7 @@ install.libseccomp.sudo:
.PHONY: completions
completions: podman podman-remote
# key = shell, value = completion filename
- declare -A outfiles=([bash]=%s [zsh]=_%s [fish]=%s.fish);\
+ declare -A outfiles=([bash]=%s [zsh]=_%s [fish]=%s.fish [powershell]=%s.ps1);\
for shell in $${!outfiles[*]}; do \
for remote in "" "-remote"; do \
podman="podman$$remote"; \
diff --git a/cmd/podman/completion/completion.go b/cmd/podman/completion/completion.go
index a4ceab4b0..472068130 100644
--- a/cmd/podman/completion/completion.go
+++ b/cmd/podman/completion/completion.go
@@ -21,7 +21,7 @@ const (
var (
file string
noDesc bool
- shells = []string{"bash", "zsh", "fish"}
+ shells = []string{"bash", "zsh", "fish", "powershell"}
completionCmd = &cobra.Command{
Use: fmt.Sprintf("completion [options] {%s}", strings.Join(shells, "|")),
Short: "Generate shell autocompletions",
@@ -76,6 +76,12 @@ func completion(cmd *cobra.Command, args []string) error {
}
case "fish":
err = cmd.Root().GenFishCompletion(w, !noDesc)
+ case "powershell":
+ if noDesc {
+ err = cmd.Root().GenPowerShellCompletion(w)
+ } else {
+ err = cmd.Root().GenPowerShellCompletionWithDesc(w)
+ }
}
if err != nil {
diff --git a/cmd/podman/root.go b/cmd/podman/root.go
index 7722e35dd..2b77afbeb 100644
--- a/cmd/podman/root.go
+++ b/cmd/podman/root.go
@@ -3,7 +3,7 @@ package main
import (
"fmt"
"os"
- "path"
+ "path/filepath"
"runtime"
"runtime/pprof"
"strings"
@@ -57,7 +57,7 @@ Options:
var (
rootCmd = &cobra.Command{
- Use: path.Base(os.Args[0]) + " [options]",
+ Use: filepath.Base(os.Args[0]) + " [options]",
Long: "Manage pods, containers and images",
SilenceUsage: true,
SilenceErrors: true,
diff --git a/completions/powershell/podman-remote.ps1 b/completions/powershell/podman-remote.ps1
new file mode 100644
index 000000000..9cdbabc52
--- /dev/null
+++ b/completions/powershell/podman-remote.ps1
@@ -0,0 +1,227 @@
+# powershell completion for podman-remote -*- shell-script -*-
+
+function __podman-remote_debug {
+ if ($env:BASH_COMP_DEBUG_FILE) {
+ "$args" | Out-File -Append -FilePath "$env:BASH_COMP_DEBUG_FILE"
+ }
+}
+
+filter __podman-remote_escapeStringWithSpecialChars {
+ $_ -replace '\s|#|@|\$|;|,|''|\{|\}|\(|\)|"|`|\||<|>|&','`$&'
+}
+
+Register-ArgumentCompleter -CommandName 'podman-remote' -ScriptBlock {
+ param(
+ $WordToComplete,
+ $CommandAst,
+ $CursorPosition
+ )
+
+ # Get the current command line and convert into a string
+ $Command = $CommandAst.CommandElements
+ $Command = "$Command"
+
+ __podman-remote_debug ""
+ __podman-remote_debug "========= starting completion logic =========="
+ __podman-remote_debug "WordToComplete: $WordToComplete Command: $Command CursorPosition: $CursorPosition"
+
+ # The user could have moved the cursor backwards on the command-line.
+ # We need to trigger completion from the $CursorPosition location, so we need
+ # to truncate the command-line ($Command) up to the $CursorPosition location.
+ # Make sure the $Command is longer then the $CursorPosition before we truncate.
+ # This happens because the $Command does not include the last space.
+ if ($Command.Length -gt $CursorPosition) {
+ $Command=$Command.Substring(0,$CursorPosition)
+ }
+ __podman-remote_debug "Truncated command: $Command"
+
+ $ShellCompDirectiveError=1
+ $ShellCompDirectiveNoSpace=2
+ $ShellCompDirectiveNoFileComp=4
+ $ShellCompDirectiveFilterFileExt=8
+ $ShellCompDirectiveFilterDirs=16
+
+ # Prepare the command to request completions for the program.
+ # Split the command at the first space to separate the program and arguments.
+ $Program,$Arguments = $Command.Split(" ",2)
+ $RequestComp="$Program __complete $Arguments"
+ __podman-remote_debug "RequestComp: $RequestComp"
+
+ # we cannot use $WordToComplete because it
+ # has the wrong values if the cursor was moved
+ # so use the last argument
+ if ($WordToComplete -ne "" ) {
+ $WordToComplete = $Arguments.Split(" ")[-1]
+ }
+ __podman-remote_debug "New WordToComplete: $WordToComplete"
+
+
+ # Check for flag with equal sign
+ $IsEqualFlag = ($WordToComplete -Like "--*=*" )
+ if ( $IsEqualFlag ) {
+ __podman-remote_debug "Completing equal sign flag"
+ # Remove the flag part
+ $Flag,$WordToComplete = $WordToComplete.Split("=",2)
+ }
+
+ if ( $WordToComplete -eq "" -And ( -Not $IsEqualFlag )) {
+ # 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 method.
+ __podman-remote_debug "Adding extra empty parameter"
+ # We need to use `"`" to pass an empty argument a "" or '' does not work!!!
+ $RequestComp="$RequestComp" + ' `"`"'
+ }
+
+ __podman-remote_debug "Calling $RequestComp"
+ #call the command store the output in $out and redirect stderr and stdout to null
+ # $Out is an array contains each line per element
+ Invoke-Expression -OutVariable out "$RequestComp" 2>&1 | Out-Null
+
+
+ # get directive from last line
+ [int]$Directive = $Out[-1].TrimStart(':')
+ if ($Directive -eq "") {
+ # There is no directive specified
+ $Directive = 0
+ }
+ __podman-remote_debug "The completion directive is: $Directive"
+
+ # remove directive (last element) from out
+ $Out = $Out | Where-Object { $_ -ne $Out[-1] }
+ __podman-remote_debug "The completions are: $Out"
+
+ if (($Directive -band $ShellCompDirectiveError) -ne 0 ) {
+ # Error code. No completion.
+ __podman-remote_debug "Received error from custom completion go code"
+ return
+ }
+
+ $Longest = 0
+ $Values = $Out | ForEach-Object {
+ #Split the output in name and description
+ $Name, $Description = $_.Split("`t",2)
+ __podman-remote_debug "Name: $Name Description: $Description"
+
+ # Look for the longest completion so that we can format things nicely
+ if ($Longest -lt $Name.Length) {
+ $Longest = $Name.Length
+ }
+
+ # Set the description to a one space string if there is none set.
+ # This is needed because the CompletionResult does not accept an empty string as argument
+ if (-Not $Description) {
+ $Description = " "
+ }
+ @{Name="$Name";Description="$Description"}
+ }
+
+
+ $Space = " "
+ if (($Directive -band $ShellCompDirectiveNoSpace) -ne 0 ) {
+ # remove the space here
+ __podman-remote_debug "ShellCompDirectiveNoSpace is called"
+ $Space = ""
+ }
+
+ if (($Directive -band $ShellCompDirectiveNoFileComp) -ne 0 ) {
+ __podman-remote_debug "ShellCompDirectiveNoFileComp is called"
+
+ if ($Values.Length -eq 0) {
+ # Just print an empty string here so the
+ # shell does not start to complete paths.
+ # We cannot use CompletionResult here because
+ # it does not accept an empty string as argument.
+ ""
+ return
+ }
+ }
+
+ if ((($Directive -band $ShellCompDirectiveFilterFileExt) -ne 0 ) -or
+ (($Directive -band $ShellCompDirectiveFilterDirs) -ne 0 )) {
+ __podman-remote_debug "ShellCompDirectiveFilterFileExt ShellCompDirectiveFilterDirs are not supported"
+
+ # return here to prevent the completion of the extensions
+ return
+ }
+
+ $Values = $Values | Where-Object {
+ # filter the result
+ $_.Name -like "$WordToComplete*"
+
+ # Join the flag back if we have a equal sign flag
+ if ( $IsEqualFlag ) {
+ __podman-remote_debug "Join the equal sign flag back to the completion value"
+ $_.Name = $Flag + "=" + $_.Name
+ }
+ }
+
+ # Get the current mode
+ $Mode = (Get-PSReadLineKeyHandler | Where-Object {$_.Key -eq "Tab" }).Function
+ __podman-remote_debug "Mode: $Mode"
+
+ $Values | ForEach-Object {
+
+ # store temporay because switch will overwrite $_
+ $comp = $_
+
+ # PowerShell supports three different completion modes
+ # - TabCompleteNext (default windows style - on each key press the next option is displayed)
+ # - Complete (works like bash)
+ # - MenuComplete (works like zsh)
+ # You set the mode with Set-PSReadLineKeyHandler -Key Tab -Function <mode>
+
+ # CompletionResult Arguments:
+ # 1) CompletionText text to be used as the auto completion result
+ # 2) ListItemText text to be displayed in the suggestion list
+ # 3) ResultType type of completion result
+ # 4) ToolTip text for the tooltip with details about the object
+
+ switch ($Mode) {
+
+ # bash like
+ "Complete" {
+
+ if ($Values.Length -eq 1) {
+ __podman-remote_debug "Only one completion left"
+
+ # insert space after value
+ [System.Management.Automation.CompletionResult]::new($($comp.Name | __podman-remote_escapeStringWithSpecialChars) + $Space, "$($comp.Name)", 'ParameterValue', "$($comp.Description)")
+
+ } else {
+ # Add the proper number of spaces to align the descriptions
+ while($comp.Name.Length -lt $Longest) {
+ $comp.Name = $comp.Name + " "
+ }
+
+ # Check for empty description and only add parentheses if needed
+ if ($($comp.Description) -eq " " ) {
+ $Description = ""
+ } else {
+ $Description = " ($($comp.Description))"
+ }
+
+ [System.Management.Automation.CompletionResult]::new("$($comp.Name)$Description", "$($comp.Name)$Description", 'ParameterValue', "$($comp.Description)")
+ }
+ }
+
+ # zsh like
+ "MenuComplete" {
+ # insert space after value
+ # MenuComplete will automatically show the ToolTip of
+ # the highlighted value at the bottom of the suggestions.
+ [System.Management.Automation.CompletionResult]::new($($comp.Name | __podman-remote_escapeStringWithSpecialChars) + $Space, "$($comp.Name)", 'ParameterValue', "$($comp.Description)")
+ }
+
+ # TabCompleteNext and in case we get something unknown
+ Default {
+ # Like MenuComplete but we don't want to add a space here because
+ # the user need to press space anyway to get the completion.
+ # Description will not be shown because thats not possible with TabCompleteNext
+ [System.Management.Automation.CompletionResult]::new($($comp.Name | __podman-remote_escapeStringWithSpecialChars), "$($comp.Name)", 'ParameterValue', "$($comp.Description)")
+ }
+ }
+
+ }
+}
+
+# This file is generated with "podman-remote completion"; see: podman-completion(1)
diff --git a/completions/powershell/podman.ps1 b/completions/powershell/podman.ps1
new file mode 100644
index 000000000..6b6f832d2
--- /dev/null
+++ b/completions/powershell/podman.ps1
@@ -0,0 +1,227 @@
+# powershell completion for podman -*- shell-script -*-
+
+function __podman_debug {
+ if ($env:BASH_COMP_DEBUG_FILE) {
+ "$args" | Out-File -Append -FilePath "$env:BASH_COMP_DEBUG_FILE"
+ }
+}
+
+filter __podman_escapeStringWithSpecialChars {
+ $_ -replace '\s|#|@|\$|;|,|''|\{|\}|\(|\)|"|`|\||<|>|&','`$&'
+}
+
+Register-ArgumentCompleter -CommandName 'podman' -ScriptBlock {
+ param(
+ $WordToComplete,
+ $CommandAst,
+ $CursorPosition
+ )
+
+ # Get the current command line and convert into a string
+ $Command = $CommandAst.CommandElements
+ $Command = "$Command"
+
+ __podman_debug ""
+ __podman_debug "========= starting completion logic =========="
+ __podman_debug "WordToComplete: $WordToComplete Command: $Command CursorPosition: $CursorPosition"
+
+ # The user could have moved the cursor backwards on the command-line.
+ # We need to trigger completion from the $CursorPosition location, so we need
+ # to truncate the command-line ($Command) up to the $CursorPosition location.
+ # Make sure the $Command is longer then the $CursorPosition before we truncate.
+ # This happens because the $Command does not include the last space.
+ if ($Command.Length -gt $CursorPosition) {
+ $Command=$Command.Substring(0,$CursorPosition)
+ }
+ __podman_debug "Truncated command: $Command"
+
+ $ShellCompDirectiveError=1
+ $ShellCompDirectiveNoSpace=2
+ $ShellCompDirectiveNoFileComp=4
+ $ShellCompDirectiveFilterFileExt=8
+ $ShellCompDirectiveFilterDirs=16
+
+ # Prepare the command to request completions for the program.
+ # Split the command at the first space to separate the program and arguments.
+ $Program,$Arguments = $Command.Split(" ",2)
+ $RequestComp="$Program __complete $Arguments"
+ __podman_debug "RequestComp: $RequestComp"
+
+ # we cannot use $WordToComplete because it
+ # has the wrong values if the cursor was moved
+ # so use the last argument
+ if ($WordToComplete -ne "" ) {
+ $WordToComplete = $Arguments.Split(" ")[-1]
+ }
+ __podman_debug "New WordToComplete: $WordToComplete"
+
+
+ # Check for flag with equal sign
+ $IsEqualFlag = ($WordToComplete -Like "--*=*" )
+ if ( $IsEqualFlag ) {
+ __podman_debug "Completing equal sign flag"
+ # Remove the flag part
+ $Flag,$WordToComplete = $WordToComplete.Split("=",2)
+ }
+
+ if ( $WordToComplete -eq "" -And ( -Not $IsEqualFlag )) {
+ # 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 method.
+ __podman_debug "Adding extra empty parameter"
+ # We need to use `"`" to pass an empty argument a "" or '' does not work!!!
+ $RequestComp="$RequestComp" + ' `"`"'
+ }
+
+ __podman_debug "Calling $RequestComp"
+ #call the command store the output in $out and redirect stderr and stdout to null
+ # $Out is an array contains each line per element
+ Invoke-Expression -OutVariable out "$RequestComp" 2>&1 | Out-Null
+
+
+ # get directive from last line
+ [int]$Directive = $Out[-1].TrimStart(':')
+ if ($Directive -eq "") {
+ # There is no directive specified
+ $Directive = 0
+ }
+ __podman_debug "The completion directive is: $Directive"
+
+ # remove directive (last element) from out
+ $Out = $Out | Where-Object { $_ -ne $Out[-1] }
+ __podman_debug "The completions are: $Out"
+
+ if (($Directive -band $ShellCompDirectiveError) -ne 0 ) {
+ # Error code. No completion.
+ __podman_debug "Received error from custom completion go code"
+ return
+ }
+
+ $Longest = 0
+ $Values = $Out | ForEach-Object {
+ #Split the output in name and description
+ $Name, $Description = $_.Split("`t",2)
+ __podman_debug "Name: $Name Description: $Description"
+
+ # Look for the longest completion so that we can format things nicely
+ if ($Longest -lt $Name.Length) {
+ $Longest = $Name.Length
+ }
+
+ # Set the description to a one space string if there is none set.
+ # This is needed because the CompletionResult does not accept an empty string as argument
+ if (-Not $Description) {
+ $Description = " "
+ }
+ @{Name="$Name";Description="$Description"}
+ }
+
+
+ $Space = " "
+ if (($Directive -band $ShellCompDirectiveNoSpace) -ne 0 ) {
+ # remove the space here
+ __podman_debug "ShellCompDirectiveNoSpace is called"
+ $Space = ""
+ }
+
+ if (($Directive -band $ShellCompDirectiveNoFileComp) -ne 0 ) {
+ __podman_debug "ShellCompDirectiveNoFileComp is called"
+
+ if ($Values.Length -eq 0) {
+ # Just print an empty string here so the
+ # shell does not start to complete paths.
+ # We cannot use CompletionResult here because
+ # it does not accept an empty string as argument.
+ ""
+ return
+ }
+ }
+
+ if ((($Directive -band $ShellCompDirectiveFilterFileExt) -ne 0 ) -or
+ (($Directive -band $ShellCompDirectiveFilterDirs) -ne 0 )) {
+ __podman_debug "ShellCompDirectiveFilterFileExt ShellCompDirectiveFilterDirs are not supported"
+
+ # return here to prevent the completion of the extensions
+ return
+ }
+
+ $Values = $Values | Where-Object {
+ # filter the result
+ $_.Name -like "$WordToComplete*"
+
+ # Join the flag back if we have a equal sign flag
+ if ( $IsEqualFlag ) {
+ __podman_debug "Join the equal sign flag back to the completion value"
+ $_.Name = $Flag + "=" + $_.Name
+ }
+ }
+
+ # Get the current mode
+ $Mode = (Get-PSReadLineKeyHandler | Where-Object {$_.Key -eq "Tab" }).Function
+ __podman_debug "Mode: $Mode"
+
+ $Values | ForEach-Object {
+
+ # store temporay because switch will overwrite $_
+ $comp = $_
+
+ # PowerShell supports three different completion modes
+ # - TabCompleteNext (default windows style - on each key press the next option is displayed)
+ # - Complete (works like bash)
+ # - MenuComplete (works like zsh)
+ # You set the mode with Set-PSReadLineKeyHandler -Key Tab -Function <mode>
+
+ # CompletionResult Arguments:
+ # 1) CompletionText text to be used as the auto completion result
+ # 2) ListItemText text to be displayed in the suggestion list
+ # 3) ResultType type of completion result
+ # 4) ToolTip text for the tooltip with details about the object
+
+ switch ($Mode) {
+
+ # bash like
+ "Complete" {
+
+ if ($Values.Length -eq 1) {
+ __podman_debug "Only one completion left"
+
+ # insert space after value
+ [System.Management.Automation.CompletionResult]::new($($comp.Name | __podman_escapeStringWithSpecialChars) + $Space, "$($comp.Name)", 'ParameterValue', "$($comp.Description)")
+
+ } else {
+ # Add the proper number of spaces to align the descriptions
+ while($comp.Name.Length -lt $Longest) {
+ $comp.Name = $comp.Name + " "
+ }
+
+ # Check for empty description and only add parentheses if needed
+ if ($($comp.Description) -eq " " ) {
+ $Description = ""
+ } else {
+ $Description = " ($($comp.Description))"
+ }
+
+ [System.Management.Automation.CompletionResult]::new("$($comp.Name)$Description", "$($comp.Name)$Description", 'ParameterValue', "$($comp.Description)")
+ }
+ }
+
+ # zsh like
+ "MenuComplete" {
+ # insert space after value
+ # MenuComplete will automatically show the ToolTip of
+ # the highlighted value at the bottom of the suggestions.
+ [System.Management.Automation.CompletionResult]::new($($comp.Name | __podman_escapeStringWithSpecialChars) + $Space, "$($comp.Name)", 'ParameterValue', "$($comp.Description)")
+ }
+
+ # TabCompleteNext and in case we get something unknown
+ Default {
+ # Like MenuComplete but we don't want to add a space here because
+ # the user need to press space anyway to get the completion.
+ # Description will not be shown because thats not possible with TabCompleteNext
+ [System.Management.Automation.CompletionResult]::new($($comp.Name | __podman_escapeStringWithSpecialChars), "$($comp.Name)", 'ParameterValue', "$($comp.Description)")
+ }
+ }
+
+ }
+}
+
+# This file is generated with "podman completion"; see: podman-completion(1)
diff --git a/docs/source/markdown/podman-completion.1.md b/docs/source/markdown/podman-completion.1.md
index 50b0b6145..59d88f699 100644
--- a/docs/source/markdown/podman-completion.1.md
+++ b/docs/source/markdown/podman-completion.1.md
@@ -4,10 +4,10 @@
podman\-completion - Generate shell completion scripts
## SYNOPSIS
-**podman completion** [*options*] *bash*|*zsh*|*fish*
+**podman completion** [*options*] *bash*|*zsh*|*fish*|*powershell*
## DESCRIPTION
-The completion command allows you to generate shell completion scripts. Supported shells are **bash**, **zsh** and **fish**.
+The completion command generates shell completion scripts for a variety of shells. Supported shells are **bash**, **zsh**, **fish** and **powershell**.
These script are used by the shell to provide suggestions and complete commands when you are typing the command and press [TAB].
@@ -25,32 +25,39 @@ Do not provide description in the completions.
## Installation
### BASH
-Make sure you have `bash-completion` installed on your system.
+Make sure you have `bash-completion` installed on the system.
-To load the completion script into your current session run:
+To load the completion script into the current session run:
`source <(podman completion bash)`
-To make it available in all your bash sessions run:
+To make it available for all bash sessions run:
`podman completion bash -f /etc/bash_completion.d/podman`
### ZSH
-If shell completion is not already enabled in your environment you will need to enable it. You can execute the following once:
+If shell completion is not already enabled in the environment you will need to enable it. You can execute the following once:
`echo "autoload -U compinit; compinit" >> ~/.zshrc`
-To make it available in all your zsh sessions run:
+To make it available for all zsh sessions run:
`podman completion zsh -f "${fpath[1]}/_podman"`
Once you reload the shell the autocompletion should be working.
### FISH
-To load the completion script into your current session run:
+To load the completion script into the current session run:
`podman completion fish | source`
-To make it available in all your fish sessions run:
+To make it available for all fish sessions run:
`podman completion fish -f ~/.config/fish/completions/podman.fish`
+### POWERSHELL
+To load the completion script into the current session run:
+`podman.exe completion powershell | Out-String | Invoke-Expression`
+
+To make it available in all powershell sessions that a user has, write the
+completion output to a file and source that to the user's powershell profile.
+More information about profiles is available with `Get-Help about_Profiles`.
## SEE ALSO
[podman(1)](podman.1.md)