commit 0f33720d29e330cb5180cdf45e01ba822e89a994
Author: Juergen Spitzmueller <sp...@lyx.org>
Date:   Fri Mar 9 17:27:55 2018 +0100

    tex2lyx: support for \includeonly
    
    (cherry picked from commit 15fd17d83fb2b98d1ff226a79353e42f6e0247d4)
---
 src/tex2lyx/Preamble.cpp |   38 ++++++++
 src/tex2lyx/Preamble.h   |    1 +
 src/tex2lyx/TODO.txt     |    2 -
 src/tex2lyx/tex2lyx.h    |    7 ++
 src/tex2lyx/text.cpp     |  212 +++++++++++++++++++++++-----------------------
 status.23x               |    2 +
 6 files changed, 154 insertions(+), 108 deletions(-)

diff --git a/src/tex2lyx/Preamble.cpp b/src/tex2lyx/Preamble.cpp
index 48dc8d6..78293bf 100644
--- a/src/tex2lyx/Preamble.cpp
+++ b/src/tex2lyx/Preamble.cpp
@@ -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
diff --git a/src/tex2lyx/Preamble.h b/src/tex2lyx/Preamble.h
index 074a85c..9c70dca 100644
--- a/src/tex2lyx/Preamble.h
+++ b/src/tex2lyx/Preamble.h
@@ -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;
 
diff --git a/src/tex2lyx/TODO.txt b/src/tex2lyx/TODO.txt
index fc4bb99..8f83133 100644
--- a/src/tex2lyx/TODO.txt
+++ b/src/tex2lyx/TODO.txt
@@ -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
diff --git a/src/tex2lyx/tex2lyx.h b/src/tex2lyx/tex2lyx.h
index ff81856..c830b05 100644
--- a/src/tex2lyx/tex2lyx.h
+++ b/src/tex2lyx/tex2lyx.h
@@ -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).
  *
diff --git a/src/tex2lyx/text.cpp b/src/tex2lyx/text.cpp
index 914b42c..285a818 100644
--- a/src/tex2lyx/text.cpp
+++ b/src/tex2lyx/text.cpp
@@ -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)
 {
diff --git a/status.23x b/status.23x
index d77a58e..73a43d8 100644
--- a/status.23x
+++ b/status.23x
@@ -25,6 +25,8 @@ What's new
 
 - Add support for chapterbib.
 
+- Add support for \includeonly.
+
 
 * USER INTERFACE
 

Reply via email to