Introduce a new "RequiredArgs" tag for layouts. This functions much as

the OptionalArgs tag does and is implemented by the now misnamed
InsetOptArgs, except that its content gets wrapped in "{}" rather than
"[]". Required arguments do not actually have to be provided, but they
are always output. 

This will allow e.g. beamer's Block environment to be implemented
without ERT.

Documentation to follow.


git-svn-id: svn://svn.lyx.org/lyx/lyx-devel/trunk@34591 a592a061-630c-0410-9148-cb99ea01b6c8
This commit is contained in:
Richard Heck 2010-06-04 21:50:08 +00:00
parent 8bbd8bc44c
commit b0097bcddb
11 changed files with 113 additions and 37 deletions

View File

@ -94,6 +94,9 @@ import os, re, string, sys
# Incremented to format 26, 29 March 2010 by rgh
# Added CiteFormat.
# Incremented to format 27, 4 June 2010 by rgh
# Added RequiredArgs tag.
# Do not forget to document format change in Customization
# Manual (section "Declaring a new text class").
@ -101,7 +104,7 @@ import os, re, string, sys
# development/tools/updatelayouts.sh script to update all
# layout files to the new format.
currentFormat = 26
currentFormat = 27
def usage(prog_name):
@ -274,7 +277,7 @@ def convert(lines):
continue
# Only new features
if format >= 24 and format <= 25:
if format >= 24 and format <= 26:
i += 1
continue

View File

@ -106,6 +106,7 @@ enum LayoutTags {
LT_HTMLTITLE,
LT_SPELLCHECK,
LT_REFPREFIX,
LT_REQARGS,
LT_INTITLE // keep this last!
};
@ -118,7 +119,6 @@ Layout::Layout()
latextype = LATEX_PARAGRAPH;
intitle = false;
inpreamble = false;
optionalargs = 0;
needprotect = false;
keepempty = false;
font = inherit_font;
@ -214,6 +214,7 @@ bool Layout::read(Lexer & lex, TextClass const & tclass)
{ "passthru", LT_PASS_THRU },
{ "preamble", LT_PREAMBLE },
{ "refprefix", LT_REFPREFIX },
{ "requiredargs", LT_REQARGS },
{ "requires", LT_REQUIRES },
{ "rightmargin", LT_RIGHTMARGIN },
{ "spacing", LT_SPACING },
@ -320,7 +321,11 @@ bool Layout::read(Lexer & lex, TextClass const & tclass)
break;
case LT_OPTARGS:
lex >> optionalargs ;
lex >> optargs;
break;
case LT_REQARGS:
lex >> reqargs;
break;
case LT_NEED_PROTECT:

View File

@ -241,8 +241,15 @@ public:
bool intitle;
/// Is the content to go in the preamble rather than the body?
bool inpreamble;
/// Does this layout allow for an optional parameter?
int optionalargs;
/// Number of requried arguments for this command or environment
unsigned int reqargs;
/// Number of optional arguments for this command or environment
/// These MUST come at the beginning, so:
/// \cmd[opt1][opt2]{req1}{here is the text from LyX}
/// is fine. But:
/// \cmd[opt1]{req1}[opt2]{here is the text from LyX}
/// is not.
unsigned int optargs;
/// Which counter to step
docstring counter;
/// Prefix to use when creating labels

View File

@ -2341,11 +2341,13 @@ bool Text::getStatus(Cursor & cur, FuncRequest const & cmd,
case LFUN_INFO_INSERT:
code = INFO_CODE;
break;
case LFUN_OPTIONAL_INSERT:
case LFUN_OPTIONAL_INSERT: {
code = OPTARG_CODE;
enable = cur.paragraph().insetList().count(OPTARG_CODE)
< cur.paragraph().layout().optionalargs;
Layout const & lay = cur.paragraph().layout();
int const numargs = lay.reqargs + lay.optargs;
enable = cur.paragraph().insetList().count(OPTARG_CODE) < numargs;
break;
}
case LFUN_INDEX_INSERT:
code = INDEX_CODE;
break;

View File

@ -65,7 +65,7 @@ private:
};
// Keep the changes documented in the Customization manual.
int const FORMAT = 26;
int const FORMAT = 27;
bool layout2layout(FileName const & filename, FileName const & tempfile)

