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.