1
0
mirror of https://git.lyx.org/repos/lyx.git synced 2024-12-14 17:39:58 +00:00
lyx_mirror/development/mathmacros/architecture.lyx
Stefan Schimanski 79398fd8d4 * description of the math macro implementation
* testcases for math macros


git-svn-id: svn://svn.lyx.org/lyx/lyx-devel/trunk@23761 a592a061-630c-0410-9148-cb99ea01b6c8
2008-03-15 10:54:26 +00:00

1700 lines
32 KiB
Plaintext

#LyX 1.5.2 created this file. For more info see http://www.lyx.org/
\lyxformat 276
\begin_document
\begin_header
\textclass article
\language english
\inputencoding auto
\font_roman default
\font_sans default
\font_typewriter default
\font_default_family default
\font_sc false
\font_osf false
\font_sf_scale 100
\font_tt_scale 100
\graphics default
\paperfontsize default
\papersize default
\use_geometry false
\use_amsmath 1
\use_esint 1
\cite_engine basic
\use_bibtopic false
\paperorientation portrait
\secnumdepth 3
\tocdepth 3
\paragraph_separation indent
\defskip medskip
\quotes_language english
\papercolumns 1
\papersides 1
\paperpagestyle default
\tracking_changes false
\output_changes false
\author ""
\author ""
\end_header
\begin_body
\begin_layout Title
Dynamic Macros for LyX
\end_layout
\begin_layout Author
Stefan Schimanski
\newline
\begin_inset LatexCommand url
target "sts@1stein.org"
\end_inset
\end_layout
\begin_layout Date
21.10.2007
\end_layout
\begin_layout Section
The old system
\end_layout
\begin_layout Standard
LyX has the concept of math macros for quite some time.
In LyX 1.4 or 1.5 you can create one in your document by calling the
\family typewriter
math-macro
\family default
command in the mini buffer.
Visually this results in something equivalent to a TeX macro:
\begin_inset listings
inline false
status open
\begin_layout Standard
\backslash
newcommand{
\backslash
foo}{
\backslash
frac{1}{2}}
\end_layout
\end_inset
\end_layout
\begin_layout Standard
After LyX processed this, the command is available in math environments
in the same documents.
But internally there is nothing more than
\series bold
one
\series default
global macro table.
The position inside the document does not matter.
The command is available even in front of the definition.
But even worse, this global macro table is global for all opened documents.
If two buffers use the same macro name with different definitions, you
are in trouble.
The behaviour is undefined.
If you are lucky LyX will not crash.
Nothing must be said about redefining a macro later in the document: the
behaviour of LyX will not be what you expect.
\end_layout
\begin_layout Standard
LyX 1.4 and 1.5 do not show the support for this kind of macro very prominently.
In fact it is described in the
\begin_inset Quotes eld
\end_inset
Extended Features
\begin_inset Quotes erd
\end_inset
manual.
But there is no menu item to create macros.
Next to the mentioned method with the mini buffer you can use the
\begin_inset Quotes eld
\end_inset
Ctrl-L
\begin_inset Quotes erd
\end_inset
short cut to convert a raw
\backslash
newcommand into a LyX math macro.
Hence the role of macro is more of a power user tool for users who know
what they are doing.
\end_layout
\begin_layout Section
A wish list for a new macro implementation
\end_layout
\begin_layout Standard
In the following usecases are shown which can be wished to be supported
if macros are reimplemented.
Most of them are not possible in the old implemention, or at least very
hard to do.
\end_layout
\begin_layout Enumerate
Define a
\series bold
new macro
\series default
with a known arity ("arity" = number of arguments).
Use instances later on in the document.
\end_layout
\begin_layout Enumerate
\series bold
Redefine
\series default
a macro to use the same macro name with different definitions in different
areas of the document.
\end_layout
\begin_layout Enumerate
Have
\family typewriter
\backslash
newcommand
\family default
in the preamble (i.e.
by importing tex code) or
\series bold
not accessible
\series default
as a LyX macro in another way, and then define the command as a native
LyX math macro later.
All the uses of the old command should then turn into instances of the
LyX math macro.
\end_layout
\begin_layout Enumerate
\series bold
Rename
\series default
a macro and also adapt all the instance of the macro in the document.
\end_layout
\begin_layout Enumerate
\series bold
Change the arity
\series default
of a macro (normaly probably increase it), maybe with a default value used
in instances of the macro (possibly empty).
\end_layout
\begin_layout Enumerate
\series bold
Removal
\series default
of a macro.
\end_layout
\begin_layout Enumerate
Insertion of a macro via the
\series bold
menu
\series default
like "Insert->MathMacro".
\end_layout
\begin_layout Enumerate
\series bold
Moving
\series default
of a macro.
\end_layout
\begin_layout Enumerate
\series bold
\begin_inset LatexCommand label
name "sub:listedit"
\end_inset
\series default
Editing of a macro instance as a
\series bold
list
\series default
of #1: __, #2: __, i.e.
it
\series bold
unfold
\series default
s when the cursor goes inside.
\end_layout
\begin_layout Enumerate
Editing of macros
\series bold
inline
\series default
(the macro definition will be read-only, only the arguments as holes are
editable).
\end_layout
\begin_layout Enumerate
Changing of the
\series bold
editing behaviour
\series default
of
\series bold
\begin_inset LatexCommand ref
reference "sub:listedit"
\end_inset
\series default
for certain macros, not only globally.
\end_layout
\begin_layout Enumerate
Defining dynamic
\series bold
macros inside of macros
\series default
.
\end_layout
\begin_layout Enumerate
Using macros with the
\series bold
same name
\series default
, but different definitions in different open documents or parts of the
same document.
\end_layout
\begin_layout Enumerate
Using macros from the
\series bold
master document
\series default
.
\end_layout
\begin_layout Enumerate
Using the same argument, e.g.
#1, (
\series bold
non-linearly
\series default
) more than once in the definition, like
\family typewriter
\backslash
newcommand{
\backslash
ntothen}[1]{#1^#1}
\end_layout
\begin_layout Enumerate
\series bold
Patterns
\series default
like
\family typewriter
\backslash
def
\backslash
foo #1/#2{
\backslash
frac{#1}{#2}}
\end_layout
\begin_layout Enumerate
\series bold
Higher order
\series default
substitution (or call-by-name text substition) like
\family typewriter
\backslash
def
\backslash
foo #1{#1 12}
\family default
, which is applicable like
\family typewriter
\backslash
foo
\backslash
frac
\family default
to give
\family typewriter
1/2
\end_layout
\begin_layout Enumerate
\series bold
Optional
\series default
parameters like
\family typewriter
\backslash
newcommand{
\backslash
foo}[2][x]{#2_#1}
\end_layout
\begin_layout Standard
The old implementation supports the following:
\series bold
new macro
\series default
,
\series bold
moving
\series default
,
\series bold
list
\series default
,
\series bold
master document
\series default
,
\series bold
non-linear.
\series default
Though support of master documents is more or less an coincidence by the
global table.
\end_layout
\begin_layout Standard
The implementation described later (short: the new implementation) supports
the following:
\series bold
new macro
\series default
,
\series bold
redefine
\series default
,
\series bold
not accesible
\series default
,
\series bold
change the arity
\series default
,
\series bold
removal
\series default
,
\series bold
menu
\series default
,
\series bold
moving
\series default
,
\series bold
unfolds
\series default
,
\series bold
inline
\series default
,
\series bold
same name
\series default
,
\series bold
master documents
\series default
,
\series bold
non-linearly
\series default
,
\series bold
optional
\series default
.
\end_layout
\begin_layout Standard
Not supported are:
\series bold
patterns
\series default
,
\series bold
higher order
\series default
,
\series bold
macros inside of macros
\series default
,
\series bold
editing behaviour
\series default
,
\series bold
list
\series default
,
\series bold
rename
\series default
.
The last 3 should be doable without much work, maybe also
\series bold
patterns
\series default
.
\end_layout
\begin_layout Subsection
Main deficiencies of the old system
\end_layout
\begin_layout Standard
The main problem of the old implementation is that it is not dynamic at
all.
A macro is resolved (i.e.
the lookup in the global table takes place) when the internal object is
created, e.g.
while parsing of the
\family typewriter
.lyx
\family default
document or when typing
\family typewriter
\backslash
foo
\family default
.
If no macro definition of the right name exists at this time, an ERT is
created.
\end_layout
\begin_layout Standard
Moreover there is no position awareness of the definition, only during loading
of a document there is something like that because macro definitions are
put into the global table at the point in the document where it appears.
\end_layout
\begin_layout Section
A new approach
\end_layout
\begin_layout Standard
The goal of a new macro approach must be to support as many use cases subsection
1.2 as possible, or at least make an implementation possible of the remaining
ones.
Moreover a proper implementation better brings most of TeX's power of math
command into LyX.
\end_layout
\begin_layout Standard
In a few words the new approach could be described as follow:
\end_layout
\begin_layout Itemize
A macro is a dynamic inset which can
\begin_inset Quotes eld
\end_inset
eat up
\begin_inset Quotes erd
\end_inset
or
\begin_inset Quotes eld
\end_inset
spit out
\begin_inset Quotes erd
\end_inset
insets which follow the macro, depending on the success to resolve it and
the arity of the macro definition at the position in the document.
\end_layout
\begin_layout Itemize
Macros are resolved again everytime it is redrawn on screen if the macro
definition changed which is valid at the position.
\end_layout
\begin_layout Standard
This
\begin_inset Quotes eld
\end_inset
eat up
\begin_inset Quotes erd
\end_inset
and
\begin_inset Quotes eld
\end_inset
spit out
\begin_inset Quotes erd
\end_inset
process is the key idea.
Imagine a macro definition
\family typewriter
\backslash
newcommand{
\backslash
foo}[2]{a#1b#2c}
\family default
which is valid when a macro
\family typewriter
\backslash
foo
\family default
appears in the context
\family typewriter
\backslash
foo ABCD
\family default
.
When the macro is drawn the definition is checked and the arity is compared
to the number of
\begin_inset Quotes eld
\end_inset
eaten
\begin_inset Quotes erd
\end_inset
insets.
At the beginning the latter will be zero.
Because the arity of
\family typewriter
\backslash
foo
\family default
is 2, the macro inset will eat up 2 insets (the
\family typewriter
A
\family default
and the
\family typewriter
B
\family default
), hence internally the macro
\family typewriter
\backslash
foo
\family default
is changed to arity 2 and
\family typewriter
A
\family default
and
\family typewriter
B
\family default
are moved into it.
The visual representation of macro is that of the definition with the arguments
replaced by the eaten insets.
So eventually you will see
\family typewriter
aAbBcCD
\family default
on screen.
\end_layout
\begin_layout Standard
When you change the macro definition at the position into a unary macro,
e.g.
\family typewriter
\backslash
newcommand{
\backslash
foo}[1]{a#1b}
\family default
, the macro inset will spit out the second eaten inset, here the
\family typewriter
B
\family default
.
Hence you will eventually see
\family typewriter
aAbBCD
\family default
.
\end_layout
\begin_layout Standard
This process is done automatically, transparent to the user and in a fast
way everytime the macro is rendered and the definition has changed.
\end_layout
\begin_layout Standard
If you look at the produced TeX code of the
\family typewriter
\backslash
foo ABCD
\family default
you will notice that it didn't change during all this eating and spitting.
This is what you expect from a macro in TeX.
There the whole sense of command (i.e.
macros) is that you keep the same TeX code, independently from the macro
definition.
This approach carries this over to the LyX world.
\end_layout
\begin_layout Subsection
The implementation
\end_layout
\begin_layout Subsubsection
MathData
\end_layout
\begin_layout Standard
When a MathData object is drawn, more precisely when the metrics are computed,
all math macros in the
\family typewriter
MathData
\family default
are processed in the way described in the previous section.
If the arity of definition of a macro is changed the spitting/eating process
takes place.
This is implemented in
\family typewriter
MathData::updateMacros
\family default
, in a quite straight forward way.
\end_layout
\begin_layout Standard
Some complexity comes into the game by the necessary updating of the current
cursor.
If the user unfolds a macro the arity practically changes to zero, hence
the arguments are spit out.
If the cursor was inside an argument before, it should be in the same argument
after the unfolding.
The same should be the case for folding.
\end_layout
\begin_layout Standard
The metrics calculation is, by its typing, a const method, i.e.
it shouldn't change the
\family typewriter
MathData
\family default
object.
The macro updating though does changes of course.
Technically this is true, semantically (taking the produced TeX code as
semantics) it is not because nothing changes by eating/spitting or folding/unfo
lding with the later output.
To still allow these changes in
\family typewriter
MathData::metrics
\family default
a
\family typewriter
const_cast
\family default
is used.
This is somewhat ugly and a cleaner solution should be found.
Maybe one day the drawing and metrics will merge, then it would make sense
to think about the
\family typewriter
const_cast
\family default
as well again.
\end_layout
\begin_layout Subsubsection
Macro Table
\end_layout
\begin_layout Standard
How does the
\family typewriter
MathData
\family default
know which macro definitions are known at its position in the buffer? During
the metrics call a
\family typewriter
MacroContext
\family default
is passed around as an element of the
\family typewriter
MetricsInfo
\family default
class.
This context can be asked to resolve a macro name.
\end_layout
\begin_layout Standard
To make this possible it has to know about a position in the buffer.
In fact it knows about the paragraph in the buffer, and in addition it
has a
\begin_inset Quotes eld
\end_inset
local
\begin_inset Quotes erd
\end_inset
\family typewriter
MacroTable
\family default
.
The latter is used to also resolve macros correctly which are defined in
the paragraph where the macro appears.
The inset loop in the
\family typewriter
TextMetrics::redoParagraph
\family default
creates and updates the
\family typewriter
MacroContext
\family default
and the local macros in the expected way.
\end_layout
\begin_layout Standard
All the other macros are resolved by the
\family typewriter
MacroContext
\family default
by asking the buffer directly.
For this the
\family typewriter
MacroContext
\family default
, as written above, knows the paragraph it belongs to.
It passes this information to the buffer (via
\family typewriter
Buffer::hasMacro(docstring name, Paragraph par)
\family default
) and the buffer then uses the
\family typewriter
par.macrocontextPosition()
\family default
information to lookup the defined macros at the position in the map
\family typewriter
Buffer::pimpl->macros
\family default
.
This maps macro names and positions to the macro definitions.
which are defined at the position or before.
\end_layout
\begin_layout Standard
The missing bit is how the buffer creates this map.
This is done in the same way as in the old macro implementation, namely
by the Buffer::updateMacros method which iterates over the top-level inset
of the buffer.
It is called from
\family typewriter
BufferView::processUpdateFlags
\family default
very often.
This sounds slow, but it turned out that it is not noticable in fact.
In LyX 1.5 the same is done as well already.
Maybe some optimisation could help though, but was not investigated.
\end_layout
\begin_layout Standard
To support master documents there will a last lookup (if the previous lookup
were not successfull) by asking the master buffer.
\end_layout
\begin_layout Subsection
File Format
\end_layout
\begin_layout Standard
The file format concerning macros in the old macro implementation is not
well defined.
As described above there is a big difference between the visual semantics
(what the user sees inside LyX 1.5) and the latex semantics (what LaTeX
will make out of the document) are not the same.
\end_layout
\begin_layout Standard
The new approach changes this for most documents (if the user does not do
any dirty tricks at least) to be the same.
So from the file format point of view there probably should not be any
conversion needed to a new file format.
\end_layout
\begin_layout Standard
One exception of this comes from the support for optional arguments in the
new implementation.
Those were not available in the old format.
\end_layout
\begin_layout Subsubsection
Simple Macros
\end_layout
\begin_layout Standard
Macro definitions are stored in the following way:
\begin_inset listings
inline false
status open
\begin_layout Standard
\backslash
begin_inset FormulaMacro
\end_layout
\begin_layout Standard
\backslash
newcommand{
\backslash
abc}[1]{
\backslash
sin
\backslash
left(
\backslash
frac{-3}{#1}
\backslash
right)}
\end_layout
\begin_layout Standard
\backslash
end_inset
\end_layout
\end_inset
\end_layout
\begin_layout Standard
The resulting LaTeX code is as expected:
\begin_inset listings
inline false
status open
\begin_layout Standard
\backslash
newcommand{
\backslash
abc}[1]{
\backslash
sin
\backslash
left(
\backslash
frac{-3}{#1}
\backslash
right)}
\end_layout
\end_inset
\end_layout
\begin_layout Subsubsection
One Optional Argument
\end_layout
\begin_layout Standard
With one optional argument the LyX code looks like this:
\begin_inset listings
inline false
status open
\begin_layout Standard
\backslash
begin_inset FormulaMacro
\end_layout
\begin_layout Standard
\backslash
newcommand{
\backslash
abc}[1][42]{
\backslash
sin
\backslash
left(
\backslash
frac{-3}{#1}
\backslash
right)}
\end_layout
\begin_layout Standard
\backslash
end_inset
\end_layout
\end_inset
and the LaTeX code again is the same:
\begin_inset listings
inline false
status open
\begin_layout Standard
\backslash
newcommand{
\backslash
abc}[1][42]{
\backslash
sin
\backslash
left(
\backslash
frac{-3}{#1}
\backslash
right)}
\end_layout
\end_inset
\end_layout
\begin_layout Subsubsection
Multi Optional Argument Macro
\end_layout
\begin_layout Standard
More than one optional argument is not supported by LaTeX.
There are several solutions to allow them by defining some custom
\family typewriter
\backslash
newcommand
\family default
, but this is not standarized.
It might make sense for LyX to also support those when importing, but this
is not implemented.
Instead the new implementation will create valid standard LaTeX code by
outputting what the user sees on screen in LyX:
\begin_inset listings
inline false
status open
\begin_layout Standard
\backslash
begin_inset FormulaMacro
\end_layout
\begin_layout Standard
\backslash
newcommand{
\backslash
xyz}[2][42][28]{
\backslash
sqrt{#1}+
\backslash
ln
\backslash
left(
\backslash
frac{#2}{82}
\backslash
right)}
\end_layout
\begin_layout Standard
\backslash
end_inset
\end_layout
\end_inset
with the LaTeX code:
\begin_inset listings
inline false
status open
\begin_layout Standard
\backslash
newcommand{
\backslash
xyz}[2][42]{
\backslash
sqrt{#1}+
\backslash
ln
\backslash
left(
\backslash
frac{#2}{82}
\backslash
right)}
\end_layout
\end_inset
When the user creates an instance of
\backslash
xyz without substituting the optional argument, e.g.
by
\begin_inset listings
inline false
status open
\begin_layout Standard
\backslash
xyz
\end_layout
\end_inset
LyX will create the following LaTeX code when exporting to LaTeX:
\begin_inset listings
inline false
status open
\begin_layout Standard
\backslash
xyz{28}
\end_layout
\end_inset
So the optional argument is not optional anymore after export, but explicit.
\end_layout
\begin_layout Subsubsection
\backslash
def style
\end_layout
\begin_layout Standard
Last but not least, as in the old implementation you can use
\family typewriter
\backslash
def
\family default
macros, i.e.
TeX style definitions.
They don't support optional arguments.
They don't support
\begin_inset Quotes eld
\end_inset
patterns
\begin_inset Quotes erd
\end_inset
of the shape
\family typewriter
\backslash
def
\backslash
term #1+#2{#1+#2}
\family default
where you can use it as in
\family typewriter
\backslash
term 43+12
\family default
.
\end_layout
\begin_layout Subsubsection
Redefinition
\end_layout
\begin_layout Standard
On export LyX will correctly use
\family typewriter
\backslash
newcommand
\family default
and
\family typewriter
\backslash
renewcommand
\family default
if needed.
This is not visible in the LyX file format though.
\end_layout
\begin_layout Subsection
How it looks to the user
\end_layout
\begin_layout Subsubsection
Creation
\end_layout
\begin_layout Standard
Macro definitions look more or less the same as in the old implementation.
I.e.
there is a macro definition inset showing the macro like
\family typewriter
\backslash
foo{#1}:={a#1b}
\family default
.
You can create i
\family typewriter
t
\family default
via the
\begin_inset Quotes eld
\end_inset
math-macro foo 4
\begin_inset Quotes erd
\end_inset
to create a macro
\family typewriter
\backslash
foo
\family default
with 4 parameters.
\end_layout
\begin_layout Standard
A second way to create them is to write down the LaTeX definition like
\family typewriter
\backslash
newcommand
\backslash
foo{abc}
\family default
as plain text.
Select it and press Ctrl-m.
\end_layout
\begin_layout Standard
The last way, which is new with the new implementation, is to use the Insert/Mat
h/Macro menu item.
\end_layout
\begin_layout Subsubsection
Modification
\end_layout
\begin_layout Standard
The are the following actions defined:
\end_layout
\begin_layout Standard
\begin_inset Tabular
<lyxtabular version="3" rows="12" columns="2">
<features>
<column alignment="center" valignment="top" leftline="true" width="0">
<column alignment="center" valignment="top" leftline="true" rightline="true" width="0">
<row topline="true" bottomline="true">
<cell alignment="center" valignment="top" topline="true" leftline="true" usebox="none">
\begin_inset Text
\begin_layout Standard
Action
\end_layout
\end_inset
</cell>
<cell alignment="center" valignment="top" topline="true" leftline="true" rightline="true" usebox="none">
\begin_inset Text
\begin_layout Standard
Menu
\end_layout
\end_inset
</cell>
</row>
<row topline="true">
<cell alignment="center" valignment="top" topline="true" leftline="true" usebox="none">
\begin_inset Text
\begin_layout Standard
math-macro-unfold
\end_layout
\end_inset
</cell>
<cell alignment="center" valignment="top" topline="true" leftline="true" rightline="true" usebox="none">
\begin_inset Text
\begin_layout Standard
View/Unfold Math Macro
\end_layout
\end_inset
</cell>
</row>
<row topline="true">
<cell alignment="center" valignment="top" topline="true" leftline="true" usebox="none">
\begin_inset Text
\begin_layout Standard
math-macro-fold
\end_layout
\end_inset
</cell>
<cell alignment="center" valignment="top" topline="true" leftline="true" rightline="true" usebox="none">
\begin_inset Text
\begin_layout Standard
View/Fold Math Macro
\end_layout
\end_inset
</cell>
</row>
<row topline="true">
<cell alignment="center" valignment="top" topline="true" leftline="true" usebox="none">
\begin_inset Text
\begin_layout Standard
math-macro-add-param
\end_layout
\end_inset
</cell>
<cell alignment="center" valignment="top" topline="true" leftline="true" rightline="true" usebox="none">
\begin_inset Text
\begin_layout Standard
Edit/Math/Macro/Append Parameter
\end_layout
\end_inset
</cell>
</row>
<row topline="true">
<cell alignment="center" valignment="top" topline="true" leftline="true" usebox="none">
\begin_inset Text
\begin_layout Standard
math-macro-remove-param
\end_layout
\end_inset
</cell>
<cell alignment="center" valignment="top" topline="true" leftline="true" rightline="true" usebox="none">
\begin_inset Text
\begin_layout Standard
Edit/Math/Macro/Remove Last Parameter
\end_layout
\end_inset
</cell>
</row>
<row topline="true">
<cell alignment="center" valignment="top" topline="true" leftline="true" usebox="none">
\begin_inset Text
\begin_layout Standard
math-macro-append-greedy-param
\end_layout
\end_inset
</cell>
<cell alignment="center" valignment="top" topline="true" leftline="true" rightline="true" usebox="none">
\begin_inset Text
\begin_layout Standard
Edit/Math/Macro/Append Parameter Eating From the Right
\end_layout
\end_inset
</cell>
</row>
<row topline="true">
<cell alignment="center" valignment="top" topline="true" leftline="true" usebox="none">
\begin_inset Text
\begin_layout Standard
math-macro-make-optional
\end_layout
\end_inset
</cell>
<cell alignment="center" valignment="top" topline="true" leftline="true" rightline="true" usebox="none">
\begin_inset Text
\begin_layout Standard
Edit/Math/Macro/Make First Non-Optional into Optional Parameter
\end_layout
\end_inset
</cell>
</row>
<row topline="true">
<cell alignment="center" valignment="top" topline="true" leftline="true" usebox="none">
\begin_inset Text
\begin_layout Standard
math-macro-remove-greedy-param
\end_layout
\end_inset
</cell>
<cell alignment="center" valignment="top" topline="true" leftline="true" rightline="true" usebox="none">
\begin_inset Text
\begin_layout Standard
Edit/Math/Macro/Remove Last Parameter Spitting Out To The Right
\end_layout
\end_inset
</cell>
</row>
<row topline="true">
<cell alignment="center" valignment="top" topline="true" leftline="true" usebox="none">
\begin_inset Text
\begin_layout Standard
math-macro-make-nonoptional
\end_layout
\end_inset
</cell>
<cell alignment="center" valignment="top" topline="true" leftline="true" rightline="true" usebox="none">
\begin_inset Text
\begin_layout Standard
Edit/Math/Macro/Make Last Optional into Non-Optional Parameter
\end_layout
\end_inset
</cell>
</row>
<row topline="true">
<cell alignment="center" valignment="top" topline="true" leftline="true" usebox="none">
\begin_inset Text
\begin_layout Standard
math-macro-add-optional-param
\end_layout
\end_inset
</cell>
<cell alignment="center" valignment="top" topline="true" leftline="true" rightline="true" usebox="none">
\begin_inset Text
\begin_layout Standard
Edit/Math/Macro/Insert Optional Parameter
\end_layout
\end_inset
</cell>
</row>
<row topline="true">
<cell alignment="center" valignment="top" topline="true" leftline="true" usebox="none">
\begin_inset Text
\begin_layout Standard
math-macro-remove-optional-param
\end_layout
\end_inset
</cell>
<cell alignment="center" valignment="top" topline="true" leftline="true" rightline="true" usebox="none">
\begin_inset Text
\begin_layout Standard
Edit/Math/Macro/Remove Optional Parameter
\end_layout
\end_inset
</cell>
</row>
<row topline="true" bottomline="true">
<cell alignment="center" valignment="top" topline="true" leftline="true" usebox="none">
\begin_inset Text
\begin_layout Standard
math-macro-add-greedy-optional-param
\end_layout
\end_inset
</cell>
<cell alignment="center" valignment="top" topline="true" leftline="true" rightline="true" usebox="none">
\begin_inset Text
\begin_layout Standard
Edit/Math/Macro/Append Optional Parameter Eating From the Right
\end_layout
\end_inset
</cell>
</row>
</lyxtabular>
\end_inset
\end_layout
\begin_layout Subsubsection
Greedy vs.
Non-Greedy
\end_layout
\begin_layout Standard
As described above the key idea is that macros and eat up and spit out parameter
s, depending on their arity.
This makes them very dynamic and powerful, but at the same time adds some
complexity which must be understood by the user to effectively use the
macros.
\end_layout
\begin_layout Standard
Hence if the arity is increased (i.e.
another parameter is added to a macro) there are two ways to do that: if
this is done greedily the macro tries to eat up another inset from the
right.
This is the natural way if you import a document and then start to define
a macros with LyX's math macros.
Then you want that the macros take the (existing) paramenters from the
right.
\end_layout
\begin_layout Standard
The second case is the non-greedy use case.
E.g.
you want to change a macro to take another parameter because you just found
out that your notation needs another index.
Then you want to insert this non-greedily.
All macro instances in your text should get another parameter without touching
the surrouindings.
\end_layout
\begin_layout Standard
The greedy variants of the actions have the word
\begin_inset Quotes eld
\end_inset
greedy
\begin_inset Quotes erd
\end_inset
in their name.
\end_layout
\begin_layout Standard
Some of the actions also take a paramenter to define the position to act
on in the parameter list.
E.g.
you can write
\family typewriter
math-macro-add-param 2
\family default
in the mini-buffer to add a parameter at position 2.
\end_layout
\begin_layout Subsubsection
Folding/Unfolding
\end_layout
\begin_layout Standard
Sometimes it is desireable to switch to the TeX code of a macro instance,
i.e.
without any substitution using the macro definition.
This can be done with the fold/unfold actions.
You can use the
\family typewriter
Ctrl-+
\family default
and
\family typewriter
Ctrl--
\family default
shortcuts for that.
\end_layout
\begin_layout Standard
If you nest macro instances these actions will unfold from inside to the
outside and the same for folding.
This is supposed to replace the old list display when entering a macro.
\end_layout
\begin_layout Subsubsection
Toolbar
\end_layout
\begin_layout Standard
Currently there is no toolbar for math macros.
Because the menu hierarchy is very deep a toolbar would make the life a
lot easier.
It shouldn't be hard to implement that.
\end_layout
\begin_layout Subsubsection
More natural macro definition editing
\end_layout
\begin_layout Standard
Instead of the described actions it would desirable to add another more
natural way to edit macros.
The vision is that the user can put the cursor everywhere inside of the
macro definition inset which shows (already now!) the definition in the
way
\family typewriter
\backslash
name{#1}{#2}:={definition}
\family default
.
The user should be able to use the backspace and the
\family typewriter
{
\family default
key to remove and add parameters when the cursor is in the parameter definition
part.
For a non-greedy macro-append one could put a small (+) button or a hungry
packman
\family typewriter
(<
\family default
behind the
\family typewriter
{#2}
\family default
in front of the definition.
\end_layout
\begin_layout Standard
For implementing this one has to customize the
\family typewriter
MathInsetNest
\family default
a lot to handle the keypresses correctly, because it's probably not directly
doable with
\family typewriter
MathInsetNest
\family default
in a simple way with its children insets.
\end_layout
\begin_layout Subsubsection
Keyboard navigation
\end_layout
\begin_layout Standard
You can jump from
\family typewriter
#n
\family default
to
\family typewriter
#n+1
\family default
with the cursor key and conversely backwards.
This navigation is not visual.
I.e.
the user can define macros like
\family typewriter
\backslash
foo{#1}{#2}:={#2+#1}
\family default
.
Then the cursor jumps first to the right and then to the left where the
#1 is.
This can be confusing.
One could think about a visual movement mode by taking the position of
the macro argument insets into account to find the next inset for the cursor
keys.
This should be doable.
\end_layout
\end_body
\end_document