2017-10-31 11:24:21 +03: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 14:23:07 +03: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 19:42:23 +03:00
* is generic enough @ flags can be used to alter its behaviour .
2019-01-22 14:23:07 +03: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 13:16:17 +03: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 18:18:28 +03:00
char * *
2019-06-18 13:16:17 +03:00
virshCommaStringListComplete ( const char * input ,
const char * * options )
{
const size_t optionsLen = virStringListLength ( options ) ;
2019-10-15 16:16:31 +03:00
g_autofree char * inputCopy = NULL ;
2019-06-18 13:16:17 +03: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 14:49:46 +03:00
inputCopy = g_strdup ( input ) ;
2019-06-18 13:16:17 +03: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 16:26:14 +03:00
if ( inputCopy )
ret [ nret ] = g_strdup_printf ( " %s,%s " , inputCopy , options [ i ] ) ;
else
2019-10-20 14:49:46 +03:00
ret [ nret ] = g_strdup ( options [ i ] ) ;
2019-06-18 13:16:17 +03:00
nret + + ;
}
2019-10-16 14:35:54 +03:00
return g_steal_pointer ( & ret ) ;
2019-06-18 13:16:17 +03:00
}