mirror of
https://git.lyx.org/repos/lyx.git
synced 2024-11-25 19:07:45 +00:00
tex2lyx: import minted listings
This commit updates tex2lyx in order to also import minted listings. For the floating version of a listing, minted uses the listing environment, a concept that is not shared with the listings package, towards which our listings inset is geared. For this reason, a kludge is necessary when importing minted listings not previously exported by LyX itself. If the floating listing contains only a caption and a label (other than the listing itself), everything is fine and the import is (or aims to be) perfect. But, as in all other floating ebvironments, one can also stick there other elements, which don't have a place in the listings inset. So, in order to avoid a data loss, tex2lyx sticks everything into the caption. In this way, things may be rearranged in the GUI, if necessary. There is no other way, apart from a complete redesign of the listings inset, of course. However, I think that this is an acceptable compromise.
This commit is contained in:
parent
195e55d3f4
commit
7a9bb85184
@ -183,9 +183,10 @@ const char * const known_xetex_packages[] = {"arabxetex", "fixlatvian",
|
||||
const char * const known_lyx_packages[] = {"amsbsy", "amsmath", "amssymb",
|
||||
"amstext", "amsthm", "array", "babel", "booktabs", "calc", "CJK", "color",
|
||||
"float", "fontspec", "framed", "graphicx", "hhline", "ifthen", "longtable",
|
||||
"makeidx", "multirow", "nomencl", "pdfpages", "prettyref", "refstyle", "rotating",
|
||||
"rotfloat", "splitidx", "setspace", "subscript", "textcomp", "tipa", "tipx",
|
||||
"tone", "ulem", "url", "varioref", "verbatim", "wrapfig", "xcolor", "xunicode", 0};
|
||||
"makeidx", "minted", "multirow", "nomencl", "pdfpages", "prettyref", "refstyle",
|
||||
"rotating", "rotfloat", "splitidx", "setspace", "subscript", "textcomp", "tipa",
|
||||
"tipx", "tone", "ulem", "url", "varioref", "verbatim", "wrapfig", "xcolor",
|
||||
"xunicode", 0};
|
||||
|
||||
// codes used to remove packages that are loaded automatically by LyX.
|
||||
// Syntax: package_beg_sep<name>package_mid_sep<package loading code>package_end_sep
|
||||
@ -554,6 +555,7 @@ Preamble::Preamble() : one_language(true), explicit_babel(false),
|
||||
h_use_hyperref = "false";
|
||||
h_use_microtype = "false";
|
||||
h_use_refstyle = false;
|
||||
h_use_minted = false;
|
||||
h_use_packages["amsmath"] = "1";
|
||||
h_use_packages["amssymb"] = "0";
|
||||
h_use_packages["cancel"] = "0";
|
||||
@ -990,6 +992,8 @@ void Preamble::handle_package(Parser &p, string const & name,
|
||||
else if (is_known(name, known_lyx_packages) && options.empty()) {
|
||||
if (name == "splitidx")
|
||||
h_use_indices = "true";
|
||||
if (name == "minted")
|
||||
h_use_minted = "true";
|
||||
if (name == "refstyle")
|
||||
h_use_refstyle = true;
|
||||
else if (name == "prettyref")
|
||||
@ -1261,7 +1265,8 @@ bool Preamble::writeLyXHeader(ostream & os, bool subdoc, string const & outfiled
|
||||
<< "\\paperorientation " << h_paperorientation << '\n'
|
||||
<< "\\suppress_date " << h_suppress_date << '\n'
|
||||
<< "\\justification " << h_justification << '\n'
|
||||
<< "\\use_refstyle " << h_use_refstyle << '\n';
|
||||
<< "\\use_refstyle " << h_use_refstyle << '\n'
|
||||
<< "\\use_minted " << h_use_minted << '\n';
|
||||
if (!h_fontcolor.empty())
|
||||
os << "\\fontcolor " << h_fontcolor << '\n';
|
||||
if (!h_notefontcolor.empty())
|
||||
|
@ -48,6 +48,8 @@ public:
|
||||
std::string fontCJK() const { return h_font_cjk; }
|
||||
///
|
||||
void fontCJK(std::string const & f) { h_font_cjk_set = true; h_font_cjk = f; }
|
||||
///
|
||||
bool minted() const { return h_use_minted; }
|
||||
/// The document language
|
||||
std::string docLanguage() const { return h_language; }
|
||||
/// The language of text which is not explicitly marked
|
||||
@ -216,6 +218,7 @@ private:
|
||||
std::string h_use_default_options;
|
||||
std::string h_use_hyperref;
|
||||
bool h_use_refstyle;
|
||||
bool h_use_minted;
|
||||
|
||||
/*!
|
||||
* Add package \p name with options \p options to used_packages.
|
||||
|
@ -151,19 +151,6 @@ Format LaTeX feature LyX feature
|
||||
btprint "bibbysection"
|
||||
534 Chapterbib support
|
||||
\usepackage{chapterbib} \multibib child
|
||||
544 Minted support
|
||||
Non-floating: InsetListings
|
||||
\begin{minted}[opts]{language}
|
||||
...
|
||||
\end{minted}
|
||||
Floating:
|
||||
\begin{listing}[placement]
|
||||
\begin{minted}[opts]{language}
|
||||
...
|
||||
\end{minted}
|
||||
\end{listing}
|
||||
Inline (where '?' is any char):
|
||||
\mintinline[opts]{language}?...?
|
||||
|
||||
|
||||
|
||||
|
@ -63,6 +63,7 @@
|
||||
\suppress_date false
|
||||
\justification true
|
||||
\use_refstyle 0
|
||||
\use_minted 0
|
||||
\index Index
|
||||
\shortcut idx
|
||||
\color #008000
|
||||
|
@ -63,6 +63,7 @@
|
||||
\suppress_date false
|
||||
\justification true
|
||||
\use_refstyle 0
|
||||
\use_minted 0
|
||||
\index Index
|
||||
\shortcut idx
|
||||
\color #008000
|
||||
|
@ -61,6 +61,7 @@
|
||||
\suppress_date false
|
||||
\justification true
|
||||
\use_refstyle 0
|
||||
\use_minted 0
|
||||
\index Index
|
||||
\shortcut idx
|
||||
\color #008000
|
||||
|
@ -61,6 +61,7 @@
|
||||
\suppress_date false
|
||||
\justification true
|
||||
\use_refstyle 0
|
||||
\use_minted 0
|
||||
\index Index
|
||||
\shortcut idx
|
||||
\color #008000
|
||||
|
@ -62,6 +62,7 @@
|
||||
\suppress_date false
|
||||
\justification true
|
||||
\use_refstyle 0
|
||||
\use_minted 0
|
||||
\index Index
|
||||
\shortcut idx
|
||||
\color #008000
|
||||
|
@ -61,6 +61,7 @@ algorithm2e
|
||||
\suppress_date false
|
||||
\justification true
|
||||
\use_refstyle 0
|
||||
\use_minted 0
|
||||
\index Index
|
||||
\shortcut idx
|
||||
\color #008000
|
||||
|
@ -87,6 +87,7 @@
|
||||
\suppress_date false
|
||||
\justification true
|
||||
\use_refstyle 0
|
||||
\use_minted 0
|
||||
\notefontcolor #0000ff
|
||||
\backgroundcolor #ff5500
|
||||
\boxbgcolor #ffff00
|
||||
|
@ -97,6 +97,7 @@
|
||||
\suppress_date false
|
||||
\justification true
|
||||
\use_refstyle 0
|
||||
\use_minted 0
|
||||
\index Index
|
||||
\shortcut idx
|
||||
\color #008000
|
||||
|
@ -73,6 +73,7 @@
|
||||
\suppress_date false
|
||||
\justification true
|
||||
\use_refstyle 0
|
||||
\use_minted 0
|
||||
\index Index
|
||||
\shortcut idx
|
||||
\color #008000
|
||||
|
@ -59,6 +59,7 @@
|
||||
\suppress_date false
|
||||
\justification true
|
||||
\use_refstyle 0
|
||||
\use_minted 0
|
||||
\index Index
|
||||
\shortcut idx
|
||||
\color #008000
|
||||
|
@ -59,6 +59,7 @@ theorems-ams
|
||||
\suppress_date false
|
||||
\justification true
|
||||
\use_refstyle 0
|
||||
\use_minted 0
|
||||
\index Index
|
||||
\shortcut idx
|
||||
\color #008000
|
||||
|
@ -59,6 +59,7 @@ theorems-ams
|
||||
\suppress_date false
|
||||
\justification true
|
||||
\use_refstyle 1
|
||||
\use_minted 0
|
||||
\index Index
|
||||
\shortcut idx
|
||||
\color #008000
|
||||
|
@ -56,6 +56,7 @@
|
||||
\suppress_date false
|
||||
\justification true
|
||||
\use_refstyle 0
|
||||
\use_minted 0
|
||||
\index Index
|
||||
\shortcut idx
|
||||
\color #008000
|
||||
|
@ -92,6 +92,7 @@ logicalmkup
|
||||
\suppress_date true
|
||||
\justification true
|
||||
\use_refstyle 0
|
||||
\use_minted 0
|
||||
\index Index
|
||||
\shortcut idx
|
||||
\color #008000
|
||||
|
@ -63,6 +63,7 @@
|
||||
\suppress_date false
|
||||
\justification true
|
||||
\use_refstyle 0
|
||||
\use_minted 0
|
||||
\index Index
|
||||
\shortcut idx
|
||||
\color #008000
|
||||
|
@ -52,6 +52,7 @@
|
||||
\suppress_date false
|
||||
\justification true
|
||||
\use_refstyle 0
|
||||
\use_minted 0
|
||||
\index Index
|
||||
\shortcut idx
|
||||
\color #008000
|
||||
|
@ -321,6 +321,15 @@ char const * const known_tones[] = {"15", "51", "45", "12", "454", 0};
|
||||
// string to store the float type to be able to determine the type of subfloats
|
||||
string float_type = "";
|
||||
|
||||
// string to store the float status of minted listings
|
||||
string minted_float = "";
|
||||
|
||||
// whether a caption has been parsed for a floating minted listing
|
||||
bool minted_float_has_caption = false;
|
||||
|
||||
// The caption for non-floating minted listings
|
||||
string minted_nonfloat_caption = "";
|
||||
|
||||
|
||||
/// splits "x=z, y=b" into a map and an ordered keyword vector
|
||||
void split_map(string const & s, map<string, string> & res, vector<string> & keys)
|
||||
@ -1312,12 +1321,22 @@ void parse_outer_box(Parser & p, ostream & os, unsigned flags, bool outer,
|
||||
}
|
||||
|
||||
|
||||
void parse_listings(Parser & p, ostream & os, Context & parent_context, bool in_line)
|
||||
void parse_listings(Parser & p, ostream & os, Context & parent_context,
|
||||
bool in_line, bool use_minted)
|
||||
{
|
||||
parent_context.check_layout(os);
|
||||
begin_inset(os, "listings\n");
|
||||
if (p.hasOpt()) {
|
||||
string arg = p.verbatimOption();
|
||||
string arg = p.hasOpt() ? p.verbatimOption() : string();
|
||||
if (use_minted) {
|
||||
string const language = p.getArg('{', '}');
|
||||
p.skip_spaces(true);
|
||||
arg += string(arg.empty() ? "" : ",") + "language=" + language;
|
||||
if (!minted_float.empty()) {
|
||||
arg += string(arg.empty() ? "" : ",") + minted_float;
|
||||
minted_nonfloat_caption.clear();
|
||||
}
|
||||
}
|
||||
if (!arg.empty()) {
|
||||
os << "lstparams " << '"' << arg << '"' << '\n';
|
||||
if (arg.find("\\color") != string::npos)
|
||||
preamble.registerAutomaticallyLoadedPackage("color");
|
||||
@ -1329,6 +1348,19 @@ void parse_listings(Parser & p, ostream & os, Context & parent_context, bool in_
|
||||
os << "status collapsed\n";
|
||||
Context context(true, parent_context.textclass);
|
||||
context.layout = &parent_context.textclass.plainLayout();
|
||||
if (use_minted && prefixIs(minted_nonfloat_caption, "[t]")) {
|
||||
minted_nonfloat_caption.erase(0,3);
|
||||
os << "\n\\begin_layout Plain Layout\n";
|
||||
begin_inset(os, "Caption Standard\n");
|
||||
Context newcontext(true, context.textclass,
|
||||
context.layout, 0, context.font);
|
||||
newcontext.check_layout(os);
|
||||
os << minted_nonfloat_caption << "\n";
|
||||
newcontext.check_end_layout(os);
|
||||
end_inset(os);
|
||||
os << "\n\\end_layout\n";
|
||||
minted_nonfloat_caption.clear();
|
||||
}
|
||||
string s;
|
||||
if (in_line) {
|
||||
// set catcodes to verbatim early, just in case.
|
||||
@ -1337,10 +1369,41 @@ void parse_listings(Parser & p, ostream & os, Context & parent_context, bool in_
|
||||
//FIXME: handler error condition
|
||||
s = p.verbatimStuff(delim).second;
|
||||
// context.new_paragraph(os);
|
||||
} else
|
||||
} else if (use_minted) {
|
||||
s = p.verbatimEnvironment("minted");
|
||||
} else {
|
||||
s = p.verbatimEnvironment("lstlisting");
|
||||
}
|
||||
output_ert(os, s, context);
|
||||
end_inset(os);
|
||||
if (use_minted && prefixIs(minted_nonfloat_caption, "[b]")) {
|
||||
minted_nonfloat_caption.erase(0,3);
|
||||
os << "\n\\begin_layout Plain Layout\n";
|
||||
begin_inset(os, "Caption Standard\n");
|
||||
Context newcontext(true, context.textclass,
|
||||
context.layout, 0, context.font);
|
||||
newcontext.check_layout(os);
|
||||
os << minted_nonfloat_caption << "\n";
|
||||
newcontext.check_end_layout(os);
|
||||
end_inset(os);
|
||||
os << "\n\\end_layout\n";
|
||||
minted_nonfloat_caption.clear();
|
||||
}
|
||||
// Don't close the inset here for floating minted listings.
|
||||
// It will be closed at the end of the listing environment.
|
||||
if (!use_minted || minted_float.empty())
|
||||
end_inset(os);
|
||||
else {
|
||||
eat_whitespace(p, os, parent_context, true);
|
||||
Token t = p.get_token();
|
||||
if (t.asInput() != "\\end") {
|
||||
// If anything follows, collect it into a caption.
|
||||
minted_float_has_caption = true;
|
||||
os << "\n\\begin_layout Plain Layout\n"; // outer layout
|
||||
begin_inset(os, "Caption Standard\n");
|
||||
os << "\n\\begin_layout Plain Layout\n"; // inner layout
|
||||
}
|
||||
p.putback();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -1707,9 +1770,104 @@ void parse_environment(Parser & p, ostream & os, bool outer,
|
||||
preamble.registerAutomaticallyLoadedPackage("framed");
|
||||
}
|
||||
|
||||
else if (name == "lstlisting") {
|
||||
else if (name == "listing") {
|
||||
minted_float = "float";
|
||||
eat_whitespace(p, os, parent_context, false);
|
||||
parse_listings(p, os, parent_context, false);
|
||||
string const opt = p.hasOpt() ? p.getArg('[', ']') : string();
|
||||
if (!opt.empty())
|
||||
minted_float += "=" + opt;
|
||||
// If something precedes \begin{minted}, we output it at the end
|
||||
// as a caption, in order to keep it inside the listings inset.
|
||||
eat_whitespace(p, os, parent_context, true);
|
||||
p.pushPosition();
|
||||
Token const & t = p.get_token();
|
||||
p.skip_spaces(true);
|
||||
string const envname = p.next_token().cat() == catBegin
|
||||
? p.getArg('{', '}') : string();
|
||||
bool prologue = t.asInput() != "\\begin" || envname != "minted";
|
||||
p.popPosition();
|
||||
minted_float_has_caption = false;
|
||||
string content = parse_text_snippet(p, FLAG_END, outer,
|
||||
parent_context);
|
||||
size_t i = content.find("\\begin_inset listings");
|
||||
bool minted_env = i != string::npos;
|
||||
string caption;
|
||||
if (prologue) {
|
||||
caption = content.substr(0, i);
|
||||
content.erase(0, i);
|
||||
}
|
||||
parent_context.check_layout(os);
|
||||
if (minted_env && minted_float_has_caption) {
|
||||
eat_whitespace(p, os, parent_context, true);
|
||||
os << content << "\n";
|
||||
if (!caption.empty())
|
||||
os << caption << "\n";
|
||||
os << "\n\\end_layout\n"; // close inner layout
|
||||
end_inset(os); // close caption inset
|
||||
os << "\n\\end_layout\n"; // close outer layout
|
||||
} else if (!caption.empty()) {
|
||||
if (!minted_env) {
|
||||
begin_inset(os, "listings\n");
|
||||
os << "lstparams " << '"' << minted_float << '"' << '\n';
|
||||
os << "inline false\n";
|
||||
os << "status collapsed\n";
|
||||
}
|
||||
os << "\n\\begin_layout Plain Layout\n";
|
||||
begin_inset(os, "Caption Standard\n");
|
||||
Context newcontext(true, parent_context.textclass,
|
||||
0, 0, parent_context.font);
|
||||
newcontext.check_layout(os);
|
||||
os << caption << "\n";
|
||||
newcontext.check_end_layout(os);
|
||||
end_inset(os);
|
||||
os << "\n\\end_layout\n";
|
||||
} else if (content.empty()) {
|
||||
begin_inset(os, "listings\n");
|
||||
os << "lstparams " << '"' << minted_float << '"' << '\n';
|
||||
os << "inline false\n";
|
||||
os << "status collapsed\n";
|
||||
} else {
|
||||
os << content << "\n";
|
||||
}
|
||||
end_inset(os); // close listings inset
|
||||
parent_context.check_end_layout(os);
|
||||
parent_context.new_paragraph(os);
|
||||
p.skip_spaces();
|
||||
minted_float.clear();
|
||||
minted_float_has_caption = false;
|
||||
}
|
||||
|
||||
else if (name == "lstlisting" || name == "minted") {
|
||||
bool use_minted = name == "minted";
|
||||
eat_whitespace(p, os, parent_context, false);
|
||||
if (use_minted && minted_float.empty()) {
|
||||
// look ahead for a bottom caption
|
||||
p.pushPosition();
|
||||
bool found_end_minted = false;
|
||||
while (!found_end_minted && p.good()) {
|
||||
Token const & t = p.get_token();
|
||||
p.skip_spaces();
|
||||
string const envname =
|
||||
p.next_token().cat() == catBegin
|
||||
? p.getArg('{', '}') : string();
|
||||
found_end_minted = t.asInput() == "\\end"
|
||||
&& envname == "minted";
|
||||
}
|
||||
eat_whitespace(p, os, parent_context, true);
|
||||
Token const & t = p.get_token();
|
||||
p.skip_spaces(true);
|
||||
if (t.asInput() == "\\lyxmintcaption") {
|
||||
string const pos = p.getArg('[', ']');
|
||||
if (pos == "b") {
|
||||
string const caption =
|
||||
parse_text_snippet(p, FLAG_ITEM,
|
||||
false, parent_context);
|
||||
minted_nonfloat_caption = "[b]" + caption;
|
||||
}
|
||||
}
|
||||
p.popPosition();
|
||||
}
|
||||
parse_listings(p, os, parent_context, false, use_minted);
|
||||
p.skip_spaces();
|
||||
}
|
||||
|
||||
@ -2503,10 +2661,16 @@ void parse_text(Parser & p, ostream & os, unsigned flags, bool outer,
|
||||
}
|
||||
|
||||
else if (p.isParagraph()) {
|
||||
if (context.new_layout_allowed)
|
||||
context.new_paragraph(os);
|
||||
else
|
||||
output_ert_inset(os, "\\par ", context);
|
||||
// In minted floating listings we will collect
|
||||
// everything into the caption, where multiple
|
||||
// paragraphs are forbidden.
|
||||
if (minted_float.empty()) {
|
||||
if (context.new_layout_allowed)
|
||||
context.new_paragraph(os);
|
||||
else
|
||||
output_ert_inset(os, "\\par ", context);
|
||||
} else
|
||||
os << ' ';
|
||||
eat_whitespace(p, os, context, true);
|
||||
}
|
||||
|
||||
@ -3165,9 +3329,10 @@ void parse_text(Parser & p, ostream & os, unsigned flags, bool outer,
|
||||
end_inset(os);
|
||||
}
|
||||
|
||||
else if (t.cs() == "lstinline") {
|
||||
else if (t.cs() == "lstinline" || t.cs() == "mintinline") {
|
||||
bool const use_minted = t.cs() == "mintinline";
|
||||
p.skip_spaces();
|
||||
parse_listings(p, os, context, true);
|
||||
parse_listings(p, os, context, true, use_minted);
|
||||
}
|
||||
|
||||
else if (t.cs() == "ensuremath") {
|
||||
@ -3190,13 +3355,22 @@ void parse_text(Parser & p, ostream & os, unsigned flags, bool outer,
|
||||
output_ert_inset(os, t.asInput(), context);
|
||||
}
|
||||
|
||||
else if (t.cs() == "tableofcontents" || t.cs() == "lstlistoflistings") {
|
||||
else if (t.cs() == "tableofcontents"
|
||||
|| t.cs() == "lstlistoflistings"
|
||||
|| t.cs() == "listoflistings") {
|
||||
string name = t.cs();
|
||||
if (preamble.minted() && name == "listoflistings")
|
||||
name.insert(0, "lst");
|
||||
context.check_layout(os);
|
||||
begin_command_inset(os, "toc", t.cs());
|
||||
begin_command_inset(os, "toc", name);
|
||||
end_inset(os);
|
||||
skip_spaces_braces(p);
|
||||
if (t.cs() == "lstlistoflistings")
|
||||
preamble.registerAutomaticallyLoadedPackage("listings");
|
||||
if (name == "lstlistoflistings") {
|
||||
if (preamble.minted())
|
||||
preamble.registerAutomaticallyLoadedPackage("minted");
|
||||
else
|
||||
preamble.registerAutomaticallyLoadedPackage("listings");
|
||||
}
|
||||
}
|
||||
|
||||
else if (t.cs() == "listoffigures" || t.cs() == "listoftables") {
|
||||
@ -3719,6 +3893,20 @@ void parse_text(Parser & p, ostream & os, unsigned flags, bool outer,
|
||||
end_inset(os);
|
||||
}
|
||||
|
||||
else if (t.cs() == "lyxmintcaption") {
|
||||
string const pos = p.getArg('[', ']');
|
||||
if (pos == "t") {
|
||||
string const caption =
|
||||
parse_text_snippet(p, FLAG_ITEM, false,
|
||||
context);
|
||||
minted_nonfloat_caption = "[t]" + caption;
|
||||
} else {
|
||||
// We already got the caption at the bottom,
|
||||
// so simply skip it.
|
||||
p.getArg('{', '}');
|
||||
}
|
||||
}
|
||||
|
||||
else if (t.cs() == "printindex" || t.cs() == "printsubindex") {
|
||||
context.check_layout(os);
|
||||
string commandname = t.cs();
|
||||
@ -4613,14 +4801,19 @@ void parse_text(Parser & p, ostream & os, unsigned flags, bool outer,
|
||||
docstring const name = newinsetlayout->name();
|
||||
bool const caption = name.find(from_ascii("Caption:")) == 0;
|
||||
if (caption) {
|
||||
begin_inset(os, "Caption ");
|
||||
os << to_utf8(name.substr(8)) << '\n';
|
||||
// Already done for floating minted listings.
|
||||
if (minted_float.empty()) {
|
||||
begin_inset(os, "Caption ");
|
||||
os << to_utf8(name.substr(8)) << '\n';
|
||||
}
|
||||
} else {
|
||||
begin_inset(os, "Flex ");
|
||||
os << to_utf8(name) << '\n'
|
||||
<< "status collapsed\n";
|
||||
}
|
||||
if (newinsetlayout->isPassThru()) {
|
||||
if (!minted_float.empty()) {
|
||||
parse_text_snippet(p, os, FLAG_ITEM, false, context);
|
||||
} else if (newinsetlayout->isPassThru()) {
|
||||
// set catcodes to verbatim early, just in case.
|
||||
p.setCatcodes(VERBATIM_CATCODES);
|
||||
string delim = p.get_token().asInput();
|
||||
@ -4636,7 +4829,10 @@ void parse_text(Parser & p, ostream & os, unsigned flags, bool outer,
|
||||
parse_text_in_inset(p, os, FLAG_ITEM, false, context, newinsetlayout);
|
||||
if (caption)
|
||||
p.skip_spaces();
|
||||
end_inset(os);
|
||||
// Minted caption insets are not closed here because
|
||||
// we collect everything into the caption.
|
||||
if (minted_float.empty())
|
||||
end_inset(os);
|
||||
}
|
||||
|
||||
else if (t.cs() == "includepdf") {
|
||||
|
Loading…
Reference in New Issue
Block a user