]> git.lyx.org Git - features.git/commitdiff
Improve LaTeX version checking
authorJuergen Spitzmueller <spitz@lyx.org>
Mon, 19 Dec 2022 14:15:41 +0000 (15:15 +0100)
committerJuergen Spitzmueller <spitz@lyx.org>
Mon, 19 Dec 2022 14:15:41 +0000 (15:15 +0100)
Instead of having to add and individually test the versions to check
for, we store the current version and test on that with a specific
function isAvailableAtLeastFrom(package, year, month, day)

Currently only used for the LaTeX version, but could also be extended
for package versions.

lib/chkconfig.ltx
src/Buffer.cpp
src/BufferParams.cpp
src/LaTeXFeatures.cpp
src/LaTeXFeatures.h
src/LaTeXPackages.cpp
src/LaTeXPackages.h
src/insets/InsetSpace.cpp
src/mathed/InsetMathGrid.cpp

index 34f9aff13252d6880328815fc16e5975af84ebf0..a9b82e6e4806698e5180fca318e6cca410f865af 100644 (file)
@@ -75,8 +75,8 @@
 \newcommand{\AddVariable}[2]{
   \immediate\write\vars{chk_#1='#2'}}
 
-\newcommand{\AddPackage}[1]{
-  \immediate\write\packages{#1}}
+\newcommand{\AddPackage}[2][]{
+  \immediate\write\packages{#2 #1}}
 
 % Tests whether an item is present
 % Syntax: \TestItem[<file>]{<name>}{<type>}{<ext>}{<iftrue>}{<iffalse>}
   \fi}
 
 
-% Test for the LaTeX version
-\newcommand{\TestLaTeXVersion}[1]{
-  \message{^^J\prefix checking for LaTeX version at least as of #1...}
-  \@ifl@t@r\fmtversion{#1}{\existstrue}{\existsfalse}
-  \ifexists
-    \message{yes^^J}
-    \AddVariable{#1}{yes}
-    \AddPackage{LaTeX-#1}
-  \else
-    \message{no^^J}
-    \AddVariable{#1}{no}
-  \fi}
-
-
 % Adapted from ltxcheck.tex
 \newcommand{\TestFont}[2][\default]{
   \def\default{#2}
   \fi}
 
 \newcommand{\TestPackage}[2][\default]{
+  \def\default{#2}
   \TestItem[#1]{#2}{package}{sty}{\AddPackage{#2}}{}}
 
 \newcommand{\TestDocClass}[2]{
 \message{^^J\prefix checking for LaTeX version... \fmtversion}
 \AddVariable{fmtversion}{\fmtversion}
 
-%%% Crucial versions
-% This one introduces \textsubscript
-\TestLaTeXVersion{2005/12/01}
-% This one introduces \UseRawInputEncoding
-\TestLaTeXVersion{2018/04/01}
-% This one introduces path encoding changes
-\TestLaTeXVersion{2019/10/01}
-% This introduces all math and text spaces
-% previously only available via amsmath
-\TestLaTeXVersion{2020/10/01}
-% This robustifies LaTeX commands
-\TestLaTeXVersion{2021/06/01}
-% Introduction of \\DocumentMetadata
-\TestLaTeXVersion{2022/06/01}
+%%% Store the current LaTeX version
+\AddPackage[\fmtversion]{LaTeX}
 
 %%% And now, the list of available languages
 % The trick is to know that \the\everyjob contains something like
index 34291542e89191be1a1d6f5ec63079cced7358de..94f4dd477c4fc86b0f2b2cf7bd697313d87515e0 100644 (file)
@@ -1966,7 +1966,7 @@ Buffer::ExportStatus Buffer::writeLaTeXSource(otexstream & os,
                                        docdir = subst(docdir, "~", "\\string~");
                                bool const nonascii = !isAscii(from_utf8(docdir));
                                // LaTeX 2019/10/01 handles non-ascii path without detokenize
-                               bool const utfpathlatex = features.isAvailable("LaTeX-2019/10/01");
+                               bool const utfpathlatex = features.isAvailableAtLeastFrom("LaTeX", 2019, 10);
                                bool const detokenize = !utfpathlatex && nonascii;
                                bool const quote = contains(docdir, ' ');
                                if (utfpathlatex && nonascii)
index 3c55756709860760ebf8b54c76f282b86dad1814..6e9cdd5f00f7054529e52add81bd0c2138c958ff 100644 (file)
@@ -1703,7 +1703,7 @@ bool BufferParams::writeLaTeX(otexstream & os, LaTeXFeatures & features,
                              FileName const & filepath) const
 {
        // DocumentMetadata must come before anything else
-       if (features.isAvailable("LaTeX-2022/06/01")
+       if (features.isAvailableAtLeastFrom("LaTeX", 2022, 6)
            && !containsOnly(document_metadata, " \n\t")) {
                // Check if the user preamble contains uncodable glyphs
                odocstringstream doc_metadata;
@@ -3430,7 +3430,7 @@ void BufferParams::writeEncodingPreamble(otexstream & os,
                case Encoding::japanese:
                        if (encoding().iconvName() != "UTF-8"
                            && !features.runparams().isFullUnicode()
-                           && features.isAvailable("LaTeX-2018/04/01"))
+                           && features.isAvailableAtLeastFrom("LaTeX", 2018, 4))
                                // don't default to [utf8]{inputenc} with LaTeX >= 2018/04
                                os << "\\UseRawInputEncoding\n";
                        break;
@@ -3457,7 +3457,7 @@ void BufferParams::writeEncodingPreamble(otexstream & os,
                }
        }
        if ((inputenc == "auto-legacy-plain" || features.isRequired("japanese"))
-           && features.isAvailable("LaTeX-2018/04/01"))
+           && features.isAvailableAtLeastFrom("LaTeX", 2018, 4))
                // don't default to [utf8]{inputenc} with LaTeX >= 2018/04
                os << "\\UseRawInputEncoding\n";
 }
index 69194b1fee5fb7e9797d5f9fd4205ce2950ef40d..0bed75a07363e708fa6e4a7e52593cc081db99a5 100644 (file)
@@ -827,6 +827,12 @@ bool LaTeXFeatures::isAvailable(string const & name)
 }
 
 
+bool LaTeXFeatures::isAvailableAtLeastFrom(string const & name, int const y, int const m, int const d)
+{
+       return LaTeXPackages::isAvailableAtLeastFrom(name, y, m, d);
+}
+
+
 namespace {
 
 void addSnippet(std::list<TexString> & list, TexString ts, bool allow_dupes)
@@ -1514,7 +1520,7 @@ string const LaTeXFeatures::getPackages() const
 
        // fixltx2e provides subscript
        if (mustProvide("subscript") && !isRequired("fixltx2e")
-           && !isAvailable("LaTeX-2005/12/01"))
+           && !isAvailableAtLeastFrom("LaTeX", 2005, 12))
                packages << "\\usepackage{subscript}\n";
 
        // footmisc must be loaded after setspace
index 91d27e8c704b52050a7d6d987647ced385c6d458..a19d2ab68a4dcb4d4115884b19eedd5bea5ff2a3 100644 (file)
@@ -108,6 +108,10 @@ public:
        void provide(std::string const & name);
        /// Is the (required) package available?
        static bool isAvailable(std::string const & name);
+       /// Is the (required) package available at least as of version
+       /// y/m/d?
+       static bool isAvailableAtLeastFrom(std::string const & name,
+                                          int const y, int const m, int const d = 1);
        /// Has the package been required?
        bool isRequired(std::string const & name) const;
        /** Is this feature already provided
index a231a2294a469bd23f89e081a6410238a46e9535..4df2528c2e4d832e073350489ace80fdcd5db858 100644 (file)
 
 #include "Lexer.h"
 
+#include "support/convert.h"
 #include "support/FileName.h"
 #include "support/filetools.h"
 #include "support/lstrings.h"
 
+#include <regex>
+
 
 using namespace std;
 using namespace lyx::support;
@@ -55,8 +58,13 @@ void LaTeXPackages::getAvailable()
                case Lexer::LEX_FEOF:
                        finished = true;
                        break;
-               default:
-                       packages_.insert(lex.getString());
+               default: {
+                       string const p = lex.getString();
+                       // Parse optional version info
+                       lex.eatLine();
+                       string const v = lex.getString();
+                       packages_.insert(make_pair(p, v));
+               }
                }
        }
 }
@@ -69,7 +77,59 @@ bool LaTeXPackages::isAvailable(string const & name)
        string n = name;
        if (suffixIs(n, ".sty"))
                n.erase(name.length() - 4);
-       return packages_.find(n) != packages_.end();
+       for (auto const & package : packages_) {
+               if (package.first == n)
+                       return true;
+       }
+       return false;
+}
+
+
+bool LaTeXPackages::isAvailableAtLeastFrom(string const & name,
+                                          int const y, int const m, int const d)
+{
+       if (packages_.empty())
+               getAvailable();
+
+       bool result = false;
+       // Check for yyyy-mm-dd
+       static regex const reg("([\\d]{4})-([\\d]{2})-([\\d]{2})");
+       for (auto const & package : packages_) {
+               if (package.first == name && !package.second.empty()) {
+                       smatch sub;
+                       if (regex_match(package.second, sub, reg)) {
+                               // Test whether date is same or newer.
+                               //
+                               // Test for year first
+                               int const avail_y = convert<int>(sub.str(1));
+                               if (avail_y < y)
+                                       // our year is older: bad!
+                                       break;
+                               if (avail_y > y) {
+                                       // our year is newer: good!
+                                       result = true;
+                                       break;
+                               }
+                               // Same year: now test month
+                               int const avail_m = convert<int>(sub.str(2));
+                               if (avail_m < m)
+                                       // our month is older: bad!
+                                       break;
+                               if (avail_m > m) {
+                                       // our month is newer: good!
+                                       result = true;
+                                       break;
+                               }
+                               // Same year and month: test day
+                               if (convert<int>(sub.str(3)) >= d) {
+                                       // day same or newer: good!
+                                       result = true;
+                                       break;
+                               }
+                       }
+               }
+       }
+       return result;
 }
 
 } // namespace lyx
index ff67e0a460504caf59bc9da09f44100c04480b7b..dba6d039f6143d63ae45f4df4777ee6d6fc5608a 100644 (file)
@@ -28,9 +28,13 @@ public:
        static void getAvailable();
        /// Is the (required) package available?
        static bool isAvailable(std::string const & name);
+       /// Is the (required) package available at least as of
+       /// version y/m/d?
+       static bool isAvailableAtLeastFrom(std::string const & name,
+                                          int const y, int const m, int const d = 1);
 private:
        /// The available (required) packages
-       typedef std::set<std::string> Packages;
+       typedef std::set<std::pair<std::string,std::string>> Packages;
        ///
        static Packages packages_;
 };
index 3f86eb8c074cf1c1775b6ca50c920d72e3fa85fc..b7323b61629d7a2a683399ca6a98e0f67a84301e 100644 (file)
@@ -895,7 +895,7 @@ docstring InsetSpace::xhtml(XMLStream & xs, OutputParams const &) const
 
 void InsetSpace::validate(LaTeXFeatures & features) const
 {
-       if (features.isAvailable("LaTeX-2020/10/01"))
+       if (features.isAvailableAtLeastFrom("LaTeX", 2020, 10))
                // As of this version, the LaTeX kernel
                // includes all spaces.
                return;
index 85511e6ddfad4af59d26c1dd50bd3af42506430e..0061bdd71595c1582f162379b40a478a3291b1ee 100644 (file)
@@ -1252,7 +1252,7 @@ void InsetMathGrid::write(TeXMathStream & os,
        // \\ is a robust command and its protection
        // is no longer necessary
        bool const fragile = os.fragile()
-                       && !LaTeXFeatures::isAvailable("LaTeX-2021/06/01");
+                       && !LaTeXFeatures::isAvailableAtLeastFrom("LaTeX", 2021, 06);
        for (row_type row = beg_row; row < end_row; ++row) {
                os << verboseHLine(rowinfo_[row].lines);
                // don't write & and empty cells at end of line,