mirror of https://gitee.com/openkylin/libvirt.git
191 lines
5.5 KiB
C
191 lines
5.5 KiB
C
/*
|
|
* 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"
|
|
|
|
/**
|
|
* 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
|
|
* is generic enough @flags can be used to alter its behaviour.
|
|
* 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.
|
|
*/
|
|
|
|
|
|
/**
|
|
* virshEnumComplete:
|
|
* @last: The number of element in enum (pass VIR_XXX_LAST)
|
|
* @intToStr: integer to string conversion (pass virXXXTypeToString)
|
|
*
|
|
* Convenient function to generate completions across all values
|
|
* of given enum. The enum, or values we want to generate, must
|
|
* start at 0 and be continuous until @last.
|
|
*
|
|
* Returns: string list of completions.
|
|
*/
|
|
char **
|
|
virshEnumComplete(unsigned int last,
|
|
const char *(*intToStr)(int))
|
|
{
|
|
char **ret = NULL;
|
|
size_t i;
|
|
|
|
ret = g_new0(char *, last + 1);
|
|
|
|
for (i = 0; i < last; i++)
|
|
ret[i] = g_strdup(intToStr(i));
|
|
|
|
return ret;
|
|
}
|
|
|
|
|
|
/**
|
|
* 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 functions, 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.
|
|
*/
|
|
char **
|
|
virshCommaStringListComplete(const char *input,
|
|
const char **options)
|
|
{
|
|
const size_t optionsLen = g_strv_length((char **) options);
|
|
g_autofree char *inputCopy = NULL;
|
|
g_auto(GStrv) inputList = NULL;
|
|
g_auto(GStrv) ret = NULL;
|
|
size_t nret = 0;
|
|
size_t i;
|
|
|
|
if (STREQ_NULLABLE(input, " "))
|
|
input = NULL;
|
|
|
|
if (input) {
|
|
char *comma = NULL;
|
|
|
|
inputCopy = g_strdup(input);
|
|
|
|
if ((comma = strrchr(inputCopy, ',')))
|
|
*comma = '\0';
|
|
else
|
|
g_clear_pointer(&inputCopy, g_free);
|
|
}
|
|
|
|
if (inputCopy && !(inputList = g_strsplit(inputCopy, ",", 0)))
|
|
return NULL;
|
|
|
|
ret = g_new0(char *, optionsLen + 1);
|
|
|
|
for (i = 0; i < optionsLen; i++) {
|
|
if (inputList &&
|
|
g_strv_contains((const char **)inputList, options[i]))
|
|
continue;
|
|
|
|
if (inputCopy)
|
|
ret[nret] = g_strdup_printf("%s,%s", inputCopy, options[i]);
|
|
else
|
|
ret[nret] = g_strdup(options[i]);
|
|
|
|
nret++;
|
|
}
|
|
|
|
return g_steal_pointer(&ret);
|
|
}
|
|
|
|
|
|
/**
|
|
* virshCompletePathLocalExisting:
|
|
*
|
|
* Complete a path to a existing file used as input. The file is used as input
|
|
* for virsh so only local files are considered.
|
|
*
|
|
* Note: For now this is a no-op. Readline does the correct thing.
|
|
*/
|
|
char **
|
|
virshCompletePathLocalExisting(vshControl *ctl G_GNUC_UNUSED,
|
|
const vshCmd *cmd G_GNUC_UNUSED,
|
|
unsigned int completerflags G_GNUC_UNUSED)
|
|
{
|
|
return NULL;
|
|
}
|
|
|
|
|
|
/**
|
|
* virshCompleteEmpty:
|
|
*
|
|
* Complete nothing. For cases where an user input is required and we can't
|
|
* suggest anything.
|
|
*
|
|
* TODO: This is currently just an annotation, readline still completes local
|
|
* file list.
|
|
*/
|
|
char **
|
|
virshCompleteEmpty(vshControl *ctl G_GNUC_UNUSED,
|
|
const vshCmd *cmd G_GNUC_UNUSED,
|
|
unsigned int completerflags G_GNUC_UNUSED)
|
|
{
|
|
return NULL;
|
|
}
|