Excellent.

On Wednesday, August 20, 2014 2:38:50 PM UTC+3, Edward K. Ream wrote:
>
> In an earlier post I said:
>
> QQQ
> Strictly speaking, tab cycling doesn't have to be disabled for all colon 
> commands.  One could imaging a list of commands that use tab to complete 
> file names. Otoh, maintaining that list would be clumsy, and it would add 
> still more special cases to ga.do_tab.
> QQQ
>
> This post describes a much better way, done at rev 3994eca...Leo build:  
> 20140820060754.
>
> The new code is gorgeous, if I do say so myself. Even better, the solution 
> is a design pattern with many applications.
>
> The trick is to replace functions implementing commands by classes having 
> __call__ methods.  See the P.P.S for details.
>
> Yes, this has all been done before.  Several of Leo's commands are 
> implemented this way.  But read on...
>
> What's new is that classes can "advertise" their ability to do various 
> things.  Here, the classes implementing vim commands advertise, by having a 
> tab_callback method, that they want to handle a tab that follows their 
> name.  ga.do_tab then defers to the vim command.
>
> There are several really cool things about this code.
>
> 1.  ga.do_tab, and its helper, ga.do_tab_callback, no longer know 
> *anything* about colon commands, or what any command intends to do with the 
> tab(!!).  If the command handler has a tab_callback attribute, 
> ga.do_tab_callback just does::
>
>      ga.reset_tab_cycling()
>      k.functionTail = tail # For k.getFileName.
>      handler.tab_callback()
>
> Nothing could be simpler, or more general.
>
> 2. The code in the command classes is simplified as well.  No need for a 
> kludgy test event.get_arg_value.  See the P.S. for the full implementation 
> of the :tabnew command.
>
> The overall result is a spectacular collapse in complexity, which the 
> attendant increase in power and generality.
>
> Edward
>
> P.S.  Here is the flattened form of the class that handles the :tabnew 
> command (does not require vim-mode).  In particular, note that the __call__ 
> and tab_callback methods are trivial.  This is the way it is written in The 
> Book.
>
> class LoadFileAtCursor:
>     '''
>     A class to handle Vim's :tabnew command.
>     This class supports the do_tab callback.
>     '''
>     def __init__(self,vc):
>         '''Ctor for VimCommands.LoadFileAtCursor class.'''
>         self.vc = vc
>
>     __name__ = ':r'
>         # Required.
>
>     def __call__(self,event=None):
>         '''Prompt for a file name, the open a new Leo tab.'''
>         self.vc.c.k.getFileName(event,callback=self.open_file_by_name)
>         
>     def tab_callback(self):
>         '''Called when the user types :tabnew<tab>'''
>         self.vc.c.k.getFileName(event=None,callback=self.open_file_by_name)
>         
>     def open_file_by_name(self,fn):
>         c = self.vc.c
>         if fn and not g.os_path_isdir(fn):
>             c2 = g.openWithFileName(fn,old_c=c)
>             try:
>                 g.app.gui.runAtIdle(c2.treeWantsFocusNow)
>             except Exception:
>                 pass
>         else:
>             c.new()
>
> P.P.S. This pattern is particularly well suited to Leo, because the 
> various getPublicCommands methods reference those functions when create 
> command dictionaries.  Here, we replace just two entries in the dict::
>
>     ':r':   vc.LoadFileAtCursor(vc),
>     ':tabnew': vc.Tabnew(vc),
>
> This creates instances of the LoadFileAtCursor and Tabnew classes. In 
> other words, we replace a function by an instance of a class.  All such 
> classes must have __call__ methods, so that Leo can "call" the instance as 
> if it were a function.
>
> 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 leo-editor+unsubscr...@googlegroups.com.
To post to this group, send email to leo-editor@googlegroups.com.
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