Framework for help export from wrapper binary.
authorTeemu Murtola <teemu.murtola@gmail.com>
Thu, 5 Sep 2013 03:22:08 +0000 (06:22 +0300)
committerGerrit Code Review <gerrit@gerrit.gromacs.org>
Thu, 19 Sep 2013 03:16:37 +0000 (05:16 +0200)
- Add a separate CommandLineHelpContext.  This class layers extra
  information on top of a HelpWriterContext, specific for command-line
  help export.
- Add a global instance of the above to be able to pass it into
  write_man() through functions unaware of its existence.  Make
  write_man() use the instance if present.
- Add -export option for 'gmx help', and an interface that needs to be
  implemented to export a particular format.

Related to #685 and #969.

Change-Id: Ica16895f8136a09bc5995812c4da5363d097c2b1

15 files changed:
src/gromacs/commandline/cmdlinehelpcontext.cpp [new file with mode: 0644]
src/gromacs/commandline/cmdlinehelpcontext.h [new file with mode: 0644]
src/gromacs/commandline/cmdlinehelpwriter.cpp
src/gromacs/commandline/cmdlinehelpwriter.h
src/gromacs/commandline/cmdlinemodule.h
src/gromacs/commandline/cmdlinemodulemanager.cpp
src/gromacs/commandline/tests/cmdlinehelpwriter.cpp
src/gromacs/commandline/tests/cmdlinemodulemanager.cpp
src/gromacs/gmxlib/statutil.cpp
src/gromacs/onlinehelp/helpwritercontext.cpp
src/gromacs/onlinehelp/wman.cpp
src/gromacs/onlinehelp/wman.h
src/gromacs/trajectoryanalysis/cmdlinerunner.cpp
src/gromacs/trajectoryanalysis/cmdlinerunner.h
src/testutils/testoptions.cpp

