Sort all includes in src/gromacs
[alexxy/gromacs.git] / src / gromacs / commandline / cmdlinehelpwriter.cpp
index 86a9dee1c60568bfac39c1cb68e7fb8dde969c0e..0c79bd393451006b0e4c5161ced2b0ab4170a1dd 100644 (file)
  * \author Teemu Murtola <teemu.murtola@gmail.com>
  * \ingroup module_commandline
  */
+#include "gmxpre.h"
+
 #include "cmdlinehelpwriter.h"
 
+#include <cstring>
+
+#include <algorithm>
 #include <string>
 
 #include <boost/scoped_ptr.hpp>
 
 #include "gromacs/commandline/cmdlinehelpcontext.h"
-#include "gromacs/commandline/shellcompletions.h"
 #include "gromacs/onlinehelp/helpformat.h"
 #include "gromacs/onlinehelp/helpwritercontext.h"
 #include "gromacs/options/basicoptions.h"
 #include "gromacs/options/options.h"
 #include "gromacs/options/optionsvisitor.h"
 #include "gromacs/options/timeunitmanager.h"
+#include "gromacs/utility/arrayref.h"
 #include "gromacs/utility/exceptions.h"
 #include "gromacs/utility/file.h"
 #include "gromacs/utility/stringutil.h"
 
+#include "shellcompletions.h"
+
 namespace gmx
 {
 
@@ -358,6 +365,103 @@ descriptionWithOptionDetails(const CommonFormatterData &common,
     return description;
 }
 
+/********************************************************************
+ * OptionsSynopsisFormatter
+ */
+
+/*! \brief
+ * Formatter implementation for synopsis.
+ */
+class SynopsisFormatter : public OptionsFormatterInterface
+{
+    public:
+        //! Creates a helper object for formatting the synopsis.
+        explicit SynopsisFormatter(const HelpWriterContext &context)
+            : context_(context), lineLength_(0), indent_(0), currentLength_(0)
+        {
+        }
+
+        //! Starts formatting the synopsis.
+        void start(const char *name);
+        //! Finishes formatting the synopsis.
+        void finish();
+
+        virtual void formatOption(const OptionInfo &option);
+
+    private:
+        const HelpWriterContext &context_;
+        int                      lineLength_;
+        int                      indent_;
+        int                      currentLength_;
+
+        GMX_DISALLOW_COPY_AND_ASSIGN(SynopsisFormatter);
+};
+
+void SynopsisFormatter::start(const char *name)
+{
+    currentLength_ = std::strlen(name) + 1;
+    indent_        = std::min(currentLength_, 13);
+    File &file = context_.outputFile();
+    switch (context_.outputFormat())
+    {
+        case eHelpOutputFormat_Console:
+            lineLength_ = 78;
+            file.writeString(name);
+            break;
+        case eHelpOutputFormat_Man:
+            lineLength_ = 70;
+            file.writeString(name);
+            break;
+        case eHelpOutputFormat_Html:
+            lineLength_ = 78;
+            file.writeLine("<pre>");
+            file.writeString(name);
+            break;
+        default:
+            GMX_THROW(NotImplementedError("Synopsis formatting not implemented for this output format"));
+    }
+}
+
+void SynopsisFormatter::finish()
+{
+    File &file = context_.outputFile();
+    file.writeLine();
+    if (context_.outputFormat() == eHelpOutputFormat_Html)
+    {
+        file.writeLine("</pre>");
+    }
+    file.writeLine();
+}
+
+void SynopsisFormatter::formatOption(const OptionInfo &option)
+{
+    std::string name, value;
+    formatOptionNameAndValue(option, &name, &value);
+    std::string fullOptionText(" [-" + name);
+    if (!value.empty())
+    {
+        fullOptionText.append(" ");
+        fullOptionText.append(value);
+    }
+    fullOptionText.append("]");
+    const int   totalLength = fullOptionText.size();
+
+    if (context_.outputFormat() == eHelpOutputFormat_Html)
+    {
+        value = replaceAll(value, "<", "&lt;");
+        value = replaceAll(value, ">", "&gt;");
+    }
+
+    File &file = context_.outputFile();
+    currentLength_ += totalLength;
+    if (currentLength_ >= lineLength_)
+    {
+        file.writeString(formatString("\n%*c", indent_ - 1, ' '));
+        currentLength_ = indent_ - 1 + totalLength;
+    }
+    file.writeString(fullOptionText);
+}
+
 /********************************************************************
  * OptionsListFormatter
  */
@@ -371,12 +475,12 @@ class OptionsListFormatter : public OptionsFormatterInterface
         //! Creates a helper object for formatting options.
         OptionsListFormatter(const HelpWriterContext   &context,
                              const CommonFormatterData &common,
-                             bool                       bConsole);
+                             const char                *title);
 
         //! Initiates a new section in the options list.
