[libvirt] [PATCH 09/11] virsh: convert command line parsing to use GOptionContext
Pavel Hrdina
phrdina at redhat.com
Tue Oct 1 09:37:17 UTC 2019
On Fri, Sep 27, 2019 at 06:17:31PM +0100, Daniel P. Berrangé wrote:
> The GOptionContext API has the benefit over getopt_long that it will
> automatically handle --help output formatting.
>
> Signed-off-by: Daniel P. Berrangé <berrange at redhat.com>
> ---
> tools/virsh.c | 303 ++++++++++++++++++++++----------------------------
> 1 file changed, 135 insertions(+), 168 deletions(-)
>
> diff --git a/tools/virsh.c b/tools/virsh.c
> index ec20f35a77..6c469ff576 100644
> --- a/tools/virsh.c
> +++ b/tools/virsh.c
> @@ -23,7 +23,6 @@
>
> #include <stdarg.h>
> #include <unistd.h>
> -#include <getopt.h>
> #include <sys/time.h>
> #include <fcntl.h>
> #include <time.h>
> @@ -445,53 +444,36 @@ virshDeinit(vshControl *ctl)
> }
>
> /*
> - * Print usage
> + * Build help description for commands
> */
> -static void
> -virshUsage(void)
> +static char *
> +virshBuildDescription(void)
> {
> const vshCmdGrp *grp;
> const vshCmdDef *cmd;
> -
> - fprintf(stdout, _("\n%s [options]... [<command_string>]"
> - "\n%s [options]... <command> [args...]\n\n"
> - " options:\n"
> - " -c | --connect=URI hypervisor connection URI\n"
> - " -d | --debug=NUM debug level [0-4]\n"
> - " -e | --escape <char> set escape sequence for console\n"
> - " -h | --help this help\n"
> - " -k | --keepalive-interval=NUM\n"
> - " keepalive interval in seconds, 0 for disable\n"
> - " -K | --keepalive-count=NUM\n"
> - " number of possible missed keepalive messages\n"
> - " -l | --log=FILE output logging to file\n"
> - " -q | --quiet quiet mode\n"
> - " -r | --readonly connect readonly\n"
> - " -t | --timing print timing information\n"
> - " -v short version\n"
> - " -V long version\n"
> - " --version[=TYPE] version, TYPE is short or long (default short)\n"
> - " commands (non interactive mode):\n\n"), progname,
> - progname);
> + GString *str = g_string_new("Commands (non interactive mode):\n\n");
>
> for (grp = cmdGroups; grp->name; grp++) {
> - fprintf(stdout, _(" %s (help keyword '%s')\n"),
> - grp->name, grp->keyword);
> + g_string_append_printf(str,
> + _(" %s (help keyword '%s')\n"),
> + grp->name, grp->keyword);
> for (cmd = grp->commands; cmd->name; cmd++) {
> if (cmd->flags & VSH_CMD_FLAG_ALIAS)
> continue;
> - fprintf(stdout,
> - " %-30s %s\n", cmd->name,
> - _(vshCmddefGetInfo(cmd, "help")));
> + g_string_append_printf(str,
> + " %-30s %s\n",
> + cmd->name,
> + _(vshCmddefGetInfo(cmd, "help")));
> }
> - fprintf(stdout, "\n");
> + g_string_append_printf(str, "\n");
> }
>
> - fprintf(stdout, "%s",
> - _("\n (specify help <group> for details about the commands in the group)\n"));
> - fprintf(stdout, "%s",
> - _("\n (specify help <command> for details about the command)\n\n"));
> - return;
> + g_string_append_printf(str,
> + _("Specify help <group> for details about the commands in the group)\n"));
> + g_string_append_printf(str,
> + _("Specify help <command> for details about the command)\n"));
> +
> + return g_string_free(str, FALSE);
> }
>
> /*
> @@ -647,6 +629,22 @@ virshAllowedEscapeChar(char c)
> ('@' <= c && c <= '_');
> }
>
> +static gboolean
> +virshVersion(const gchar *option_name G_GNUC_UNUSED,
> + const gchar *value,
> + gpointer data,
> + GError **error G_GNUC_UNUSED)
> +{
> + vshControl *ctl = data;
> +
> + if (value == NULL || STRNEQ(value, "long"))
> + puts(VERSION);
> + else
> + virshShowVersion(ctl);
> +
> + exit(EXIT_SUCCESS);
> +}
> +
> /*
> * argv[]: virsh [options] [command]
> *
> @@ -654,152 +652,121 @@ virshAllowedEscapeChar(char c)
> static bool
> virshParseArgv(vshControl *ctl, int argc, char **argv)
> {
> - int arg, len, debug, keepalive;
> - size_t i;
> - int longindex = -1;
> + int debug = 0;
> + bool version = false;
> + size_t len;
> virshControlPtr priv = ctl->privData;
> - struct option opt[] = {
> - {"connect", required_argument, NULL, 'c'},
> - {"debug", required_argument, NULL, 'd'},
> - {"escape", required_argument, NULL, 'e'},
> - {"help", no_argument, NULL, 'h'},
> - {"keepalive-interval", required_argument, NULL, 'k'},
> - {"keepalive-count", required_argument, NULL, 'K'},
> - {"log", required_argument, NULL, 'l'},
> - {"quiet", no_argument, NULL, 'q'},
> - {"readonly", no_argument, NULL, 'r'},
> - {"timing", no_argument, NULL, 't'},
> - {"version", optional_argument, NULL, 'v'},
> - {NULL, 0, NULL, 0}
> + char *logfile = NULL;
> + int keepalive_interval = INT_MAX;
> + int keepalive_count = INT_MAX;
> + GOptionEntry opt[] = {
> + { "connect", 'c', 0,
> + G_OPTION_ARG_STRING, &ctl->connname,
> + _("hypervisor connection URI"), "URI" },
> + { "debug", 'd', 0,
> + G_OPTION_ARG_INT, &debug,
> + _("debug level [0-4]\n"), "LEVEL" },
> + { "escape", 'e', 0,
> + G_OPTION_ARG_STRING, &priv->escapeChar,
> + _("set escape sequence for console"), "ESCAPE" },
> + { "keepalive-interval", 'k', 0,
> + G_OPTION_ARG_INT, &keepalive_interval,
> + _("keepalive interval in seconds, 0 for disable"), "SECS" },
> + { "keepalive-count", 'K', 0,
> + G_OPTION_ARG_INT, &keepalive_count,
> + _("number of possible missed keepalive messages"), "NUM" },
> + { "log", 'l', 0,
> + G_OPTION_ARG_STRING, &logfile,
> + _("output logging to file"), "FILENAME" },
> + { "quiet", 'q', 0,
> + G_OPTION_ARG_NONE, &ctl->quiet,
> + _("quite mode"), NULL },
> + { "readonly", 'r', 0,
> + G_OPTION_ARG_NONE, &priv->readonly,
> + _("connect readonly"), NULL },
> + { "timing", 't', 0,
> + G_OPTION_ARG_NONE, &ctl->timing,
> + _("print timing information"), NULL },
> + { "version", 'v', G_OPTION_FLAG_OPTIONAL_ARG,
> + G_OPTION_ARG_CALLBACK, virshVersion,
> + _("print short version"), "[short]" },
> + { "version", 'V', 0,
> + G_OPTION_ARG_NONE, &version,
> + _("print long version"), "long" },
We should be able to have both -v and -V call virshVersion if the
functions will look like this:
static gboolean
virshVersion(const gchar *option_name,
const gchar *value,
gpointer data,
GError **error G_GNUC_UNUSED)
{
vshControl *ctl = data;
if (STREQ(option_name, "-V") || STREQ_NULLABLE(value, "long"))
virshShowVersion(ctl);
else
puts(VERSION);
exit(EXIT_SUCCESS);
}
That way we will have only a single place where the version printing
code is.
Otherwise looks good to me.
Pavel
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 833 bytes
Desc: not available
URL: <http://listman.redhat.com/archives/libvir-list/attachments/20191001/412cc1f3/attachment-0001.sig>
More information about the libvir-list
mailing list