The following is an Engineering Notebook post.  Please read carefully if 
you write plugins or are one of Leo's core developers.  Everyone else can 
safely ignore this post.

The present (g.new_dispatch) project simplifies Leo's code as follows:

1. Decorators will define all Leo commands.  All getPublicCommands methods 
will disappear, along with their association lists of command names and 
bound methods.

2. Leo will never call c.universalCallback.

I understand neither it's docstring, nor its code, nor why it is needed. 
Leo will be better off without it and the corresponding 'wrap' argument to 
k.registerCommand. This wrapper gives rise to wretched code:

@g.command('cke-text-open')
def cmd_OpenEditor(kwargs, at_rich=False):
    '''Open the rich text editor, hide the regular editor.'''
    c = kwargs['c'] if isinstance(kwargs, dict) else kwargs

Apparently, kwargs might be two different kinds of objects depending on who 
calls the function.  This kind of code *must go*.  In an emergency, code 
could add ivars/attributes to exiting events, but even that would be too 
complex by half.

3. The Plugin class in plugins_menu.py creates Leo commands for functions 
whose names start with cmd_.  It took me hours yesterday to figure out that 
this was happening.

<< Look for additional commands >> creates yet another wrapper, with yet 
another signature. The wrapper now has a more conforming signature and a 
better name:

def plugins_menu_wrapper(kwargs, cmd=cmd):
    return cmd(kwargs['c'])

This signature allows a unit test to pass even when plugins_menu_wrapper is 
not wrapped *again*.

Happily, all of this is going to go away.  @g.command will define all 
commands in plugins. No more invisible cmd_ naming convention.

4. class AtButtonCallback now supports the __name__ attribute using a new 
__getattr__ method. This allows k.registerCommand *not *to know about the 
AtButtonCallback wrapper.

5. The LeoKeyEvent class now has a get method.  Code can now call 
event.get('c') in all cases.  Probably ditto for kwargs.get('c').

*Summary*

The new_dispatch project simplifies some of the most complex code in Leo.  
It is worth a week's work.

I followed three principles while simplifying the code:

1. *Eliminate malignant if statements*.

    c = kwargs['c'] if isinstance(kwargs, dict) else kwargs

proliferates implementation details from one part of Leo to another.  As a 
result, it becomes much harder to change code without side effects.  I have 
been dealing with such side effects all week.

This is only the most egregious example.  I have been casting out "if" 
statements wherever possible.

2. *Regularize interfaces*.

- @cmd or @g.command decorators will define all Leo commands.
- The cmd_ convention will disappear, along with the complex code that 
creates it.
- event.get('c') will work in any code decorated by @cmd or @g.command.
- AtButtonCallback instances now have a __name__.

3. *Regularize objects*.

Changing the interface of an object by wrapping it is unacceptable. 
c.universalCallback must go. 

That's all for now. All comments welcome.

Edward

-- 
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