]> git.lyx.org Git - lyx.git/blobdiff - src/LaTeX.cpp
Try even harder to obtain an instant preview
[lyx.git] / src / LaTeX.cpp
index 22a3a97d465022849fc0568923f635344a4b57d0..38a457deb512a50d765f801f0c965bfa01665d4f 100644 (file)
@@ -110,7 +110,9 @@ LaTeX::LaTeX(string const & latex, OutputParams const & rp,
 
 void LaTeX::deleteFilesOnError() const
 {
-       // currently just a dummy function.
+       // Note that we do not always call this function when there is an error.
+       // For example, if there is an error but an output file is produced we
+       // still would like to output (export/view) the file.
 
        // What files do we have to delete?
 
@@ -142,6 +144,9 @@ void LaTeX::deleteFilesOnError() const
        // Also remove the aux file
        FileName const aux(changeExtension(file.absFileName(), ".aux"));
        aux.removeFile();
+
+       // Remove the output file, which is often generated even if error
+       output_file.removeFile();
 }
 
 
@@ -153,6 +158,7 @@ int LaTeX::run(TeXErrors & terr)
        // each time the .tex file changes.
 {
        int scanres = NO_ERRORS;
+       int bscanres = NO_ERRORS;
        unsigned int count = 0; // number of times run
        num_errors = 0; // just to make sure.
        unsigned int const MAX_RUN = 6;
@@ -225,7 +231,8 @@ int LaTeX::run(TeXErrors & terr)
        LYXERR(Debug::LATEX, "Run #" << count);
        message(runMessage(count));
 
-       startscript();
+       int const exit_code = startscript();
+
        scanres = scanLogFile(terr);
        if (scanres & ERROR_RERUN) {
                LYXERR(Debug::LATEX, "Rerunning LaTeX");
@@ -233,11 +240,6 @@ int LaTeX::run(TeXErrors & terr)
                scanres = scanLogFile(terr);
        }
 
-       if (scanres & ERRORS) {
-               deleteFilesOnError();
-               return scanres; // return on error
-       }
-
        vector<AuxInfo> const bibtex_info = scanAuxFiles(aux_file);
        if (!run_bibtex && bibtex_info_old != bibtex_info)
                run_bibtex = true;
@@ -268,7 +270,12 @@ int LaTeX::run(TeXErrors & terr)
                                runparams);
        }
        FileName const nlofile(changeExtension(file.absFileName(), ".nlo"));
-       if (head.haschanged(nlofile))
+       // If all nomencl entries are removed, nomencl writes an empty nlo file.
+       // DepTable::hasChanged() returns false in this case, since it does not
+       // distinguish empty files from non-existing files. This is why we need
+       // the extra checks here (to trigger a rerun). Cf. discussions in #8905.
+       // FIXME: Sort out the real problem in DepTable.
+       if (head.haschanged(nlofile) || (nlofile.exists() && nlofile.isFileEmpty()))
                rerun |= runMakeIndexNomencl(file, ".nlo", ".nls");
        FileName const glofile(changeExtension(file.absFileName(), ".glo"));
        if (head.haschanged(glofile))
@@ -292,13 +299,8 @@ int LaTeX::run(TeXErrors & terr)
                updateBibtexDependencies(head, bibtex_info);
                rerun |= runBibTeX(bibtex_info, runparams);
                FileName const blgfile(changeExtension(file.absFileName(), ".blg"));
-               if (blgfile.exists()) {
-                       int bscanres = scanBlgFile(head, terr);
-                       if (bscanres & ERRORS) {
-                               deleteFilesOnError();
-                               return bscanres; // return on error
-                       }
-               }
+               if (blgfile.exists())
+                       bscanres = scanBlgFile(head, terr);
        } else if (!had_depfile) {
                /// If we run pdflatex on the file after running latex on it,
                /// then we do not need to run bibtex, but we do need to
@@ -326,10 +328,6 @@ int LaTeX::run(TeXErrors & terr)
                message(runMessage(count));
                startscript();
                scanres = scanLogFile(terr);
-               if (scanres & ERRORS) {
-                       deleteFilesOnError();
-                       return scanres; // return on error
-               }
 
                // update the depedencies
                deplog(head); // reads the latex log
@@ -352,13 +350,8 @@ int LaTeX::run(TeXErrors & terr)
                updateBibtexDependencies(head, bibtex_info);
                rerun |= runBibTeX(bibtex_info, runparams);
                FileName const blgfile(changeExtension(file.absFileName(), ".blg"));
-               if (blgfile.exists()) {
-                       int bscanres = scanBlgFile(head, terr);
-                       if (bscanres & ERRORS) {
-                               deleteFilesOnError();
-                               return bscanres; // return on error
-                       }
-               }
+               if (blgfile.exists())
+                       bscanres = scanBlgFile(head, terr);
        }
 
        // 4