diff --git a/src/gromacs/commandline/cmdlinehelpcontext.cpp b/src/gromacs/commandline/cmdlinehelpcontext.cpp
new file mode 100644 (file)
index 0000000..803f415
--- /dev/null
@@ -0,0 +1,130 @@
+/*
+ * This file is part of the GROMACS molecular simulation package.
+ *
+ * Copyright (c) 2013, by the GROMACS development team, led by
+ * David van der Spoel, Berk Hess, Erik Lindahl, and including many
+ * others, as listed in the AUTHORS file in the top-level source
+ * directory and at http://www.gromacs.org.
+ *
+ * GROMACS is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public License
+ * as published by the Free Software Foundation; either version 2.1
+ * of the License, or (at your option) any later version.
+ *
+ * GROMACS is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with GROMACS; if not, see
+ * http://www.gnu.org/licenses, or write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA.
+ *
+ * If you want to redistribute modifications to GROMACS, please
+ * consider that scientific software is very special. Version
+ * control is crucial - bugs must be traceable. We will be happy to
+ * consider code for inclusion in the official distribution, but
+ * derived work must not be called official GROMACS. Details are found
+ * in the README & COPYING files - if they are missing, get the
+ * official version at http://www.gromacs.org.
+ *
+ * To help us fund GROMACS development, we humbly ask that you cite
+ * the research papers on the package. Check out http://www.gromacs.org.
+ */
+/*! \internal \file
+ * \brief
+ * Implements gmx::CommandLineHelpContext.
+ *
+ * \author Teemu Murtola <teemu.murtola@gmail.com>
+ * \ingroup module_commandline
+ */
+#include "cmdlinehelpcontext.h"
+
+#include "gromacs/utility/gmxassert.h"
+
+namespace gmx
+{
+
+namespace
+{
+
+/*! \internal \brief
+ * Stores the global context set with GlobalCommandLineHelpContext.
+ *
+ * This is not protected by a mutex, since it is only used in command-line
+ * start-up (i.e., single-threaded context), and is inherently not thread-safe.
+ */
+const CommandLineHelpContext *g_globalContext = NULL;
+
+}   // namespace
+
+/*! \internal \brief
+ * Private implementation class for CommandLineHelpContext.
+ *
+ * \ingroup module_commandline
+ */
+class CommandLineHelpContext::Impl
+{
+    public:
+        //! Creates the implementation class and the low-level context.
+        Impl(File *file, HelpOutputFormat format)
+            : writerContext_(file, format), moduleDisplayName_("gmx")
+        {
+        }
+
+        //! Wrapped lower-level context.
+        HelpWriterContext  writerContext_;
+        //! Display name for the module for which help is written.
+        std::string        moduleDisplayName_;
+};
+
+CommandLineHelpContext::CommandLineHelpContext(
+        File *file, HelpOutputFormat format)
+    : impl_(new Impl(file, format))
+{
+}
+
+CommandLineHelpContext::~CommandLineHelpContext()
+{
+}
+
+void CommandLineHelpContext::setModuleDisplayName(const std::string &name)
+{
+    impl_->moduleDisplayName_ = name;
+}
+
+const HelpWriterContext &CommandLineHelpContext::writerContext() const
+{
+    return impl_->writerContext_;
+}
+
+const char *CommandLineHelpContext::moduleDisplayName() const
+{
+    return impl_->moduleDisplayName_.c_str();
+}
+
+/********************************************************************
+ * GlobalCommandLineHelpContext
+ */
+
+// static
+const CommandLineHelpContext *GlobalCommandLineHelpContext::get()
+{
+    return g_globalContext;
+}
+
+GlobalCommandLineHelpContext::GlobalCommandLineHelpContext(
+        const CommandLineHelpContext &context)
+{
+    GMX_RELEASE_ASSERT(g_globalContext == NULL,
+                       "Global context set more than once");
+    g_globalContext = &context;
+}
+
+GlobalCommandLineHelpContext::~GlobalCommandLineHelpContext()
+{
+    g_globalContext = NULL;
+}
+
+} // namespace gmx
diff --git a/src/gromacs/commandline/cmdlinehelpcontext.h b/src/gromacs/commandline/cmdlinehelpcontext.h
new file mode 100644 (file)
index 0000000..6b768e7
--- /dev/null
@@ -0,0 +1,129 @@
+/*
+ * This file is part of the GROMACS molecular simulation package.
+ *
+ * Copyright (c) 2013, by the GROMACS development team, led by
+ * David van der Spoel, Berk Hess, Erik Lindahl, and including many
+ * others, as listed in the AUTHORS file in the top-level source
+ * directory and at http://www.gromacs.org.
+ *
+ * GROMACS is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public License
+ * as published by the Free Software Foundation; either version 2.1
+ * of the License, or (at your option) any later version.
+ *
+ * GROMACS is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with GROMACS; if not, see
+ * http://www.gnu.org/licenses, or write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA.
+ *
+ * If you want to redistribute modifications to GROMACS, please
+ * consider that scientific software is very special. Version
+ * control is crucial - bugs must be traceable. We will be happy to
+ * consider code for inclusion in the official distribution, but
+ * derived work must not be called official GROMACS. Details are found
+ * in the README & COPYING files - if they are missing, get the
+ * official version at http://www.gromacs.org.
+ *
+ * To help us fund GROMACS development, we humbly ask that you cite
+ * the research papers on the package. Check out http://www.gromacs.org.
+ */
+/*! \libinternal \file
+ * \brief
+ * Declares gmx::CommandLineHelpContext.
+ *
+ * \author Teemu Murtola <teemu.murtola@gmail.com>
+ * \inlibraryapi
+ * \ingroup module_commandline
+ */
+#ifndef GMX_COMMANDLINE_CMDLINEHELPCONTEXT_H
+#define GMX_COMMANDLINE_CMDLINEHELPCONTEXT_H
+
+#include "../onlinehelp/helpwritercontext.h"
+#include "../utility/common.h"
+
+namespace gmx
+{
+
+/*! \libinternal \brief
+ * Context information for writing out command-line help.
+ *
+ * This class wraps a HelpWriterContext, extending it with information specific
+ * for command-line help export.  This way, code using only the routines in the
+ * onlinehelp module is not exposed to extra features of the command-line help
+ * export.
+ *
+ * \ingroup module_commandline
+ */
+class CommandLineHelpContext
+{
+    public:
+        /*! \brief
+         * Creates the context.
+         *
+         * Wraps the constructor of HelpWriterContext.
+         */
+        CommandLineHelpContext(File *file, HelpOutputFormat format);
+        ~CommandLineHelpContext();
+
+        /*! \brief
+         * Sets a display name for the module for which help is being written.
+         *
+         * \throws std::bad_alloc if out of memory.
+         */
+        void setModuleDisplayName(const std::string &name);
+
+        //! Returns the lower-level context for writing the help.
+        const HelpWriterContext &writerContext() const;
+        /*! \brief
+         * Returns a display name for the module for which help is being written.
+         *
+         * Does not throw.
+         */
+        const char *moduleDisplayName() const;
+
+    private:
+        class Impl;
+
+        PrivateImplPointer<Impl> impl_;
+};
+
+/*! \libinternal \brief
+ * Helper for passing CommandLineHelpContext into parse_common_args().
+ *
+ * This class provides a mechanism to set and retrieve a global
+ * CommandLineHelpContext object.  It is used to pass this object into
+ * parse_common_args() from CommandLineModuleManager::runAsMainCMain() through
+ * the main() function that is not aware of the wrapper binary mechanism.
+ * It is not thread-safe because in this limited use case, it is always called
+ * from a single-threaded context.
+ *
+ * \inlibraryapi
+ * \ingroup module_onlinehelp
+ */
+class GlobalCommandLineHelpContext
+{
+    public:
+        //! Returns the global context, or NULL if not set.
+        static const CommandLineHelpContext *get();
+
+        /*! \brief
+         * Sets the global context for the scope.
+         *
+         * The global context is cleared when this object goes out of scope.
+         *
+         * It is an error to have more than one GlobalCommandLineHelpContext
+         * object in existence at the same time.
+         */
+        explicit GlobalCommandLineHelpContext(const CommandLineHelpContext &context);
+        //! Clears the global context.
+        ~GlobalCommandLineHelpContext();
+};
+
+} // namespace gmx
+
+#endif
index d91cc3f19a8f1fba511723f8c970bf1e1da9733e..7781fb8e1cb0538f6494ffd3d7743db4f1a17b58 100644 (file)
@@ -43,6 +43,7 @@
 
 #include <string>
 
