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.