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
\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.

View File

@ -154,6 +154,7 @@ int const LYX_FORMAT = LYX_FORMAT_TEX2LYX;
/// used modules
LayoutModuleList used_modules;
vector<string> preloaded_modules;
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.
// 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<string, DocumentClassPtr > 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<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.
// Only add it if the definition can be found in the preamble of the
@ -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;