+#include "gromacs/commandline/cmdlinehelpcontext.h"
 #include "gromacs/onlinehelp/helpformat.h"
 #include "gromacs/onlinehelp/helpwritercontext.h"
 #include "gromacs/options/basicoptions.h"
@@ -532,11 +533,12 @@ CommandLineHelpWriter &CommandLineHelpWriter::setTimeUnitString(const char *time
     return *this;
 }
 
-void CommandLineHelpWriter::writeHelp(const HelpWriterContext &context)
+void CommandLineHelpWriter::writeHelp(const CommandLineHelpContext &context)
 {
     boost::scoped_ptr<OptionsFormatterInterface> formatter;
-    CommonFormatterData common(impl_->timeUnit_.c_str());
-    switch (context.outputFormat())
+    const HelpWriterContext                     &writerContext = context.writerContext();
+    CommonFormatterData                          common(impl_->timeUnit_.c_str());
+    switch (writerContext.outputFormat())
     {
         case eHelpOutputFormat_Console:
             formatter.reset(new OptionsConsoleFormatter(common));
@@ -547,12 +549,12 @@ void CommandLineHelpWriter::writeHelp(const HelpWriterContext &context)
             GMX_THROW(NotImplementedError(
                               "Command-line help is not implemented for this output format"));
     }
-    OptionsFilter filter(context, formatter.get());
+    OptionsFilter filter(writerContext, formatter.get());
     filter.setShowHidden(impl_->bShowHidden_);
 
     if (impl_->bShowDescriptions_)
     {
-        File &file = context.outputFile();
+        File &file = writerContext.outputFile();
         file.writeLine("DESCRIPTION");
         file.writeLine("-----------");
         file.writeLine();
index d67c4fc4fe76c95eedfb625465b0aaf9fa4eb31d..56249f84f154ea84072b2bd1d3a1baa8528e7fac 100644 (file)
@@ -1,7 +1,7 @@
 /*
  * This file is part of the GROMACS molecular simulation package.
  *
- * Copyright (c) 2010,2011,2012, by the GROMACS development team, led by
+ * Copyright (c) 2010,2011,2012,2013, by the GROMACS development team, led by
  * David van der Spoel, Berk Hess, Erik Lindahl, and including many
  * others, as listed in the AUTHORS file in the top-level source
  * directory and at http://www.gromacs.org.
@@ -48,7 +48,7 @@
 namespace gmx
 {
 
-class HelpWriterContext;
+class CommandLineHelpContext;
 class Options;
 
 /*! \brief
@@ -95,7 +95,7 @@ class CommandLineHelpWriter
          * \throws    std::bad_alloc if out of memory.
          * \throws    FileIOError on any I/O error.
          */
-        void writeHelp(const HelpWriterContext &context);
+        void writeHelp(const CommandLineHelpContext &context);
 
     private:
         class Impl;
index d8b1f5c3b2bc55ba917c0d2e5fa2d49a9622e97f..5a3e3e5f4f58a00d10f63f462c35669d0098b731 100644 (file)
@@ -1,7 +1,7 @@
 /*
  * This file is part of the GROMACS molecular simulation package.
  *
- * Copyright (c) 2012, by the GROMACS development team, led by
+ * Copyright (c) 2012,2013, by the GROMACS development team, led by
  * David van der Spoel, Berk Hess, Erik Lindahl, and including many
  * others, as listed in the AUTHORS file in the top-level source
  * directory and at http://www.gromacs.org.
@@ -46,7 +46,7 @@
 namespace gmx
 {
 
-class HelpWriterContext;
+class CommandLineHelpContext;
 
 /*! \brief
  * Module that can be run from command line using CommandLineModuleManager.
@@ -86,7 +86,7 @@ class CommandLineModuleInterface
          * \throws    std::bad_alloc if out of memory.
          * \throws    FileIOError on any I/O error.
          */
-        virtual void writeHelp(const HelpWriterContext &context) const = 0;
+        virtual void writeHelp(const CommandLineHelpContext &context) const = 0;
 };
 
 } // namespace gmx
index 68e16ef9960c5ce5675724bf7835248dd4fdccc0..785507f1662f8f1696867b71d44ea8587cdbc3d0 100644 (file)
 #include <string>
 #include <utility>
 
+#include <boost/scoped_ptr.hpp>
+
 #include "gromacs/legacyheaders/copyrite.h"
 #include "gromacs/legacyheaders/network.h"
 
+#include "gromacs/commandline/cmdlinehelpcontext.h"
 #include "gromacs/commandline/cmdlinemodule.h"
 #include "gromacs/commandline/cmdlineparser.h"
 #include "gromacs/onlinehelp/helpformat.h"
@@ -224,9 +227,35 @@ class ModuleHelpTopic : public HelpTopicInterface
 
 void ModuleHelpTopic::writeHelp(const HelpWriterContext &context) const
 {
-    module_.writeHelp(context);
+    CommandLineHelpContext newContext(&context.outputFile(),
+                                      context.outputFormat());
+    module_.writeHelp(newContext);
 }
 
