compiler/cli: PrintHelpText prints to stdout instead of stderr

Fixes #698.

PrintHelpText now prints to standard output instead of to standard error.
The purpose of this CL is to make it easy for users to grep for matches
otherwise stderr output has to be awkwardly redirectly to stdout
using this shell trick  `2>&1`, for example
```shell
protoc --help 2>&1 | grep cpp
```

of which we shouldn't be making users have to work that hard just to
get use of --help.

+ Exhibits:
* Before:
```shell
$ protoc --help | grep cpp
Usage: protoc [OPTION] PROTO_FILES
Parse PROTO_FILES and generate output based on the options given:
  -IPATH, --proto_path=PATH   Specify the directory in which to search
for
                              imports.  May be specified multiple times;
                              directories will be searched in order.  If
not
                              given, the current working directory is
used.
  --version                   Show version info and exit.
  -h, --help                  Show this text and exit.
  --encode=MESSAGE_TYPE       Read a text-format message of the given
type
                              from standard input and write it in binary
                              to standard output.  The message type must
                              be defined in PROTO_FILES or their
imports.
  --decode=MESSAGE_TYPE       Read a binary message of the given type
from
                              standard input and write it in text format
                              to standard output.  The message type must
                              be defined in PROTO_FILES or their
imports.
  --decode_raw                Read an arbitrary protocol message from
                              standard input and write the raw tag/value
                              pairs in text format to standard output.
No
                              PROTO_FILES should be given when using
this
                              flag.
  -oFILE,                     Writes a FileDescriptorSet (a protocol
buffer,
    --descriptor_set_out=FILE defined in descriptor.proto) containing
all of
                              the input files to FILE.
  --include_imports           When using --descriptor_set_out, also
include
                              all dependencies of the input files in the
                              set, so that the set is self-contained.
  --include_source_info       When using --descriptor_set_out, do not
strip
                              SourceCodeInfo from the
FileDescriptorProto.
                              This results in vastly larger descriptors
that
                              include information about the original
                              location of each decl in the source file
as
                              well as surrounding comments.
  --dependency_out=FILE       Write a dependency output file in the
format
                              expected by make. This writes the
transitive
                              set of input file paths to FILE
  --error_format=FORMAT       Set the format in which to print errors.
                              FORMAT may be 'gcc' (the default) or
'msvs'
                              (Microsoft Visual Studio format).
  --print_free_field_numbers  Print the free field numbers of the
messages
                              defined in the given proto files. Groups
share
                              the same field number space with the
parent
                              message. Extension ranges are counted as
                              occupied fields numbers.

  --plugin=EXECUTABLE         Specifies a plugin executable to use.
                              Normally, protoc searches the PATH for
                              plugins, but you may specify additional
                              executables not in the path using this
flag.
                              Additionally, EXECUTABLE may be of the
form
                              NAME=PATH, in which case the given plugin
name
                              is mapped to the given executable even if
                              the executable's own name differs.
  --cpp_out=OUT_DIR           Generate C++ header and source.
  --csharp_out=OUT_DIR        Generate C# source file.
  --java_out=OUT_DIR          Generate Java source file.
  --javanano_out=OUT_DIR      Generate Java Nano source file.
  --js_out=OUT_DIR            Generate JavaScript source.
  --objc_out=OUT_DIR          Generate Objective C header and source.
  --python_out=OUT_DIR        Generate Python source file.
  --ruby_out=OUT_DIR          Generate Ruby source file.
```

* After:
```shell
$ protoc --help | grep cpp
  --plugin=EXECUTABLE         Specifies a plugin executable to use.
                              Normally, protoc searches the PATH for
                              plugins, but you may specify additional
                              executables not in the path using this
flag.
                              Additionally, EXECUTABLE may be of the
form
                              NAME=PATH, in which case the given plugin
name
                              is mapped to the given executable even if
                              the executable's own name differs.
  --cpp_out=OUT_DIR           Generate C++ header and source.
  --csharp_out=OUT_DIR        Generate C# source file.
  --java_out=OUT_DIR          Generate Java source file.
  --javanano_out=OUT_DIR      Generate Java Nano source file.
  --js_out=OUT_DIR            Generate JavaScript source.
  --objc_out=OUT_DIR          Generate Objective C header and source.
  --python_out=OUT_DIR        Generate Python source file.
  --ruby_out=OUT_DIR          Generate Ruby source file.
```
pull/2023/head
Emmanuel Odeke 9 years ago
parent 2b7430d96a
commit 769b693564
No known key found for this signature in database
GPG Key ID: 1CA47A292F89DD40
  1. 6
      src/google/protobuf/compiler/command_line_interface.cc
  2. 20
      src/google/protobuf/compiler/command_line_interface_unittest.cc

