Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to display commandline operand description in --help output

I am using Boost.program_options to parse commandlines for my implementation of POSIX utilities. As a simple example, take cmp.

Now I would like to have an extra argument --help which shows a description of all arguments, which is important in this case. I have:

po::options_description options("Options");
options.add_options()("help", "Show this help output.")
                     (",l", "(Lowercase ell.) Write the byte number (decimal) and the differing bytes (octal) for each difference.")
                     (",s", "Write nothing for differing files; return exit status only.")

po::positional_options_description operands;
operands.add("file1", 1);//, "A pathname of the first file to be compared. If file1 is '-', the standard input shall be used.")
operands.add("file2", 1);//, "A pathname of the second file to be compared. If file2 is '-', the standard input shall be used.");

po::variables_map vm;
po::store(po::command_line_parser(argc, argv).options(options).positional(operands).run(), vm);
po::notify(vm);

if(vm.count("help"))
{
  std::cout << "cmp: compare two files\nUsage: cmp [ -l | -s ] file1 file2\n" << options;
  return 0;
}

which is unable to show the file1 and file2 options' description. I can of course add them to options, but this would add at least two unwanted arguments [-]-file{1,2}, which I really do not want. I just want this output for --help (without obviously hardcoding it):

cmp: compare two files
Usage: cmp [ -l | -s ] file1 file2
Options:
  --help                Show this help output.
  -l                    (Lowercase ell.) Write the byte number (decimal) and the differing bytes (octal) for each difference.
  -s                    Write nothing for differing files; return exit status only.
Operands:
  file1                 A pathname of the first file to be compared. If file1 is '-', the standard input shall be used.
  file2                 A pathname of the second file to be compared. If file2 is '-', the standard input shall be used.

Is there any way to achieve this without hacking around the library? I'd think this is pretty basic stuff, but I can't find it in any of the tutorials.

UPDATE For everyone's benefit, I submitted a feature request for this, in a hopefully backwards compatible way.

like image 734
rubenvb Avatar asked Nov 13 '22 07:11

rubenvb


1 Answers

It's not ideal, but how about creating a "dummy" set of program options, let the boost::program_options formatter format its help text for you, and then just remove the dashes with a quick replace?

Then output that help text in addition to the options help text.

Something like this:

po::options_description dummy_options("Operands");
dummy_options.add_options()
    ("file1", po::value<std::string>(), "A pathname of the first file to be compared. If file1 is '-', the standard input shall be used.")
    ("file2", po::value<std::string>(), "A pathname of the second file to be compared. If file2 is '-', the standard input shall be used.")
    ;

std::stringstream s;
s << dummy_options;
std::string dummy_help_text = s.str();
boost::replace_all(dummy_help_text, "--", "");
boost::replace_all(dummy_help_text, "arg", "     ");

std::cout << dummy_help_text << std::endl;

The output looks like this:

Operands:
  file1                 A pathname of the first file to be compared. If file1
                        is '-', the standard input shall be used.
  file2                 A pathname of the second file to be compared. If file2
                        is '-', the standard input shall be used.

It's not ideal because, among other things, the the spacing between columns will not match the help output from your other options output. But for something quick-and-dirty, that basically works, it could be OK.

It's a thought, anyway.

(I do not see anything in the Boost.Program_Options API that allows you to do this the "right" way, either. https://stackoverflow.com/a/3621947/368896 gives a hint that this sort of thing is not supported, but that is 3 years old now.)

like image 56
Dan Nissenbaum Avatar answered Nov 14 '22 21:11

Dan Nissenbaum