In the thread, "vim mode is a great success, even when not enabled", I said,

    "The code for every kind of completion tab is hairy,  but a filename
    completion/browsing tab would be useful not just for vim commands.
    Imo, Leo must have this."

Well, it turns out that Leo already has such code: k.getFileName.  It is 
used by the open-outline-by-name command. Alas, k.getFileName is pretty 
much broken.  Apparently, nobody uses open-outline-by-name, or they have 
used it once and given up on Leo :-(

Last night I found a way to remove *all* the behind-the-scenes complexity 
with tab completion in k.getFileName. This Aha should apply to Leo's 
workhorse k.getArg method as well. I'll discuss the (interesting!) coding 
details in the P.S.

Some real work remains: the code that actually computes the completion list 
needs a lot of work.  I expect to finish it today, if birthday revels do 
not interfere ;-)

Edward

P.S. Engineering Note Book: feel free to ignore.

I began the task of fixing k.getFileName by creating a FileNameChooser 
class.  Not pushed yet.

The original intention of the FileNameChooser class was to hide the details 
of the code.  Like this::

    def getFileName():
        '''Create a FileNameChooser and use it to get a file name.'''
        fnc = FileNameChooser(c,handler,filterExt='.py')
            # handler=None,prefix='Enter File Name:',tabName='Dired')
        fnc.get_file_name()

I have often found that creating a helper class like this clarifies the 
code in unexpected ways. Rather than dealing with a set of a set of helper 
methods of k (class KeyHandlerClass), grouping the methods into a new class 
simplifies everything.

The old code in both k.getFileName and k.getArg keeps track of several 
truly ugly and hard-to-understand ivars, whose only real purpose is to keep 
track of the "protected" label in the minibuffer, so as either ignore it or 
prevent the label from being deleted by a backspace character. In the new 
class it was much easier to see that none of this complexity is needed!  
The trick is to define the following methods::

    def extend_label(fnc,s):
        '''Extend the label by s.'''
        fnc.c.k.extendLabel(s,select=False,protect=False)
    
    def get_label(fnc):
        '''Return the label, not including the prompt.'''
        return fnc.c.k.getLabel(ignorePrompt=True)
    
    def set_label(fnc,s):
        '''Set the label after the prompt to s. The prompt never changes.'''
        fnc.c.k.setLabel(fnc.prompt,protect=True)
        fnc.c.k.extendLabel(s or '',select=False,protect=False

As you can see, these are simply thin wrappers on the corresponding k 
methods, but they deal only with what follows the prompt.  All the apparent 
complexity of tab completion simply disappears!  We use fnc.get_label to 
get the text to be completed, and use fnc.set_label/extend_label to update 
the label.

All this is obvious in retrospect, but I would never have seen it without 
creating the new class.  Pretty amazing.

P.P.S.   This collapse in complexity might apply to k.getArg as well, but 
there are complications.   k.getArg has accreted over the years, and it 
contains several hacks (keyword arguments) not related to tab completion. 
It might not be possible for k.getArg to create a new instance of, say, a 
GetArg class without having unpleasant ripple effects throughout Leo. 

If k.getArg *can* create one-off instances of the GetArg class, then both 
the GetArg and FileNameChooser classes would likely become a subclass of a 
BaseGetArg class.

EKR

-- 
You received this message because you are subscribed to the Google Groups 
"leo-editor" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to [email protected].
To post to this group, send email to [email protected].
Visit this group at http://groups.google.com/group/leo-editor.
For more options, visit https://groups.google.com/d/optout.

Reply via email to