From b8648dea168f59b722cd0f16c8557c9c2e44682b Mon Sep 17 00:00:00 2001 From: Georg Baum Date: Tue, 23 Oct 2012 20:45:21 +0200 Subject: [PATCH] Implement tex2lyx -m switch (bug #8393) With this new command line switch a list of modules can be loaded unconditionally. This seems to be needed for the literate programming formats, and it is useful to work around bug #5702 as well. --- src/tex2lyx/tex2lyx.1in | 8 ++++ src/tex2lyx/tex2lyx.cpp | 94 +++++++++++++++++++++++++++++++++-------- 2 files changed, 84 insertions(+), 18 deletions(-) diff --git a/src/tex2lyx/tex2lyx.1in b/src/tex2lyx/tex2lyx.1in index 6eccf0d0cb..c91560a262 100644 --- a/src/tex2lyx/tex2lyx.1in +++ b/src/tex2lyx/tex2lyx.1in @@ -21,6 +21,7 @@ options. .PP \fBtex2lyx\fR [ \fB\-userdir\fR \fIuserdir\fR ] [ \fB\-systemdir\fR \fIsystemdir\fR ] [ \fB\-f\fR ] [ \fB\-n\fR ] [ \fB\-c\fR \fItextclass\fR ] +[\ \fB\-m\fR \fImodule1\fR[,\fImodule2\fR...]] [\ \fB\-s\fR\ \fIsfile1\fR[,\fIsfile2\fR...]] [ \fB\-skipchildren\fR ] [ \fB\-roundtrip\fR ] [ \fB\-copyfiles\fR ] \fIinputfile\fR [ \fIoutputfile\fR ] .\" .PP @@ -41,6 +42,13 @@ matter or \f(CW\ebegin{document}\fR command. LyX files created by \fBtex2lyx\fR from partial files can be included in an existing LyX file using the \*[lq]Include LyX File\*[rq] command from LyX's Insert menu. .TP +.BI \-m +Module. Load the given modules. This is useful if \fBtex2lyx\fR does not +automatically detect a given module, but you know the modules that provide +some commands or environments that are used in the imported file. The modules +are loaded in the given order. If a module \fIfoo\fR depends on a module +\fIbar\fR, \fIbar\fR must be given before \fIfoo\fR. +.TP .BI \-f Force. \fBtex2lyx\fR will not run if the .lyx file it would generate already exists. Use the \fB\-f\fR option (carefully) to clobber any existing files. diff --git a/src/tex2lyx/tex2lyx.cpp b/src/tex2lyx/tex2lyx.cpp index 360c126d8f..1abdecb2c9 100644 --- a/src/tex2lyx/tex2lyx.cpp +++ b/src/tex2lyx/tex2lyx.cpp @@ -154,6 +154,7 @@ int const LYX_FORMAT = LYX_FORMAT_TEX2LYX; /// used modules LayoutModuleList used_modules; +vector preloaded_modules; void convertArgs(string const & o1, bool o2, vector & arguments) @@ -234,28 +235,16 @@ InsetLayout const * findInsetLayoutWithoutModule(TextClass const & textclass, } -bool checkModule(string const & name, bool command) +namespace { + +typedef map ModuleMap; +ModuleMap modules; +void initModules() { - // Cache to avoid slowdown by repated searches - static set failed[2]; - - // Only add the module if the command was actually defined in the LyX preamble - if (command) { - if (possible_textclass_commands.find('\\' + name) == possible_textclass_commands.end()) - return false; - } else { - if (possible_textclass_environments.find(name) == possible_textclass_environments.end()) - return false; - } - if (failed[command].find(name) != failed[command].end()) - return false; - // Create list of dummy document classes if not already done. // This is needed since a module cannot be read on its own, only as // part of a document class. LayoutFile const & baseClass = LayoutFileList::get()[textclass.name()]; - typedef map ModuleMap; - static ModuleMap modules; static bool init = true; if (init) { baseClass.load(); @@ -272,6 +261,49 @@ bool checkModule(string const & name, bool command) } init = false; } +} + + +bool addModule(string const & module) +{ + initModules(); + LayoutFile const & baseClass = LayoutFileList::get()[textclass.name()]; + if (!used_modules.moduleCanBeAdded(module, &baseClass)) + return false; + FileName layout_file = libFileSearch("layouts", module, "module"); + if (textclass.read(layout_file, TextClass::MODULE)) { + used_modules.push_back(module); + // speed up further searches: + // the module does not need to be checked anymore. + ModuleMap::iterator const it = modules.find(module); + if (it != modules.end()) + modules.erase(it); + return true; + } + return false; +} + +} + + +bool checkModule(string const & name, bool command) +{ + // Cache to avoid slowdown by repated searches + static set failed[2]; + + // Only add the module if the command was actually defined in the LyX preamble + if (command) { + if (possible_textclass_commands.find('\\' + name) == possible_textclass_commands.end()) + return false; + } else { + if (possible_textclass_environments.find(name) == possible_textclass_environments.end()) + return false; + } + if (failed[command].find(name) != failed[command].end()) + return false; + + initModules(); + LayoutFile const & baseClass = LayoutFileList::get()[textclass.name()]; // Try to find a module that defines the command. // Only add it if the definition can be found in the preamble of the @@ -289,7 +321,7 @@ bool checkModule(string const & name, bool command) continue; if (findInsetLayoutWithoutModule(textclass, name, command)) continue; - DocumentClassConstPtr c = it->second; + DocumentClassConstPtr c = it->second; Layout const * layout = findLayoutWithoutModule(*c, name, command); InsetLayout const * insetlayout = layout ? 0 : findInsetLayoutWithoutModule(*c, name, command); @@ -459,6 +491,7 @@ int parse_help(string const &, string const &) cerr << "Usage: tex2lyx [options] infile.tex [outfile.lyx]\n" "Options:\n" "\t-c textclass Declare the textclass.\n" + "\t-m mod1[,mod2...] Load the given modules.\n" "\t-copyfiles Copy all included files to the directory of outfile.lyx.\n" "\t-e encoding Set the default encoding (latex name).\n" "\t-f Force overwrite of .lyx files.\n" @@ -511,6 +544,15 @@ int parse_class(string const & arg, string const &) } +int parse_module(string const & arg, string const &) +{ + if (arg.empty()) + error_message("Missing modules string after -m switch"); + split(arg, preloaded_modules, ','); + return 1; +} + + int parse_encoding(string const & arg, string const &) { if (arg.empty()) @@ -599,6 +641,7 @@ void easyParse(int & argc, char * argv[]) cmdmap["-version"] = parse_version; cmdmap["--version"] = parse_version; cmdmap["-c"] = parse_class; + cmdmap["-m"] = parse_module; cmdmap["-e"] = parse_encoding; cmdmap["-f"] = parse_force; cmdmap["-s"] = parse_syntaxfile; @@ -714,6 +757,21 @@ bool tex2lyx(idocstream & is, ostream & os, string encoding) preamble.parse(p, documentclass, textclass); + // Load preloaded modules. + // This needs to be done after the preamble is parsed, since the text + // class may not be known before. It neds to be done before parsing + // body, since otherwise the commands/environments provided by the + // modules would be parsed as ERT. + for (size_t i = 0; i < preloaded_modules.size(); ++i) { + if (!addModule(preloaded_modules[i])) { + cerr << "Error: Could not load module \"" + << preloaded_modules[i] << "\"." << endl; + return false; + } + } + // Ensure that the modules are not loaded again for included files + preloaded_modules.clear(); + active_environments.push_back("document"); Context context(true, textclass); stringstream ss;