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.