+/********************************************************************
+ * HelpExportInterface
+ */
+
+/*! \internal \brief
+ * Callbacks for exporting help information for command-line modules.
+ *
+ * \ingroup module_commandline
+ */
+class HelpExportInterface
+{
+    public:
+        virtual ~HelpExportInterface() {};
+
+        /*! \brief
+         * Called to export the help for each module.
+         *
+         * \param[in] tag     Unique tag for the module (gmx-something).
+         * \param[in] module  Module for which the help should be exported.
+         */
+        virtual void exportModuleHelp(const std::string                &tag,
+                                      const CommandLineModuleInterface &module) = 0;
+};
+
 }   // namespace
 
 /********************************************************************
@@ -267,16 +296,19 @@ class CommandLineHelpModule : public CommandLineModuleInterface
         }
 
         virtual int run(int argc, char *argv[]);
-        virtual void writeHelp(const HelpWriterContext &context) const;
+        virtual void writeHelp(const CommandLineHelpContext &context) const;
 
     private:
-        CompositeHelpTopicPointer   rootTopic_;
+        void exportHelp(HelpExportInterface *exporter) const;
+
+        boost::scoped_ptr<RootHelpTopic>  rootTopic_;
+        const CommandLineModuleMap       &modules_;
 
         GMX_DISALLOW_COPY_AND_ASSIGN(CommandLineHelpModule);
 };
 
 CommandLineHelpModule::CommandLineHelpModule(const CommandLineModuleMap &modules)
-    : rootTopic_(new RootHelpTopic(modules))
+    : rootTopic_(new RootHelpTopic(modules)), modules_(modules)
 {
 }
 
@@ -287,6 +319,22 @@ void CommandLineHelpModule::addTopic(HelpTopicPointer topic)
 
 int CommandLineHelpModule::run(int argc, char *argv[])
 {
+    const char *const exportFormats[] = { "man", "html", "completion" };
+    std::string       exportFormat;
+    Options           options(NULL, NULL);
+    options.addOption(StringOption("export").store(&exportFormat)
+                          .enumValue(exportFormats));
+    CommandLineParser(&options).parse(&argc, argv);
+    if (!exportFormat.empty())
+    {
+        boost::scoped_ptr<HelpExportInterface> exporter;
+        {
+            GMX_THROW(NotImplementedError("This help format is not implemented"));
+        }
+        exportHelp(exporter.get());
+        return 0;
+    }
+
     HelpWriterContext context(&File::standardOutput(),
                               eHelpOutputFormat_Console);
     HelpManager       helpManager(*rootTopic_, context);
@@ -306,13 +354,38 @@ int CommandLineHelpModule::run(int argc, char *argv[])
     return 0;
 }
 
-void CommandLineHelpModule::writeHelp(const HelpWriterContext &context) const
+void CommandLineHelpModule::writeHelp(const CommandLineHelpContext &context) const
 {
-    context.writeTextBlock(
+    const HelpWriterContext &writerContext = context.writerContext();
+    // TODO: Implement.
+    if (writerContext.outputFormat() != eHelpOutputFormat_Console)
+    {
+        return;
+    }
+    writerContext.writeTextBlock(
             "Usage: [PROGRAM] help [<command>|<topic> [<subtopic> [...]]]");
     // TODO: More information.
 }
 
+void CommandLineHelpModule::exportHelp(HelpExportInterface *exporter) const
+{
+    // TODO: Would be nicer to have the file names supplied by the build system
+    // and/or export a list of files from here.
+    const char *const program =
+        ProgramInfo::getInstance().invariantProgramName().c_str();
+
+    CommandLineModuleMap::const_iterator module;
+    for (module = modules_.begin(); module != modules_.end(); ++module)
+    {
+        if (module->second->shortDescription() != NULL)
+        {
+            const char *const moduleName = module->first.c_str();
+            std::string       tag(formatString("%s-%s", program, moduleName));
+            exporter->exportModuleHelp(tag, *module->second);
+        }
+    }
+}
+
 namespace
 {
 
@@ -362,18 +435,25 @@ class CMainCommandLineModule : public CommandLineModuleInterface
         {
             return mainFunction_(argc, argv);
         }
-        virtual void writeHelp(const HelpWriterContext &context) const
+        virtual void writeHelp(const CommandLineHelpContext &context) const
         {
-            if (context.outputFormat() != eHelpOutputFormat_Console)
-            {
-                GMX_THROW(NotImplementedError(
-                                  "Command-line help is not implemented for this output format"));
-            }
-            char *argv[2];
+            const HelpOutputFormat format = context.writerContext().outputFormat();
+            char                  *argv[2];
+            int                    argc = 1;
             // TODO: The constness should not be cast away.
             argv[0] = const_cast<char *>(name_);
-            argv[1] = const_cast<char *>("-h");
-            mainFunction_(2, argv);
+            switch (format)
+            {
+                case eHelpOutputFormat_Console:
+                    argv[1] = const_cast<char *>("-h");
+                    argc    = 2;
+                    break;
+                default:
+                    GMX_THROW(NotImplementedError(
+                                      "Command-line help is not implemented for this output format"));
+            }
+            GlobalCommandLineHelpContext global(context);
+            mainFunction_(argc, argv);
         }
 
     private:
index a211134ef7f461eeb0e57b0d2f8e25bf4ab89232..e05c5780176458fc83a611c838c659bfc1cdc1a1 100644 (file)
@@ -49,8 +49,8 @@
 
 #include "gromacs/legacyheaders/types/simple.h"
 
+#include "gromacs/commandline/cmdlinehelpcontext.h"
 #include "gromacs/commandline/cmdlinehelpwriter.h"
-#include "gromacs/onlinehelp/helpwritercontext.h"
 #include "gromacs/options/basicoptions.h"
 #include "gromacs/options/filenameoption.h"
 #include "gromacs/options/options.h"
@@ -76,9 +76,9 @@ class CommandLineHelpWriterTest : public ::gmx::test::StringTestBase
 
 void CommandLineHelpWriterTest::checkHelp(gmx::CommandLineHelpWriter *writer)
 {
-    std::string            filename = tempFiles_.getTemporaryFilePath("helptext.txt");
-    gmx::File              file(filename, "w");
-    gmx::HelpWriterContext context(&file, gmx::eHelpOutputFormat_Console);
+    std::string                 filename = tempFiles_.getTemporaryFilePath("helptext.txt");
+    gmx::File                   file(filename, "w");
+    gmx::CommandLineHelpContext context(&file, gmx::eHelpOutputFormat_Console);
     writer->writeHelp(context);
     file.close();
 
index 6c8c2e774eb24f43598780ad23a3bb13763fba0e..8e1f7042fe352904d5a0a63d4a0010ee7ccb9c93 100644 (file)
@@ -48,6 +48,7 @@
 
 #include <gmock/gmock.h>
 
+#include "gromacs/commandline/cmdlinehelpcontext.h"
 #include "gromacs/commandline/cmdlinemodule.h"
 #include "gromacs/commandline/cmdlinemodulemanager.h"
 #include "gromacs/utility/programinfo.h"
@@ -81,7 +82,7 @@ class MockModule : public gmx::CommandLineModuleInterface
         virtual const char *shortDescription() const { return descr_; }
 
         MOCK_METHOD2(run, int(int argc, char *argv[]));
-        MOCK_CONST_METHOD1(writeHelp, void(const gmx::HelpWriterContext &context));
+        MOCK_CONST_METHOD1(writeHelp, void(const gmx::CommandLineHelpContext &context));
 
     private:
         const char             *name_;
index d0fdf27dbd0c5b210b32ed59ff1af26b8e61f132..e72c7c6036efcb7c9a673b8b6a5e8304a6d1c696 100644 (file)
@@ -372,18 +372,6 @@ static void pdesc(char *desc)
     }
 }
 
-static FILE *man_file(const output_env_t oenv, const char *mantp)
-{
-    FILE       *fp;
-    char        buf[256];
-    const char *pr = output_env_get_short_program_name(oenv);
-
-    sprintf(buf, "%s.%s", pr, mantp);
-    fp = gmx_fio_fopen(buf, "w");
-
-    return fp;
-}
-
 static int add_parg(int npargs, t_pargs *pa, t_pargs *pa_add)
 {
     memcpy(&(pa[npargs]), pa_add, sizeof(*pa_add));
@@ -551,7 +539,6 @@ gmx_bool parse_common_args(int *argc, char *argv[], unsigned long Flags,
           "HIDDENWrite file with debug information, 1: short, 2: also x and f" },
     };
 #define NPCA_PA asize(pca_pa)
-    FILE    *fp;
     gmx_bool bExit, bXvgr;
     int      i, j, k, npall, max_pa;
 
@@ -755,7 +742,7 @@ gmx_bool parse_common_args(int *argc, char *argv[], unsigned long Flags,
     {
         if (bHelp)
         {
-            write_man(stderr, "help", output_env_get_program_name(*oenv),
+            write_man("help", output_env_get_program_name(*oenv),
                       ndesc, desc, nfile, fnm, npall, all_pa, nbugs, bugs, bHidden);
         }
         else if (bVerbose)
@@ -770,26 +757,17 @@ gmx_bool parse_common_args(int *argc, char *argv[], unsigned long Flags,
         if (!strcmp(manstr[0], "completion"))
         {
             /* one file each for csh, bash and zsh if we do completions */
