]> git.lyx.org Git - features.git/commitdiff
Introduce a new "RequiredArgs" tag for layouts. This functions much as
authorRichard Heck <rgheck@comcast.net>
Fri, 4 Jun 2010 21:50:08 +0000 (21:50 +0000)
committerRichard Heck <rgheck@comcast.net>
Fri, 4 Jun 2010 21:50:08 +0000 (21:50 +0000)
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

lib/scripts/layout2layout.py
src/Layout.cpp
src/Layout.h
src/Text3.cpp
src/TextClass.cpp
src/insets/InsetCaption.cpp
src/insets/InsetOptArg.cpp
src/insets/InsetOptArg.h
src/output_latex.cpp
src/output_latex.h
src/tex2lyx/text.cpp

index 782a02637ec1b182520946b05574b0e60ae49d13..0c85e57ad7f62850dbee0309ec33f78b6fdb516f 100644 (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
 
index 7a26c8cf65a6a640dc66204fe187d4ee801f4a3a..cd7b5d43233b961f1be4744fd1a8b9afc7ca9fc0 100644 (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:
index 73edd052fcd1698e6dd8ef90fe0e8f0ae209d616..0a398d31c29b2ac0e9fda2bd413cc35910e2b091 100644 (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
index 0dd3b6492c96ee94fb1906e658d4fa0ae9533c95..e9c08f403e12b08cd30c051fed0395cab7ab39fb 100644 (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;
index bbf54cc946ac9c72760aa643207289a2d9af3fbb..3b72f4b592c3a4b835f13bc57a15a1ceacd1c08b 100644 (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)
index ab696b93398bae7acb713eec86da0cb4db51b483..c3661594aa9a993182f809112f96145ea606433e 100644 (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);
 }
 
 
index 544b213aae429c09962ba4722de736badd0db1af..340dac55a4abf0d8dc6f89471d1934329a66bb16 100644 (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;
 }
 
index 2584049a61287e0351320d631f41a84586063b24..c1cbeeccbed3e5c90016bee60f503a764b6851a1 100644 (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; }
 
index cdd42aaf4325222dffc0f18efff4d343bca6e20c..727fe4206df92ebe009ba13b5cb015f1e06a7eac 100644 (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;
index 84bd800a8aadac963572407a46f13e38ba389d8a..9a7de7ed69d12714ac07b5c5f162b0c97408fca7 100644 (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,
-                     odocstream & os, OutputParams const & runparams,
-                     int number);
+/// 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,
+               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
index a39a460233b1d01f53d2eacdafa8d3f862fe306a..ab6a101706cfea57ac55488cfede2c58c0dafdff 100644 (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