[PATCH 9/9] tools: Set IFS for bash completion script

Michal Privoznik mprivozn at redhat.com
Tue Jan 26 13:27:13 UTC 2021

The way our bash completion string is that is gets user's input
and lets virsh completion code do all the work by calling 'virsh
complete -- $INPUT". The 'complete' command is a "secret",
unlisted command that exists solely for this purpose. After it
has done it's part, it prints candidates onto stdout, each
candidate on its own line, e.g. like this:

  # virsh complete -- "net-u"

These strings are then stored into a bash array $A like this:

  A=($($1 ${CMDLINE} complete -- "${INPUT[@]}" 2>/dev/null))

This array is then thrown back at bash completion to produce
desired output. So far so good. Except, when there is an option
with space. For instance:

  # virsh complete -- start --domain ""
  uefi\ duplicate

Bash interprets that as another array item because by default,
Internal Field Separator (IFS) = set of characters that bash uses
to split words at, is: space, TAB, newline. We don't want space
nor TAB. Therefore, we have to set $IFS when storing 'virsh
complete' output into the array.

Thanks to Peter who suggested it.

Resolves: https://gitlab.com/libvirt/libvirt/-/issues/116
Signed-off-by: Michal Privoznik <mprivozn at redhat.com>
 tools/bash-completion/vsh | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/tools/bash-completion/vsh b/tools/bash-completion/vsh
index fb38e8616f..bbb25fc3eb 100644
--- a/tools/bash-completion/vsh
+++ b/tools/bash-completion/vsh
@@ -56,7 +56,7 @@ _vsh_complete()
     # the name of the command whose arguments are being
     # completed.
     # Therefore, we might just run $1.
-    A=($($1 ${CMDLINE} complete -- "${INPUT[@]}" 2>/dev/null))
+    IFS=$'\n' A=($($1 ${CMDLINE} complete -- "${INPUT[@]}" 2>/dev/null))
     COMPREPLY=($(compgen -W "${A[*]%--}" -- ${cur}))
     __ltrim_colon_completions "$cur"

More information about the libvir-list mailing list