#include <sstream>
#include <vector>
-using lyx::support::ChangeExtension;
-using lyx::support::MakeAbsPath;
-using lyx::support::MakeRelPath;
-using lyx::support::rtrim;
-using lyx::support::suffixIs;
-using lyx::support::contains;
-using lyx::support::subst;
+
+namespace lyx {
+
+using support::addExtension;
+using support::changeExtension;
+using support::FileName;
+using support::makeAbsPath;
+using support::makeRelPath;
+using support::rtrim;
+using support::suffixIs;
+using support::contains;
+using support::subst;
using std::cerr;
using std::endl;
* No starred form other than "cite*" known.
*/
char const * const known_jurabib_commands[] = { "cite", "citet", "citep",
-"citealt", "citealp", "citeauthor", "citeyear", "citeyearpar", "fullcite",
+"citealt", "citealp", "citeauthor", "citeyear", "citeyearpar",
// jurabib commands not (yet) supported by LyX:
+// "fullcite",
// "footcite", "footcitet", "footcitep", "footcitealt", "footcitealp",
// "footciteauthor", "footciteyear", "footciteyearpar",
"citefield", "citetitle", "cite*", 0 };
/// the same as known_quotes with .lyx names
char const * const known_coded_quotes[] = { "gld", "grd", "gld",
-"grd", "gls", "fls", "frd", 0};
+"grd", "gls", "fls", "frs", 0};
/// LaTeX names for font sizes
char const * const known_sizes[] = { "tiny", "scriptsize", "footnotesize",
*/
char const * const known_tex_extensions[] = {"tex", 0};
+/// spaces known by InsetSpace
+char const * const known_spaces[] = { " ", "space", ",", "thinspace", "quad",
+"qquad", "enspace", "enskip", "negthinspace", 0};
+
+/// the same as known_spaces with .lyx names
+char const * const known_coded_spaces[] = { "space{}", "space{}",
+"thinspace{}", "thinspace{}", "quad{}", "qquad{}", "enspace{}", "enskip{}",
+"negthinspace{}", 0};
+
/// splits "x=z, y=b" into a map
map<string, string> split_map(string const & s)
return true;
}
+}
+
string translate_len(string const & length)
{
}
+namespace {
+
/*!
* Translates a LaTeX length into \p value, \p unit and
* \p special parts suitable for a box inset.
string find_file(string const & name, string const & path,
char const * const * extensions)
{
+ // FIXME UNICODE encoding of name and path may be wrong (makeAbsPath
+ // expects utf8)
for (char const * const * what = extensions; *what; ++what) {
- // We don't use ChangeExtension() because it does the wrong
- // thing if name contains a dot.
- string const trial = name + '.' + (*what);
- if (fs::exists(MakeAbsPath(trial, path)))
+ string const trial = addExtension(name, *what);
+ if (fs::exists(makeAbsPath(trial, path).toFilesystemEncoding()))
return trial;
}
return string();
LyXLayout_ptr findLayout(LyXTextClass const & textclass,
string const & name)
{
- LyXTextClass::const_iterator beg = textclass.begin();
+ LyXTextClass::const_iterator beg = textclass.begin();
LyXTextClass::const_iterator end = textclass.end();
LyXTextClass::const_iterator
* Parse all arguments of \p command
*/
void parse_arguments(string const & command,
- vector<ArgumentType> const & template_arguments,
- Parser & p, ostream & os, bool outer, Context & context)
+ vector<ArgumentType> const & template_arguments,
+ Parser & p, ostream & os, bool outer, Context & context)
{
string ert = command;
size_t no_arguments = template_arguments.size();
case required:
// This argument contains regular LaTeX
handle_ert(os, ert + '{', context);
+ eat_whitespace(p, os, context, false);
parse_text(p, os, FLAG_ITEM, outer, context);
ert = "}";
break;
{
if (known_commands.find(command) != known_commands.end()) {
parse_arguments(command, known_commands[command], p, os,
- outer, context);
+ outer, context);
return true;
}
return false;
/// parse an unknown environment
void parse_unknown_environment(Parser & p, string const & name, ostream & os,
- unsigned flags, bool outer,
- Context & parent_context)
+ unsigned flags, bool outer,
+ Context & parent_context)
{
if (name == "tabbing")
// We need to remember that we have to handle '\=' specially
void parse_environment(Parser & p, ostream & os, bool outer,
- Context & parent_context)
+ Context & parent_context)
{
LyXLayout_ptr newlayout;
string const name = p.getArg('{', '}');
else if (!parent_context.new_layout_allowed)
parse_unknown_environment(p, name, os, FLAG_END, outer,
- parent_context);
+ parent_context);
// Alignment settings
else if (name == "center" || name == "flushleft" || name == "flushright" ||
- name == "centering" || name == "raggedright" || name == "raggedleft") {
+ name == "centering" || name == "raggedright" || name == "raggedleft") {
eat_whitespace(p, os, parent_context, false);
// We must begin a new paragraph if not already done
if (! parent_context.atParagraphStart()) {
if (specialfont)
parent_context.new_layout_allowed = false;
parse_arguments("\\begin{" + name + "}", arguments, p, os,
- outer, parent_context);
+ outer, parent_context);
if (contents == verbatim)
handle_ert(os, p.verbatimEnvironment(name),
- parent_context);
+ parent_context);
else
parse_text_snippet(p, os, FLAG_END, outer,
- parent_context);
+ parent_context);
handle_ert(os, "\\end{" + name + "}", parent_context);
if (specialfont)
parent_context.new_layout_allowed = new_layout_allowed;
else
parse_unknown_environment(p, name, os, FLAG_END, outer,
- parent_context);
+ parent_context);
active_environments.pop_back();
}
if (t.cat() == catComment)
parse_comment(p, os, t, context);
else if ((! eatParagraph && p.isParagraph()) ||
- (t.cat() != catSpace && t.cat() != catNewline)) {
+ (t.cat() != catSpace && t.cat() != catNewline)) {
p.putback();
return;
}
/// convention (relative to .lyx file) if it is relative
void fix_relative_filename(string & name)
{
- if (lyx::support::AbsolutePath(name))
+ if (lyx::support::absolutePath(name))
return;
- name = MakeRelPath(MakeAbsPath(name, getMasterFilePath()),
- getParentFilePath());
+ // FIXME UNICODE encoding of name may be wrong (makeAbsPath expects
+ // utf8)
+ name = makeRelPath(makeAbsPath(name, getMasterFilePath()).absFilename(),
+ getParentFilePath());
+}
+
+
+/// Parse a NoWeb Scrap section. The initial "<<" is already parsed.
+void parse_noweb(Parser & p, ostream & os, Context & context)
+{
+ // assemble the rest of the keyword
+ string name("<<");
+ bool scrap = false;
+ while (p.good()) {
+ Token const & t = p.get_token();
+ if (t.asInput() == ">" && p.next_token().asInput() == ">") {
+ name += ">>";
+ p.get_token();
+ scrap = (p.good() && p.next_token().asInput() == "=");
+ if (scrap)
+ name += p.get_token().asInput();
+ break;
+ }
+ name += t.asInput();
+ }
+
+ if (!scrap || !context.new_layout_allowed ||
+ !context.textclass.hasLayout("Scrap")) {
+ cerr << "Warning: Could not interpret '" << name
+ << "'. Ignoring it." << endl;
+ return;
+ }
+
+ // We use new_paragraph instead of check_end_layout because the stuff
+ // following the noweb chunk needs to start with a \begin_layout.
+ // This may create a new paragraph even if there was none in the
+ // noweb file, but the alternative is an invalid LyX file. Since
+ // noweb code chunks are implemented with a layout style in LyX they
+ // always must be in an own paragraph.
+ context.new_paragraph(os);
+ Context newcontext(true, context.textclass, context.textclass["Scrap"]);
+ newcontext.check_layout(os);
+ os << name;
+ while (p.good()) {
+ Token const & t = p.get_token();
+ // We abuse the parser a bit, because this is no TeX syntax
+ // at all.
+ if (t.cat() == catEscape)
+ os << subst(t.asInput(), "\\", "\n\\backslash\n");
+ else
+ os << subst(t.asInput(), "\n", "\n\\newline\n");
+ // The scrap chunk is ended by an @ at the beginning of a line.
+ // After the @ the line may contain a comment and/or
+ // whitespace, but nothing else.
+ if (t.asInput() == "@" && p.prev_token().cat() == catNewline &&
+ (p.next_token().cat() == catSpace ||
+ p.next_token().cat() == catNewline ||
+ p.next_token().cat() == catComment)) {
+ while (p.good() && p.next_token().cat() == catSpace)
+ os << p.get_token().asInput();
+ if (p.next_token().cat() == catComment)
+ // The comment includes a final '\n'
+ os << p.get_token().asInput();
+ else {
+ if (p.next_token().cat() == catNewline)
+ p.get_token();
+ os << '\n';
+ }
+ break;
+ }
+ }
+ newcontext.check_end_layout(os);
}
} // anonymous namespace
skip_braces(p);
}
+ else if (t.asInput() == "<"
+ && p.next_token().asInput() == "<" && noweb_mode) {
+ p.get_token();
+ parse_noweb(p, os, context);
+ }
+
else if (t.cat() == catSpace || (t.cat() == catNewline && ! p.isParagraph()))
check_space(p, os, context);
+ else if (t.character() == '[' && noweb_mode &&
+ p.next_token().character() == '[') {
+ // These can contain underscores
+ p.putback();
+ string const s = p.getFullOpt() + ']';
+ if (p.next_token().character() == ']')
+ p.get_token();
+ else
+ cerr << "Warning: Inserting missing ']' in '"
+ << s << "'." << endl;
+ handle_ert(os, s, context);
+ }
+
else if (t.cat() == catLetter ||
t.cat() == catOther ||
t.cat() == catAlign ||
}
else if (t.cat() == catBegin &&
- p.next_token().cat() == catEnd) {
+ p.next_token().cat() == catEnd) {
// {}
Token const prev = p.prev_token();
p.get_token();
} else if (! context.new_layout_allowed) {
handle_ert(os, "{", context);
parse_text_snippet(p, os, FLAG_BRACE_LAST,
- outer, context);
+ outer, context);
handle_ert(os, "}", context);
} else if (is_known(next.cs(), known_sizes)) {
// next will change the size, so we must
// reset it here
parse_text_snippet(p, os, FLAG_BRACE_LAST,
- outer, context);
+ outer, context);
if (!context.atParagraphStart())
os << "\n\\size "
<< context.font.size << "\n";
// next will change the font family, so we
// must reset it here
parse_text_snippet(p, os, FLAG_BRACE_LAST,
- outer, context);
+ outer, context);
if (!context.atParagraphStart())
os << "\n\\family "
<< context.font.family << "\n";
// next will change the font series, so we
// must reset it here
parse_text_snippet(p, os, FLAG_BRACE_LAST,
- outer, context);
+ outer, context);
if (!context.atParagraphStart())
os << "\n\\series "
<< context.font.series << "\n";
// next will change the font shape, so we
// must reset it here
parse_text_snippet(p, os, FLAG_BRACE_LAST,
- outer, context);
+ outer, context);
if (!context.atParagraphStart())
os << "\n\\shape "
<< context.font.shape << "\n";
} else if (is_known(next.cs(), known_old_font_families) ||
- is_known(next.cs(), known_old_font_series) ||
- is_known(next.cs(), known_old_font_shapes)) {
+ is_known(next.cs(), known_old_font_series) ||
+ is_known(next.cs(), known_old_font_shapes)) {
// next will change the font family, series
// and shape, so we must reset it here
parse_text_snippet(p, os, FLAG_BRACE_LAST,
- outer, context);
+ outer, context);
if (!context.atParagraphStart())
os << "\n\\family "
<< context.font.family
} else {
handle_ert(os, "{", context);
parse_text_snippet(p, os, FLAG_BRACE_LAST,
- outer, context);
+ outer, context);
handle_ert(os, "}", context);
}
}
if (p.next_token().character() == '[') {
p.get_token(); // eat '['
s = parse_text_snippet(p, FLAG_BRACK_LAST,
- outer, context);
+ outer, context);
optarg = true;
}
context.set_item();
// Must attempt to parse "Section*" before "Section".
else if ((p.next_token().asInput() == "*") &&
- context.new_layout_allowed &&
+ context.new_layout_allowed &&
// The single '=' is meant here.
(newlayout = findLayout(context.textclass,
t.cs() + '*')).get() &&
// The single '=' is meant here.
else if (context.new_layout_allowed &&
- (newlayout = findLayout(context.textclass, t.cs())).get() &&
+ (newlayout = findLayout(context.textclass, t.cs())).get() &&
newlayout->isCommand()) {
output_command_layout(os, p, outer, context, newlayout);
p.skip_spaces();
string const path = getMasterFilePath();
// We want to preserve relative / absolute filenames,
// therefore path is only used for testing
- if (!fs::exists(MakeAbsPath(name, path))) {
+ // FIXME UNICODE encoding of name and path may be
+ // wrong (makeAbsPath expects utf8)
+ if (!fs::exists(makeAbsPath(name, path).toFilesystemEncoding())) {
// The file extension is probably missing.
// Now try to find it out.
string const dvips_name =
find_file(name, path,
- known_dvips_graphics_formats);
+ known_dvips_graphics_formats);
string const pdftex_name =
find_file(name, path,
- known_pdftex_graphics_formats);
+ known_pdftex_graphics_formats);
if (!dvips_name.empty()) {
if (!pdftex_name.empty()) {
cerr << "This file contains the "
- "latex snippet\n"
- "\"\\includegraphics{"
+ "latex snippet\n"
+ "\"\\includegraphics{"
<< name << "}\".\n"
- "However, files\n\""
+ "However, files\n\""
<< dvips_name << "\" and\n\""
<< pdftex_name << "\"\n"
- "both exist, so I had to make a "
- "choice and took the first one.\n"
- "Please move the unwanted one "
- "someplace else and try again\n"
- "if my choice was wrong."
+ "both exist, so I had to make a "
+ "choice and took the first one.\n"
+ "Please move the unwanted one "
+ "someplace else and try again\n"
+ "if my choice was wrong."
<< endl;
}
name = dvips_name;
name = pdftex_name;
}
- if (fs::exists(MakeAbsPath(name, path)))
+ // FIXME UNICODE encoding of name and path may be
+ // wrong (makeAbsPath expects utf8)
+ if (fs::exists(makeAbsPath(name, path).toFilesystemEncoding()))
fix_relative_filename(name);
else
cerr << "Warning: Could not find graphics file '"
}
else if (t.cs() == "footnote" ||
- (t.cs() == "thanks" && context.layout->intitle)) {
+ (t.cs() == "thanks" && context.layout->intitle)) {
p.skip_spaces();
context.check_layout(os);
begin_inset(os, "Foot\n");
else if (t.cs() == "textrm")
parse_text_attributes(p, os, FLAG_ITEM, outer,
- context, "\\family",
- context.font.family, "roman");
+ context, "\\family",
+ context.font.family, "roman");
else if (t.cs() == "textsf")
parse_text_attributes(p, os, FLAG_ITEM, outer,
- context, "\\family",
- context.font.family, "sans");
+ context, "\\family",
+ context.font.family, "sans");
else if (t.cs() == "texttt")
parse_text_attributes(p, os, FLAG_ITEM, outer,
- context, "\\family",
- context.font.family, "typewriter");
+ context, "\\family",
+ context.font.family, "typewriter");
else if (t.cs() == "textmd")
parse_text_attributes(p, os, FLAG_ITEM, outer,
- context, "\\series",
- context.font.series, "medium");
+ context, "\\series",
+ context.font.series, "medium");
else if (t.cs() == "textbf")
parse_text_attributes(p, os, FLAG_ITEM, outer,
- context, "\\series",
- context.font.series, "bold");
+ context, "\\series",
+ context.font.series, "bold");
else if (t.cs() == "textup")
parse_text_attributes(p, os, FLAG_ITEM, outer,
- context, "\\shape",
- context.font.shape, "up");
+ context, "\\shape",
+ context.font.shape, "up");
else if (t.cs() == "textit")
parse_text_attributes(p, os, FLAG_ITEM, outer,
- context, "\\shape",
- context.font.shape, "italic");
+ context, "\\shape",
+ context.font.shape, "italic");
else if (t.cs() == "textsl")
parse_text_attributes(p, os, FLAG_ITEM, outer,
- context, "\\shape",
- context.font.shape, "slanted");
+ context, "\\shape",
+ context.font.shape, "slanted");
else if (t.cs() == "textsc")
parse_text_attributes(p, os, FLAG_ITEM, outer,
- context, "\\shape",
- context.font.shape, "smallcaps");
+ context, "\\shape",
+ context.font.shape, "smallcaps");
else if (t.cs() == "textnormal" || t.cs() == "normalfont") {
context.check_layout(os);
}
else if (use_natbib &&
- is_known(t.cs(), known_natbib_commands) &&
- ((t.cs() != "citefullauthor" &&
- t.cs() != "citeyear" &&
- t.cs() != "citeyearpar") ||
- p.next_token().asInput() != "*")) {
+ is_known(t.cs(), known_natbib_commands) &&
+ ((t.cs() != "citefullauthor" &&
+ t.cs() != "citeyear" &&
+ t.cs() != "citeyearpar") ||
+ p.next_token().asInput() != "*")) {
context.check_layout(os);
// tex lyx
// \citet[before][after]{a} \citet[after][before]{a}
}
else if (use_jurabib &&
- is_known(t.cs(), known_jurabib_commands)) {
+ is_known(t.cs(), known_jurabib_commands)) {
context.check_layout(os);
string const command = '\\' + t.cs();
char argumentOrder = '\0';
vector<string> const & options = used_packages["jurabib"];
if (std::find(options.begin(), options.end(),
- "natbiborder") != options.end())
+ "natbiborder") != options.end())
argumentOrder = 'n';
else if (std::find(options.begin(), options.end(),
- "jurabiborder") != options.end())
+ "jurabiborder") != options.end())
argumentOrder = 'j';
// text before the citation
string const citation = p.verbatim_item();
if (!before.empty() && argumentOrder == '\0') {
cerr << "Warning: Assuming argument order "
- "of jurabib version 0.6 for\n'"
+ "of jurabib version 0.6 for\n'"
<< command << before << after << '{'
<< citation << "}'.\n"
- "Add 'jurabiborder' to the jurabib "
- "package options if you used an\n"
- "earlier jurabib version." << endl;
+ "Add 'jurabiborder' to the jurabib "
+ "package options if you used an\n"
+ "earlier jurabib version." << endl;
}
begin_inset(os, "LatexCommand ");
os << command << after << before
}
else if (is_known(t.cs(), known_sizes) &&
- context.new_layout_allowed) {
+ context.new_layout_allowed) {
char const * const * where = is_known(t.cs(), known_sizes);
context.check_layout(os);
Font const oldFont = context.font;
}
else if (is_known(t.cs(), known_font_families) &&
- context.new_layout_allowed) {
+ context.new_layout_allowed) {
char const * const * where =
is_known(t.cs(), known_font_families);
context.check_layout(os);
}
else if (is_known(t.cs(), known_font_series) &&
- context.new_layout_allowed) {
+ context.new_layout_allowed) {
char const * const * where =
is_known(t.cs(), known_font_series);
context.check_layout(os);
}
else if (is_known(t.cs(), known_font_shapes) &&
- context.new_layout_allowed) {
+ context.new_layout_allowed) {
char const * const * where =
is_known(t.cs(), known_font_shapes);
context.check_layout(os);
eat_whitespace(p, os, context, false);
}
else if (is_known(t.cs(), known_old_font_families) &&
- context.new_layout_allowed) {
+ context.new_layout_allowed) {
char const * const * where =
is_known(t.cs(), known_old_font_families);
context.check_layout(os);
}
else if (is_known(t.cs(), known_old_font_series) &&
- context.new_layout_allowed) {
+ context.new_layout_allowed) {
char const * const * where =
is_known(t.cs(), known_old_font_series);
context.check_layout(os);
}
else if (is_known(t.cs(), known_old_font_shapes) &&
- context.new_layout_allowed) {
+ context.new_layout_allowed) {
char const * const * where =
is_known(t.cs(), known_old_font_shapes);
context.check_layout(os);
else if (t.cs() == "=" && (flags & FLAG_TABBING))
handle_ert(os, t.asInput(), context);
- else if (t.cs() == "H" || t.cs() == "c" || t.cs() == "^"
+ else if (t.cs() == "H" || t.cs() == "c" || t.cs() == "^"
|| t.cs() == "'" || t.cs() == "`"
|| t.cs() == "~" || t.cs() == "." || t.cs() == "=") {
// we need the trim as the LyX parser chokes on such spaces
context.check_layout(os);
- os << "\n\\i \\" << t.cs() << "{"
+ os << "\\i \\" << t.cs() << "{"
<< trim(parse_text_snippet(p, FLAG_ITEM, outer, context), " ")
<< "}\n";
}
skip_braces(p); // eat {}
}
- else if (t.cs() == "i" || t.cs() == "j") {
+ else if (t.cs() == "i" || t.cs() == "j" || t.cs() == "l" ||
+ t.cs() == "L") {
context.check_layout(os);
- os << "\\" << t.cs() << ' ';
+ os << "\\i \\" << t.cs() << "{}\n";
skip_braces(p); // eat {}
}
string const path = getMasterFilePath();
// We want to preserve relative / absolute filenames,
// therefore path is only used for testing
+ // FIXME UNICODE encoding of filename and path may be
+ // wrong (makeAbsPath expects utf8)
if (t.cs() == "include" &&
- !fs::exists(MakeAbsPath(filename, path))) {
+ !fs::exists(makeAbsPath(filename, path).toFilesystemEncoding())) {
// The file extension is probably missing.
// Now try to find it out.
string const tex_name =
find_file(filename, path,
- known_tex_extensions);
+ known_tex_extensions);
if (!tex_name.empty())
filename = tex_name;
}
- if (fs::exists(MakeAbsPath(filename, path))) {
+ // FIXME UNICODE encoding of filename and path may be
+ // wrong (makeAbsPath expects utf8)
+ if (fs::exists(makeAbsPath(filename, path).toFilesystemEncoding())) {
string const abstexname =
- MakeAbsPath(filename, path);
+ makeAbsPath(filename, path).absFilename();
string const abslyxname =
- ChangeExtension(abstexname, ".lyx");
+ changeExtension(abstexname, ".lyx");
fix_relative_filename(filename);
string const lyxname =
- ChangeExtension(filename, ".lyx");
+ changeExtension(filename, ".lyx");
if (t.cs() != "verbatiminput" &&
- tex2lyx(abstexname, abslyxname)) {
+ tex2lyx(abstexname, FileName(abslyxname))) {
os << name << '{' << lyxname << "}\n";
} else {
os << name << '{' << filename << "}\n";
parse_box(p, os, FLAG_ITEM, outer, context, true);
else if (t.cs() == "smallskip" ||
- t.cs() == "medskip" ||
+ t.cs() == "medskip" ||
t.cs() == "bigskip" ||
t.cs() == "vfill") {
context.check_layout(os);
skip_braces(p);
}
- else if (t.cs() == "newpage") {
+ else if (is_known(t.cs(), known_spaces)) {
+ char const * const * where = is_known(t.cs(), known_spaces);
context.check_layout(os);
- // FIXME: what about \\clearpage and \\pagebreak?
- os << "\n\\newpage\n";
+ begin_inset(os, "InsetSpace ");
+ os << '\\' << known_coded_spaces[where - known_spaces]
+ << '\n';
+ // LaTeX swallows whitespace after all spaces except
+ // "\\,". We have to do that here, too, because LyX
+ // adds "{}" which would make the spaces significant.
+ if (t.cs() != ",")
+ eat_whitespace(p, os, context, false);
+ // LyX adds "{}" after all spaces except "\\ " and
+ // "\\,", so we have to remove "{}".
+ // "\\,{}" is equivalent to "\\," in LaTeX, so we
+ // remove the braces after "\\,", too.
+ if (t.cs() != " ")
+ skip_braces(p);
+ }
+
+ else if (t.cs() == "newpage" ||
+ t.cs() == "clearpage" ||
+ t.cs() == "cleardoublepage") {
+ context.check_layout(os);
+ // FIXME: what about \\pagebreak?
+ os << "\n\\" << t.cs() << "\n";
skip_braces(p); // eat {}
}
else if (t.cs() == "newcommand" ||
- t.cs() == "providecommand" ||
- t.cs() == "renewcommand") {
+ t.cs() == "providecommand" ||
+ t.cs() == "renewcommand") {
// these could be handled by parse_command(), but
// we need to call add_known_command() here.
string name = t.asInput();
string const opt2 = p.getFullOpt();
add_known_command(command, opt1, !opt2.empty());
string const ert = name + '{' + command + '}' +
- opt1 + opt2 +
- '{' + p.verbatim_item() + '}';
+ opt1 + opt2 +
+ '{' + p.verbatim_item() + '}';
handle_ert(os, ert, context);
}
}
// }])
+
+
+} // namespace lyx