-            fp = man_file(*oenv, "completion-zsh");
-
-            write_man(fp, "completion-zsh", output_env_get_program_name(*oenv),
+            write_man("completion-zsh", output_env_get_short_program_name(*oenv),
                       ndesc, desc, nfile, fnm, npall, all_pa, nbugs, bugs, bHidden);
-            gmx_fio_fclose(fp);
-            fp = man_file(*oenv, "completion-bash");
-            write_man(fp, "completion-bash", output_env_get_program_name(*oenv),
+            write_man("completion-bash", output_env_get_short_program_name(*oenv),
                       ndesc, desc, nfile, fnm, npall, all_pa, nbugs, bugs, bHidden);
-            gmx_fio_fclose(fp);
-            fp = man_file(*oenv, "completion-csh");
-            write_man(fp, "completion-csh", output_env_get_program_name(*oenv),
+            write_man("completion-csh", output_env_get_short_program_name(*oenv),
                       ndesc, desc, nfile, fnm, npall, all_pa, nbugs, bugs, bHidden);
-            gmx_fio_fclose(fp);
         }
         else
         {
-            fp = man_file(*oenv, manstr[0]);
-            write_man(fp, manstr[0], output_env_get_program_name(*oenv),
+            write_man(manstr[0], output_env_get_short_program_name(*oenv),
                       ndesc, desc, nfile, fnm, npall, all_pa, nbugs, bugs, bHidden);
-            gmx_fio_fclose(fp);
         }
     }
 
index e355455c1565684978e83e7fca102bbed084a205..94dfbb150a56b8854dd04efd2d5383aadb82d32f 100644 (file)
@@ -1,7 +1,7 @@
 /*
  * This file is part of the GROMACS molecular simulation package.
  *
- * Copyright (c) 2012, by the GROMACS development team, led by
+ * Copyright (c) 2012,2013, by the GROMACS development team, led by
  * David van der Spoel, Berk Hess, Erik Lindahl, and including many
  * others, as listed in the AUTHORS file in the top-level source
  * directory and at http://www.gromacs.org.
@@ -44,6 +44,7 @@
 #include <cctype>
 
 #include <algorithm>
+#include <string>
 
 #include "gromacs/legacyheaders/smalloc.h"
 
@@ -108,13 +109,6 @@ class HelpWriterContext::Impl
 HelpWriterContext::HelpWriterContext(File *file, HelpOutputFormat format)
     : impl_(new Impl(file, format))
 {
-    if (format != eHelpOutputFormat_Console)
-    {
-        // TODO: Implement once the situation with Redmine issue #969 is more
-        // clear.
-        GMX_THROW(NotImplementedError(
-                          "This output format is not implemented"));
-    }
 }
 
 HelpWriterContext::~HelpWriterContext()
@@ -133,6 +127,13 @@ File &HelpWriterContext::outputFile() const
 
 std::string HelpWriterContext::substituteMarkup(const std::string &text) const
 {
+    if (outputFormat() != eHelpOutputFormat_Console)
+    {
+        // TODO: Implement once the situation with Redmine issue #969 is more
+        // clear.
+        GMX_THROW(NotImplementedError(
+                          "This output format is not implemented"));
+    }
     char            *resultStr = check_tty(text.c_str());
     scoped_ptr_sfree resultGuard(resultStr);
     return std::string(resultStr);
@@ -140,6 +141,13 @@ std::string HelpWriterContext::substituteMarkup(const std::string &text) const
 
 void HelpWriterContext::writeTitle(const std::string &title) const
 {
+    if (outputFormat() != eHelpOutputFormat_Console)
+    {
+        // TODO: Implement once the situation with Redmine issue #969 is more
+        // clear.
+        GMX_THROW(NotImplementedError(
+                          "This output format is not implemented"));
+    }
     File &file = outputFile();
     file.writeLine(toUpperCase(title));
     file.writeLine();
@@ -147,6 +155,13 @@ void HelpWriterContext::writeTitle(const std::string &title) const
 
 void HelpWriterContext::writeTextBlock(const std::string &text) const
 {
+    if (outputFormat() != eHelpOutputFormat_Console)
+    {
+        // TODO: Implement once the situation with Redmine issue #969 is more
+        // clear.
+        GMX_THROW(NotImplementedError(
+                          "This output format is not implemented"));
+    }
     TextLineWrapper wrapper;
     wrapper.settings().setLineLength(78);
     const char     *program = ProgramInfo::getInstance().programName().c_str();
index f869c215f4257b22d67fc7a4f908aae7a749d4c7..603c78d646389b12fb961e7d2a869e8d6097be01 100644 (file)
 
 #include <string>
 
+#include "gromacs/commandline/cmdlinehelpcontext.h"
 #include "gromacs/onlinehelp/wman.h"
 #include "gromacs/utility/exceptions.h"
+#include "gromacs/utility/file.h"
 #include "gromacs/utility/stringutil.h"
 
 #include "gmx_fatal.h"
@@ -979,7 +981,7 @@ static void write_bashcompl(FILE *out,
     fprintf(out, "esac }\ncomplete -F _%s_compl %s\n", ShortProgram(), ShortProgram());
 }
 
-void write_man(FILE *out, const char *mantp,
+void write_man(const char *mantp,
                const char *program,
                int nldesc, const char **desc,
                int nfile, t_filenm *fnm,
@@ -987,7 +989,6 @@ void write_man(FILE *out, const char *mantp,
                int nbug, const char **bugs,
                gmx_bool bHidden)
 {
-    const char *pr;
     int         i, npar;
     t_pargs    *par;
 
@@ -995,9 +996,25 @@ void write_man(FILE *out, const char *mantp,
 
     links = init_linkdata();
 
-    /* Don't write hidden options to completions, it just
-     * makes the options more complicated for normal users
-     */
+    const gmx::CommandLineHelpContext *context
+        = gmx::GlobalCommandLineHelpContext::get();
+    bool  bFileOpened = false;
+    FILE *out;
+    if (context != NULL)
+    {
+        out = context->writerContext().outputFile().handle();
+    }
+    else if (strcmp(mantp, "help") == 0)
+    {
+        out = stderr;
+    }
+    else
+    {
+        char buf[256];
+        sprintf(buf, "%s.%s", program, mantp);
+        out         = gmx_fio_fopen(buf, "w");
+        bFileOpened = true;
+    }
 
     if (bHidden)
     {
@@ -1018,29 +1035,21 @@ void write_man(FILE *out, const char *mantp,
         }
     }
 
-    if ((pr = strrchr(program, DIR_SEPARATOR)) == NULL)
-    {
-        pr = program;
-    }
-    else
-    {
-        pr += 1;
-    }
     if (strcmp(mantp, "tex") == 0)
     {
-        write_texman(out, pr, nldesc, desc, nfile, fnm, npar, par, nbug, bugs, links);
+        write_texman(out, program, nldesc, desc, nfile, fnm, npar, par, nbug, bugs, links);
     }
     if (strcmp(mantp, "nroff") == 0)
     {
-        write_nroffman(out, pr, nldesc, desc, nfile, fnm, npar, par, nbug, bugs, links);
+        write_nroffman(out, program, nldesc, desc, nfile, fnm, npar, par, nbug, bugs, links);
     }
     if (strcmp(mantp, "help") == 0)
     {
-        write_ttyman(out, pr, nldesc, desc, nfile, fnm, npar, par, nbug, bugs, links);
+        write_ttyman(out, program, nldesc, desc, nfile, fnm, npar, par, nbug, bugs, links);
     }
     if (strcmp(mantp, "html") == 0)
     {
-        write_htmlman(out, pr, nldesc, desc, nfile, fnm, npar, par, nbug, bugs, links);
+        write_htmlman(out, program, nldesc, desc, nfile, fnm, npar, par, nbug, bugs, links);
     }
     if (strcmp(mantp, "completion-zsh") == 0)
     {
@@ -1055,6 +1064,11 @@ void write_man(FILE *out, const char *mantp,
         write_cshcompl(out, nfile, fnm, npar, par);
     }
 
+    if (bFileOpened)
+    {
+        gmx_fio_fclose(out);
+    }
+
     if (!bHidden)
     {
         sfree(par);
index 1173d480e9e53ac7eeb681389fe6e4ed5a25f392..82bdccbc4fe097ac47d961642adc65c576529a8b 100644 (file)
@@ -41,7 +41,7 @@
 extern "C" {
 #endif
 
-void write_man(FILE *out, const char *mantp, const char *program,
+void write_man(const char *mantp, const char *program,
                int nldesc, const char **desc,
                int nfile, t_filenm *fnm,
                int npargs, t_pargs *pa,
index 8b5c60d703f496880b1e5c8f0dc3dde91490a8f3..ee5875bfb1ad3203d407ba0a4ec52fbc4357a750 100644 (file)
@@ -1,7 +1,7 @@
 /*
  * This file is part of the GROMACS molecular simulation package.
  *
- * Copyright (c) 2010,2011,2012, by the GROMACS development team, led by
+ * Copyright (c) 2010,2011,2012,2013, by the GROMACS development team, led by
  * David van der Spoel, Berk Hess, Erik Lindahl, and including many
  * others, as listed in the AUTHORS file in the top-level source
  * directory and at http://www.gromacs.org.
@@ -50,6 +50,7 @@
 #include "gromacs/legacyheaders/statutil.h"
 
 #include "gromacs/analysisdata/paralleloptions.h"
+#include "gromacs/commandline/cmdlinehelpcontext.h"
 #include "gromacs/commandline/cmdlinehelpwriter.h"
 #include "gromacs/commandline/cmdlinemodule.h"
 #include "gromacs/commandline/cmdlinemodulemanager.h"
@@ -115,8 +116,8 @@ TrajectoryAnalysisCommandLineRunner::Impl::printHelp(
     TrajectoryAnalysisRunnerCommon::HelpFlags flags = common.helpFlags();
     if (flags != 0)
     {
-        HelpWriterContext context(&File::standardError(),
-                                  eHelpOutputFormat_Console);
+        CommandLineHelpContext context(&File::standardError(),
+                                       eHelpOutputFormat_Console);
         CommandLineHelpWriter(options)
             .setShowDescriptions(flags & TrajectoryAnalysisRunnerCommon::efHelpShowDescriptions)
             .setShowHidden(flags & TrajectoryAnalysisRunnerCommon::efHelpShowHidden)
@@ -209,7 +210,7 @@ TrajectoryAnalysisCommandLineRunner::run(int argc, char *argv[])
 {
     TrajectoryAnalysisModule *module = impl_->module_;
 
-    SelectionCollection  selections;
+    SelectionCollection       selections;
     selections.setDebugLevel(impl_->debugLevel_);
 
     TrajectoryAnalysisSettings      settings;
@@ -280,7 +281,7 @@ TrajectoryAnalysisCommandLineRunner::run(int argc, char *argv[])
 
 
 void
-TrajectoryAnalysisCommandLineRunner::writeHelp(const HelpWriterContext &context)
+TrajectoryAnalysisCommandLineRunner::writeHelp(const CommandLineHelpContext &context)
 {
     // TODO: This method duplicates some code from run() and Impl::printHelp().
     // See how to best refactor it to share the common code.
@@ -340,7 +341,7 @@ class TrajectoryAnalysisCommandLineRunner::Impl::RunnerCommandLineModule
         virtual const char *shortDescription() const { return description_; };
 
         virtual int run(int argc, char *argv[]);
-        virtual void writeHelp(const HelpWriterContext &context) const;
+        virtual void writeHelp(const CommandLineHelpContext &context) const;
 
     private:
         const char             *name_;
@@ -359,8 +360,13 @@ int TrajectoryAnalysisCommandLineRunner::Impl::RunnerCommandLineModule::run(
 }
 
 void TrajectoryAnalysisCommandLineRunner::Impl::RunnerCommandLineModule::writeHelp(
-        const HelpWriterContext &context) const
+        const CommandLineHelpContext &context) const
 {
+    // TODO: Implement #969.
+    if (context.writerContext().outputFormat() != eHelpOutputFormat_Console)
+    {
+        return;
+    }
     TrajectoryAnalysisModulePointer     module(factory_());
     TrajectoryAnalysisCommandLineRunner runner(module.get());
     runner.writeHelp(context);
index 540e3bc9328de5132437689c85a535f00d8337f4..fefb93ef9b3c63a3da8355269f2e3fb35e7b4534 100644 (file)
@@ -1,7 +1,7 @@
 /*
  * This file is part of the GROMACS molecular simulation package.
  *
- * Copyright (c) 2010,2011,2012, by the GROMACS development team, led by
+ * Copyright (c) 2010,2011,2012,2013, by the GROMACS development team, led by
  * David van der Spoel, Berk Hess, Erik Lindahl, and including many
  * others, as listed in the AUTHORS file in the top-level source
  * directory and at http://www.gromacs.org.
@@ -50,7 +50,7 @@ namespace gmx
 {
 
 class CommandLineModuleManager;
-class HelpWriterContext;
+class CommandLineHelpContext;
 class TrajectoryAnalysisModule;
 
 /*! \brief
@@ -146,7 +146,7 @@ class TrajectoryAnalysisCommandLineRunner
          * \throws    std::bad_alloc if out of memory.
          * \throws    FileIOError on any I/O error.
          */
-        void writeHelp(const HelpWriterContext &context);
+        void writeHelp(const CommandLineHelpContext &context);
 
     private:
         //! Smart pointer type for managing a trajectory analysis module.
index e97eed1ad6ec445b777da7d3263ed84323b4a7a1..591c16bc9095366635de7d45fe64d4e5ad5076b9 100644 (file)
@@ -50,9 +50,9 @@
 
 #include "gromacs/legacyheaders/thread_mpi/mutex.h"
 
+#include "gromacs/commandline/cmdlinehelpcontext.h"
 #include "gromacs/commandline/cmdlinehelpwriter.h"
 #include "gromacs/commandline/cmdlineparser.h"
-#include "gromacs/onlinehelp/helpwritercontext.h"
 #include "gromacs/options/basicoptions.h"
 #include "gromacs/options/options.h"
 #include "gromacs/utility/common.h"
@@ -126,7 +126,7 @@ void TestOptionsRegistry::initOptions(Options *options)
     // TODO: Have some deterministic order for the options; now it depends on
     // the order in which the global initializers are run.
     tMPI::lock_guard<tMPI::mutex> lock(listMutex_);
-    ProviderList::const_iterator i;
+    ProviderList::const_iterator  i;
     for (i = providerList_.begin(); i != providerList_.end(); ++i)
     {
         (*i)->initOptions(options);
@@ -139,12 +139,12 @@ void printHelp(const Options &options)
     std::fprintf(stderr,
                  "\nYou can use the following GROMACS-specific command-line flags\n"
                  "to control the behavior of the tests:\n\n");
-    HelpWriterContext context(&File::standardError(),
-                              eHelpOutputFormat_Console);
+    CommandLineHelpContext context(&File::standardError(),
+                                   eHelpOutputFormat_Console);
     CommandLineHelpWriter(options).writeHelp(context);
 }
 
-} // namespace
+}       // namespace
 
 void registerTestOptions(const char *name, TestOptionsProvider *provider)
 {
@@ -161,7 +161,7 @@ void initTestUtils(const char *dataPath, int *argc, char ***argv)
         {
             TestFileManager::setInputDataDirectory(dataPath);
         }
-        bool bHelp = false;
+        bool    bHelp = false;
         Options options(NULL, NULL);
         // TODO: A single option that accepts multiple names would be nicer.
         // Also, we recognize -help, but GTest doesn't, which leads to a bit