From f107cc6f5853c3d428818fbb848985e90eeb9963 Mon Sep 17 00:00:00 2001 From: Teemu Murtola Date: Thu, 5 Sep 2013 06:22:08 +0300 Subject: [PATCH] Framework for help export from wrapper binary. - 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 --- src/gromacs/commandline/cmdlinehelpcontext.cpp | 130 +++++++++++++++++++++ src/gromacs/commandline/cmdlinehelpcontext.h | 129 ++++++++++++++++++++ src/gromacs/commandline/cmdlinehelpwriter.cpp | 12 +- src/gromacs/commandline/cmdlinehelpwriter.h | 6 +- src/gromacs/commandline/cmdlinemodule.h | 6 +- src/gromacs/commandline/cmdlinemodulemanager.cpp | 110 ++++++++++++++--- .../commandline/tests/cmdlinehelpwriter.cpp | 8 +- .../commandline/tests/cmdlinemodulemanager.cpp | 3 +- src/gromacs/gmxlib/statutil.cpp | 32 +---- src/gromacs/onlinehelp/helpwritercontext.cpp | 31 +++-- src/gromacs/onlinehelp/wman.cpp | 48 +++++--- src/gromacs/onlinehelp/wman.h | 2 +- src/gromacs/trajectoryanalysis/cmdlinerunner.cpp | 20 ++-- src/gromacs/trajectoryanalysis/cmdlinerunner.h | 6 +- src/testutils/testoptions.cpp | 12 +- 15 files changed, 455 insertions(+), 100 deletions(-) create mode 100644 src/gromacs/commandline/cmdlinehelpcontext.cpp create mode 100644 src/gromacs/commandline/cmdlinehelpcontext.h diff --git a/src/gromacs/commandline/cmdlinehelpcontext.cpp b/src/gromacs/commandline/cmdlinehelpcontext.cpp new file mode 100644 index 0000000000..803f41522c --- /dev/null +++ b/src/gromacs/commandline/cmdlinehelpcontext.cpp @@ -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 + * \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 index 0000000000..6b768e78ea --- /dev/null +++ b/src/gromacs/commandline/cmdlinehelpcontext.h @@ -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 + * \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_; +}; + +/*! \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 diff --git a/src/gromacs/commandline/cmdlinehelpwriter.cpp b/src/gromacs/commandline/cmdlinehelpwriter.cpp index d91cc3f19a..7781fb8e1c 100644 --- a/src/gromacs/commandline/cmdlinehelpwriter.cpp +++ b/src/gromacs/commandline/cmdlinehelpwriter.cpp @@ -43,6 +43,7 @@ #include +#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 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(); diff --git a/src/gromacs/commandline/cmdlinehelpwriter.h b/src/gromacs/commandline/cmdlinehelpwriter.h index d67c4fc4fe..56249f84f1 100644 --- a/src/gromacs/commandline/cmdlinehelpwriter.h +++ b/src/gromacs/commandline/cmdlinehelpwriter.h @@ -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; diff --git a/src/gromacs/commandline/cmdlinemodule.h b/src/gromacs/commandline/cmdlinemodule.h index d8b1f5c3b2..5a3e3e5f4f 100644 --- a/src/gromacs/commandline/cmdlinemodule.h +++ b/src/gromacs/commandline/cmdlinemodule.h @@ -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 diff --git a/src/gromacs/commandline/cmdlinemodulemanager.cpp b/src/gromacs/commandline/cmdlinemodulemanager.cpp index 68e16ef996..785507f166 100644 --- a/src/gromacs/commandline/cmdlinemodulemanager.cpp +++ b/src/gromacs/commandline/cmdlinemodulemanager.cpp @@ -47,9 +47,12 @@ #include #include +#include + #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 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 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 [| [ [...]]]"); // 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(name_); - argv[1] = const_cast("-h"); - mainFunction_(2, argv); + switch (format) + { + case eHelpOutputFormat_Console: + argv[1] = const_cast("-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: diff --git a/src/gromacs/commandline/tests/cmdlinehelpwriter.cpp b/src/gromacs/commandline/tests/cmdlinehelpwriter.cpp index a211134ef7..e05c578017 100644 --- a/src/gromacs/commandline/tests/cmdlinehelpwriter.cpp +++ b/src/gromacs/commandline/tests/cmdlinehelpwriter.cpp @@ -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(); diff --git a/src/gromacs/commandline/tests/cmdlinemodulemanager.cpp b/src/gromacs/commandline/tests/cmdlinemodulemanager.cpp index 6c8c2e774e..8e1f7042fe 100644 --- a/src/gromacs/commandline/tests/cmdlinemodulemanager.cpp +++ b/src/gromacs/commandline/tests/cmdlinemodulemanager.cpp @@ -48,6 +48,7 @@ #include +#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_; diff --git a/src/gromacs/gmxlib/statutil.cpp b/src/gromacs/gmxlib/statutil.cpp index d0fdf27dbd..e72c7c6036 100644 --- a/src/gromacs/gmxlib/statutil.cpp +++ b/src/gromacs/gmxlib/statutil.cpp @@ -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); } } diff --git a/src/gromacs/onlinehelp/helpwritercontext.cpp b/src/gromacs/onlinehelp/helpwritercontext.cpp index e355455c15..94dfbb150a 100644 --- a/src/gromacs/onlinehelp/helpwritercontext.cpp +++ b/src/gromacs/onlinehelp/helpwritercontext.cpp @@ -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 #include +#include #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(); diff --git a/src/gromacs/onlinehelp/wman.cpp b/src/gromacs/onlinehelp/wman.cpp index f869c215f4..603c78d646 100644 --- a/src/gromacs/onlinehelp/wman.cpp +++ b/src/gromacs/onlinehelp/wman.cpp @@ -40,8 +40,10 @@ #include +#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); diff --git a/src/gromacs/onlinehelp/wman.h b/src/gromacs/onlinehelp/wman.h index 1173d480e9..82bdccbc4f 100644 --- a/src/gromacs/onlinehelp/wman.h +++ b/src/gromacs/onlinehelp/wman.h @@ -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, diff --git a/src/gromacs/trajectoryanalysis/cmdlinerunner.cpp b/src/gromacs/trajectoryanalysis/cmdlinerunner.cpp index 8b5c60d703..ee5875bfb1 100644 --- a/src/gromacs/trajectoryanalysis/cmdlinerunner.cpp +++ b/src/gromacs/trajectoryanalysis/cmdlinerunner.cpp @@ -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); diff --git a/src/gromacs/trajectoryanalysis/cmdlinerunner.h b/src/gromacs/trajectoryanalysis/cmdlinerunner.h index 540e3bc932..fefb93ef9b 100644 --- a/src/gromacs/trajectoryanalysis/cmdlinerunner.h +++ b/src/gromacs/trajectoryanalysis/cmdlinerunner.h @@ -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. diff --git a/src/testutils/testoptions.cpp b/src/testutils/testoptions.cpp index e97eed1ad6..591c16bc90 100644 --- a/src/testutils/testoptions.cpp +++ b/src/testutils/testoptions.cpp @@ -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 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 -- 2.11.4.GIT