@@ -405,10 +398,6 @@ int LaTeX::run(TeXErrors & terr)
                message(runMessage(count));
                startscript();
                scanres = scanLogFile(terr);
-               if (scanres & ERRORS) {
-                       deleteFilesOnError();
-                       return scanres; // return on error
-               }
 
                // keep this updated
                head.update();
@@ -416,7 +405,25 @@ int LaTeX::run(TeXErrors & terr)
 
        // Write the dependencies to file.
        head.write(depfile);
+
+       if (scanres & NO_OUTPUT) {
+               // A previous run could have left a PDF and since
+               // no PDF is created if NO_OUTPUT, we remove any
+               // existing PDF and temporary files so that an
+               // incorrect PDF is not displayed, which could otherwise
+               // happen if View is run again because the checksum will
+               // be the same so any lingering PDF will be viewed.
+               deleteFilesOnError();
+       }
+
+       if (exit_code)
+               scanres |= NONZERO_ERROR;
+
        LYXERR(Debug::LATEX, "Done.");
+
+       if (bscanres & ERRORS)
+               return bscanres; // return on error
+
        return scanres;
 }
 
@@ -629,8 +636,8 @@ int LaTeX::scanLogFile(TeXErrors & terr)
        FileName const fn = FileName(makeAbsPath(tmp));
        ifstream ifs(fn.toFilesystemEncoding().c_str());
        bool fle_style = false;
-       static regex file_line_error(".+\\.\\D+:[0-9]+: (.+)");
-       static regex child_file(".*([0-9]+[A-Za-z]*_.+\\.tex).*");
+       static regex const file_line_error(".+\\.\\D+:[0-9]+: (.+)");
+       static regex const child_file(".*([0-9]+[A-Za-z]*_.+\\.tex).*");
        // Flag for 'File ended while scanning' message.
        // We need to wait for subsequent processing.
        string wait_for_error;
@@ -661,8 +668,8 @@ int LaTeX::scanLogFile(TeXErrors & terr)
                                size_t len = j == string::npos
                                                ? token.substr(i + 1).length()
                                                : j - i - 1;
-                               if (regex_match(token.substr(i + 1, len),
-                                                       sub, child_file)) {
+                               string const substr = token.substr(i + 1, len);
+                               if (regex_match(substr, sub, child_file)) {
                                        string const name = sub.str(1);
                                        child.push(make_pair(name, pnest));
                                        i += len;
@@ -804,16 +811,21 @@ int LaTeX::scanLogFile(TeXErrors & terr)
                                if (!getline(ifs, tmp))
                                        break;
                                tmp = rtrim(tmp, "\r");
-                               if (++count > 10)
+                               // 15 is somewhat arbitrarily chosen, based on practice.
+                               // We used 10 for 14 years and increased it to 15 when we
+                               // saw one case.
+                               if (++count > 15)
                                        break;
                        } while (!prefixIs(tmp, "l."));
                        if (prefixIs(tmp, "l.")) {
                                // we have a latex error
                                retval |=  TEX_ERROR;
                                if (contains(desc,
-                                   "Package babel Error: You haven't defined the language") ||
-                                   contains(desc,
-                                   "Package babel Error: You haven't loaded the option"))
+                                       "Package babel Error: You haven't defined the language")
+                                   || contains(desc,
+                                       "Package babel Error: You haven't loaded the option")
+                                   || contains(desc,
+                                       "Package babel Error: Unknown language"))
                                        retval |= ERROR_RERUN;
                                // get the line number:
                                int line = 0;
@@ -1008,7 +1020,7 @@ bool completeFilename(string const & ff, DepTable & head)
 }
 
 
-int iterateLine(string const token, regex const reg, string const & closing,
+int iterateLine(string const & token, regex const & reg, string const & closing,
                int fragment_pos, DepTable & head)
 {
        smatch what;
@@ -1208,7 +1220,7 @@ void LaTeX::deplog(DepTable & head)
                // (and in addition to those above)
                if (regex_match(token, sub, reg5)) {
                        // search for strings in <...>
-                       static regex reg5_1("<([^>]+)(.)");
+                       static regex const reg5_1("<([^>]+)(.)");
                        fragment_pos = iterateLine(token, reg5_1, ">",
                                                   fragment_pos, head);
                        fragment = (fragment_pos != -1);
@@ -1221,7 +1233,7 @@ void LaTeX::deplog(DepTable & head)
                // where "File: file.ext" would be skipped
                if (regex_match(token, sub, reg6)) {
                        // search for strings in (...)
-                       static regex reg6_1("\\(([^()]+)(.)");
+                       static regex const reg6_1("\\(([^()]+)(.)");
                        fragment_pos = iterateLine(token, reg6_1, ")",
                                                   fragment_pos, head);
                        fragment = (fragment_pos != -1);