mirror of
https://git.lyx.org/repos/lyx.git
synced 2024-11-22 01:59:02 +00:00
Actually tex2lyx can handle modules since some time (#5702), but not theorems (#5776). Now the following issues are fixed: - Modules that depend on other modules can be loaded, since the dependencies are loaded first - Default moduls of the text class are loaded correctly - \newtheorem is recognized as a command that defines new environments and treated similar to \newenvironment
This commit is contained in:
parent
1094128fe1
commit
78a7743166
@ -67,10 +67,8 @@ bool LayoutModuleList::moduleCanBeAdded(string const & modName,
|
||||
if (!lm)
|
||||
return true;
|
||||
|
||||
// Is this module explicitly excluded by the document class?
|
||||
const_iterator const exclmodstart = lay->excludedModules().begin();
|
||||
const_iterator const exclmodend = lay->excludedModules().end();
|
||||
if (find(exclmodstart, exclmodend, modName) != exclmodend)
|
||||
// Does this module conflict with the document class or any loaded modules?
|
||||
if (moduleConflicts(modName, lay))
|
||||
return false;
|
||||
|
||||
// Is this module already provided by the document class?
|
||||
@ -79,26 +77,13 @@ bool LayoutModuleList::moduleCanBeAdded(string const & modName,
|
||||
if (find(provmodstart, provmodend, modName) != provmodend)
|
||||
return false;
|
||||
|
||||
// Check for conflicts with used modules
|
||||
// first the provided modules...
|
||||
const_iterator provmodit = provmodstart;
|
||||
for (; provmodit != provmodend; ++provmodit) {
|
||||
if (!LyXModule::areCompatible(modName, *provmodit))
|
||||
return false;
|
||||
}
|
||||
// and then the selected modules
|
||||
const_iterator mit = begin();
|
||||
const_iterator const men = end();
|
||||
for (; mit != men; ++mit)
|
||||
if (!LyXModule::areCompatible(modName, *mit))
|
||||
return false;
|
||||
|
||||
// Check whether some required module is available
|
||||
vector<string> const reqs = lm->getRequiredModules();
|
||||
if (reqs.empty())
|
||||
return true;
|
||||
|
||||
mit = begin(); // reset
|
||||
const_iterator mit = begin();
|
||||
const_iterator const men = end();
|
||||
vector<string>::const_iterator rit = reqs.begin();
|
||||
vector<string>::const_iterator ren = reqs.end();
|
||||
bool foundone = false;
|
||||
@ -114,6 +99,32 @@ bool LayoutModuleList::moduleCanBeAdded(string const & modName,
|
||||
}
|
||||
|
||||
|
||||
bool LayoutModuleList::moduleConflicts(string const & modName,
|
||||
LayoutFile const * const lay) const
|
||||
{
|
||||
// Is this module explicitly excluded by the document class?
|
||||
const_iterator const exclmodstart = lay->excludedModules().begin();
|
||||
const_iterator const exclmodend = lay->excludedModules().end();
|
||||
if (find(exclmodstart, exclmodend, modName) != exclmodend)
|
||||
return true;
|
||||
// Check for conflicts with used modules
|
||||
// first the provided modules...
|
||||
const_iterator provmodit = lay->providedModules().begin();
|
||||
const_iterator const provmodend = lay->providedModules().end();
|
||||
for (; provmodit != provmodend; ++provmodit) {
|
||||
if (!LyXModule::areCompatible(modName, *provmodit))
|
||||
return true;
|
||||
}
|
||||
// and then the selected modules
|
||||
const_iterator mit = begin();
|
||||
const_iterator const men = end();
|
||||
for (; mit != men; ++mit)
|
||||
if (!LyXModule::areCompatible(modName, *mit))
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
void LayoutModuleList::addDefaultModules(LayoutFile const * const lay,
|
||||
std::list<string> removedModules)
|
||||
{
|
||||
|
@ -57,7 +57,10 @@ public:
|
||||
std::list<std::string> const & list() const { return lml_; }
|
||||
/// Checks to make sure module's requriements are satisfied, that it does
|
||||
/// not conflict with already-present modules, isn't already loaded, etc.
|
||||
bool moduleCanBeAdded(std::string const & modName,
|
||||
bool moduleCanBeAdded(std::string const & modName,
|
||||
LayoutFile const * const lay) const;
|
||||
/// Like !moduleCanBeAdded(), but does not check requirements
|
||||
bool moduleConflicts(std::string const & modName,
|
||||
LayoutFile const * const lay) const;
|
||||
/// If the user changes the base class for a given document, then the
|
||||
/// associated module list has to be updated. This just calls
|
||||
|
@ -28,6 +28,7 @@ TEST_FILES = \
|
||||
test/foo.png \
|
||||
test/test-insets.tex \
|
||||
test/test.ltx \
|
||||
test/test-modules.tex \
|
||||
test/test-structure.tex \
|
||||
test/XeTeX-polyglossia.tex \
|
||||
test/xfigtest.fig \
|
||||
|
@ -1428,6 +1428,22 @@ void Preamble::parse(Parser & p, string const & forceclass,
|
||||
|
||||
}
|
||||
|
||||
else if (t.cs() == "newtheorem") {
|
||||
string const name = p.getArg('{', '}');
|
||||
string const opt1 = p.getFullOpt();
|
||||
string const opt2 = p.getFullOpt();
|
||||
string const body = p.verbatim_item();
|
||||
string const opt3 = p.getFullOpt();
|
||||
|
||||
add_known_theorem(name, opt1, !opt2.empty(),
|
||||
from_utf8("\\newtheorem{" + name + '}' +
|
||||
opt1 + opt2 + '{' + body + '}' + opt3));
|
||||
|
||||
if (!in_lyx_preamble)
|
||||
h_preamble << "\\newtheorem{" << name << '}'
|
||||
<< opt1 << opt2 << '{' << '}' << opt3;
|
||||
}
|
||||
|
||||
else if (t.cs() == "def") {
|
||||
string name = p.get_token().cs();
|
||||
// In fact, name may be more than the name:
|
||||
|
@ -9,7 +9,7 @@ project(test)
|
||||
set(_test_depend "test.ltx")
|
||||
set(_test_output)
|
||||
|
||||
foreach(_arg test-structure test-insets box-color-size-space-align CJK XeTeX-polyglossia)
|
||||
foreach(_arg test-structure test-insets test-modules box-color-size-space-align CJK XeTeX-polyglossia)
|
||||
list(APPEND _test_depend "${TOP_SRC_DIR}/src/tex2lyx/test/${_arg}.tex")
|
||||
list(APPEND _test_output "${CMAKE_CURRENT_BINARY_DIR}/${_arg}.lyx.tex")
|
||||
list(APPEND _test_output "${CMAKE_CURRENT_BINARY_DIR}/${_arg}.lyx.lyx")
|
||||
|
@ -46,8 +46,8 @@ def main(argv):
|
||||
outputdir = os.path.join(os.path.dirname(tex2lyx), "test")
|
||||
|
||||
files = ['test.ltx', 'test-structure.tex', 'test-insets.tex', \
|
||||
'box-color-size-space-align.tex', 'CJK.tex', \
|
||||
'XeTeX-polyglossia.tex']
|
||||
'test-modules.tex', 'box-color-size-space-align.tex', \
|
||||
'CJK.tex', 'XeTeX-polyglossia.tex']
|
||||
|
||||
errors = []
|
||||
overwrite = (outputdir == inputdir)
|
||||
|
156
src/tex2lyx/test/test-modules.lyx.lyx
Normal file
156
src/tex2lyx/test/test-modules.lyx.lyx
Normal file
@ -0,0 +1,156 @@
|
||||
#LyX file created by tex2lyx 2.1.0dev
|
||||
\lyxformat 445
|
||||
\begin_document
|
||||
\begin_header
|
||||
\textclass amsart
|
||||
\begin_preamble
|
||||
\usepackage{babel}
|
||||
|
||||
\end_preamble
|
||||
\use_default_options false
|
||||
\begin_modules
|
||||
theorems-ams
|
||||
\end_modules
|
||||
\maintain_unincluded_children false
|
||||
\language english
|
||||
\language_package default
|
||||
\inputencoding latin9
|
||||
\fontencoding T1
|
||||
\font_roman default
|
||||
\font_sans default
|
||||
\font_typewriter default
|
||||
\font_math auto
|
||||
\font_default_family default
|
||||
\use_non_tex_fonts false
|
||||
\font_sc false
|
||||
\font_osf false
|
||||
\font_sf_scale 100
|
||||
\font_tt_scale 100
|
||||
\graphics default
|
||||
\default_output_format default
|
||||
\output_sync 0
|
||||
\bibtex_command default
|
||||
\index_command default
|
||||
\paperfontsize default
|
||||
\spacing single
|
||||
\use_hyperref false
|
||||
\papersize default
|
||||
\use_geometry false
|
||||
\use_package amsmath 1
|
||||
\use_package amssymb 0
|
||||
\use_package esint 1
|
||||
\use_package mathdots 0
|
||||
\use_package mathtools 0
|
||||
\use_package mhchem 0
|
||||
\use_package undertilde 0
|
||||
\cite_engine basic
|
||||
\cite_engine_type numerical
|
||||
\biblio_style plain
|
||||
\use_bibtopic false
|
||||
\use_indices false
|
||||
\paperorientation portrait
|
||||
\suppress_date false
|
||||
\justification true
|
||||
\use_refstyle 0
|
||||
\index Index
|
||||
\shortcut idx
|
||||
\color #008000
|
||||
\end_index
|
||||
\secnumdepth 3
|
||||
\tocdepth 3
|
||||
\paragraph_separation indent
|
||||
\paragraph_indentation default
|
||||
\quotes_language english
|
||||
\papercolumns 1
|
||||
\papersides 1
|
||||
\paperpagestyle default
|
||||
\tracking_changes false
|
||||
\output_changes false
|
||||
\html_math_output 0
|
||||
\html_css_as_file 0
|
||||
\html_be_strict false
|
||||
\end_header
|
||||
|
||||
\begin_body
|
||||
|
||||
\begin_layout Standard
|
||||
|
||||
This is a dummy file
|
||||
\end_layout
|
||||
|
||||
\begin_layout Standard
|
||||
|
||||
It has a theorem, a lemma and a proof.
|
||||
\end_layout
|
||||
|
||||
\begin_layout Standard
|
||||
|
||||
The theorem is recognized is a style provided by the module theorems-ams, since the preamble code matches.
|
||||
\end_layout
|
||||
|
||||
\begin_layout Standard
|
||||
|
||||
The lemma is not recognized as a command provided by a module, since the preamble code is from an older version of
|
||||
\begin_inset ERT
|
||||
status collapsed
|
||||
|
||||
\begin_layout Standard
|
||||
|
||||
LyX
|
||||
\end_layout
|
||||
|
||||
\end_inset
|
||||
|
||||
, and modules are only loaded if the preamble code matches (otherwise you could easily get completely different output for some often used names like
|
||||
\backslash
|
||||
theorem.
|
||||
\end_layout
|
||||
|
||||
\begin_layout Standard
|
||||
|
||||
The proof is recognized as a builtin style provided by the text class.
|
||||
\end_layout
|
||||
|
||||
\begin_layout Standard
|
||||
|
||||
|
||||
\begin_inset ERT
|
||||
status collapsed
|
||||
|
||||
\begin_layout Standard
|
||||
|
||||
|
||||
\backslash
|
||||
begin{lem}
|
||||
\end_layout
|
||||
|
||||
\end_inset
|
||||
|
||||
this is a lemma
|
||||
\begin_inset ERT
|
||||
status collapsed
|
||||
|
||||
\begin_layout Standard
|
||||
|
||||
|
||||
\backslash
|
||||
end{lem}
|
||||
\end_layout
|
||||
|
||||
\end_inset
|
||||
|
||||
|
||||
\end_layout
|
||||
|
||||
\begin_layout Theorem
|
||||
|
||||
this is the theorem
|
||||
\end_layout
|
||||
|
||||
\begin_layout Proof
|
||||
|
||||
this is the proof
|
||||
\end_layout
|
||||
|
||||
\end_body
|
||||
\end_document
|
43
src/tex2lyx/test/test-modules.tex
Normal file
43
src/tex2lyx/test/test-modules.tex
Normal file
@ -0,0 +1,43 @@
|
||||
%% LyX 1.6.1 created this file. For more info, see http://www.lyx.org/.
|
||||
%% Do not edit unless you really know what you are doing.
|
||||
\documentclass[oneside,english]{amsart}
|
||||
\usepackage[T1]{fontenc}
|
||||
\usepackage[latin9]{inputenc}
|
||||
\usepackage{amsthm}
|
||||
|
||||
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% Textclass specific LaTeX commands.
|
||||
\numberwithin{equation}{section} %% Comment out for sequentially-numbered
|
||||
\numberwithin{figure}{section} %% Comment out for sequentially-numbered
|
||||
\providecommand{\theoremname}{Theorem}
|
||||
\theoremstyle{plain}
|
||||
\theoremstyle{plain}
|
||||
\newtheorem{thm}{\protect\theoremname}
|
||||
\theoremstyle{plain}
|
||||
\newtheorem{lem}[thm]{Lemma}
|
||||
|
||||
\usepackage{babel}
|
||||
|
||||
\begin{document}
|
||||
This is a dummy file
|
||||
|
||||
It has a theorem, a lemma and a proof.
|
||||
|
||||
The theorem is recognized is a style provided by the module theorems-ams,
|
||||
since the preamble code matches.
|
||||
|
||||
The lemma is not recognized as a command provided by a module, since the
|
||||
preamble code is from an older version of LyX, and modules are only loaded
|
||||
if the preamble code matches (otherwise you could easily get completely
|
||||
different output for some often used names like \textbackslash theorem.
|
||||
|
||||
The proof is recognized as a builtin style provided by the text class.
|
||||
|
||||
\begin{lem}
|
||||
this is a lemma\end{lem}
|
||||
\begin{thm}
|
||||
this is the theorem\end{thm}
|
||||
\begin{proof}
|
||||
this is the proof
|
||||
\end{proof}
|
||||
|
||||
\end{document}
|
@ -36,6 +36,7 @@
|
||||
#include "support/Systemcall.h"
|
||||
|
||||
#include <cstdlib>
|
||||
#include <algorithm>
|
||||
#include <iostream>
|
||||
#include <string>
|
||||
#include <sstream>
|
||||
@ -150,6 +151,7 @@ CommandMap known_environments;
|
||||
CommandMap known_math_environments;
|
||||
FullCommandMap possible_textclass_commands;
|
||||
FullEnvironmentMap possible_textclass_environments;
|
||||
FullCommandMap possible_textclass_theorems;
|
||||
int const LYX_FORMAT = LYX_FORMAT_TEX2LYX;
|
||||
|
||||
/// used modules
|
||||
@ -206,6 +208,17 @@ void add_known_environment(string const & environment, string const & o1,
|
||||
}
|
||||
|
||||
|
||||
void add_known_theorem(string const & theorem, string const & o1,
|
||||
bool o2, docstring const & definition)
|
||||
{
|
||||
vector<ArgumentType> arguments;
|
||||
convertArgs(o1, o2, arguments);
|
||||
if (!definition.empty())
|
||||
possible_textclass_theorems[theorem] =
|
||||
FullCommand(arguments, definition);
|
||||
}
|
||||
|
||||
|
||||
Layout const * findLayoutWithoutModule(TextClass const & textclass,
|
||||
string const & name, bool command)
|
||||
{
|
||||
@ -239,6 +252,69 @@ namespace {
|
||||
|
||||
typedef map<string, DocumentClassPtr> ModuleMap;
|
||||
ModuleMap modules;
|
||||
|
||||
|
||||
bool addModule(string const module, LayoutFile const & baseClass, LayoutModuleList & m, vector<string> & visited)
|
||||
{
|
||||
// avoid endless loop for circular dependency
|
||||
vector<string>::const_iterator const vb = visited.begin();
|
||||
vector<string>::const_iterator const ve = visited.end();
|
||||
if (find(vb, ve, module) != ve) {
|
||||
cerr << "Circular dependency detected for module " << module << '\n';
|
||||
return false;
|
||||
}
|
||||
LyXModule const * const lm = theModuleList[module];
|
||||
if (!lm) {
|
||||
cerr << "Could not find module " << module << " in module list.\n";
|
||||
return false;
|
||||
}
|
||||
bool foundone = false;
|
||||
LayoutModuleList::const_iterator const exclmodstart = baseClass.excludedModules().begin();
|
||||
LayoutModuleList::const_iterator const exclmodend = baseClass.excludedModules().end();
|
||||
LayoutModuleList::const_iterator const provmodstart = baseClass.providedModules().begin();
|
||||
LayoutModuleList::const_iterator const provmodend = baseClass.providedModules().end();
|
||||
vector<string> const reqs = lm->getRequiredModules();
|
||||
if (reqs.empty())
|
||||
foundone = true;
|
||||
else {
|
||||
LayoutModuleList::const_iterator mit = m.begin();
|
||||
LayoutModuleList::const_iterator men = m.end();
|
||||
vector<string>::const_iterator rit = reqs.begin();
|
||||
vector<string>::const_iterator ren = reqs.end();
|
||||
for (; rit != ren; ++rit) {
|
||||
if (find(mit, men, *rit) != men) {
|
||||
foundone = true;
|
||||
break;
|
||||
}
|
||||
if (find(provmodstart, provmodend, *rit) != provmodend) {
|
||||
foundone = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!foundone) {
|
||||
visited.push_back(module);
|
||||
for (rit = reqs.begin(); rit != ren; ++rit) {
|
||||
if (find(exclmodstart, exclmodend, *rit) == exclmodend) {
|
||||
if (addModule(*rit, baseClass, m, visited)) {
|
||||
foundone = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
visited.pop_back();
|
||||
}
|
||||
}
|
||||
if (!foundone) {
|
||||
cerr << "Could not add required modules for " << module << ".\n";
|
||||
return false;
|
||||
}
|
||||
if (!m.moduleCanBeAdded(module, &baseClass))
|
||||
return false;
|
||||
m.push_back(module);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
void initModules()
|
||||
{
|
||||
// Create list of dummy document classes if not already done.
|
||||
@ -253,10 +329,9 @@ void initModules()
|
||||
for (; it != end; ++it) {
|
||||
string const module = it->getID();
|
||||
LayoutModuleList m;
|
||||
// FIXME this excludes all modules that depend on another one
|
||||
if (!m.moduleCanBeAdded(module, &baseClass))
|
||||
vector<string> v;
|
||||
if (!addModule(module, baseClass, m, v))
|
||||
continue;
|
||||
m.push_back(module);
|
||||
modules[module] = getDocumentClass(baseClass, m);
|
||||
}
|
||||
init = false;
|
||||
@ -292,12 +367,17 @@ bool checkModule(string const & name, bool command)
|
||||
static set<string> failed[2];
|
||||
|
||||
// Only add the module if the command was actually defined in the LyX preamble
|
||||
bool theorem = false;
|
||||
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 (possible_textclass_environments.find(name) == possible_textclass_environments.end()) {
|
||||
if (possible_textclass_theorems.find(name) != possible_textclass_theorems.end())
|
||||
theorem = true;
|
||||
else
|
||||
return false;
|
||||
}
|
||||
}
|
||||
if (failed[command].find(name) != failed[command].end())
|
||||
return false;
|
||||
@ -315,7 +395,7 @@ bool checkModule(string const & name, bool command)
|
||||
ModuleMap::iterator const end = modules.end();
|
||||
for (ModuleMap::iterator it = modules.begin(); it != end; ++it) {
|
||||
string const module = it->first;
|
||||
if (!used_modules.moduleCanBeAdded(module, &baseClass))
|
||||
if (used_modules.moduleConflicts(module, &baseClass))
|
||||
continue;
|
||||
if (findLayoutWithoutModule(textclass, name, command))
|
||||
continue;
|
||||
@ -338,6 +418,11 @@ bool checkModule(string const & name, bool command)
|
||||
possible_textclass_commands['\\' + name];
|
||||
if (preamble.find(cmd.def) != docstring::npos)
|
||||
add = true;
|
||||
} else if (theorem) {
|
||||
FullCommand const & thm =
|
||||
possible_textclass_theorems[name];
|
||||
if (preamble.find(thm.def) != docstring::npos)
|
||||
add = true;
|
||||
} else {
|
||||
FullEnvironment const & env =
|
||||
possible_textclass_environments[name];
|
||||
@ -756,6 +841,12 @@ bool tex2lyx(idocstream & is, ostream & os, string encoding)
|
||||
//p.dump();
|
||||
|
||||
preamble.parse(p, documentclass, textclass);
|
||||
list<string> removed_modules;
|
||||
LayoutFile const & baseClass = LayoutFileList::get()[textclass.name()];
|
||||
if (!used_modules.adaptToBaseClass(&baseClass, removed_modules)) {
|
||||
cerr << "Could not load default modules for text class." << endl;
|
||||
return false;
|
||||
}
|
||||
|
||||
// Load preloaded modules.
|
||||
// This needs to be done after the preamble is parsed, since the text
|
||||
@ -795,7 +886,7 @@ bool tex2lyx(idocstream & is, ostream & os, string encoding)
|
||||
preamble.addModule(*it);
|
||||
}
|
||||
if (!preamble.writeLyXHeader(os, !active_environments.empty())) {
|
||||
cerr << "Could write LyX file header." << endl;
|
||||
cerr << "Could not write LyX file header." << endl;
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -106,6 +106,8 @@ void add_known_command(std::string const & command, std::string const & o1,
|
||||
extern void add_known_environment(std::string const & environment,
|
||||
std::string const & o1, bool o2, docstring const & beg,
|
||||
docstring const & end);
|
||||
extern void add_known_theorem(std::string const & theorem,
|
||||
std::string const & o1, bool o2, docstring const & definition);
|
||||
extern Layout const * findLayoutWithoutModule(TextClass const & textclass,
|
||||
std::string const & name, bool command);
|
||||
extern InsetLayout const * findInsetLayoutWithoutModule(
|
||||
@ -164,6 +166,8 @@ extern CommandMap known_math_environments;
|
||||
extern FullCommandMap possible_textclass_commands;
|
||||
/// Environments that might be defined by the document class or modules
|
||||
extern FullEnvironmentMap possible_textclass_environments;
|
||||
/// Theorems that might be defined by the document class or modules
|
||||
extern FullCommandMap possible_textclass_theorems;
|
||||
///
|
||||
extern bool noweb_mode;
|
||||
/// Did we recognize any pdflatex-only construct?
|
||||
|
Loading…
Reference in New Issue
Block a user