@ -1446,7 +1446,7 @@ CommandLineInterface::InterpretArgument(const string& name,
void CommandLineInterface::PrintHelpText() {
// Sorry for indentation here; line wrapping would be uglier.
std::cerr <<
std::cout <<
"Usage: " << executable_name_ << " [OPTION] PROTO_FILES\n"
"Parse PROTO_FILES and generate output based on the options given:\n"
" -IPATH, --proto_path=PATH Specify the directory in which to search for\n"
@ -1493,7 +1493,7 @@ void CommandLineInterface::PrintHelpText() {
" occupied fields numbers.\n"
<< std::endl;
if (!plugin_prefix_.empty()) {
std::cerr <<
std::cout <<
" --plugin=EXECUTABLE Specifies a plugin executable to use.\n"
" Normally, protoc searches the PATH for\n"
" plugins, but you may specify additional\n"
@ -1509,7 +1509,7 @@ void CommandLineInterface::PrintHelpText() {
// FIXME(kenton): If the text is long enough it will wrap, which is ugly,
// but fixing this nicely (e.g. splitting on spaces) is probably more
// trouble than it's worth.
std::cerr << " " << iter->first << "=OUT_DIR "
std::cout << " " << iter->first << "=OUT_DIR "
<< string(19 - iter->first.size(), ' ') // Spaces for alignment.
<< iter->second.help_text << std::endl;
}

@ -156,6 +156,11 @@ class CommandLineInterfaceTest : public testing::Test {
// Checks that the captured stdout is the same as the expected_text.
void ExpectCapturedStdout(const string& expected_text);
// Checks that Run() returned zero and the stdout contains the given
// substring.
void ExpectCapturedStdoutSubstringWithZeroReturnCode(
const string& expected_substring);
// Returns true if ExpectErrorSubstring(expected_substring) would pass, but
// does not fail otherwise.
bool HasAlternateErrorSubstring(const string& expected_substring);
@ -488,6 +493,11 @@ void CommandLineInterfaceTest::ExpectCapturedStdout(
EXPECT_EQ(expected_text, captured_stdout_);
}
void CommandLineInterfaceTest::ExpectCapturedStdoutSubstringWithZeroReturnCode(
const string& expected_substring) {
EXPECT_EQ(0, return_code_);
EXPECT_PRED_FORMAT2(testing::IsSubstring, expected_substring, captured_stdout_);
}
void CommandLineInterfaceTest::ExpectFileContent(
const string& filename, const string& content) {
@ -1703,11 +1713,11 @@ TEST_F(CommandLineInterfaceTest, GeneratorPluginNotAllowed) {
TEST_F(CommandLineInterfaceTest, HelpText) {
Run("test_exec_name --help");
ExpectErrorSubstringWithZeroReturnCode("Usage: test_exec_name ");
ExpectErrorSubstringWithZeroReturnCode("--test_out=OUT_DIR");
ExpectErrorSubstringWithZeroReturnCode("Test output.");
ExpectErrorSubstringWithZeroReturnCode("--alt_out=OUT_DIR");
ExpectErrorSubstringWithZeroReturnCode("Alt output.");
ExpectCapturedStdoutSubstringWithZeroReturnCode("Usage: test_exec_name ");
ExpectCapturedStdoutSubstringWithZeroReturnCode("--test_out=OUT_DIR");
ExpectCapturedStdoutSubstringWithZeroReturnCode("Test output.");
ExpectCapturedStdoutSubstringWithZeroReturnCode("--alt_out=OUT_DIR");
ExpectCapturedStdoutSubstringWithZeroReturnCode("Alt output.");
}
TEST_F(CommandLineInterfaceTest, GccFormatErrors) {

Loading…
Cancel
Save