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

Reply via email to