\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
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)
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;
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;
}
}
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";
}
}
+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)
// 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
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
#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;
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));
+ }
}
}
}
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
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_;
};
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;
// \\ 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,