什么是打印使用/帮助(-帮助)的最佳实践?


13

在为UNIX的CLI编写工具时,应如何使程序打印出帮助和/或用法?

我通常使用fprintf(stderr, "help text here");,但是有几个问题。

  • 首先,我不确定是否应该使用stderr。可以,还是应该使用stdout
  • 可以想象,帮助文本很长,具体取决于该工具有多少选项。现在,我通常只需"strings like that\n"在第二个参数中输入几个即可。但是,这用五十行或更多行帮助文本填充了我的源代码。根本不容易管理。我该怎么办呢?
  • 当工具不是用C或类似C的语言编写时,我倾向于在可能的情况下使用here-docs(在Perl中最为明显)。我不能在C语言中使用它,但是我可以使用类似的东西吗?
  • 我正在考虑将其放在a的headerfile.h内部#define HELP "help text here",我从未在野外看到它,也不知道我是否应该真正使用它。

理想情况下,我可以将文本放在外部文件中并包含它。但是,使用#include它似乎是错误的。那我该怎么办?

这个想法是要有一个易于管理的帮助文本。将其包含在源代码中并不是很方便。


1
源代码中的50行有什么不好的呢?放在最后。这不像您必须定期对其进行处理。
whatsisname 2012年

2
@whatsisname用法,对正常和longopts有所帮助。我最终在sourcode中有大约200行字符串。除此之外,我不认为这是最好的做法,等有一定投入帮助文本的更有效的方式,等等
帕勒蒙

Answers:


8

从目标平台的内部启发自己

看一下BSD的源代码。例如,这是:

  • usage(void)对于NetBSD的/usr/bin/uname工具[ 来源 ]:

    usage(void)
    {
        fprintf(stderr, "usage: uname [-amnprsv]\n");
        exit(EXIT_FAILURE);
    }
    
  • usage(void)用于NetBSD的/usr/bin/telnet[ 来源 ]

  • usage(void)用于OpenBSD的/bin/ls[ 来源 ]

看看替代品

并自己决定它们是好是坏。您可以使用Google CodeSearch查找其他人,例如:

如您所见,这些和上面列出的BSD系统集成工具之间的风格不同。这并不意味着您必须遵循其中一个。但是通常最好环顾四周,并寻求一致的解决方案。

50条帮助线的非标准解决方案...

如果您不希望避免使用50行文本,则可以简单地从文本文件中读取帮助(以纯文本格式,或者man如果创建了源代码,则可以直接解析的源代码)。我发现这是一种相当优雅的方式(您甚至可以查找文本文档),但是对于核心系统程序,这将使它们固有地不安全并引入故障点。其他人会争辩说,这对于a usagehelpmessage 来说很沉重,但这并不是像在快速紧密的循环中那样调用这些消息...

如有疑问,请跟随巨人。


9

我使用stdout,因为帮助不是错误。

如果这对C语言有很大帮助,我会尝试模仿here-docs:

printf("This is the help for MyWonderfulApp\n"
       "Options are:\n"
       "    --help: display what you are reading now\n"
       "    --quiet: output nothing\n");

但是大多数时候我都是man使用nroff -man专用标签编写页面的。应用内帮助仅包含引用该man页面。


但是帮助不一定是标准输出,不是吗?怎么stdlog
greyfade 2013年

@greyfade:是stdlog标准C吗?
mouviciel 2013年

@mouviciel:...我以为是。我猜不是。C ++有一个相关的标准流(cincoutcerrclog),所以我想我还以为stdlog是在C标准。我的错。
greyfade 2013年

2

如果我是你,我会刚开放的来源greptailcatyour_other_favorite_unix_shell_command,看看它是如何做在那里。我敢肯定,他们的方法已经深思熟虑,并且可以被许多人维护。

关于stderrstdout。这真的很简单,如果有错误-仅写stderr信息-即可stdout。例如,如果我使用错误的选项运行您的工具,则可能要显示一个错误,例如Use --help for usage,该错误所属stderr。如果我使用有效选项运行您的工具--help,请使用stdout

如果您不希望在代码附近使用长帮助字符串,请不要这样做。头文件中的#define非常好,但这实际上是个人喜好。如果我必须阅读命令行工具的代码,我希望它的帮助字符串位于处理用户提供的选项的文件中。


2
那没有回答他的问题。
Mavrik

嗯,减法是怎么回事?做什么的?
devmiles.com 2012年

@Mavrik:第一段是。
haylem

1

我使用gnu getopts库。有关帮助的示例,请参见此示例项目,尤其是parser.y底部的main方法。

由于它是用大括号括起来的,因此我使用的vim编辑器可以将行折叠在一起,并且在不需要时甚至不会注意到它们。


1

如果我使用C或不想使用Boost库,那么我会坚持使用GNU getopt。否则,我更喜欢Boost Program Options,它可以自动打印帮助。

我还考虑猜测正确的选项是涉及选项处理的最佳实践之一。我从Git那里学到了它,现在在我的项目中使用了它。如果用户输入一些未知的命令行选项,则基本上使用Damerau–Levenshtein距离打印最佳匹配。

我写了一篇有关此小文章,您可以作为示例。

希望能帮助到你 :)


1

显然,用cout <<printf()代码编写一个空洞页面很麻烦,尤其是当您需要更改并重新填充段落时。因此,显然最好将文本编辑到一个单独的文件中,例如使用emacs,您可以在其中更轻松地设置文本格式。

然后,您可以使用以下sed脚本将该文本文件转换为合法的C头文件:

s/\"/\\\"/g
s/$/\\n"/
s/^/"/
1i\
const char *helpStr = 
$a\
;

然后,在# include-将头文件添加到源代码中之后,您只需使用

cout << helpStr;
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.