-        void startSection(const char *title)
+        void startSection(const char *header)
         {
-            title_      = title;
+            header_     = header;
             bDidOutput_ = false;
         }
         //! Finishes a section in the options list.
@@ -394,11 +498,16 @@ class OptionsListFormatter : public OptionsFormatterInterface
     private:
         void writeSectionStartIfNecessary()
         {
+            if (title_ != NULL)
+            {
+                context_.writeTitle(title_);
+                title_ = NULL;
+            }
             if (!bDidOutput_)
             {
-                if (title_ != NULL)
+                if (header_ != NULL)
                 {
-                    context_.writeTitle(title_);
+                    context_.writeTextBlock(header_);
                 }
                 context_.writeOptionListStart();
             }
@@ -409,6 +518,7 @@ class OptionsListFormatter : public OptionsFormatterInterface
         const CommonFormatterData             &common_;
         boost::scoped_ptr<TextTableFormatter>  consoleFormatter_;
         const char                            *title_;
+        const char                            *header_;
         bool                                   bDidOutput_;
 
         GMX_DISALLOW_COPY_AND_ASSIGN(OptionsListFormatter);
@@ -417,10 +527,11 @@ class OptionsListFormatter : public OptionsFormatterInterface
 OptionsListFormatter::OptionsListFormatter(
         const HelpWriterContext   &context,
         const CommonFormatterData &common,
-        bool                       bConsole)
-    : context_(context), common_(common), title_(NULL), bDidOutput_(false)
+        const char                *title)
+    : context_(context), common_(common),
+      title_(title), header_(NULL), bDidOutput_(false)
 {
-    if (bConsole)
+    if (context.outputFormat() == eHelpOutputFormat_Console)
     {
         consoleFormatter_.reset(new TextTableFormatter());
         consoleFormatter_->setFirstColumnIndent(1);
@@ -498,12 +609,17 @@ class CommandLineHelpWriter::Impl
         //! Sets the Options object to use for generating help.
         explicit Impl(const Options &options);
 
+        //! Format the list of known issues.
+        void formatBugs(const HelpWriterContext &context);
+
         //! Options object to use for generating help.
-        const Options          &options_;
+        const Options               &options_;
+        //! List of bugs/knows issues.
+        ConstArrayRef<const char *>  bugs_;
         //! Time unit to show in descriptions.
-        std::string             timeUnit_;
+        std::string                  timeUnit_;
         //! Whether to write descriptions to output.
-        bool                    bShowDescriptions_;
+        bool                         bShowDescriptions_;
 };
 
 CommandLineHelpWriter::Impl::Impl(const Options &options)
@@ -512,6 +628,45 @@ CommandLineHelpWriter::Impl::Impl(const Options &options)
 {
 }
 
+void CommandLineHelpWriter::Impl::formatBugs(const HelpWriterContext &context)
+{
+    if (bugs_.empty())
+    {
+        return;
+    }
+    context.writeTitle("Known Issues");
+    if (context.outputFormat() != eHelpOutputFormat_Console)
+    {
+        context.writeTextBlock("[UL]");
+    }
+    ConstArrayRef<const char *>::const_iterator i;
+    for (i = bugs_.begin(); i != bugs_.end(); ++i)
+    {
+        const char *const bug = *i;
+        // TODO: The context should be able to do this also for console output, but
+        // that requires a lot more elaborate parser for the markup.
+        if (context.outputFormat() == eHelpOutputFormat_Console)
+        {
+            TextLineWrapperSettings settings;
+            settings.setIndent(2);
+            settings.setFirstLineIndent(0);
+            settings.setLineLength(78);
+            context.outputFile().writeLine(
+                    context.substituteMarkupAndWrapToString(
+                            settings, formatString("* %s", bug)));
+        }
+        else
+        {
+            context.writeTextBlock(formatString("[LI]%s", bug));
+        }
+    }
+    if (context.outputFormat() != eHelpOutputFormat_Console)
+    {
+        context.writeTextBlock("[ul]");
+    }
+}
+
+
 /********************************************************************
  * CommandLineHelpWriter
  */
@@ -525,18 +680,27 @@ CommandLineHelpWriter::~CommandLineHelpWriter()
 {
 }
 
-CommandLineHelpWriter &CommandLineHelpWriter::setShowDescriptions(bool bSet)
+CommandLineHelpWriter &
+CommandLineHelpWriter::setShowDescriptions(bool bSet)
 {
     impl_->bShowDescriptions_ = bSet;
     return *this;
 }
 
-CommandLineHelpWriter &CommandLineHelpWriter::setTimeUnitString(const char *timeUnit)
+CommandLineHelpWriter &
+CommandLineHelpWriter::setTimeUnitString(const char *timeUnit)
 {
     impl_->timeUnit_ = timeUnit;
     return *this;
 }
 
+CommandLineHelpWriter &
+CommandLineHelpWriter::setKnownIssues(const ConstArrayRef<const char *> &bugs)
+{
+    impl_->bugs_ = bugs;
+    return *this;
+}
+
 void CommandLineHelpWriter::writeHelp(const CommandLineHelpContext &context)
 {
     if (context.isCompletionExport())
@@ -546,18 +710,18 @@ void CommandLineHelpWriter::writeHelp(const CommandLineHelpContext &context)
         return;
     }
     const HelpWriterContext &writerContext = context.writerContext();
-    const bool               bConsole
-        = (writerContext.outputFormat() == eHelpOutputFormat_Console);
     OptionsFilter            filter;
     filter.setShowHidden(context.showHidden());
 
-    File &file = writerContext.outputFile();
-    if (!bConsole)
     {
-        // TODO: Write a proper synopsis, with all the options.
         writerContext.writeTitle("Synopsis");
-        writerContext.writeTextBlock(context.moduleDisplayName());
-        file.writeLine("\n\n");
+        SynopsisFormatter synopsisFormatter(writerContext);
+        synopsisFormatter.start(context.moduleDisplayName());
+        filter.formatSelected(OptionsFilter::eSelectFileOptions,
+                              &synopsisFormatter, impl_->options_);
+        filter.formatSelected(OptionsFilter::eSelectOtherOptions,
+                              &synopsisFormatter, impl_->options_);
+        synopsisFormatter.finish();
     }
 
     if (impl_->bShowDescriptions_)
@@ -566,15 +730,17 @@ void CommandLineHelpWriter::writeHelp(const CommandLineHelpContext &context)
         descriptionFormatter.format(impl_->options_, "Description");
     }
     CommonFormatterData    common(impl_->timeUnit_.c_str());
-    OptionsListFormatter   formatter(writerContext, common, bConsole);
-    formatter.startSection("File Options");
+    OptionsListFormatter   formatter(writerContext, common, "Options");
+    formatter.startSection("Options to specify input and output files:[PAR]");
     filter.formatSelected(OptionsFilter::eSelectFileOptions,
                           &formatter, impl_->options_);
     formatter.finishSection();
-    formatter.startSection("Options");
+    formatter.startSection("Other options:[PAR]");
     filter.formatSelected(OptionsFilter::eSelectOtherOptions,
                           &formatter, impl_->options_);
     formatter.finishSection();
+
+    impl_->formatBugs(writerContext);
 }
 
 } // namespace gmx