简体   繁体   English

如何使用GLib强制命令行选项?

[英]How to make command-line options mandatory with GLib?

I use GLib to parse some command-line options. 我使用GLib来解析一些命令行选项。 The problem is that I want to make two of those options mandatory so that the program terminates with the help screen if the user omits them. 问题是我想强制选择其中两个选项,以便在用户省略它们时程序终止于帮助屏幕。

My code looks like this: 我的代码看起来像这样:

static gint line   = -1;
static gint column = -1;

static GOptionEntry options[] =
{
    {"line", 'l', 0, G_OPTION_ARG_INT, &line, "The line", "L"},
    {"column", 'c', 0, G_OPTION_ARG_INT, &column, "The column", "C"},
    {NULL}
};

...

int main(int argc, char** argv)
{
    GError *error = NULL;
    GOptionContext *context;

    context = g_option_context_new ("- test");
    g_option_context_add_main_entries (context, options, NULL);

    if (!g_option_context_parse(context, &argc, &argv, &error))
    {
        usage(error->message, context);
    }

    ...

    return 0;
}

If I omit one of those parameters or both on the command-line g_option_context_parse() still succeeds and the values in question (line and or column) are still -1. 如果我在命令行中省略其中一个参数或两者都没有,那么g_option_context_parse()仍然成功,并且有问题的值(行和/或列)仍为-1。 How can I tell GLib to fail parsing if the user doesn't pass both options on the command-line? 如果用户没有在命令行上传递这两个选项,我怎么能告诉GLib解析失败? Maybe I'm just blind but I couldn't find a flag I can put into my GOptionEntry data structure to tell it to make those fields mandatory. 也许我只是盲目但我找不到我可以放入GOptionEntry数据结构的标志,告诉它要强制使用这些字段。

Of course I could check if one of those variables is still -1 but then the user could just have passed this value on the command-line and I want to print a separate error message if the values are out of range. 当然我可以检查其中一个变量是否仍为-1但是用户可能只是在命令行上传递了这个值,如果值超出范围,我想打印一个单独的错误消息。

It's up to you to check argument sanity (beyond parsing), that goes for getopt as well. 由你来检查参数的健全性(除了解析之外),这也适用于getopt The problem is, when making things 'mandatory', you will often run into cases where 'mandatory' applies only in the absence of other arguments. 问题是,当使事情“强制性”时,您经常会遇到“强制性”仅在没有其他参数的情况下适用的情况。

For instance, ./program --help should require no additional arguments, likewise for ./program --version . 例如,。/ ./program --help应该不需要额外的参数,同样适用于./program --version Putting the logic of "require --foo and --bar unless --version OR --help" in the parser itself would border on bloat and overcomplexity. 在解析器本身中使用“require --foo and --bar除非--version OR --help”的逻辑将与膨胀和过度复杂相关。

You simply must check the value of line and column after arguments are parsed to ensure that they were set to something. 您只需在解析参数后检查linecolumn的值,以确保它们已设置为某些值。 It's entirely possible to put all of that logic into a function (eg check_sanity() ) if you are worried about clutter in main() . 如果您担心main()混乱,完全可以将所有逻辑放入函数(例如check_sanity() main()

In summary, the behavior that you are seeing is by design, I don't think it's likely to change. 总之,您所看到的行为是设计的,我不认为它可能会改变。 If either variable remains as it was initialized after the parser runs, the user forgot to specify the respective option. 如果在解析器运行后初始化任一变量,则用户忘记指定相应的选项。

It is impossible to achieve with GLib, I checked documentation and source code. 用GLib实现是不可能的,我检查了文档和源代码。 You may want to submit a feature request, and/or live with your proposed workaround despite the mentioned drawback. 尽管存在上述缺陷,您可能希望提交功能请求,和/或与您提议的解决方法一起使用。

I've run into a similar problem recently, and I think (don't know yet for sure but looks doable) it's doable with 2 callbacks. 我最近遇到了类似的问题, 我认为 (目前还不确定,但看起来可行)这可以通过2次回调来实现。 The arg processing callback would do whatever you want to indicate that the arg being parsed has been entered (bitmask?, ...). arg处理回调会做任何你想要表明已经输入的arg(bitmask?,...)。 It would also store the parsed value (see gotcha below.) Set up this callback as a GOptionArgFunc and point to it in your GOptionEntry array using the G_OPTION_ARG_CALLBACK flag. 它还会存储解析后的值(参见下面的问题。)将此回调设置为GOptionArgFunc并使用G_OPTION_ARG_CALLBACK标志指向GOptionEntry数组中的G_OPTION_ARG_CALLBACK

The post parsing callback would check to see whether all requireds had been entered. 解析后回调将检查是否已输入所有必需项。 Set up this callback as a GOptionParseFunc and point to it using g_option_group_set_parse_hooks . 将此回调设置为GOptionParseFunc并使用g_option_group_set_parse_hooks指向它。

If you use g_option_group_new you can pass it user_data (address to your bitmask?, ...) to use in both callbacks. 如果您使用g_option_group_new您可以将它传递给user_data (地址到您的位掩码?,...)以在两个回调中使用。 Use g_option_group_add_entries and g_option_context_set_main_group instead of g_option_context_add_main_entries to get the group's entries associated with the GOptionContext . 使用g_option_group_add_entriesg_option_context_set_main_group而不是g_option_context_add_main_entries来获取与GOptionContext关联的组条目。

The only gotcha I see so far is that you have to set up your own pointer-to-entry array to use to actually set your entries' parsed values, since the GOptionEntry arg_data field would be used to point to the arg callback function. 到目前为止我唯一看到的问题是你必须设置自己的指针到条目数组来实际设置条目的解析值,因为GOptionEntry arg_data字段将用于指向arg回调函数。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM