Hold on... this is a biggie!
I've been concentrating on the frontends recently and will continue to do so
until I knock them into better shape. What follows is a direct consequence of
this.
In what follows, by "insets" I mean "insets with parameters that can be
modified with a dialog"
Currently LyX is in a mess when it comes to insets and how to apply changes
to them from the frontends. We store a pointer to the inset in the frontend
and apply any changes directly.
This breaks the "everything has an LFUN and goes through dispatch" rule and
means further that modifying existing insets using (shock!) the LyX server is
impossible.
Some hard coded fudges exist but they're crap, can't cope with "complex"
inset parameters and are all-together not satisfactory.
I have been thinking about a Better Way. It will result in far fewer LFUNs
and greater flexibility. Here's the plan:
Communicating info to the GUI frontend
===============================
We can tell LyX to open or close the dialog for an existing inset:
LFUN_INSET_DIALOG_OPEN
LFUN_INSET_DIALOG_CLOSE
Note that we need just two LFUNs here. LyX will find the next inset following
the current cursor position and apply the LFUNs to it.
This is similar to the toggle scheme that JMarc and I played with some time
ago (and that I'm going to resurrect). Indeed I think we should also have
LFUN_INSET_DIALOG_TOGGLE
that invokes the two LFUNs above.
We can tell LyX to open an inset dialog when no inset exists, the idea being
that the user can then subsequently create an inset by apply()ing the
dialog's parameters. We'll need LFUNs for each inset type:
LFUN_BIBTEX_DIALOG_OPEN
LFUN_CITATION_DIALOG_OPEN
LFUN_TABULAR_DIALOG_OPEN
Communicating info to the LyX server
==============================
If we want to modify an existing inset using the LyX server and thence the
outside world, we must first pass this info /to/ the outside world. For this
I propose
LFUN_INSET_TO_LYXSERVER
So what to pass and how? I propose using the Inset::write method to output
the info in a consistent, documented format. We should also output the LyX
format version, so that the outside app knows how to read the data. Thus it
would receive
buffer BUFFER_ID
inset INSET_ID
\lyxformat 220
\begin_inset LatexCommand \citet{Butler:Tsuda97,Tsuda:etal99}
\end_inset
It should receive BUFFER_ID for the not-too-distant-day when we can have
multiple buffers being edited at the same time.
It must receive INSET_ID so that the outside program can modify the data and
then have it applied to the correct inset.
Communicating info back to LyX from the world outside
============================================
Both the LyX server and the GUI frontends will use the same LFUNs
To apply data to create a new inset at the current cursor position:
LFUN_INSET_CREATE
To apply data to an existing inset (and hence modify it):
LFUN_INSET_MODIFY
Both LFUNs will go through dispatch (of course) and so the data must be in
the form of a string. I propose using the inset::write method for this too
LFUN_INSET_CREATE would result in
buffer BUFFER_ID
\lyxformat 220
\begin_inset LatexCommand \citet{Butler:Tsuda97,Tsuda:etal99}
\end_inset
being passed through dispatch. The lyxformat data will enable us to read data
from eg pybliographer that hasn't quite kept up with us or wishes to support
a few LyX versions. We just send the string to Jos� and Dekel's python
scripts before passing it to the inset::read method.
LFUN_INSET_MODIFY needs also the INSET_ID to be passed
buffer BUFFER_ID
inset INSET_ID
\lyxformat 220
\begin_inset LatexCommand \citet{Butler:Tsuda97,Tsuda:etal99}
\end_inset
What we lose
===========
The ability to create new insets directly from the minibuffer. Currently
citation-insert Baker
will insert a citation to Baker directly in the text. I think that's just
hard-coding useless code for the sake of it. It can't be scaled to complex
parameters and is neither generic nor powerful.
Problems
=======
The only real problem with this whole approach lies with INSET_ID. What
should I use? The inset address? Will it be expensive to find the inset?
(Currently we store the inset pointer in the frontend and apply() directly,
but that circumvents dispatch() and isn't very nice, as I've already
mentioned.)
What do you think about the plan? Is it feasible? I think that it will clean
up the whole area and will adapt automatically as LyX evolves.
Thoughts welcome and good night ;-)
Angus