OK, here is a better formatted patch, preserving encoding etc. Thanks
for the feedback. The update is still being done in metrics() in the
same way that the macro expansion was being done previously. I have
changed it to cast away the const-ness rather than make cells_ mutable.
Assuming that the interface & function of the patch is acceptable I
will now implement a doDispatch(). In addition to changing the name
& number of arguments, I will also remove the expansion from metrics().
This will also negate the need for the mutable on MathMacro::tmpl_ and
MathMacro::expanded_.
If I rename a macro template, does it seem reasonable to automatically
update the name in all instantiations of that template?
thanks,
andrew
Index: text3.C
===================================================================
RCS file: /var/cvs/lyx/lyx-devel/src/text3.C,v
retrieving revision 1.323
diff -u -r1.323 text3.C
--- text3.C 31 Dec 2005 11:40:32 -0000 1.323
+++ text3.C 27 Jan 2006 02:06:30 -0000
@@ -1254,10 +1254,10 @@
else {
string s = cmd.argument;
string const s1 = token(s, ' ', 1);
- int const nargs = s1.empty() ? 0 : convert<int>(s1);
+// int const nargs = s1.empty() ? 0 : convert<int>(s1);
string const s2 = token(s, ' ', 2);
string const type = s2.empty() ? "newcommand" : s2;
- cur.insert(new MathMacroTemplate(token(s, ' ', 0), nargs, type));
+ cur.insert(new MathMacroTemplate(token(s, ' ', 0), s1, type));
//cur.nextInset()->edit(cur, true);
}
break;
Index: mathed/math_macro.C
===================================================================
RCS file: /var/cvs/lyx/lyx-devel/src/mathed/math_macro.C,v
retrieving revision 1.136
diff -u -r1.136 math_macro.C
--- mathed/math_macro.C 5 Oct 2005 21:19:32 -0000 1.136
+++ mathed/math_macro.C 27 Jan 2006 02:06:39 -0000
@@ -59,22 +59,28 @@
{
if (!MacroTable::globalMacros().has(name())) {
mathed_string_dim(mi.base.font, "Unknown: " + name(), dim);
- } else if (editing(mi.base.bv)) {
- asArray(MacroTable::globalMacros().get(name()).def(), tmpl_);
- LyXFont font = mi.base.font;
- augmentFont(font, "lyxtex");
- tmpl_.metrics(mi, dim);
- dim.wid += mathed_string_width(font, name()) + 10;
- int ww = mathed_string_width(font, "#1: ");
- for (idx_type i = 0; i < nargs(); ++i) {
- MathArray const & c = cell(i);
- c.metrics(mi);
- dim.wid = max(dim.wid, c.width() + ww);
- dim.des += c.height() + 10;
- }
} else {
- MacroTable::globalMacros().get(name()).expand(cells_, expanded_);
- expanded_.metrics(mi, dim);
+ const idx_type defArgs = static_cast<idx_type>(MacroTable::globalMacros().get(name()).numargs());
+ if (nargs() < defArgs)
+ ((MathMacro*)this)->cells_.resize(defArgs);
+
+ if (editing(mi.base.bv)) {
+ asArray(MacroTable::globalMacros().get(name()).def(), tmpl_);
+ LyXFont font = mi.base.font;
+ augmentFont(font, "lyxtex");
+ tmpl_.metrics(mi, dim);
+ dim.wid += mathed_string_width(font, name()) + 10;
+ int ww = mathed_string_width(font, "#1: ");
+ for (idx_type i = 0; i < nargs(); ++i) {
+ MathArray const & c = cell(i);
+ c.metrics(mi);
+ dim.wid = max(dim.wid, c.width() + ww);
+ dim.des += c.height() + 10;
+ }
+ } else {
+ MacroTable::globalMacros().get(name()).expand(cells_, expanded_);
+ expanded_.metrics(mi, dim);
+ }
}
metricsMarkers2(dim);
dim_ = dim;
@@ -158,6 +164,8 @@
void MathMacro::updateExpansion() const
{
+ if (MacroTable::globalMacros().has(name()))
+ MacroTable::globalMacros().get(name()).expand(cells_, expanded_);
//expanded_.substitute(*this);
}
@@ -173,3 +181,4 @@
os << "Macro: " << name();
}
+
Index: mathed/math_macro.h
===================================================================
RCS file: /var/cvs/lyx/lyx-devel/src/mathed/math_macro.h,v
retrieving revision 1.103
diff -u -r1.103 math_macro.h
--- mathed/math_macro.h 5 Oct 2005 21:19:32 -0000 1.103
+++ mathed/math_macro.h 27 Jan 2006 02:06:39 -0000
@@ -55,10 +55,14 @@
///
void infoize2(std::ostream &) const;
-private:
- virtual std::auto_ptr<InsetBase> doClone() const;
+ virtual MathMacro *asMacro() { return this; }
+ virtual MathMacro const *asMacro() const { return this; }
+
///
void updateExpansion() const;
+
+private:
+ virtual std::auto_ptr<InsetBase> doClone() const;
///
void expand() const;
Index: mathed/math_macrotable.C
===================================================================
RCS file: /var/cvs/lyx/lyx-devel/src/mathed/math_macrotable.C,v
retrieving revision 1.74
diff -u -r1.74 math_macrotable.C
--- mathed/math_macrotable.C 24 Jul 2004 10:55:28 -0000 1.74
+++ mathed/math_macrotable.C 27 Jan 2006 02:06:40 -0000
@@ -15,6 +15,7 @@
#include "math_macroarg.h"
#include "math_support.h"
#include "math_sqrtinset.h"
+#include "math_parser.h"
#include "debug.h"
#include "dociterator.h"
@@ -42,15 +43,58 @@
{}
-void MacroData::expand(vector<MathArray> const & args, MathArray & to) const
+void MacroData::doExpand(vector<MathArray> const & args, MathArray const &from, MathArray & to)
{
- MathSqrtInset inset; // Hack. Any inset with a cell would do.
- asArray(disp_.empty() ? def_ : disp_, inset.cell(0));
- //lyxerr << "MathData::expand: args: " << args << endl;
- //lyxerr << "MathData::expand: ar: " << inset.cell(0) << endl;
- for (DocIterator it = doc_iterator_begin(inset); it; it.forwardChar()) {
+ if (from.size() == 0)
+ return;
+
+ MathSqrtInset inset;
+ inset.cell(0) = from; // Hack. Any inset with a cell would do.
+
+// for (size_t j=0; j<args.size(); j++)
+// lyxerr << "MathData::expand: args(" << j << "): " << args[j] << endl;
+// lyxerr << "MathData::expand: ar: " << inset.cell(0) << endl;
+ for (DocIterator it = doc_iterator_begin(inset); it; it.forwardChar()) {
if (!it.nextInset())
continue;
+
+ if (it.nextInset()->lyxCode() == InsetBase::MATHMACRO_CODE) {
+ MathMacroTemplate *p = static_cast<MathMacroTemplate*>(it.nextInset());
+
+ // first we parse the name, replacing any macro args
+ MathArray arNameRes;
+ doExpand(args, p->cell(0), arNameRes);
+ string parsedName = asString(arNameRes);
+
+ MathArray arNumArgsRes;
+ doExpand(args, p->cell(1), arNumArgsRes);
+ string numArgs = asString(arNumArgsRes);
+
+ // then we replace the definition and display
+ MathArray ar1;
+ doExpand(args, p->cell(2), ar1);
+
+ MathArray ar2;
+ doExpand(args, p->cell(3), ar2);
+
+ MathMacroTemplate *p1 = new MathMacroTemplate(parsedName, numArgs, "newcommand", ar1, ar2);
+
+ // add the resulting macro to the global table
+ MacroTable::globalMacros().insert(p1->name(), p1->asMacroData());
+
+ // replace the one in the array with the new parsed version
+ MathArray tmpAr;
+ tmpAr.push_back(MathAtom(p1));
+
+ it.cell().erase(it.pos());
+ DocIterator::pos_type oldSize = it.lastpos();
+ it.cell().insert(it.pos(), tmpAr);
+ // attempt to skip the macro since it's already expanded
+ it.pos() = it.pos() + it.lastpos() - oldSize;
+
+ continue;
+ }
+
if (it.nextInset()->lyxCode() != InsetBase::MATHMACROARG_CODE)
continue;
//it.cell().erase(it.pos());
@@ -58,13 +102,22 @@
size_t n = static_cast<MathMacroArgument*>(it.nextInset())->number();
if (n <= args.size()) {
it.cell().erase(it.pos());
+ DocIterator::pos_type oldSize = it.lastpos();
it.cell().insert(it.pos(), args[n - 1]);
+ // attempt to skip the argument value just inserted
+ it.pos() = it.pos() + it.lastpos() - oldSize;
}
}
//lyxerr << "MathData::expand: res: " << inset.cell(0) << endl;
to = inset.cell(0);
}
+void MacroData::expand(vector<MathArray> const & args, MathArray & to) const
+{
+ MathArray fromAr;
+ asArray(disp_.empty() ? def_ : disp_, fromAr);
+ doExpand(args, fromAr, to);
+}
// The global table.
MacroTable & MacroTable::globalMacros()
Index: mathed/math_macrotable.h
===================================================================
RCS file: /var/cvs/lyx/lyx-devel/src/mathed/math_macrotable.h,v
retrieving revision 1.23
diff -u -r1.23 math_macrotable.h
--- mathed/math_macrotable.h 20 Apr 2004 08:51:15 -0000 1.23
+++ mathed/math_macrotable.h 27 Jan 2006 02:06:40 -0000
@@ -33,7 +33,9 @@
///
int numargs() const { return numargs_; }
/// replace #1,#2,... by given MathAtom 0,1,..
- void expand(std::vector<MathArray> const & from, MathArray & to) const;
+ void expand(std::vector<MathArray> const & args, MathArray & to) const;
+ ///
+ static void doExpand(std::vector<MathArray> const & args, MathArray const &from, MathArray & to);
private:
///
Index: mathed/math_macrotemplate.C
===================================================================
RCS file: /var/cvs/lyx/lyx-devel/src/mathed/math_macrotemplate.C,v
retrieving revision 1.72
diff -u -r1.72 math_macrotemplate.C
--- mathed/math_macrotemplate.C 24 Jan 2006 11:04:30 -0000 1.72
+++ mathed/math_macrotemplate.C 27 Jan 2006 02:06:41 -0000
@@ -15,6 +15,8 @@
#include "math_parser.h"
#include "math_support.h"
+#include "funcrequest.h"
+
#include "cursor.h"
#include "debug.h"
#include "gettext.h"
@@ -25,6 +27,7 @@
#include "frontends/font_metrics.h"
#include "support/lstrings.h"
+#include "support/convert.h"
using lyx::support::bformat;
@@ -35,28 +38,45 @@
MathMacroTemplate::MathMacroTemplate()
- : MathNestInset(2), numargs_(0), name_(), type_("newcommand")
+ : MathNestInset(4), type_("newcommand")
{
initMath();
}
+/*
MathMacroTemplate::MathMacroTemplate(string const & nm, int numargs,
string const & type, MathArray const & ar1, MathArray const & ar2)
- : MathNestInset(2), numargs_(numargs), name_(nm), type_(type)
+ : MathNestInset(4), type_(type)
{
initMath();
if (numargs_ > 9)
lyxerr << "MathMacroTemplate::MathMacroTemplate: wrong # of arguments: "
- << numargs_ << std::endl;
- cell(0) = ar1;
- cell(1) = ar2;
+ << numargs << std::endl;
+
+ asArray(nm, cell(0));
+
+ asArray(convert<string>(numargs), cell(1));
+
+ cell(2) = ar1;
+ cell(3) = ar2;
+}
+*/
+
+MathMacroTemplate::MathMacroTemplate(string const & nm, string const & numargs,
+ string const & type, MathArray const & ar1, MathArray const & ar2)
+ : MathNestInset(4), type_(type)
+{
+ asArray(nm, cell(0));
+ asArray(numargs, cell(1));
+ cell(2) = ar1;
+ cell(3) = ar2;
}
MathMacroTemplate::MathMacroTemplate(std::istream & is)
- : MathNestInset(2), numargs_(0), name_()
+ : MathNestInset(4)
{
initMath();
@@ -85,25 +105,25 @@
int MathMacroTemplate::numargs() const
{
- return numargs_;
+ return convert<int>(asString(cell(1)));
}
void MathMacroTemplate::numargs(int numargs)
{
- numargs_ = numargs;
+ asArray(convert<string>(numargs), cell(1));
}
string MathMacroTemplate::name() const
{
- return name_;
+ return asString(cell(0));
}
string MathMacroTemplate::prefix() const
{
- return bformat(_(" Macro: %1$s: "), name_);
+ return string(" Macro: ");
}
@@ -111,10 +131,13 @@
{
cell(0).metrics(mi);
cell(1).metrics(mi);
- dim.wid = cell(0).width() + cell(1).width() + 20
- + font_metrics::width(prefix(), mi.base.font);
- dim.asc = std::max(cell(0).ascent(), cell(1).ascent()) + 7;
- dim.des = std::max(cell(0).descent(), cell(1).descent()) + 7;
+ cell(2).metrics(mi);
+ cell(3).metrics(mi);
+ dim.wid = cell(0).width() + cell(1).width() + cell(2).width() + cell(3).width() + 26 +
+ font_metrics::width(prefix(), mi.base.font) + 8 +
+ font_metrics::width(":[]", mi.base.font);
+ dim.asc = std::max(cell(2).ascent(), cell(3).ascent()) + 7;
+ dim.des = std::max(cell(2).descent(), cell(3).descent()) + 7;
dim_ = dim;
}
@@ -154,12 +177,27 @@
int const w0 = cell(0).width();
int const w1 = cell(1).width();
+ int const w2 = cell(2).width();
+ int const w3 = cell(3).width();
+
cell(0).draw(pi, x + 2, y + 1);
+ x += w0 + 4;
+
+ pi.pain.text(x, y, ": [", font);
+ x += font_metrics::width(": [", pi.base.font) + 2;
+ cell(1).draw(pi, x, y + 1);
+ x += w1 + 2;
+ pi.pain.text(x, y, "]", font);
+ x += font_metrics::width("]", pi.base.font);
+
+ cell(2).draw(pi, x + 2, y + 1);
+ pi.pain.rectangle(x, y - dim_.ascent() + 3,
+ w2 + 4, dim_.height() - 6, LColor::mathline);
+ x += w2 + 6;
+
+ cell(3).draw(pi, x + 2, y + 1);
pi.pain.rectangle(x, y - dim_.ascent() + 3,
- w0 + 4, dim_.height() - 6, LColor::mathline);
- cell(1).draw(pi, x + 8 + w0, y + 1);
- pi.pain.rectangle(x + w0 + 6, y - dim_.ascent() + 3,
- w1 + 4, dim_.height() - 6, LColor::mathline);
+ w3 + 4, dim_.height() - 6, LColor::mathline);
}
@@ -186,17 +224,17 @@
void MathMacroTemplate::write(WriteStream & os) const
{
if (type_ == "def") {
- os << "\\def\\" << name_.c_str();
- for (int i = 1; i <= numargs_; ++i)
+ os << "\\def\\" << name().c_str();
+ for (int i = 1; i <= numargs(); ++i)
os << '#' << i;
} else {
// newcommand or renewcommand
- os << "\\" << type_.c_str() << "{\\" << name_.c_str() << '}';
- if (numargs_ > 0)
- os << '[' << numargs_ << ']';
+ os << "\\" << type_.c_str() << "{\\" << name().c_str() << '}';
+ if (cell(1).size() > 0)
+ os << '[' << asString(cell(1)).c_str() << ']';
}
- os << '{' << cell(0) << "}";
+ os << '{' << cell(2) << "}";
if (os.latex()) {
// writing .tex. done.
@@ -204,12 +242,12 @@
} else {
// writing .lyx, write special .tex export only if necessary
if (!cell(1).empty())
- os << "\n{" << cell(1) << '}';
+ os << "\n{" << cell(3) << '}';
}
}
MacroData MathMacroTemplate::asMacroData() const
{
- return MacroData(asString(cell(0)), numargs(), asString(cell(1)));
+ return MacroData(asString(cell(2)), numargs(), asString(cell(3)));
}
Index: mathed/math_macrotemplate.h
===================================================================
RCS file: /var/cvs/lyx/lyx-devel/src/mathed/math_macrotemplate.h,v
retrieving revision 1.47
diff -u -r1.47 math_macrotemplate.h
--- mathed/math_macrotemplate.h 23 Nov 2004 23:04:51 -0000 1.47
+++ mathed/math_macrotemplate.h 27 Jan 2006 02:06:41 -0000
@@ -24,11 +24,17 @@
///
MathMacroTemplate();
///
- MathMacroTemplate(std::string const & name, int nargs,
+/* MathMacroTemplate(std::string const & name, int nargs,
std::string const & type,
MathArray const & = MathArray(),
MathArray const & = MathArray());
- ///
+*/
+ ///
+ MathMacroTemplate(std::string const & name, std::string const & nargs,
+ std::string const & type,
+ MathArray const & = MathArray(),
+ MathArray const & = MathArray());
+ ///
explicit MathMacroTemplate(std::istream & is);
///
void edit(LCursor & cur, bool left);
@@ -64,10 +70,6 @@
/// prefix in inset
std::string prefix() const;
- ///
- int numargs_;
- ///
- std::string name_;
/// newcommand or renewcommand or def
std::string type_;
};
Index: mathed/math_parser.C
===================================================================
RCS file: /var/cvs/lyx/lyx-devel/src/mathed/math_parser.C,v
retrieving revision 1.316
diff -u -r1.316 math_parser.C
--- mathed/math_parser.C 8 Nov 2005 15:12:05 -0000 1.316
+++ mathed/math_parser.C 27 Jan 2006 02:06:45 -0000
@@ -856,38 +856,33 @@
{
string const type = t.cs();
string name;
- int nargs = 0;
+ string nargs;
if (t.cs() == "def") {
// get name
name = getToken().cs();
// read parameter
string pars;
+ int tmpArgC = 0;
while (good() && nextToken().cat() != catBegin) {
pars += getToken().cs();
- ++nargs;
+ ++tmpArgC;
}
- nargs /= 2;
+ tmpArgC /= 2;
+ if (tmpArgC > 0)
+ nargs = convert<string>(tmpArgC);
//lyxerr << "read \\def parameter list '" << pars << "'" << endl;
} else { // t.cs() == "newcommand" || t.cs() == "renewcommand"
- if (getToken().cat() != catBegin) {
- error("'{' in \\newcommand expected (1) ");
+ name = parse_verbatim_item();
+ if (name.length() == 0)
+ {
+ error("<\\name> in \\newcommand expected");
return;
}
-
- name = getToken().cs();
-
- if (getToken().cat() != catEnd) {
- error("'}' in \\newcommand expected");
- return;
- }
-
- string const arg = getArg('[', ']');
- if (!arg.empty())
- nargs = convert<int>(arg);
-
+
+ nargs = getArg('[', ']');
}
MathArray ar1;
@@ -907,8 +902,7 @@
if (nextToken().cat() == catBegin)
parse(ar2, FLAG_ITEM, MathInset::MATH_MODE);
- cell->push_back(MathAtom(new MathMacroTemplate(name, nargs, type,
- ar1, ar2)));
+ cell->push_back(MathAtom(new MathMacroTemplate(name, nargs, type, ar1, ar2)));
}
else if (t.cs() == "(") {
@@ -1339,6 +1333,8 @@
parse(at.nucleus()->cell(i), FLAG_ITEM, m);
skipSpaces();
}
+ if (at.nucleus()->asMacro())
+ at.nucleus()->asMacro()->updateExpansion();
cell->push_back(at);
}
}
