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.
