For some reason bash completion doesn't work when I obtain from help text. I know this sounds cryptic but please read further to understand me.
This is my C++ file compiled and placed as dbcmd
executable file in one of the PATHs:
$ cat dbcmd.cpp
#include <iostream>
#include <string>
#include <vector>
static void usage()
{
std::cerr << "Usage: dbcmd [<command> [<command-args>]]\n";
std::cerr << "Commands:\n";
std::vector<std::string> commands;
commands.push_back("backup");
commands.push_back("db-backup");
commands.push_back("db-purge");
commands.push_back("load");
commands.push_back("debug");
commands.push_back("analyze");
commands.push_back("cycle");
commands.push_back("endday");
commands.push_back("gendbset");
commands.push_back("help");
commands.push_back("perform");
commands.push_back("print");
commands.push_back("remove");
commands.push_back("restart");
commands.push_back("dump");
commands.push_back("start");
commands.push_back("status");
commands.push_back("stop");
commands.push_back("tables");
commands.push_back("info");
commands.push_back("update");
for (auto command: commands)
std::cerr << " " << command << "\n";
}
int main()
{
usage();
return 0;
}
And this is my bash completion script (credit):
$ cat dbcmd_completion.bash
#/usr/bin/env bash
_dbcmd_completions()
{
if [ "${#COMP_WORDS[@]}" != "2" ]; then
return
fi
local IFS=$'\n'
local list_var="$(dbcmd|awk -F '\t' '{printf("%s", $1)}'|sed 's/.*://'|sed 's/^\s.//'|sed 's/\s\+/ /g')"
local suggestions=($(compgen -W "$list_var" -- "${COMP_WORDS[1]}"))
if [ "${#suggestions[@]}" == "1" ]; then
local number="${suggestions[0]/%\ */}"
COMPREPLY=("$number")
else
for i in "${!suggestions[@]}"; do
suggestions[$i]="$(printf '%*s' "-$COLUMNS" "${suggestions[$i]}")"
done
COMPREPLY=("${suggestions[@]}")
fi
}
_dothis_completions()
{
if [ "${#COMP_WORDS[@]}" != "2" ]; then
return
fi
local list_var="backup db-backup db-purge load debug analyze cycle endday gendbset help perform print remove restart dump start status stop tables info update"
local suggestions=($(compgen -W "$list_var" -- "${COMP_WORDS[1]}"))
if [ "${#suggestions[@]}" == "1" ]; then
local number="${suggestions[0]/%\ */}"
COMPREPLY=("$number")
else
for i in "${!suggestions[@]}"; do
suggestions[$i]="$(printf '%*s' "-$COLUMNS" "${suggestions[$i]}")"
done
COMPREPLY=("${suggestions[@]}")
fi
}
#complete -F _dothis_completions dbcmd
complete -F _dbcmd_completions dbcmd
When I uncomment and use _dothis_completions
it works perfectly, but _dbcmd_completions
--which obtains completion list from help text of dbcmd
--doesn't work. When TAB is pressed it produces weird behaviour. When you execute echo $list_var
basically in both of the functions produce the same result. Not sure why bash completion doesn't like awk/sed produced result. This is on RH 9.
Can anyone provide a solution to this?
Finally able to solve this. Things to note are; 1. Removed IFS 2.redirecting stderr output to stdout
Working script is:
$ cat dbcmd_completion.bash
#/usr/bin/env bash
_dbcmd_completions()
{
if [ "${#COMP_WORDS[@]}" != "2" ]; then
return
fi
local list_var="$(dbcmd 2>&1|awk -F '\t' '{printf("%s", $1)}'|sed 's/.*://'|sed 's/^\s.//'|sed 's/\s\+/ /g')"
local suggestions=($(compgen -W "$list_var" -- "${COMP_WORDS[1]}"))
if [ "${#suggestions[@]}" == "1" ]; then
local number="${suggestions[0]/%\ */}"
COMPREPLY=("$number")
else
for i in "${!suggestions[@]}"; do
suggestions[$i]="$(printf '%*s' "-$COLUMNS" "${suggestions[$i]}")"
done
COMPREPLY=("${suggestions[@]}")
fi
}
complete -F _dbcmd_completions dbcmd