Hi!

I've been wanting to have some kind of word-completion mechanism in LyX (something like C-p in vim or M-/ in emacs). The only mention of this that I found was in the unanswered questions section in the FAQ (http://wiki.lyx.org/FAQ/Unanswered#toc2), or on the Complaints page in the LyX wiki, so I gather that it doesn't exist yet. Since I have a little spare time on my hands at the moment, I thought maybe I'd try writing a patch. (More on this later...)

While trying to get my bearings in the code, I noticed that there was a stub for a transpose function (LFUN_TRANSPOSE_CHARS), so I thought that writing that function would be a good exercise for getting familiar with the code. Attached is a patch (against 1.4.3) which adds the transpose functionality. (Of course, to make it at all useful, it really needs to be bound to a key --- I bound it to C-t for myself, but I didn't include that in the patch, as C-t is already taken.)

A few comments about the patch:
* It took me a while to figure this out, but I was finally able to get it so that undo sees the transposition as a single atomic action; * the same goes for making sure that the transposition *is* tracked by the change-tracking mechanism. * There is still a problem with a transposition which takes place on the border between two languages (at least, I have the problem when moving between English and Hebrew, which is RTL). There's no real reason to ever want to transpose such a case, so the patch could be committed as is; on the other hand, if someone can help me out with fixing this, that would be great. (What I need to know is, how do I identify the transition between languages/directions? I'd just as soon just cancel the action if I recognize that I'm on such a border.) * I have a feeling that what I currently do for checking that both characters are "regular text" (and not an inset, for example), is not complete; however, it seems to work. Again, if someone could help me out with how better to check for this condition, I'll fix the code if necessary.

Is there any documentation for developers? Specifically, something which explains in general how the document/buffer is stored in memory (i.e.: how are insets, language changes, etc. represented)?

Finally, back to word-completion: I've started working on that, but the main problem I've run into is preserving state between consecutive invocations. For example, let's say C-p is bound to this function. So the first time I call C-p, the word which the cursor is at is completed. The problem is, if I immediately (i.e., before moving the cursor or doing anything else in the document) press C-p again, I would like to get the next possible completion. But (a) how do I know that this is not the first call to the completion function, and (b) is there any way to keep track of the list of possible completion that I already found the first time around, so that I don't need to go through the whole buffer again?

I'd appreciate any thoughts or suggestions on this (all of the above).

Thanks,
Dov
Index: src/lyxtext.h
===================================================================
--- src/lyxtext.h       (revision 15158)
+++ src/lyxtext.h       (working copy)
@@ -244,6 +244,8 @@
        };
        /// Change the case of the word at cursor position.
        void changeCase(LCursor & cur, TextCase action);
+       /// Transpose characters at cursor position.
+       void charsTranspose(LCursor & cur);
 
        /** the DTP switches for paragraphs. LyX will store the top settings
         always in the first physical paragraph, the bottom settings in the
Index: src/text3.C
===================================================================
--- src/text3.C (revision 15158)
+++ src/text3.C (working copy)
@@ -728,7 +728,7 @@
                break;
 
        case LFUN_TRANSPOSE_CHARS:
-               recordUndo(cur);
+               charsTranspose(cur);
                break;
 
        case LFUN_PASTE:
Index: src/text.C
===================================================================
--- src/text.C  (revision 15158)
+++ src/text.C  (working copy)
@@ -1585,6 +1585,55 @@
 }
 
 
+// Transposes the character at the cursor with the one before it.
+void LyXText::charsTranspose(LCursor & cur)
+{
+       BOOST_ASSERT(this == cur.text());
+       CursorSlice from;
+
+       from = cur.top();
+       
+       pos_type pos = from.pos();
+       pit_type par = from.pit();
+       
+       // If cursor is at end of paragraph, transpose last two characters.
+       if (pos == cur.lastpos()) {
+               --pos;
+       }
+       
+       // If there is no previous character in paragraph, don't do anything.
+       if (pos < 1) {
+               return;
+       }
+       
+       --pos; // Just more convenient to work from the first character.
+
+       // Don't do anything if one of the "characters" is not regular text.
+       if (pars_[par].isInset(pos) || pars_[par].isInset(pos + 1))
+               return;
+
+       // Build the transposed string.
+       char transposed[3];
+       transposed[0] = pars_[par].getChar(pos + 1);
+       transposed[1] = pars_[par].getChar(pos);
+       transposed[2] = '\0';
+
+       // And finally, we are ready to perform the transposition.
+       // We use erase() and insert(), which take care of tracking the
+       // change.
+       recordUndoSelection(cur);
+
+       LyXFont const font = 
+               pars_[par].getFontSettings(cur.buffer().params(), pos);
+                       
+       cur.paragraph().erase(pos, pos + 2);
+       cur.paragraph().insert(pos, transposed, font);
+       
+       // After the transposition, move cursor one position forward.
+       cursorRight(cur);
+}
+
+
 bool LyXText::Delete(LCursor & cur)
 {
        BOOST_ASSERT(this == cur.text());

Reply via email to