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.
This commit is contained in:
Georg Baum 2012-10-23 20:45:21 +02:00
parent 2626821ee2
commit b8648dea16
2 changed files with 84 additions and 18 deletions

View File

@ -21,6 +21,7 @@ options.
.PP .PP
\fBtex2lyx\fR [ \fB\-userdir\fR \fIuserdir\fR ] [ \fB\-systemdir\fR \fIsystemdir\fR ] \fBtex2lyx\fR [ \fB\-userdir\fR \fIuserdir\fR ] [ \fB\-systemdir\fR \fIsystemdir\fR ]
[ \fB\-f\fR ] [ \fB\-n\fR ] [ \fB\-c\fR \fItextclass\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\-s\fR\ \fIsfile1\fR[,\fIsfile2\fR...]] [ \fB\-skipchildren\fR ] [
\fB\-roundtrip\fR ] [ \fB\-copyfiles\fR ] \fIinputfile\fR [ \fIoutputfile\fR ] \fB\-roundtrip\fR ] [ \fB\-copyfiles\fR ] \fIinputfile\fR [ \fIoutputfile\fR ]
.\" .PP .\" .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 \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. the \*[lq]Include LyX File\*[rq] command from LyX's Insert menu.
.TP .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 .BI \-f
Force. \fBtex2lyx\fR will not run if the .lyx file it would generate already exists. 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. Use the \fB\-f\fR option (carefully) to clobber any existing files.

View File

@ -154,6 +154,7 @@ int const LYX_FORMAT = LYX_FORMAT_TEX2LYX;
/// used modules /// used modules
LayoutModuleList used_modules; LayoutModuleList used_modules;
vector<string> preloaded_modules;
void convertArgs(string const & o1, bool o2, vector<ArgumentType> & arguments) void convertArgs(string const & o1, bool o2, vector<ArgumentType> & arguments)
@ -234,28 +235,16 @@ InsetLayout const * findInsetLayoutWithoutModule(TextClass const & textclass,
} }
bool checkModule(string const & name, bool command) namespace {
typedef map<string, DocumentClassPtr> ModuleMap;
ModuleMap modules;
void initModules()
{ {
// Cache to avoid slowdown by repated searches
static set<string> 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. // Create list of dummy document classes if not already done.
// This is needed since a module cannot be read on its own, only as // This is needed since a module cannot be read on its own, only as
// part of a document class. // part of a document class.
LayoutFile const & baseClass = LayoutFileList::get()[textclass.name()]; LayoutFile const & baseClass = LayoutFileList::get()[textclass.name()];
typedef map<string, DocumentClassPtr > ModuleMap;
static ModuleMap modules;
static bool init = true; static bool init = true;
if (init) { if (init) {
baseClass.load(); baseClass.load();
@ -272,6 +261,49 @@ bool checkModule(string const & name, bool command)
} }
init = false; 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<string> 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. // Try to find a module that defines the command.
// Only add it if the definition can be found in the preamble of the // 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; continue;
if (findInsetLayoutWithoutModule(textclass, name, command)) if (findInsetLayoutWithoutModule(textclass, name, command))
continue; continue;
DocumentClassConstPtr c = it->second; DocumentClassConstPtr c = it->second;
Layout const * layout = findLayoutWithoutModule(*c, name, command); Layout const * layout = findLayoutWithoutModule(*c, name, command);
InsetLayout const * insetlayout = layout ? 0 : InsetLayout const * insetlayout = layout ? 0 :
findInsetLayoutWithoutModule(*c, name, command); findInsetLayoutWithoutModule(*c, name, command);
@ -459,6 +491,7 @@ int parse_help(string const &, string const &)
cerr << "Usage: tex2lyx [options] infile.tex [outfile.lyx]\n" cerr << "Usage: tex2lyx [options] infile.tex [outfile.lyx]\n"
"Options:\n" "Options:\n"
"\t-c textclass Declare the textclass.\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-copyfiles Copy all included files to the directory of outfile.lyx.\n"
"\t-e encoding Set the default encoding (latex name).\n" "\t-e encoding Set the default encoding (latex name).\n"
"\t-f Force overwrite of .lyx files.\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 &) int parse_encoding(string const & arg, string const &)
{ {
if (arg.empty()) if (arg.empty())
@ -599,6 +641,7 @@ void easyParse(int & argc, char * argv[])
cmdmap["-version"] = parse_version; cmdmap["-version"] = parse_version;
cmdmap["--version"] = parse_version; cmdmap["--version"] = parse_version;
cmdmap["-c"] = parse_class; cmdmap["-c"] = parse_class;
cmdmap["-m"] = parse_module;
cmdmap["-e"] = parse_encoding; cmdmap["-e"] = parse_encoding;
cmdmap["-f"] = parse_force; cmdmap["-f"] = parse_force;
cmdmap["-s"] = parse_syntaxfile; cmdmap["-s"] = parse_syntaxfile;
@ -714,6 +757,21 @@ bool tex2lyx(idocstream & is, ostream & os, string encoding)
preamble.parse(p, documentclass, textclass); 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"); active_environments.push_back("document");
Context context(true, textclass); Context context(true, textclass);
stringstream ss; stringstream ss;