mirror of
https://git.lyx.org/repos/lyx.git
synced 2024-11-21 17:51:03 +00:00
tex2lyx: support for \includeonly
(cherry picked from commit 15fd17d83f
)
This commit is contained in:
parent
42dd5f5cfa
commit
0f33720d29
@ -173,6 +173,11 @@ const char * const known_basic_color_codes[] = {"#000000", "#0000ff", "#964B00",
|
||||
const char * const known_if_3arg_commands[] = {"@ifundefined", "IfFileExists",
|
||||
0};
|
||||
|
||||
/*!
|
||||
* Known file extensions for TeX files as used by \\includeonly
|
||||
*/
|
||||
char const * const known_tex_extensions[] = {"tex", 0};
|
||||
|
||||
/// packages that work only in xetex
|
||||
/// polyglossia is handled separately
|
||||
const char * const known_xetex_packages[] = {"arabxetex", "fixlatvian",
|
||||
@ -1252,6 +1257,12 @@ bool Preamble::writeLyXHeader(ostream & os, bool subdoc, string const & outfiled
|
||||
os << *it << '\n';
|
||||
os << "\\end_modules\n";
|
||||
}
|
||||
if (!h_includeonlys.empty()) {
|
||||
os << "\\begin_includeonly\n";
|
||||
for (auto const & iofile : h_includeonlys)
|
||||
os << iofile << '\n';
|
||||
os << "\\end_includeonly\n";
|
||||
}
|
||||
os << "\\maintain_unincluded_children " << h_maintain_unincluded_children << "\n"
|
||||
<< "\\language " << h_language << "\n"
|
||||
<< "\\language_package " << h_language_package << "\n"
|
||||
@ -2040,6 +2051,33 @@ void Preamble::parse(Parser & p, string const & forceclass,
|
||||
}
|
||||
}
|
||||
|
||||
if (t.cs() == "includeonly") {
|
||||
vector<string> includeonlys = getVectorFromString(p.getArg('{', '}'));
|
||||
for (auto & iofile : includeonlys) {
|
||||
string filename(normalize_filename(iofile));
|
||||
string const path = getMasterFilePath(true);
|
||||
// We want to preserve relative/absolute filenames,
|
||||
// therefore path is only used for testing
|
||||
if (!makeAbsPath(filename, path).exists()) {
|
||||
// The file extension is probably missing.
|
||||
// Now try to find it out.
|
||||
string const tex_name =
|
||||
find_file(filename, path,
|
||||
known_tex_extensions);
|
||||
if (!tex_name.empty())
|
||||
filename = tex_name;
|
||||
}
|
||||
string outname;
|
||||
if (makeAbsPath(filename, path).exists())
|
||||
fix_child_filename(filename);
|
||||
else
|
||||
cerr << "Warning: Could not find included file '"
|
||||
<< filename << "'." << endl;
|
||||
outname = changeExtension(filename, "lyx");
|
||||
h_includeonlys.push_back(outname);
|
||||
}
|
||||
}
|
||||
|
||||
else if (is_known(t.cs(), known_if_3arg_commands)) {
|
||||
// prevent misparsing of \usepackage if it is used
|
||||
// as an argument (see e.g. our own output of
|
||||
|
@ -223,6 +223,7 @@ private:
|
||||
std::map<std::string, std::string> h_use_packages;
|
||||
std::string h_use_default_options;
|
||||
std::string h_use_hyperref;
|
||||
std::vector<std::string> h_includeonlys;
|
||||
bool h_use_refstyle;
|
||||
bool h_use_minted;
|
||||
|
||||
|
@ -39,8 +39,6 @@ Format LaTeX feature LyX feature
|
||||
363 horizontal longtable alignment InsetTabular
|
||||
364 branch file name suffix \filename_suffix
|
||||
371 automatic mhchem loading \use_mhchem
|
||||
375 \includeonly \{begin,end}_includeonly
|
||||
376 update .aux of unincluded children \maintain_unincluded_children
|
||||
377 multirow.sty InsetTabular
|
||||
378 revision info InsetInfo
|
||||
380 ? InsetPreview
|
||||
|
@ -51,6 +51,13 @@ void parse_text(Parser & p, std::ostream & os, unsigned flags, bool outer,
|
||||
Context & context);
|
||||
void check_comment_bib(std::ostream & os, Context & context);
|
||||
|
||||
void fix_child_filename(std::string & name);
|
||||
|
||||
std::string const normalize_filename(std::string const & name);
|
||||
|
||||
std::string find_file(std::string const & name, std::string const & path,
|
||||
char const * const * extensions);
|
||||
|
||||
/*!
|
||||
* Parses a subdocument, usually useful in insets (whence the name).
|
||||
*
|
||||
|
@ -482,22 +482,6 @@ void translate_box_len(string const & length, string & value, string & unit, str
|
||||
}
|
||||
|
||||
|
||||
/*!
|
||||
* Find a file with basename \p name in path \p path and an extension
|
||||
* in \p extensions.
|
||||
*/
|
||||
string find_file(string const & name, string const & path,
|
||||
char const * const * extensions)
|
||||
{
|
||||
for (char const * const * what = extensions; *what; ++what) {
|
||||
string const trial = addExtension(name, *what);
|
||||
if (makeAbsPath(trial, path).exists())
|
||||
return trial;
|
||||
}
|
||||
return string();
|
||||
}
|
||||
|
||||
|
||||
void begin_inset(ostream & os, string const & name)
|
||||
{
|
||||
os << "\n\\begin_inset " << name;
|
||||
@ -2168,96 +2152,6 @@ void get_cite_arguments(Parser & p, bool natbibOrder,
|
||||
}
|
||||
|
||||
|
||||
/// Convert filenames with TeX macros and/or quotes to something LyX
|
||||
/// can understand
|
||||
string const normalize_filename(string const & name)
|
||||
{
|
||||
Parser p(name);
|
||||
ostringstream os;
|
||||
while (p.good()) {
|
||||
Token const & t = p.get_token();
|
||||
if (t.cat() != catEscape)
|
||||
os << t.asInput();
|
||||
else if (t.cs() == "lyxdot") {
|
||||
// This is used by LyX for simple dots in relative
|
||||
// names
|
||||
os << '.';
|
||||
p.skip_spaces();
|
||||
} else if (t.cs() == "space") {
|
||||
os << ' ';
|
||||
p.skip_spaces();
|
||||
} else if (t.cs() == "string") {
|
||||
// Convert \string" to " and \string~ to ~
|
||||
Token const & n = p.next_token();
|
||||
if (n.asInput() != "\"" && n.asInput() != "~")
|
||||
os << t.asInput();
|
||||
} else
|
||||
os << t.asInput();
|
||||
}
|
||||
// Strip quotes. This is a bit complicated (see latex_path()).
|
||||
string full = os.str();
|
||||
if (!full.empty() && full[0] == '"') {
|
||||
string base = removeExtension(full);
|
||||
string ext = getExtension(full);
|
||||
if (!base.empty() && base[base.length()-1] == '"')
|
||||
// "a b"
|
||||
// "a b".tex
|
||||
return addExtension(trim(base, "\""), ext);
|
||||
if (full[full.length()-1] == '"')
|
||||
// "a b.c"
|
||||
// "a b.c".tex
|
||||
return trim(full, "\"");
|
||||
}
|
||||
return full;
|
||||
}
|
||||
|
||||
|
||||
/// Convert \p name from TeX convention (relative to master file) to LyX
|
||||
/// convention (relative to .lyx file) if it is relative
|
||||
void fix_child_filename(string & name)
|
||||
{
|
||||
string const absMasterTeX = getMasterFilePath(true);
|
||||
bool const isabs = FileName::isAbsolute(name);
|
||||
// convert from "relative to .tex master" to absolute original path
|
||||
if (!isabs)
|
||||
name = makeAbsPath(name, absMasterTeX).absFileName();
|
||||
bool copyfile = copyFiles();
|
||||
string const absParentLyX = getParentFilePath(false);
|
||||
string abs = name;
|
||||
if (copyfile) {
|
||||
// convert from absolute original path to "relative to master file"
|
||||
string const rel = to_utf8(makeRelPath(from_utf8(name),
|
||||
from_utf8(absMasterTeX)));
|
||||
// re-interpret "relative to .tex file" as "relative to .lyx file"
|
||||
// (is different if the master .lyx file resides in a
|
||||
// different path than the master .tex file)
|
||||
string const absMasterLyX = getMasterFilePath(false);
|
||||
abs = makeAbsPath(rel, absMasterLyX).absFileName();
|
||||
// Do not copy if the new path is impossible to create. Example:
|
||||
// absMasterTeX = "/foo/bar/"
|
||||
// absMasterLyX = "/bar/"
|
||||
// name = "/baz.eps" => new absolute name would be "/../baz.eps"
|
||||
if (contains(name, "/../"))
|
||||
copyfile = false;
|
||||
}
|
||||
if (copyfile) {
|
||||
if (isabs)
|
||||
name = abs;
|
||||
else {
|
||||
// convert from absolute original path to
|
||||
// "relative to .lyx file"
|
||||
name = to_utf8(makeRelPath(from_utf8(abs),
|
||||
from_utf8(absParentLyX)));
|
||||
}
|
||||
}
|
||||
else if (!isabs) {
|
||||
// convert from absolute original path to "relative to .lyx file"
|
||||
name = to_utf8(makeRelPath(from_utf8(name),
|
||||
from_utf8(absParentLyX)));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void copy_file(FileName const & src, string dstname)
|
||||
{
|
||||
if (!copyFiles())
|
||||
@ -2482,6 +2376,112 @@ void registerExternalTemplatePackages(string const & name)
|
||||
} // anonymous namespace
|
||||
|
||||
|
||||
/*!
|
||||
* Find a file with basename \p name in path \p path and an extension
|
||||
* in \p extensions.
|
||||
*/
|
||||
string find_file(string const & name, string const & path,
|
||||
char const * const * extensions)
|
||||
{
|
||||
for (char const * const * what = extensions; *what; ++what) {
|
||||
string const trial = addExtension(name, *what);
|
||||
if (makeAbsPath(trial, path).exists())
|
||||
return trial;
|
||||
}
|
||||
return string();
|
||||
}
|
||||
|
||||
|
||||
/// Convert filenames with TeX macros and/or quotes to something LyX
|
||||
/// can understand
|
||||
string const normalize_filename(string const & name)
|
||||
{
|
||||
Parser p(name);
|
||||
ostringstream os;
|
||||
while (p.good()) {
|
||||
Token const & t = p.get_token();
|
||||
if (t.cat() != catEscape)
|
||||
os << t.asInput();
|
||||
else if (t.cs() == "lyxdot") {
|
||||
// This is used by LyX for simple dots in relative
|
||||
// names
|
||||
os << '.';
|
||||
p.skip_spaces();
|
||||
} else if (t.cs() == "space") {
|
||||
os << ' ';
|
||||
p.skip_spaces();
|
||||
} else if (t.cs() == "string") {
|
||||
// Convert \string" to " and \string~ to ~
|
||||
Token const & n = p.next_token();
|
||||
if (n.asInput() != "\"" && n.asInput() != "~")
|
||||
os << t.asInput();
|
||||
} else
|
||||
os << t.asInput();
|
||||
}
|
||||
// Strip quotes. This is a bit complicated (see latex_path()).
|
||||
string full = os.str();
|
||||
if (!full.empty() && full[0] == '"') {
|
||||
string base = removeExtension(full);
|
||||
string ext = getExtension(full);
|
||||
if (!base.empty() && base[base.length()-1] == '"')
|
||||
// "a b"
|
||||
// "a b".tex
|
||||
return addExtension(trim(base, "\""), ext);
|
||||
if (full[full.length()-1] == '"')
|
||||
// "a b.c"
|
||||
// "a b.c".tex
|
||||
return trim(full, "\"");
|
||||
}
|
||||
return full;
|
||||
}
|
||||
|
||||
|
||||
/// Convert \p name from TeX convention (relative to master file) to LyX
|
||||
/// convention (relative to .lyx file) if it is relative
|
||||
void fix_child_filename(string & name)
|
||||
{
|
||||
string const absMasterTeX = getMasterFilePath(true);
|
||||
bool const isabs = FileName::isAbsolute(name);
|
||||
// convert from "relative to .tex master" to absolute original path
|
||||
if (!isabs)
|
||||
name = makeAbsPath(name, absMasterTeX).absFileName();
|
||||
bool copyfile = copyFiles();
|
||||
string const absParentLyX = getParentFilePath(false);
|
||||
string abs = name;
|
||||
if (copyfile) {
|
||||
// convert from absolute original path to "relative to master file"
|
||||
string const rel = to_utf8(makeRelPath(from_utf8(name),
|
||||
from_utf8(absMasterTeX)));
|
||||
// re-interpret "relative to .tex file" as "relative to .lyx file"
|
||||
// (is different if the master .lyx file resides in a
|
||||
// different path than the master .tex file)
|
||||
string const absMasterLyX = getMasterFilePath(false);
|
||||
abs = makeAbsPath(rel, absMasterLyX).absFileName();
|
||||
// Do not copy if the new path is impossible to create. Example:
|
||||
// absMasterTeX = "/foo/bar/"
|
||||
// absMasterLyX = "/bar/"
|
||||
// name = "/baz.eps" => new absolute name would be "/../baz.eps"
|
||||
if (contains(name, "/../"))
|
||||
copyfile = false;
|
||||
}
|
||||
if (copyfile) {
|
||||
if (isabs)
|
||||
name = abs;
|
||||
else {
|
||||
// convert from absolute original path to
|
||||
// "relative to .lyx file"
|
||||
name = to_utf8(makeRelPath(from_utf8(abs),
|
||||
from_utf8(absParentLyX)));
|
||||
}
|
||||
}
|
||||
else if (!isabs) {
|
||||
// convert from absolute original path to "relative to .lyx file"
|
||||
name = to_utf8(makeRelPath(from_utf8(name),
|
||||
from_utf8(absParentLyX)));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void parse_text(Parser & p, ostream & os, unsigned flags, bool outer,
|
||||
Context & context)
|
||||
{
|
||||
|
@ -25,6 +25,8 @@ What's new
|
||||
|
||||
- Add support for chapterbib.
|
||||
|
||||
- Add support for \includeonly.
|
||||
|
||||
|
||||
* USER INTERFACE
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user