我使用GLib来解析一些命令行选项。问题是我想要强制选择其中两个选项,以便在用户省略它时程序终止于帮助屏幕。
我的代码如下所示:
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;
}
如果我在命令行中省略其中一个参数或两者都没有,那么g_option_context_parse()仍然成功,并且有问题的值(行和/或列)仍为-1。如果用户没有在命令行上传递这两个选项,我怎么能告诉GLib解析失败?也许我只是盲目但我找不到我可以放入GOptionEntry数据结构的标志,告诉它要强制使用这些字段。
当然我可以检查其中一个变量是否仍为-1但是用户可能只是在命令行上传递了这个值,如果值超出范围,我想打印一个单独的错误消息。 / p>
答案 0 :(得分:9)
由你来检查参数的健全性(除了解析之外),这也适用于getopt
。问题是,当你把事情做成“强制性”时,你会经常遇到“强制性”仅在没有其他论据的情况下适用的情况。
例如,./program --help
应该不需要额外的参数,同样适用于./program --version
。在解析器本身中使用“require --foo and --bar除非--version OR --help”的逻辑将会出现膨胀和过度复杂的情况。
在解析参数后,您只需检查line
和column
的值,以确保它们已设置为某些内容。如果您担心check_sanity()
中的混乱,完全有可能将所有逻辑放入函数(例如main()
)。
总之,您所看到的行为是设计的,我不认为它可能会改变。如果在解析器运行后初始化任一变量,则用户忘记指定相应的选项。
答案 1 :(得分:2)
使用GLib无法实现,我检查了文档和源代码。尽管存在上述缺陷,您可能希望提交功能请求,和/或与您提议的解决方法一起使用。
答案 2 :(得分:2)
我最近遇到了类似的问题,我认为(暂时还不知道,但看起来可行)它可以通过2次回调来实现。
arg处理回调会做任何你想要表明已经输入的arg(bitmask?,...)。它还会存储已解析的值(请参阅下面的问题。)将此回调设置为GOptionArgFunc
,并使用GOptionEntry
标记指向G_OPTION_ARG_CALLBACK
数组中的回调。
解析后回调将检查是否已输入所有必需项。将此回调设置为GOptionParseFunc
,并使用g_option_group_set_parse_hooks
指向该回调。
如果您使用g_option_group_new
,可以将user_data
(地址转换为您的位掩码?,...)传递给两个回调。使用g_option_group_add_entries
和g_option_context_set_main_group
代替g_option_context_add_main_entries
来获取与GOptionContext
相关联的群组条目。
到目前为止我唯一看到的问题是,您必须设置自己的指针到条目数组,以用于实际设置您的条目'解析后的值,因为GOptionEntry
arg_data
字段将用于指向arg回调函数。