The current Keymapping package goes through an initialization process that basically converts the existing TextMorph (and ParagraphEditor) and World keyboard shortcuts to keymap entries. I have listed the converted keyboard shortcuts below. If a TextMorph has focus it will consume any of its keyboard shortcuts. I generally use the "focus follows mouse" preference but I know that a lot of people don't like this. That means that once you've edited some text in a browser, for example, you can activate these shortcuts even if your mouse isn't over the TextMorph. <m-w> is my favorite example (and the one which prompted my choice of preferences). If you have a TextMorph in focus, it will delete a word, otherwise it will close the topmost window. An additional problem is that, as we try to develop services and applications with more rich keyboard shortcuts, we are immediately confronted with needing (or wanting) to avoid the TextMorph's shortcuts in order to avoid the problem above. I see a couple solutions:
1) Try to limit the TextMorph's shortcuts to a smaller list possibly only using the meta- or control- qualifiers (the choice could be platform dependent, this is easy with Keymapping). 2) Somehow make TextMorph shortcuts "lower priority" than other morph's shortcuts. This seems hackish and the implementation would probably be just that.
I am open for other ideas as well. I think #1 is the better of the two options. I package Keymapping with three TextMorph keymaps: "traditional" (the one we have now), "simple" (to be developed) and "emacs" (because some of us old-timers still like twisting our fingers in knots). I am also open to hosting custom keymaps. I need to develop a way to save subsets of keymaps (the current UI saves entire keymaps at once). I'd like suggestions for the "simple" keymap. So, have a look at the list and make suggestions. Keep in mind that I have no plans of removing your favorite keyboard shortcut (it will always be in "traditional") but I can't promise that it won't get eliminated in "simple". Something has to give. If you like, just score the shortcuts you actually use "2" = frequent use, "1" = occasional use. Finally, keep in mind that if you choose to load the "simple" keymap, you can always add you own favorites back in...if they're missing, that is.
Stef has been talking about making Keymapping some kind of official "package" for 3.9 (not included with "base" but maybe with full? Stef?). So, I'm working on commenting the classes and building these packaged keymaps.
Thanks,
David
TextMorph:
<m-home> -> #cursorHome: <m-end> -> #cursorEnd: <m-bs> -> #backspace: <m-pgup> -> #cursorPageUp: <m-pgdn> -> #cursorPageDown: <m-cr> -> #crWithIndent: <m-esc> -> #offerMenuFromEsc: <m-left> -> #cursorLeft: <m-right> -> #cursorRight: <m-up> -> #cursorUp: <m-down> -> #cursorDown: <m-space> -> #selectWord: <ms-"> -> #enclose: <m-'> -> #enclose: <ms-(> -> #enclose: <m-,> -> #shiftEnclose: <m--> -> #changeEmphasis: <m-0> -> #changeEmphasis: <m-1> -> #changeEmphasis: <m-2> -> #changeEmphasis: <m-3> -> #changeEmphasis: <m-4> -> #changeEmphasis: <m-5> -> #changeEmphasis: <m-6> -> #changeEmphasis: <m-7> -> #changeEmphasis: <m-8> -> #changeEmphasis: <m-9> -> #changeEmphasis: <ms-<> -> #enclose: <m-=> -> #changeEmphasis: <m-[> -> #enclose: <m-a> -> #selectAll: <m-b> -> #browseIt: <m-c> -> #copySelection: <m-d> -> #doIt: <m-e> -> #exchange: <m-f> -> #find: <m-g> -> #findAgain: <m-h> -> #setSearchString: <m-i> -> #inspectIt: <m-j> -> #doAgainOnce: <m-k> -> #offerFontMenu: <m-l> -> #cancel: <m-m> -> #implementorsOfIt: <m-n> -> #sendersOfIt: <m-o> -> #spawnIt: <m-p> -> #printIt: <m-q> -> #querySymbol: <m-r> -> #recognizer: <m-s> -> #save: <m-t> -> #tempCommand: <m-u> -> #align: <m-v> -> #paste: <m-x> -> #cut: <m-y> -> #swapChars: <m-z> -> #undo: <ms-{> -> #enclose: <m-del> -> #forwardDelete: <home> -> #cursorHome: <end> -> #cursorEnd: <bs> -> #backspace: <pgup> -> #cursorPageUp: <pgdn> -> #cursorPageDown: <esc> -> #offerMenuFromEsc: <left> -> #cursorLeft: <right> -> #cursorRight: <up> -> #cursorUp: <down> -> #cursorDown: <del> -> #forwardDelete: <ms-A> -> #argAdvance: <ms-B> -> #browseItHere: <ms-C> -> #compareToClipboard: <ms-D> -> #duplicate: <ms-E> -> #methodStringsContainingIt: <ms-F> -> #displayIfFalse: <ms-G> -> #fileItIn: <ms-H> -> #cursorTopHome: <ms-I> -> #exploreIt: <ms-J> -> #doAgainMany: <ms-K> -> #changeStyle: <ms-L> -> #outdent: <ms-M> -> #selectCurrentTypeIn: <ms-N> -> #referencesToIt: <ms-P> -> #makeProjectLink: <ms-R> -> #indent: <ms-S> -> #search: <ms-T> -> #displayIfTrue: <ms-U> -> #changeLfToCr: <ms-V> -> #pasteInitials: <ms-W> -> #methodNamesContainingIt: <ms-X> -> #makeLowercase: <ms-Y> -> #makeUppercase: <ms-Z> -> #makeCapitalized: <c-home> -> #argAdvance: <c-c> -> #compareToClipboard: <c-end> -> #duplicate: <c-bs> -> #cursorTopHome: <c-pgdn> -> #outdent: <c-esc> -> #offerMenuFromEsc: <c-left> -> #cursorLeft: <c-right> -> #cursorRight: <c-up> -> #cursorUp: <c-down> -> #cursorDown: <c-del> -> #forwardDelete:
World:
<esc> -> [:evt :tgt | tgt putUpWorldMenuFromEscapeKey] <m-b> -> Open class browser <m-k> -> Workspace class>>#open <m-m> -> #putUpNewMorphMenu <m-o> -> #activateObjectsTool <m-r> -> #restoreMorphicDisplay <m-t> -> #findATranscript: <m-w> -> SystemWindow class>>#closeTopWindow <m-z> -> #undoOrRedoCommand <ms-C> -> #findAChangeSorter: <ms-F> -> CurrentProjectRefactoring class>>#currentToggleFlapsSuppressed <ms-L> -> #findAFileList: <ms-N> -> #toggleClassicNavigatorIfAppropriate <ms-P> -> #findAPreferencesPanel: <ms-R> -> #openRecentSubmissionsBrowser: <ms-W> -> #findAMessageNamesWindow: <ms-Z> -> ChangeList class>>#browseRecentLog <m-\> -> SystemWindow class>>#sendTopWindowToBack <ms-K> -> KeymapEditor class>>#open <home> -> [:evt :tgt | WorldState addDeferredUIMessage: [tgt keyboardNavigationHandler navigateFromKeystroke: evt keyCharacter] fixTemps] <end> -> [:evt :tgt | WorldState addDeferredUIMessage: [tgt keyboardNavigationHandler navigateFromKeystroke: evt keyCharacter] fixTemps] <bs> -> [:evt :tgt | WorldState addDeferredUIMessage: [tgt keyboardNavigationHandler navigateFromKeystroke: evt keyCharacter] fixTemps] <left> -> [:evt :tgt | WorldState addDeferredUIMessage: [tgt keyboardNavigationHandler navigateFromKeystroke: evt keyCharacter] fixTemps] <right> -> [:evt :tgt | WorldState addDeferredUIMessage: [tgt keyboardNavigationHandler navigateFromKeystroke: evt keyCharacter] fixTemps] <up> -> [:evt :tgt | WorldState addDeferredUIMessage: [tgt keyboardNavigationHandler navigateFromKeystroke: evt keyCharacter] fixTemps] <down> -> [:evt :tgt | WorldState addDeferredUIMessage: [tgt keyboardNavigationHandler navigateFromKeystroke: evt keyCharacter] fixTemps] <space> -> [:evt :tgt | WorldState addDeferredUIMessage: [tgt keyboardNavigationHandler navigateFromKeystroke: evt keyCharacter] fixTemps]
Stef has been talking about making Keymapping some kind of official "package" for 3.9 (not included with "base" but maybe with full? Stef?). So, I'm working on commenting the classes and building these packaged keymaps.
Hi david
Yes I would like to have keymapping as an official full package. So this is excellent that you clean and revise your package.
Now I need feedback on the following wish that is going in my mind. ***Ideally*** I would like that basic Squeak could work without keymapping UI or extra stuff.
What is the *minimal* stuff that we can put in basic that would put in place the architecture to replace the old paragraphEditor table and that could be used by keymapping in full.
Does this idea make sense? I think that this is important to work at the infrastructural level, following the way the filelist got services for tools to register themselves. This is why we will push the services-kernel of romain so that all the browsers can be enhanced by functionality by new tools. I think that this is a good way to support extensibility and modularisation.
Now my question is can we make such infrastructural changes in layered form so that the minimal can be push down and the rest stays at the full level?
Stef
stéphane ducasse wrote:
Hi david
Yes I would like to have keymapping as an official full package. So this is excellent that you clean and revise your package.
Now I need feedback on the following wish that is going in my mind. ***Ideally*** I would like that basic Squeak could work without keymapping UI or extra stuff.
Yes, I think that this is ideal.
What is the *minimal* stuff that we can put in basic that would put in place the architecture to replace the old paragraphEditor table and that could be used by keymapping in full.
As a first step one can look at the only two overrides in Keymapping (for 3.8) below. This doesn't get us too far but it makes Keymapping pluggable and removes overrides (which really irritate me).
Morph>>handleKeystroke: anEvent "System level event handling." KeymapManager debugEvent: anEvent message: self printString. anEvent wasHandled ifTrue: [^ self]. self allowsKeymapping ifTrue: [self dispatchKeystrokeToKeymappers: anEvent. anEvent wasHandled ifTrue: [^ self]]. (self handlesKeyboard: anEvent) ifFalse: [^ self]. anEvent wasHandled: true. ^ self keyStroke: anEvent
and
TextMorph>>handleKeystroke: anEvent "System level event handling." | pasteUp | KeymapManager debugEvent: anEvent message: self printString. anEvent wasHandled ifTrue: [^ self]. (self handlesKeyboard: anEvent) ifFalse: [^ self]. self allowsKeymapping ifTrue: [self dispatchKeystrokeToKeymappers: anEvent. anEvent wasHandled ifTrue: [^ self]]. anEvent wasHandled: true. anEvent keyCharacter = Character tab ifTrue: ["Allow passing through text morph inside pasteups" (self wouldAcceptKeyboardFocusUponTab and: [(pasteUp := self pasteUpMorphHandlingTabAmongFields) notNil]) ifTrue: [^ pasteUp tabHitWithEvent: anEvent]]. self keyStroke: anEvent
Note that (ignoring the debugging code) the check "self allowsKeymapping ifTrue: []" basically wraps the Keymapping specific code. So if the base image included (in Morph):
allowsKeymapping ^false
and then invoked the (unimplemented) method dispatchKeystrokeToKeymappers: as I do above my package would only have to add that method to Morph. If we wanted a registry model we could implement dispatchKeystrokeToKeymappers: as
dispatchKeystrokeToKeymappers: anEvent self registeredKeymappers do: [:each | each dispatchKeystrokeToKeymappers: anEvent for: self]
where registeredKeymappers answers the collection of all registered keymappers (do we really need to support multiple mappers?):
registeredKeymappers ^self class registeredKeymappers
and then the obvious Morph class side methods (and variable) to register them. When my tools are loaded I'd register and off we go. Want me to submit a changeset against 3.9a for your consideration?
Does this idea make sense? I think that this is important to work at the infrastructural level, following the way the filelist got services for tools to register themselves. This is why we will push the services-kernel of romain so that all the browsers can be enhanced by functionality by new tools. I think that this is a good way to support extensibility and modularisation.
I'd like to comment on this further but have to step out. I think what we're talking about is a good first step though. It doesn't really make Keymapping "pluggable" but it does get rid of overrides and makes it optional (with KM you'll just get the ParagraphEditor shortcuts).
Now my question is can we make such infrastructural changes in layered form so that the minimal can be push down and the rest stays at the full level?
See sugestion above.
David
and then the obvious Morph class side methods (and variable) to register them. When my tools are loaded I'd register and off we go. Want me to submit a changeset against 3.9a for your consideration?
I would like to hear other voices, but yes a step in that direction make sense to me. I really think that we should move towards such kind of infrastructural changes - eventNotification - services - toolRegistry - keymapping.... and the kernel should support the basic classes enabling that while UI and other more advanced logic should be built on top.
Stef
On 1 oct. 05, at 21:33, David Shaffer wrote:
TextMorph:
<m-home> -> #cursorHome: <m-end> -> #cursorEnd: <m-bs> -> #backspace: <m-pgup> -> #cursorPageUp: <m-pgdn> -> #cursorPageDown: <m-cr> -> #crWithIndent: <m-esc> -> #offerMenuFromEsc: <m-left> -> #cursorLeft: <m-right> -> #cursorRight: <m-up> -> #cursorUp: <m-down> -> #cursorDown: <m-space> -> #selectWord: <ms-"> -> #enclose: <m-'> -> #enclose: <ms-(> -> #enclose: <m-,> -> #shiftEnclose: <m--> -> #changeEmphasis: <m-0> -> #changeEmphasis: <m-1> -> #changeEmphasis: <m-2> -> #changeEmphasis: <m-3> -> #changeEmphasis: <m-4> -> #changeEmphasis: <m-5> -> #changeEmphasis: <m-6> -> #changeEmphasis: <m-7> -> #changeEmphasis: <m-8> -> #changeEmphasis: <m-9> -> #changeEmphasis: <ms-<> -> #enclose: <m-=> -> #changeEmphasis: <m-[> -> #enclose:
2 <m-a> -> #selectAll: 2 <m-b> -> #browseIt: 2 <m-c> -> #copySelection: 2<m-d> -> #doIt: <m-e> -> #exchange: <m-f> -> #find: <m-g> -> #findAgain:
replace is missing ;)
<m-h> -> #setSearchString: 2 <m-i> -> #inspectIt: <m-j> -> #doAgainOnce: <m-k> -> #offerFontMenu: <m-l> -> #cancel: 2 <m-m> -> #implementorsOfIt: 2 <m-n> -> #sendersOfIt: <m-o> -> #spawnIt: 2 <m-p> -> #printIt: <m-q> -> #querySymbol: <m-r> -> #recognizer: <m-s> -> #save: <m-t> -> #tempCommand: <m-u> -> #align: <m-v> -> #paste: <m-x> -> #cut: <m-y> -> #swapChars: <m-z> -> #undo: <ms-{> -> #enclose: <m-del> -> #forwardDelete: <home> -> #cursorHome: <end> -> #cursorEnd:
end of line ?
<bs> -> #backspace: <pgup> -> #cursorPageUp: <pgdn> -> #cursorPageDown: <esc> -> #offerMenuFromEsc: <left> -> #cursorLeft: <right> -> #cursorRight: <up> -> #cursorUp: <down> -> #cursorDown: <del> -> #forwardDelete: <ms-A> -> #argAdvance: <ms-B> -> #browseItHere: <ms-C> -> #compareToClipboard: <ms-D> -> #duplicate: <ms-E> -> #methodStringsContainingIt: <ms-F> -> #displayIfFalse: <ms-G> -> #fileItIn: <ms-H> -> #cursorTopHome: <ms-I> -> #exploreIt: <ms-J> -> #doAgainMany: <ms-K> -> #changeStyle: <ms-L> -> #outdent: <ms-M> -> #selectCurrentTypeIn: <ms-N> -> #referencesToIt: <ms-P> -> #makeProjectLink: <ms-R> -> #indent: <ms-S> -> #search: <ms-T> -> #displayIfTrue: <ms-U> -> #changeLfToCr: <ms-V> -> #pasteInitials: <ms-W> -> #methodNamesContainingIt: <ms-X> -> #makeLowercase: <ms-Y> -> #makeUppercase: <ms-Z> -> #makeCapitalized: <c-home> -> #argAdvance: <c-c> -> #compareToClipboard: <c-end> -> #duplicate: <c-bs> -> #cursorTopHome: <c-pgdn> -> #outdent: <c-esc> -> #offerMenuFromEsc: <c-left> -> #cursorLeft: <c-right> -> #cursorRight: <c-up> -> #cursorUp: <c-down> -> #cursorDown: <c-del> -> #forwardDelete:
World:
<esc> -> [:evt :tgt | tgt putUpWorldMenuFromEscapeKey] 2 <m-b> -> Open class browser <m-k> -> Workspace class>>#open <m-m> -> #putUpNewMorphMenu <m-o> -> #activateObjectsTool <m-r> -> #restoreMorphicDisplay <m-t> -> #findATranscript: <m-w> -> SystemWindow class>>#closeTopWindow <m-z> -> #undoOrRedoCommand <ms-C> -> #findAChangeSorter: <ms-F> -> CurrentProjectRefactoring class>>#currentToggleFlapsSuppressed <ms-L> -> #findAFileList: <ms-N> -> #toggleClassicNavigatorIfAppropriate <ms-P> -> #findAPreferencesPanel: <ms-R> -> #openRecentSubmissionsBrowser: <ms-W> -> #findAMessageNamesWindow: <ms-Z> -> ChangeList class>>#browseRecentLog <m-\> -> SystemWindow class>>#sendTopWindowToBack <ms-K> -> KeymapEditor class>>#open <home> -> [:evt :tgt | WorldState addDeferredUIMessage: [tgt keyboardNavigationHandler navigateFromKeystroke: evt keyCharacter] fixTemps] <end> -> [:evt :tgt | WorldState addDeferredUIMessage: [tgt keyboardNavigationHandler navigateFromKeystroke: evt keyCharacter] fixTemps] <bs> -> [:evt :tgt | WorldState addDeferredUIMessage: [tgt keyboardNavigationHandler navigateFromKeystroke: evt keyCharacter] fixTemps] <left> -> [:evt :tgt | WorldState addDeferredUIMessage: [tgt keyboardNavigationHandler navigateFromKeystroke: evt keyCharacter] fixTemps] <right> -> [:evt :tgt | WorldState addDeferredUIMessage: [tgt keyboardNavigationHandler navigateFromKeystroke: evt keyCharacter] fixTemps] <up> -> [:evt :tgt | WorldState addDeferredUIMessage: [tgt keyboardNavigationHandler navigateFromKeystroke: evt keyCharacter] fixTemps] <down> -> [:evt :tgt | WorldState addDeferredUIMessage: [tgt keyboardNavigationHandler navigateFromKeystroke: evt keyCharacter] fixTemps] <space> -> [:evt :tgt | WorldState addDeferredUIMessage: [tgt keyboardNavigationHandler navigateFromKeystroke: evt keyCharacter] fixTemps]
Am 01.10.2005 um 22:10 schrieb stéphane ducasse:
On 1 oct. 05, at 21:33, David Shaffer wrote:
<m-g> -> #findAgain:
replace is missing ;)
I think I remember that there is replace in Squeak somewhere... but hidden, like it should be in a system that is only supposed to be usable for the enlightend. ;-)
Here's an explanation from 1999: http://lists.squeakfoundation.org/pipermail/squeak-dev/1999-September/ 017515.html
The functionality is already there; it's just not obvious. To perform a "find and replace", you first do a find (cmd-f), then type in the replacement over the selection. You can then do a (cmd-j) to find and replace the next occurance, or (ctrl-j) to find and replace all remaining occurances.
Of course, we may rethink the decicion to do it differently than anyone else...
Marcus
squeak-dev@lists.squeakfoundation.org