1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190
|
/*
* vsh-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 "vsh-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.
*/
/**
* vshEnumComplete:
* @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 **
vshEnumComplete(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;
}
/**
* vshCommaStringListComplete:
* @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:
*
* vshCommaStringListComplete("str1,str2,str3",
* {"strA", "strB", "strC", NULL});
*
* Returns: string list of completions on success,
* NULL otherwise.
*/
char **
vshCommaStringListComplete(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);
}
/**
* vshCompletePathLocalExisting:
*
* 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 **
vshCompletePathLocalExisting(vshControl *ctl G_GNUC_UNUSED,
const vshCmd *cmd G_GNUC_UNUSED,
unsigned int completerflags G_GNUC_UNUSED)
{
return NULL;
}
/**
* vshCompleteEmpty:
*
* 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 **
vshCompleteEmpty(vshControl *ctl G_GNUC_UNUSED,
const vshCmd *cmd G_GNUC_UNUSED,
unsigned int completerflags G_GNUC_UNUSED)
{
return NULL;
}
|