View File

@ -229,7 +229,7 @@ int InsetCaption::latex(odocstream & os,
// optional argument.
runparams.moving_arg = true;
os << "\\caption";
int l = latexOptArgInsets(paragraphs()[0], os, runparams, 1);
int l = latexArgInsets(paragraphs()[0], os, runparams, 0, 1);
os << '{';
l += InsetText::latex(os, runparams);
os << "}\n";
@ -285,7 +285,7 @@ int InsetCaption::getArgument(odocstream & os,
int InsetCaption::getOptArg(odocstream & os,
OutputParams const & runparams) const
{
return latexOptArgInsets(paragraphs()[0], os, runparams, 1);
return latexArgInsets(paragraphs()[0], os, runparams, 0, 1);
}

View File

@ -56,15 +56,16 @@ docstring InsetOptArg::xhtml(XHTMLStream &, OutputParams const &) const
return docstring();
}
int InsetOptArg::latexOptional(odocstream & os,
OutputParams const & runparams) const
int InsetOptArg::latexArgument(odocstream & os,
OutputParams const & runparams, bool optional) const
{
odocstringstream ss;
int ret = InsetText::latex(ss, runparams);
docstring str = ss.str();
if (str.find(']') != docstring::npos)
if (optional && str.find(']') != docstring::npos)
str = '{' + str + '}';
os << '[' << str << ']';
os << (optional ? '[' : '{') << str
<< (optional ? ']' : '}');
return ret;
}

View File

@ -29,8 +29,9 @@ public:
///
InsetOptArg(Buffer *);
/// Outputting the optional parameter of a LaTeX command
int latexOptional(odocstream &, OutputParams const &) const;
/// Outputting the parameter of a LaTeX command
int latexArgument(odocstream &, OutputParams const &,
bool optional) const;
///
bool hasSettings() const { return false; }

View File

@ -34,6 +34,7 @@
#include "support/lstrings.h"
#include <boost/next_prior.hpp>
#include <list>
using namespace std;
using namespace lyx::support;
@ -167,9 +168,8 @@ TeXEnvironment(Buffer const & buf,
if (style.isEnvironment()) {
os << "\\begin{" << from_ascii(style.latexname()) << '}';
if (style.optionalargs > 0) {
int ret = latexOptArgInsets(*pit, os, runparams,
style.optionalargs);
if (style.optargs != 0 || style.reqargs != 0) {
int ret = latexArgInsets(*pit, os, runparams, style.reqargs, style.optargs);
while (ret > 0) {
texrow.newline();
--ret;
@ -279,24 +279,61 @@ TeXEnvironment(Buffer const & buf,
} // namespace anon
int latexOptArgInsets(Paragraph const & par, odocstream & os,
OutputParams const & runparams, int number)
int latexArgInsets(Paragraph const & par, odocstream & os,
OutputParams const & runparams, unsigned int reqargs,
unsigned int optargs)
{
int lines = 0;
unsigned int totalargs = reqargs + optargs;
list<InsetOptArg const *> ilist;
InsetList::const_iterator it = par.insetList().begin();
InsetList::const_iterator end = par.insetList().end();
for (; it != end && number > 0 ; ++it) {
for (; it != end; ++it) {
if (it->inset->lyxCode() == OPTARG_CODE) {
InsetOptArg * ins =
static_cast<InsetOptArg *>(it->inset);
lines += ins->latexOptional(os, runparams);
--number;
if (ilist.size() >= totalargs) {
LYXERR0("WARNING: Found extra argument inset.");
continue;
}
InsetOptArg const * ins =
static_cast<InsetOptArg const *>(it->inset);
ilist.push_back(ins);
}
}
if (!reqargs && ilist.size() == 0)
return 0;
int lines = 0;
bool const have_optional_args = ilist.size() > reqargs;
if (have_optional_args) {
unsigned int todo = ilist.size() - reqargs;
for (unsigned int i = 0; i < todo; ++i) {
InsetOptArg const * ins = ilist.front();
ilist.pop_front();
lines += ins->latexArgument(os, runparams, true);
}
}
// we should now have no more insets than there are required
// arguments.
LASSERT(ilist.size() <= reqargs, /* */);
if (!reqargs)
return lines;
for (unsigned int i = 0; i < reqargs; ++i) {
if (ilist.empty())
// a required argument wasn't given, so we output {}
os << "{}";
else {
InsetOptArg const * ins = ilist.front();
ilist.pop_front();
lines += ins->latexArgument(os, runparams, false);
}
}
return lines;
}
// FIXME: this should be anonymous
ParagraphList::const_iterator TeXOnePar(Buffer const & buf,
Text const & text,
@ -543,9 +580,8 @@ ParagraphList::const_iterator TeXOnePar(Buffer const & buf,
os << '\\' << from_ascii(style.latexname());
// Separate handling of optional argument inset.
if (style.optionalargs > 0) {
int ret = latexOptArgInsets(*pit, os, runparams,
style.optionalargs);
if (style.optargs != 0 || style.reqargs != 0) {
int ret = latexArgInsets(*pit, os, runparams, style.reqargs, style.optargs);
while (ret > 0) {
texrow.newline();
--ret;

View File

@ -25,15 +25,19 @@ namespace lyx {
class Buffer;
class BufferParams;
class Encoding;
class Layout;
class Paragraph;
class OutputParams;
class TexRow;
class Text;
/// Export up to \p number optarg insets
int latexOptArgInsets(Paragraph const & par,
/// Export up to \p reqargs required arguments and
/// \p optargs optional ones. If not enough required
/// ones are given, we'll output: {}. The optional ones
/// must all come first.
int latexArgInsets(Paragraph const & par,
odocstream & os, OutputParams const & runparams,
int number);
unsigned int reqargs, unsigned int optargs);
/** Export \p paragraphs of buffer \p buf to LaTeX.
Don't use a temporary stringstream for \p os if the final output is

View File

@ -454,7 +454,8 @@ void output_command_layout(ostream & os, Parser & p, bool outer,
}
context.check_deeper(os);
context.check_layout(os);
if (context.layout->optionalargs > 0) {
unsigned int optargs = 0;
while (optargs < context.layout->optargs) {
eat_whitespace(p, os, context, false);
if (p.next_token().character() == '[') {
p.get_token(); // eat '['
@ -463,6 +464,20 @@ void output_command_layout(ostream & os, Parser & p, bool outer,
parse_text_in_inset(p, os, FLAG_BRACK_LAST, outer, context);
end_inset(os);
eat_whitespace(p, os, context, false);
optargs++;
}
}
unsigned int reqargs = 0;
while (reqargs < context.layout->reqargs) {
eat_whitespace(p, os, context, false);
if (p.next_token().character() == '{') {
p.get_token(); // eat '['
begin_inset(os, "OptArg\n");
os << "status collapsed\n\n";
parse_text_in_inset(p, os, FLAG_BRACE_LAST, outer, context);
end_inset(os);
eat_whitespace(p, os, context, false);
reqargs++;
}
}
parse_text(p, os, FLAG_ITEM, outer, context);
@ -1150,6 +1165,8 @@ void parse_text(Parser & p, ostream & os, unsigned flags, bool outer,
if (t.character() == ']' && (flags & FLAG_BRACK_LAST))
return;
if (t.character() == '}' && (flags & FLAG_BRACE_LAST))
return;
//
// cat codes