2017-10-31 08:24:21 +00:00
|
|
|
/*
|
|
|
|
* virsh-completer.c: virsh completer callbacks
|
|
|
|
*
|
|
|
|
* Copyright (C) 2017 Red Hat, Inc.
|
|
|
|
*
|
|
|
|
* This library is free software; you can redistribute it and/or
|
|
|
|
* modify it under the terms of the GNU Lesser General Public
|
|
|
|
* License as published by the Free Software Foundation; either
|
|
|
|
* version 2.1 of the License, or (at your option) any later version.
|
|
|
|
*
|
|
|
|
* This library is distributed in the hope that it will be useful,
|
|
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
|
|
* Lesser General Public License for more details.
|
|
|
|
*
|
|
|
|
* You should have received a copy of the GNU Lesser General Public
|
|
|
|
* License along with this library. If not, see
|
|
|
|
* <http://www.gnu.org/licenses/>.
|
|
|
|
*/
|
|
|
|
|
|
|
|
#include <config.h>
|
|
|
|
|
|
|
|
#include "virsh-completer.h"
|
|
|
|
#include "viralloc.h"
|
|
|
|
#include "virstring.h"
|
|
|
|
|
2019-01-22 11:23:07 +00:00
|
|
|
/**
|
|
|
|
* A completer callback is a function that accepts three arguments:
|
|
|
|
*
|
|
|
|
* @ctl: virsh control structure
|
|
|
|
* @cmd: parsed input
|
|
|
|
* @flags: optional flags to alter completer's behaviour
|
|
|
|
*
|
|
|
|
* The @ctl contains connection to the daemon (should the
|
|
|
|
* completer need it). Any completer that requires a connection
|
|
|
|
* must check whether connection is still alive.
|
|
|
|
*
|
|
|
|
* The @cmd contains parsed user input which might be missing
|
|
|
|
* some arguments (if user is still typing the command), but may
|
|
|
|
* already contain important data. For instance if the completer
|
|
|
|
* needs domain XML it may inspect @cmd to find --domain. Using
|
|
|
|
* existing wrappers is advised. If @cmd does not contain all
|
|
|
|
* necessary bits, completer might return sensible defaults (i.e.
|
|
|
|
* generic values not tailored to specific use case) or return
|
|
|
|
* NULL (i.e. no strings are offered to the user for completion).
|
|
|
|
*
|
|
|
|
* The @flags contains a .completer_flags value defined for each
|
|
|
|
* use or 0 if no .completer_flags were specified. If a completer
|
2019-03-28 16:42:23 +00:00
|
|
|
* is generic enough @flags can be used to alter its behaviour.
|
2019-01-22 11:23:07 +00:00
|
|
|
* For instance, a completer to fetch names of domains can use
|
|
|
|
* @flags to return names of only domains in a particular state
|
|
|
|
* that the command accepts.
|
|
|
|
*
|
|
|
|
* Under no circumstances should a completer output anything.
|
|
|
|
* Neither to stdout nor to stderr. This would harm the user
|
|
|
|
* experience.
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
2019-06-18 10:16:17 +00:00
|
|
|
/**
|
|
|
|
* virshCommaStringListComplete:
|
|
|
|
* @input: user input so far
|
|
|
|
* @options: ALL options available for argument
|
|
|
|
*
|
|
|
|
* Some arguments to our commands accept the following form:
|
|
|
|
*
|
|
|
|
* virsh command --arg str1,str2,str3
|
|
|
|
*
|
|
|
|
* This does not play nicely with our completer funtions, because
|
|
|
|
* they have to return strings prepended with user's input. For
|
|
|
|
* instance:
|
|
|
|
*
|
|
|
|
* str1,str2,str3,strA
|
|
|
|
* str1,str2,str3,strB
|
|
|
|
* str1,str2,str3,strC
|
|
|
|
*
|
|
|
|
* This helper function takes care of that. In this specific case
|
|
|
|
* it would be called as follows:
|
|
|
|
*
|
|
|
|
* virshCommaStringListComplete("str1,str2,str3",
|
|
|
|
* {"strA", "strB", "strC", NULL});
|
|
|
|
*
|
|
|
|
* Returns: string list of completions on success,
|
|
|
|
* NULL otherwise.
|
|
|
|
*/
|
2019-07-18 15:18:28 +00:00
|
|
|
char **
|
2019-06-18 10:16:17 +00:00
|
|
|
virshCommaStringListComplete(const char *input,
|
|
|
|
const char **options)
|
|
|
|
{
|
|
|
|
const size_t optionsLen = virStringListLength(options);
|
2019-10-15 13:16:31 +00:00
|
|
|
g_autofree char *inputCopy = NULL;
|
2019-06-18 10:16:17 +00:00
|
|
|
VIR_AUTOSTRINGLIST inputList = NULL;
|
|
|
|
VIR_AUTOSTRINGLIST ret = NULL;
|
|
|
|
size_t nret = 0;
|
|
|
|
size_t i;
|
|
|
|
|
|
|
|
if (STREQ_NULLABLE(input, " "))
|
|
|
|
input = NULL;
|
|
|
|
|
|
|
|
if (input) {
|
|
|
|
char *comma = NULL;
|
|
|
|
|
2019-10-20 11:49:46 +00:00
|
|
|
inputCopy = g_strdup(input);
|
2019-06-18 10:16:17 +00:00
|
|
|
|
|
|
|
if ((comma = strrchr(inputCopy, ',')))
|
|
|
|
*comma = '\0';
|
|
|
|
else
|
|
|
|
VIR_FREE(inputCopy);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (inputCopy && !(inputList = virStringSplit(inputCopy, ",", 0)))
|
|
|
|
return NULL;
|
|
|
|
|
|
|
|
if (VIR_ALLOC_N(ret, optionsLen + 1) < 0)
|
|
|
|
return NULL;
|
|
|
|
|
|
|
|
for (i = 0; i < optionsLen; i++) {
|
|
|
|
if (virStringListHasString((const char **)inputList, options[i]))
|
|
|
|
continue;
|
|
|
|
|
2019-10-22 13:26:14 +00:00
|
|
|
if (inputCopy)
|
|
|
|
ret[nret] = g_strdup_printf("%s,%s", inputCopy, options[i]);
|
|
|
|
else
|
2019-10-20 11:49:46 +00:00
|
|
|
ret[nret] = g_strdup(options[i]);
|
2019-06-18 10:16:17 +00:00
|
|
|
|
|
|
|
nret++;
|
|
|
|
}
|
|
|
|
|
2019-10-16 11:35:54 +00:00
|
|
|
return g_steal_pointer(&ret);
|
2019-06-18 10:16:17 +00:00
|
|
|
}
|