Why not just have .s attribute in KeyStroke, that contains the string version?


On 5.2.2012 11:36 Edward K. Ream wrote:

The following are mostly notes to myself (and to future maintainers).
Feel free to ignore.

Rev 4972 demonstrates that the KeyStroke class can indeed distinguish
between "raw" user settings and the "canonicalized" form used
throughout Leo. Indeed, the ability to explicitly distinguish between
the two, using type checking, has already substantially clarified and
simplified the code.

BTW, this is in no way a violation of OO principles. The code is not
dispatching on the type of objects, it is merely enforcing vital
consistency checks. This code is complex: confusion about the types
of objects is intolerable. Happily, the resulting clarity allows the
code to be substantially simpler than it would otherwise be, which in
turn clarifies the code further, and so on...

Part 1: This work is vital

As described below, the forthcoming work will lead to a cascade of
other simplification. These simplifications are important for at
least three, reasons:

1. The code must be simplified so that future maintainers (including
me) will have an easier time of it.

2. The present code provides no real help in creating unit tests that
test how Leo handles keystrokes.

3. Simplifying the code will provide a more solid foundation for vim-
related bindings.


Part 2: Notes about the KeyStroke class

Objects of the KeyStroke class can be used *exactly* as a strings may
be used:

A. KeyStroke objects may be used as dictionary keys, because they
have __hash__ methods and all the so-called rich comparison methods:
__eq__, __ne__, __ge__, __gt__, __le__ and __lt__. Note that
KeyStroke objects may be compared with other KeyStroke objects,
strings and None.

B. At present, KeyStroke objects supports the find, lower and
startswith methods. This simplifies the code substantially: we can
apply these methods to either strings or KeyStroke objects, so there
is no need to create different versions of the code depending on the
value of g.new_strokes.

However, having the KeyStroke class support string methods is bad
design. Indeed, it is a symptom that the client code that uses
KeyStroke objects knows too much about the internals of KeyStroke
objects. Instead, the KeyStroke class should have higher-level
methods that use s.find, s.lower and s.startswith internally.

You could say that the fact that code in leoKeys.py calls s.find,
s.lower and s.startswith is a symptom of non OO programming. The
internal details of settings and strokes "pollutes" the code. This
must be fixed. This will likely create opportunities for further
simplifications.


Part 3: Other design changes

The present work, enabled and disabled with g.new_strokes, has been a
resounding success. The next steps will be as follows:

Better packaging.

g.new_strokes, g.isStroke and g.isStrokeOrNone should be defined in
leoKeys.py, not leoGlobals.py.
I knew from the start that such global names were only a temporary
expedient.

Now I know where they should go. leoKeys.py, not leoConfig.py, is the
proper place to handle all the details about key bindings. Indeed the
code in leoConfig.py simply parses user key settings into *strings*.
These raw strings must be converted to KeyStroke objects by
leoKeys.py.

As a result, the KeyStroke class (and the ShortcutInfo class?) should
be defined in leoKeys.py, not leoConfig.py. To make this work, we'll
want to create several factory methods: k.makeKeyStroke and
k.makeShortcutInfo.

Better separation of concerns.

The Qt key input code can be hugely simplified by calling a new
k.makeKeyStrokeFromData factory method. At present, the Qt key input
code knows *all* the details of the format of *canonicalized*
settings. This is absolutely wretched design.

Instead, the Qt input key code should simply pass the key modifiers
and other key information to k.makeKeyStrokeFromData, in a some kind
of "easy" format. For example, the Qt input key code would represent
the internal Qt modifiers as lists of strings like "alt", "ctrl",
"meta", "shift". k.makeKeyStrokeFromData would then create a *user*
setting from the components, and then call k.strokeFromSetting to
complete the transformation.

As I said in another thread, the present Qt input key code is
entangled with other code. I'll have to disentangle the code before
putting this scheme into effect.

Other classes

The easiest next step will be to integrate the presently unused
ShortcutsDict class into the code. This will eliminate the wretched
special cases for the _hash key.


Part 4: Conclusions

I have high hopes that we will see wave after wave of
simplifications. Much of the difficult work presently scattered in a
non-OO fashion throughout leoKeys.py, leoConfig.py and leoQtGui.py
will migrate to become KeyStroke methods (or methods of other
classes).

The KeyStroke class has already made possible vital type-related
assertions. Knowing *for sure* exactly what crucial data is and what
it means is a huge step forward. More steps are coming.

Edward

-- 
You received this message because you are subscribed to the Google Groups 
"leo-editor" group.
To post to this group, send email to [email protected].
To unsubscribe from this group, send email to 
[email protected].
For more options, visit this group at 
http://groups.google.com/group/leo-editor?hl=en.



-- 
You received this message because you are subscribed to the Google Groups 
"leo-editor" group.
To post to this group, send email to [email protected].
To unsubscribe from this group, send email to 
[email protected].
For more options, visit this group at 
http://groups.google.com/group/leo-editor?hl=en.

Reply via email to