* Enhancements to "minor-mode-map-alist" functionality. @ 2002-04-11 22:56 Kim F. Storm 2002-04-11 22:43 ` Stefan Monnier 2002-04-13 19:05 ` Richard Stallman 0 siblings, 2 replies; 46+ messages in thread From: Kim F. Storm @ 2002-04-11 22:56 UTC (permalink / raw) I'm almost done reworking cua-mode to use the command remapping feature, and it is much cleaner than the old package. However, the new cua package need to make some quite ugly modifications to the minor-mode-map-alist (in the post-command-hook) after _every_ command, since: - the new cua need a total of 7 minor mode keymaps, which must be processed in a specific order, and before all other minor mode keymaps - the selection of which of these minor mode keymaps are active may depend on the values of as many as 6 different variables for a single keymap However, this can be dramatically simplified by two (simple) enhancements to the minor-mode-map-alist functionality: 1) Provide a separate emulation-mode-map-alists variable where modes like cua can insert their own mode-map-alist, 2) Allow selection of the active keymaps in the alist to be based on evaluating a form in addition to a simple variable. I have already implemented these features (see attached patch), which allows me to configure all the minor mode keymaps needed by cua once and for all: (setq cua--emulation-map-alist `((lambda . (and mark-active cua-enable-cua-keys (or (eq cua-enable-cua-keys t) (not cua--explicit-region-start)) (not executing-kbd-macro) (not cua--prefix-override-timer) '(cua--prefix-override . ,cua--prefix-override-keymap))) (lambda . (and mark-active (timerp cua--prefix-override-timer) '(cua--prefix-override . ,cua--prefix-repeat-keymap))) (lambda . (and (or (eq cua-enable-cua-keys t) cua--last-region-shifted) '(cua-enable-cua-keys . ,cua--cua-keys-keymap))) (lambda . (and cua--global-mark-active (not (window-minibuffer-p)) '(cua--global-mark-active . ,cua--global-mark-keymap))) (cua--rectangle . ,cua--rectangle-keymap) (mark-active . ,cua--region-keymap) (cua-mode . ,cua-global-keymap))) (setq emulation-mode-map-alists (cons cua--emulation-map-alist emulation-mode-map-alists)) On the user visible part, this is added to the doc string for minor-mode-map-alist: Alternatively, an element may look like (lambda . FORM) where FORM is evaluated and should return either nil or a cons (SYMBOL . KEYMAP); in this case, KEYMAP is used unconditionally and SYMBOL is displayed by `describe-bindings' as the variable controlling KEYMAP. The doc string for emulation-mode-map-alists reads: List of keymap alists to use for emulations modes. It is intended for modes or packages using multiple minor-mode keymaps. Each element is a keymap alist just like `minor-mode-map-alist', and it is used the same way. The "active" keymaps in this alist are used before `minor-mode-map-alist' but after `minor-mode-overriding-map-alist'. Here is the patch which I expect to commit in a few days (when I install the new version of cua mode). Index: keymap.c =================================================================== RCS file: /cvs/emacs/src/keymap.c,v retrieving revision 1.258 diff -c -r1.258 keymap.c *** keymap.c 24 Feb 2002 00:23:20 -0000 1.258 --- keymap.c 11 Apr 2002 21:54:34 -0000 *************** *** 75,80 **** --- 75,83 ---- minor mode variables and keymaps. */ Lisp_Object Vminor_mode_overriding_map_alist; + /* List of emulation mode keymap alists. */ + Lisp_Object Vemulation_mode_map_alists; + /* Keymap mapping ASCII function key sequences onto their preferred forms. Initialized by the terminal-specific lisp files. See DEFVAR for more documentation. */ *************** *** 1277,1358 **** { int i = 0; int list_number = 0; ! Lisp_Object alist, assoc, var, val; ! Lisp_Object lists[2]; ! lists[0] = Vminor_mode_overriding_map_alist; ! lists[1] = Vminor_mode_map_alist; ! for (list_number = 0; list_number < 2; list_number++) ! for (alist = lists[list_number]; ! CONSP (alist); ! alist = XCDR (alist)) ! if ((assoc = XCAR (alist), CONSP (assoc)) ! && (var = XCAR (assoc), SYMBOLP (var)) ! && (val = find_symbol_value (var), !EQ (val, Qunbound)) ! && !NILP (val)) ! { ! Lisp_Object temp; ! ! /* If a variable has an entry in Vminor_mode_overriding_map_alist, ! and also an entry in Vminor_mode_map_alist, ! ignore the latter. */ ! if (list_number == 1) { ! val = assq_no_quit (var, lists[0]); ! if (!NILP (val)) ! continue; } ! if (i >= cmm_size) ! { ! Lisp_Object *newmodes, *newmaps; ! /* Use malloc/realloc here. See the comment above ! this function. */ ! if (cmm_maps) ! { ! BLOCK_INPUT; ! cmm_size *= 2; ! newmodes ! = (Lisp_Object *) realloc (cmm_modes, ! cmm_size * sizeof *newmodes); ! newmaps ! = (Lisp_Object *) realloc (cmm_maps, ! cmm_size * sizeof *newmaps); ! UNBLOCK_INPUT; ! } ! else ! { ! BLOCK_INPUT; ! cmm_size = 30; ! newmodes ! = (Lisp_Object *) malloc (cmm_size * sizeof *newmodes); ! newmaps ! = (Lisp_Object *) malloc (cmm_size * sizeof *newmaps); ! UNBLOCK_INPUT; ! } ! if (newmodes) ! cmm_modes = newmodes; ! if (newmaps) ! cmm_maps = newmaps; ! ! if (newmodes == NULL || newmaps == NULL) ! break; } ! /* Get the keymap definition--or nil if it is not defined. */ ! temp = internal_condition_case_1 (Findirect_function, ! XCDR (assoc), ! Qerror, current_minor_maps_error); ! if (!NILP (temp)) ! { ! cmm_modes[i] = var; ! cmm_maps [i] = temp; ! i++; ! } } if (modeptr) *modeptr = cmm_modes; if (mapptr) *mapptr = cmm_maps; --- 1280,1397 ---- { int i = 0; int list_number = 0; ! Lisp_Object alist, assoc, var, val, emul_list; ! ! emul_list = Vemulation_mode_map_alists; ! alist = Vminor_mode_overriding_map_alist; ! ! next_alist: ! for ( ; CONSP (alist); alist = XCDR (alist)) ! { ! Lisp_Object temp; ! ! if (assoc = XCAR (alist), !CONSP (assoc)) ! continue; ! ! /* Each element in the alist is a CONS cell: ! The form (VAR . KEYMAP) causes the KEYMAP to be included if the ! VAR is defined an non-nil. ! The form (lambda . FORM) evaluates the FORM which shall result in ! nil or a CONS cell (SYMBOL . KEYMAP) where the KEYMAP is included ! unconditionally (as associated with the specified SYMBOL. */ ! ! var = XCAR (assoc); ! ! if (EQ (var, Qlambda)) ! { ! if ((temp = XCDR (assoc), NILP (temp)) ! || (assoc = safe_eval (temp), !CONSP (assoc)) ! || (var = XCAR (assoc), !SYMBOLP (var))) ! continue; ! } ! else ! { ! if (!SYMBOLP (var) ! || (val = find_symbol_value (var), EQ (val, Qunbound)) ! || NILP (val)) ! continue; ! } ! /* If a variable has an entry in Vminor_mode_overriding_map_alist, ! and also an entry in Vminor_mode_map_alist, ignore the latter. */ ! if (list_number == 2) ! { ! val = assq_no_quit (var, Vminor_mode_overriding_map_alist); ! if (!NILP (val)) ! continue; ! } ! if (i >= cmm_size) ! { ! Lisp_Object *newmodes, *newmaps; ! ! /* Use malloc/realloc here. See the comment above ! this function. */ ! if (cmm_maps) ! { ! BLOCK_INPUT; ! cmm_size *= 2; ! newmodes = (Lisp_Object *) realloc (cmm_modes, ! cmm_size * sizeof *newmodes); ! newmaps = (Lisp_Object *) realloc (cmm_maps, ! cmm_size * sizeof *newmaps); ! UNBLOCK_INPUT; ! } ! else { ! BLOCK_INPUT; ! cmm_size = 30; ! newmodes = (Lisp_Object *) malloc (cmm_size * sizeof *newmodes); ! newmaps = (Lisp_Object *) malloc (cmm_size * sizeof *newmaps); ! UNBLOCK_INPUT; } ! if (newmodes) ! cmm_modes = newmodes; ! if (newmaps) ! cmm_maps = newmaps; ! ! if (newmodes == NULL || newmaps == NULL) ! break; ! } ! /* Get the keymap definition--or nil if it is not defined. */ ! temp = internal_condition_case_1 (Findirect_function, ! XCDR (assoc), ! Qerror, current_minor_maps_error); ! if (!NILP (temp)) ! { ! cmm_modes[i] = var; ! cmm_maps [i] = temp; ! i++; ! } ! } ! if (list_number < 2) ! { ! while (CONSP (emul_list)) ! { ! alist = XCAR (emul_list); ! emul_list = XCDR (emul_list); ! if (CONSP (alist)) ! { ! list_number = 1; ! goto next_alist; } + } ! alist = Vminor_mode_map_alist; ! if (CONSP (alist)) ! { ! list_number = 2; ! goto next_alist; } + } if (modeptr) *modeptr = cmm_modes; if (mapptr) *mapptr = cmm_maps; *************** *** 3568,3583 **** doc: /* Alist of keymaps to use for minor modes. Each element looks like (VARIABLE . KEYMAP); KEYMAP is used to read key sequences and look up bindings iff VARIABLE's value is non-nil. If two active keymaps bind the same key, the keymap appearing earlier in the list takes precedence. */); Vminor_mode_map_alist = Qnil; DEFVAR_LISP ("minor-mode-overriding-map-alist", &Vminor_mode_overriding_map_alist, doc: /* Alist of keymaps to use for minor modes, in current major mode. ! This variable is a alist just like `minor-mode-map-alist', and it is ! used the same way (and before `minor-mode-map-alist'); however, ! it is provided for major modes to bind locally. */); Vminor_mode_overriding_map_alist = Qnil; DEFVAR_LISP ("function-key-map", &Vfunction_key_map, doc: /* Keymap mapping ASCII function key sequences onto their preferred forms. --- 3607,3635 ---- doc: /* Alist of keymaps to use for minor modes. Each element looks like (VARIABLE . KEYMAP); KEYMAP is used to read key sequences and look up bindings iff VARIABLE's value is non-nil. + Alternatively, an element may look like (lambda . FORM) where FORM is + evaluated and should return either nil or a cons (SYMBOL . KEYMAP); + in this case, KEYMAP is used unconditionally and SYMBOL is displayed + by `describe-bindings' as the variable controlling KEYMAP. If two active keymaps bind the same key, the keymap appearing earlier in the list takes precedence. */); Vminor_mode_map_alist = Qnil; DEFVAR_LISP ("minor-mode-overriding-map-alist", &Vminor_mode_overriding_map_alist, doc: /* Alist of keymaps to use for minor modes, in current major mode. ! This variable is an alist just like `minor-mode-map-alist', and it is ! used the same way (and before `minor-mode-map-alist' and alists in ! `emulation-mode-map-alists'); however, it is provided for ! major modes to bind locally. */); Vminor_mode_overriding_map_alist = Qnil; + + DEFVAR_LISP ("emulation-mode-map-alists", &Vemulation_mode_map_alists, + doc: /* List of keymap alists to use for emulations modes. + It is intended for modes or packages using multiple minor-mode keymaps. + Each element is a keymap alist just like `minor-mode-map-alist', and it + is used the same way. The "active" keymaps in this alist are used before + `minor-mode-map-alist' but after `minor-mode-overriding-map-alist'. */); + Vemulation_mode_map_alists = Qnil; DEFVAR_LISP ("function-key-map", &Vfunction_key_map, doc: /* Keymap mapping ASCII function key sequences onto their preferred forms. ^ permalink raw reply [flat|nested] 46+ messages in thread
* Re: Enhancements to "minor-mode-map-alist" functionality. 2002-04-11 22:56 Enhancements to "minor-mode-map-alist" functionality Kim F. Storm @ 2002-04-11 22:43 ` Stefan Monnier 2002-04-12 9:31 ` Kim F. Storm 2002-04-13 19:05 ` Richard Stallman 1 sibling, 1 reply; 46+ messages in thread From: Stefan Monnier @ 2002-04-11 22:43 UTC (permalink / raw) Cc: emacs-devel > However, this can be dramatically simplified by two (simple) > enhancements to the minor-mode-map-alist functionality: > > 1) Provide a separate emulation-mode-map-alists variable where > modes like cua can insert their own mode-map-alist, As you probably know, I'm not too excited about this, since it shouldn't be necessary if we could enforce a bit more discipline in the way entries are added to minor-mode-map-alist. [ Yes, I wish we had "watchers" so we could trap modifications of particular variables. ] But I guess that I can live with it. BTW, should emulation-mode-map-alists take precedence over minor-mode-overriding-map-alist or not ? Also, have you contacted Michael Kifer to see if that would satisfy his needs for viper (I know he also had to do some funky post-command fiddling of the minor-mode-map-alist). > 2) Allow selection of the active keymaps in the alist to > be based on evaluating a form in addition to a simple variable. I generally like the idea of having the keymaps more dynamic, but I'd rather not add another form of dynamism that isn't quite good enough for everything. To be more precise, currently you can get the above "select the keymap dynamically" in a more generic way (i.e. not just for minor mode maps) by using an entry of the form: '(menu-item "foo" data :filter fun) It is mostly used for dynamic menus, but also works in other keymaps. Problem is, it only works for submaps because it is not itself a keymap and thus can't be used for a toplevel map. So if the dynamism you need is only in the `command-remap' submap, for example, your new hack is not needed. I'd rather not add a hack that's specific to minor-mode-map-alist if we could do the same for all cases instead. > I have already implemented these features (see attached patch), > which allows me to configure all the minor mode keymaps needed > by cua once and for all: In the patch, you end up evaluating elisp code from a function that already has a comment about the fact that it needs to be extra-careful about memory allocation. Also I'm not sure that all places that call this function are ready to have elisp code executed at that point (you might need some GCPROs added here and there). In other words, maybe we shouldn't evaluate the form inside this current_minor_maps function. Stefan PS: by the way, isn't it enough to fiddle with minor-mode-map-alist in after-load-hook rather than in post-command-hook ? [ assuming we had such an after-load-hook. ] ^ permalink raw reply [flat|nested] 46+ messages in thread
* Re: Enhancements to "minor-mode-map-alist" functionality. 2002-04-11 22:43 ` Stefan Monnier @ 2002-04-12 9:31 ` Kim F. Storm 2002-04-12 13:20 ` Kim F. Storm ` (2 more replies) 0 siblings, 3 replies; 46+ messages in thread From: Kim F. Storm @ 2002-04-12 9:31 UTC (permalink / raw) Cc: emacs-devel "Stefan Monnier" <monnier+gnu/emacs@rum.cs.yale.edu> writes: > > However, this can be dramatically simplified by two (simple) > > enhancements to the minor-mode-map-alist functionality: > > > > 1) Provide a separate emulation-mode-map-alists variable where > > modes like cua can insert their own mode-map-alist, > > As you probably know, I'm not too excited about this, since it shouldn't > be necessary if we could enforce a bit more discipline in the way > entries are added to minor-mode-map-alist. I doubt we can find a way to enforce that. > [ Yes, I wish we had "watchers" so we could trap modifications of > particular variables. ] > Which would still not ensure anything -- if multiple packages are watching minor-mode-map-alist and rearranges it, we'd still not be able to _ensure_ any specific ordering... > But I guess that I can live with it. Good :-) > > BTW, should emulation-mode-map-alists take precedence over > minor-mode-overriding-map-alist or not ? Based on the two existing uses of minor-mode-overriding-map-alist, I don't think it matters much, but e-m-m-a should probably take precedence over m-m-o-m-a... I'll change that. > > Also, have you contacted Michael Kifer to see if that would satisfy his > needs for viper (I know he also had to do some funky post-command > fiddling of the minor-mode-map-alist). > As far as I can see, it is _exactly_ the same problem (viper has 9 keymaps). > > 2) Allow selection of the active keymaps in the alist to > > be based on evaluating a form in addition to a simple variable. > > I generally like the idea of having the keymaps more dynamic, > but I'd rather not add another form of dynamism that isn't quite > good enough for everything. To be more precise, currently you can get > the above "select the keymap dynamically" in a more generic way > (i.e. not just for minor mode maps) by using an entry of the form: > > '(menu-item "foo" data :filter fun) > > It is mostly used for dynamic menus, but also works in other keymaps. > Problem is, it only works for submaps because it is not itself > a keymap and thus can't be used for a toplevel map. I need this at the top-level maps, so it is not applicable here. But if we could support something like (keymap :filter fun ...), it would satisfy the needs for cua. > So if the dynamism you need is only in the `command-remap' submap, > for example, your new hack is not needed. I don't think this is a hack! If so, the minor-mode-map-alist itself is a hack, since it has several obvious limitations. One of which is remedied by the minor-mode-overriding-map-alist! Actually, we could discard that feature (don't say that we should) and use either the dynamic keymap selection suggested, e.g. From diff-mode.el: ;; Neat trick from Dave Love to add more bindings in read-only mode: (add-to-list (make-local-variable 'minor-mode-overriding-map-alist) (cons 'buffer-read-only diff-mode-shared-map)) could be replaced by: ;; Neat trick from Dave Love to add more bindings in read-only mode: (add-to-list 'minor-mode-map-alist `(lambda . (and diff-minor-mode buffer-read-only '(diff-minor-mode . ,diff-mode-shared-map)))) Or maybe a simple command remapping the the buffer's local map would do just as well, e.g. From help-mode.el: ;; View mode steals RET from us. (set (make-local-variable 'minor-mode-overriding-map-alist) (list (cons 'view-mode (let ((map (make-sparse-keymap))) (set-keymap-parent map view-mode-map) (define-key map "\r" 'help-follow) map)))) could simply be ;; View mode steals RET from us. (local-set-key [remap View-scroll-line-forward] 'help-follow) [Actually, I think I'll install that change in any case]. That's the two uses of minor-mode-overriding-map-alist I could find. > > I'd rather not add a hack that's specific to minor-mode-map-alist > if we could do the same for all cases instead. > Sure. But what device do you suggest then? (keymap :filter fun ...) ? I don't object to that, but it would be _less_ efficient, since we have to search the keymap for the :filter property (like we do for a menu-item, but that is much shorter) [unless we ensure it stays at the head of the keymap list]. Also, the keymap lookup code would also have to be careful not to interpret the FUN part as a binding, and when we add binding to a map, we should be careful not to split the ":filter FUN" pair. > > I have already implemented these features (see attached patch), > > which allows me to configure all the minor mode keymaps needed > > by cua once and for all: > > In the patch, you end up evaluating elisp code from a function > that already has a comment about the fact that it needs to be extra-careful > about memory allocation. I know, but given the other options, I would expect this to do a lot less memory allocations (if any!) than the alternative (of regenerating minor-mode-map-alist after every command - and setting the 9 destinct variables needed to control it - as viper does [more or less]). In my case (cua), I don't think I make any memory allocations there at all since I only test a number of variables -- not modify anything. > Also I'm not sure that all places that call this > function are ready to have elisp code executed at that point (you might > need some GCPROs added here and there). As I've pointed out before, a lot of functions in keymap already lack proper GCPROs due to the autoload enhancements to get_keymap... And now you tell me that get_keyelt can GC as well... I don't see any GCPROs related to that either... So GC-wise this only makes things marginally worse :-/ > > In other words, maybe we shouldn't evaluate the form inside this > current_minor_maps function. > I still think it is pretty safe to do so. But I think it would be better to use menu_item_eval_property than safe_eval for this purpose. > > Stefan > > PS: by the way, isn't it enough to fiddle with minor-mode-map-alist > in after-load-hook rather than in post-command-hook ? > [ assuming we had such an after-load-hook. ] > > If some packages decide to fiddle with minor-mode-map-alist when you activate the mode the first time (rather than on load), I don't think an after-load-hook will catch that. -- Kim F. Storm <storm@cua.dk> http://www.cua.dk ^ permalink raw reply [flat|nested] 46+ messages in thread
* Re: Enhancements to "minor-mode-map-alist" functionality. 2002-04-12 9:31 ` Kim F. Storm @ 2002-04-12 13:20 ` Kim F. Storm 2002-04-12 18:46 ` Stefan Monnier 2002-04-12 18:20 ` Stefan Monnier 2002-04-13 19:05 ` Richard Stallman 2 siblings, 1 reply; 46+ messages in thread From: Kim F. Storm @ 2002-04-12 13:20 UTC (permalink / raw) Cc: emacs-devel I have been thinking more about this and I've now got a more generic solution (I think) which has a lot of potential: Nested, Conditioned Keymaps. The idea is as follows: 1) A keymap may be conditioned with (keymap :filter FORM ...) We already discussed that, and although some precautions are needed to handle this, it should be fairly trivial to implement. 2) A keymap may be nested with (keymap ... (keymap ...) ... (keymap ...) ...) The idea is that when we scan through a keymap (searching for a binding), if we encounter a nested keymap, we will [recursively] scan that keymap before continuing through the original keymap. Now, if we combine those two ideas, I can write a "single" cua-mode master keymap which contains all of the conditioned sub-keymaps I need, i.e. something like this [I know this isn't the proper way to create a keymap, but it illustrates the point I'm making]: (setq cua-mode-map (keymap :filter cua-mode (keymap :filter (and mark-active cua-enable-cua-keys (or (eq cua-enable-cua-keys t) (not cua--explicit-region-start)) (not executing-kbd-macro) (not cua--prefix-override-timer)) ,cua--prefix-override-keymap) (keymap :filter (and mark-active (timerp cua--prefix-override-timer)) ,cua--prefix-repeat-keymap) (keymap :filter (or (eq cua-enable-cua-keys t) cua--last-region-shifted) ,cua--cua-keys-keymap) (keymap :filter (and cua--global-mark-active (not (window-minibuffer-p))) ,cua--global-mark-keymap) (keymap :filter cua--rectangle ,cua--rectangle-keymap) (keymap :filter mark-active ,cua--region-keymap) ,cua-global-keymap)) (add-to-list 'minor-mode-map-alist `(cua-mode . ,cua-mode-map)) So doing this would remove the need for the emulation-mode-map-alists (which you dislike :-) as well I can easily ensure that cua-mode-map stays at the beginning of minor-mode-map-alist [will be simple in a post-command hook, or maybe by adding it to minor-mode-overriding-map-alist :-) ] Some functions may be needed to manage this, e.g. (add-keymap keymap nested &optional after) -> inserts NESTED at the beginning of KEYMAP, or after optional AFTER keymap (or last if AFTER is t) Returns NESTED. (remove-keymap keymap nested) -> removes NESTED from the KEYMAP. (set-keymap-filter keymap filter &optional new) -> sets the :filter property on KEYMAP to FILTER, removes the :filter property if FILTER is nil. If NEW is non-nil, create a new keymap and use KEYMAP as a nested of that keymap, and apply the FILTER on the new keymap. This means that we can apply a filter to an existing keymap without adding a filter to that keymap. -> returns KEYMAP if NEW is nil, or the new keymap if NEW is non-nil. (get-keymap-filter keymap) -> returns the :filter property on KEYMAP This can also be used instead of minor-mode-overriding-map-alist: >From diff-mode.el: ;; Neat trick from Dave Love to add more bindings in read-only mode: (add-to-list (make-local-variable 'minor-mode-overriding-map-alist) (cons 'buffer-read-only diff-mode-shared-map)) could be replaced by: ;; Neat trick from Kim Storm to add more bindings in read-only mode: (add-keymap 'diff-mode-map (set-keymap-filter diff-mode-shared-map 'buffer-read-only t)) -- Kim F. Storm <storm@cua.dk> http://www.cua.dk ^ permalink raw reply [flat|nested] 46+ messages in thread
* Re: Enhancements to "minor-mode-map-alist" functionality. 2002-04-12 13:20 ` Kim F. Storm @ 2002-04-12 18:46 ` Stefan Monnier [not found] ` <5xofgoobzr.fsf@kfs2.cua.dk> 2002-04-14 23:11 ` Kim F. Storm 0 siblings, 2 replies; 46+ messages in thread From: Stefan Monnier @ 2002-04-12 18:46 UTC (permalink / raw) Cc: Stefan Monnier, emacs-devel > 2) A keymap may be nested with > > (keymap ... (keymap ...) ... (keymap ...) ...) > > The idea is that when we scan through a keymap (searching for a binding), > if we encounter a nested keymap, we will [recursively] scan that > keymap before continuing through the original keymap. I like this idea so much that I have implemented it already, but for the purpose of multiple inheritance and to get rid of the infamous fix_submap_inheritance ugliness. It requires several non-trivial changes, tho. And I haven't finished taking care of all the "problems" it introduces (not all of them need to be addressed right away: for example, it doesn't work for menus yet). > So doing this would remove the need for the emulation-mode-map-alists > (which you dislike :-) as well > > I can easily ensure that cua-mode-map stays at the beginning of > minor-mode-map-alist [will be simple in a post-command hook, or maybe > by adding it to minor-mode-overriding-map-alist :-) ] I don't understand. In what way is it easier ? It still seems like you need some kind of post-command-hook thingy. Stefan ^ permalink raw reply [flat|nested] 46+ messages in thread
[parent not found: <5xofgoobzr.fsf@kfs2.cua.dk>]
[parent not found: <200204122021.g3CKLh217680@rum.cs.yale.edu>]
* Re: Enhancements to "minor-mode-map-alist" functionality. [not found] ` <200204122021.g3CKLh217680@rum.cs.yale.edu> @ 2002-04-14 22:32 ` Kim F. Storm 2002-04-16 20:18 ` Richard Stallman 0 siblings, 1 reply; 46+ messages in thread From: Kim F. Storm @ 2002-04-14 22:32 UTC (permalink / raw) Cc: emacs-devel "Stefan Monnier" <monnier+gnu/emacs@rum.cs.yale.edu> writes: > > > I like this idea so much that I have implemented it already, but > > > for the purpose of multiple inheritance and to get rid of the infamous > > > fix_submap_inheritance ugliness. It requires several non-trivial > > > changes, tho. And I haven't finished taking care of all the "problems" > > > it introduces (not all of them need to be addressed right away: for > > > example, it doesn't work for menus yet). > > > > Very good. When can I expect to see this in the tree (so I can use it?) > > I'd say "not very sooon". I can send you the code, if you want to try it out. > There are several issues as well as details about the implementation that > some developers might object to, so it's not clear that it would be accepted. > For example, access_keymap can now allocate cons cells to build the > return value (and often does). What about a very different approach: 1) We define a keymap as a list (keymap PROPS &rest bindings) where [PROPS] is an optional vector with 3 elements: [FILTER SUBMAPS PARENT] FILTER is a form which is eval'ed to determine whether this bindings in keymap should be used or ignored SUBMAPS is a list of keymaps which are used at the same level as the bindings of this keyamp, but comes before those bindings. PARENT is the parent keymap (or nil) which is the parent keymap if this keymap. 2) We modify current_minor_maps to return a array of active keymaps which includes _all_ the submaps and parent maps of any of the active keymaps. The keymaps are added in the proper order, (i.e. for each keymap first the submaps (and any submaps of those etc), then then map itself, and finally the parent map). If we do this, the existing keymap lookup functionality will take care of (among other things) multiple submap inheritance. [and it should NOT bother looking at the submaps or the parent maps, as they are included in the maps list. 3) I understand that there is a problem with evaling code which may do consing in current_minor_maps, but for most practical applications I would suppose that this isn't necessary. So maybe we can just restrict the FILTER forms/functions to not being allowed to do consing and document this restriction in the set-keymap-filter function. 4) If this is not acceptable [why not?], the interpretation of the FILTER functions must be done by the callers before actually using a keymap -- this is of course possible, but complicates the code (as we would then need to return the 'nesting level' of the keymaps in the returned maps array, so we can skip submaps of ignored maps). 5) It could be considered to rename current_minor_maps to current_maps and expand it to include the keymap and local-map property maps, the buffer local map, and the global map in the returned maps array. This would simplify the callers of current_minor_maps, and it would also allow the global map, buffer local maps, and property keymaps to have (conditioned) submaps and a parent keymap. I haven't had time to consider all the implications of this on the rest of the code, but besides the trivial changes needed to cope with the addition of the [PROPS] vector to keymaps, there are probably a few places where a little extra work is needed to get things to work smoothly. But maybe current_maps will use a helper function which can cope with expanding a single keymap into an array of submaps, and if necessary, other parts of the code can use this. Any interest in investigating these ideas further, or do you think it is a(nother) dead end? -- Kim F. Storm <storm@cua.dk> http://www.cua.dk ^ permalink raw reply [flat|nested] 46+ messages in thread
* Re: Enhancements to "minor-mode-map-alist" functionality. 2002-04-14 22:32 ` Kim F. Storm @ 2002-04-16 20:18 ` Richard Stallman 2002-04-16 22:34 ` Kim F. Storm 0 siblings, 1 reply; 46+ messages in thread From: Richard Stallman @ 2002-04-16 20:18 UTC (permalink / raw) Cc: emacs-devel SUBMAPS is a list of keymaps which are used at the same level as the bindings of this keyamp, but comes before those bindings. What does that mean? What problem is it meant to solve? 3) I understand that there is a problem with evaling code which may do consing in current_minor_maps, but for most practical applications I would suppose that this isn't necessary. So maybe we can just restrict the FILTER forms/functions to not being allowed to do consing and document this restriction in the set-keymap-filter function. There is no way to implement such a restriction, and users don't generally know which functions do consing. What we should do is make this code work correctly. ^ permalink raw reply [flat|nested] 46+ messages in thread
* Re: Enhancements to "minor-mode-map-alist" functionality. 2002-04-16 20:18 ` Richard Stallman @ 2002-04-16 22:34 ` Kim F. Storm 2002-04-18 18:46 ` Richard Stallman 0 siblings, 1 reply; 46+ messages in thread From: Kim F. Storm @ 2002-04-16 22:34 UTC (permalink / raw) Cc: emacs-devel Richard Stallman <rms@gnu.org> writes: > SUBMAPS is a list of keymaps which are used at the same > level as the bindings of this keyamp, but comes before those > bindings. > > What does that mean? Consider a keymap K which has a binding for [C-x 1], a keymap P which has a binding for [C-x 2], and a keymap S which has a binding for [C-x 3]. Keymap S has a filter which means that it is only active if mark-active is non-nil. Now, we want keymap P to be a parent map for K, and we want S to be a submap of K. With my proposal, C-x 1, C-x 2, and (if mark-active) C-x 3 will all work seemlessly *without* having to rely on fix_submap_inheritance (which only works for one submap [the parent map] anyway). > What problem is it meant to solve? Multiple keymap inheritance as well as conditional keymaps. > > 3) I understand that there is a problem with evaling code which may > do consing in current_minor_maps, but for most practical > applications I would suppose that this isn't necessary. > > So maybe we can just restrict the FILTER forms/functions to > not being allowed to do consing and document this restriction > in the set-keymap-filter function. > > There is no way to implement such a restriction, > and users don't generally know which functions do consing. This is not intended to be a user feature, it is for package writers. I didn't think we should `implement' the restriction -- simply document it. It could be a fairly short list of `safe' functions to apply to variables, e.g. and, or, not, if, eq, equal, quote, member, memq, get, assoc, car, cdr, aref, =, /=, >, >=, <, <=, symbolp, numberp, vectorp, timerp, (etc) boundp, fboundp, featurep, (etc) I believe this would cover all practical purposes, so I don't see why we need to make a significantly more complex solution to handle some theoritical cases. > > What we should do is make this code work correctly. > If you still think this is what you think is necessary, one solution could be: - memory_full set a global variable 'out-of-memory'. - the command loop will (somehow) determine whether the out-of-memory condition is no longer present e.g. if (out_of_memory) { void *tem = malloc(100000); if (tem) { out_of_memory = 0; free(tem); } } - if out_of_memory is set, the current_maps function will not evaluate the keymap filters, but just assume they evaluate to the most recent result of evaluting the filter. *) I proposed to use a vector [FILTER SUBMAPS PARENT] for the keymap properties. This could easily be extended to store the result of the most recent evaluation of the FILTER, e.g. [FILTER FRES SUBMAPS PARENT] where current_maps would store the result of eval'ing FILTER in FRES. Maybe not a perfect solution, but I believe it would work well enough for this particular purpose (after all, running out of memory fortunately isn't something we experience every day [anymore]). -- Kim F. Storm <storm@cua.dk> http://www.cua.dk ^ permalink raw reply [flat|nested] 46+ messages in thread
* Re: Enhancements to "minor-mode-map-alist" functionality. 2002-04-16 22:34 ` Kim F. Storm @ 2002-04-18 18:46 ` Richard Stallman 2002-04-18 23:07 ` Kim F. Storm 0 siblings, 1 reply; 46+ messages in thread From: Richard Stallman @ 2002-04-18 18:46 UTC (permalink / raw) Cc: emacs-devel Consider a keymap K which has a binding for [C-x 1], a keymap P which has a binding for [C-x 2], and a keymap S which has a binding for [C-x 3]. Keymap S has a filter which means that it is only active if mark-active is non-nil. Now, we want keymap P to be a parent map for K, and we want S to be a submap of K. Why do we want that? What job are you trying to do? With my proposal, C-x 1, C-x 2, and (if mark-active) C-x 3 will all work seemlessly What does it mean for them to "work"? Once again, what job are you trying to do? It is not useful to address this backwards. We must not introduce more complex features merely because they look appealing in the abstract. We have to look at the job first, then determine how much complexity is really *necessary*. > What problem is it meant to solve? Multiple keymap inheritance as well as conditional keymaps. Multiple inheritance is a mess. We should avoid it if we can. > There is no way to implement such a restriction, > and users don't generally know which functions do consing. This is not intended to be a user feature, it is for package writers. I know which users this feature is for. The users of Emacs Lisp don't generally know which functions do consing. That can change. I didn't think we should `implement' the restriction -- simply document it. No way. This proposal includes many aspects each of which is very undesirable. The entire approach is wrong. We need to start by looking at the actual problem that we actually need to solve. ^ permalink raw reply [flat|nested] 46+ messages in thread
* Re: Enhancements to "minor-mode-map-alist" functionality. 2002-04-18 18:46 ` Richard Stallman @ 2002-04-18 23:07 ` Kim F. Storm 2002-04-19 13:43 ` Stefan Monnier 2002-04-19 18:42 ` Richard Stallman 0 siblings, 2 replies; 46+ messages in thread From: Kim F. Storm @ 2002-04-18 23:07 UTC (permalink / raw) Cc: emacs-devel Richard Stallman <rms@gnu.org> writes: > Consider a keymap K which has a binding for [C-x 1], > a keymap P which has a binding for [C-x 2], and > a keymap S which has a binding for [C-x 3]. > > Keymap S has a filter which means that it is only active > if mark-active is non-nil. > > Now, we want keymap P to be a parent map for K, and > we want S to be a submap of K. > > Why do we want that? What job are you trying to do? I've described that several times by now -- I'm trying to find the right approach to address the issues with complex modes which uses a lot of keymaps (like cua and viper) and base the selection between those keymaps on combining various state information, i.e. to provide a more versatile keymap functionality than what is currently available. I think I have ironed this out for cua by now via a (tedious) post-command-hook to do this through minor-mode-map-alist, but where I could just condition a keymap with `mark-active' if the decision is made when a key is actually processed, I need an expression like (and mark-active (not deactivate-mark)) in the post-command-hook -- and hope that nothing else changes the mark state under my feet.... Here is the current cua code where the cua--fix-keymaps function is run by the post-command-hook after every command: now> (defvar cua-global-keymap (make-sparse-keymap)) now> (defvar cua--cua-keys-keymap (make-sparse-keymap)) now> (defvar cua--prefix-override-keymap (make-sparse-keymap)) now> (defvar cua--prefix-repeat-keymap (make-sparse-keymap)) now> (defvar cua--global-mark-keymap (make-sparse-keymap)) now> (defvar cua--rectangle-keymap (make-sparse-keymap)) now> (defvar cua--region-keymap (make-sparse-keymap)) now> now> (defvar cua--ena-cua-keys-keymap nil) now> (defvar cua--ena-prefix-override-keymap nil) now> (defvar cua--ena-prefix-repeat-keymap nil) now> (defvar cua--ena-region-keymap nil) now> (defvar cua--ena-global-mark-keymap nil) now> now> (defvar cua--mmap-prefix-override-keymap (cons 'cua--ena-prefix-override-keymap cua--prefix-override-keymap)) now> (defvar cua--mmap-prefix-repeat-keymap (cons 'cua--ena-prefix-repeat-keymap cua--prefix-repeat-keymap)) now> (defvar cua--mmap-cua-keys-keymap (cons 'cua--ena-cua-keys-keymap cua--cua-keys-keymap)) now> (defvar cua--mmap-global-mark-keymap (cons 'cua--ena-global-mark-keymap cua--global-mark-keymap)) now> (defvar cua--mmap-rectangle-keymap (cons 'cua--rectangle cua--rectangle-keymap)) now> (defvar cua--mmap-region-keymap (cons 'cua--ena-region-keymap cua--region-keymap)) now> (defvar cua--mmap-global-keymap (cons 'cua-mode cua-global-keymap)) now> now> (defvar cua--mmap-list now> (list cua--mmap-prefix-override-keymap now> cua--mmap-prefix-repeat-keymap now> cua--mmap-cua-keys-keymap now> cua--mmap-global-mark-keymap now> cua--mmap-rectangle-keymap now> cua--mmap-region-keymap now> cua--mmap-global-keymap)) now> now> (defun cua--fix-keymaps (disable) now> ;; Ensure that cua's keymaps are in minor-mode-map-alist and now> ;; in the correct order, and set control variables. now> (let (fix now> (mmap minor-mode-map-alist) now> (ml cua--mmap-list)) now> (while (and (not fix) mmap ml) now> (if (not (eq (car mmap) (car ml))) now> (setq fix t) now> (setq mmap (cdr mmap) now> ml (cdr ml)))) now> (if ml now> (setq fix t)) now> (when (or fix disable) now> (setq ml cua--mmap-list) now> (while ml now> (setq minor-mode-map-alist (delq (car ml) minor-mode-map-alist)) now> (setq ml (cdr ml)))) now> (when (and fix (not disable)) now> (setq minor-mode-map-alist now> (append (copy-sequence cua--mmap-list) minor-mode-map-alist)))) now> (setq cua--ena-region-keymap now> (and mark-active (not deactivate-mark))) now> (setq cua--ena-prefix-override-keymap now> (and cua--ena-region-keymap now> cua-enable-cua-keys now> (or (eq cua-enable-cua-keys t) now> (not cua--explicit-region-start)) now> (not executing-kbd-macro) now> (not cua--prefix-override-timer))) now> (setq cua--ena-prefix-repeat-keymap now> (and cua--ena-region-keymap now> (timerp cua--prefix-override-timer))) now> (setq cua--ena-cua-keys-keymap now> (and cua-enable-cua-keys now> (or (eq cua-enable-cua-keys t) now> cua--last-region-shifted))) now> (setq cua--ena-global-mark-keymap now> (and cua--global-mark-active now> (not (window-minibuffer-p))))) to the code as it would look like with a dynamic setup via the proposed emulation-mode-map-alists (andn nothing is needed in the post-command-hook): emma> (defvar cua-global-keymap (make-sparse-keymap)) emma> (defvar cua--cua-keys-keymap (make-sparse-keymap)) emma> (defvar cua--prefix-override-keymap (make-sparse-keymap)) emma> (defvar cua--prefix-repeat-keymap (make-sparse-keymap)) emma> (defvar cua--global-mark-keymap (make-sparse-keymap)) ; Initalized when cua-gmrk.el is loaded emma> (defvar cua--rectangle-keymap (make-sparse-keymap)) ; Initalized when cua-rect.el is loaded emma> (defvar cua--region-keymap (make-sparse-keymap)) emma> emma> (setq emulation-mode-map-alists emma> (cons emma> `((lambda . (and mark-active emma> cua-enable-cua-keys emma> (or (eq cua-enable-cua-keys t) emma> (not cua--explicit-region-start)) emma> (not executing-kbd-macro) emma> (not cua--prefix-override-timer) emma> '(cua--prefix-override . ,cua--prefix-override-keymap))) emma> (lambda . (and mark-active emma> (timerp cua--prefix-override-timer) emma> '(cua--prefix-override . ,cua--prefix-repeat-keymap))) emma> (lambda . (and cua-enable-cua-keys emma> (or (eq cua-enable-cua-keys t) emma> cua--last-region-shifted) emma> '(cua-enable-cua-keys . ,cua--cua-keys-keymap))) emma> (lambda . (and cua--global-mark-active emma> (not (window-minibuffer-p)) emma> '(cua--global-mark-active . ,cua--global-mark-keymap))) emma> (cua--rectangle . ,cua--rectangle-keymap) emma> (mark-active . ,cua--region-keymap) emma> (cua-mode . ,cua-global-keymap)) emma> emulation-mode-map-alists)) > > With my proposal, C-x 1, C-x 2, and (if mark-active) C-x 3 will all > work seemlessly > > What does it mean for them to "work"? Once again, what job > are you trying to do? It is not useful to address this backwards. > I have N keymaps which all make bindings starting with C-x -- and I want all of those bindings to "work". I tried the `simple' approach by putting these keymaps into the proposed `emulation-mode-map-alists', but that idea was turned down. If it wasn't for the problem evalling code in the current_minor_maps function [I believe there are ways to solve that], would that solution be acceptable? > We must not introduce more complex features merely because they look > appealing in the abstract. We have to look at the job first, then > determine how much complexity is really *necessary*. > > > What problem is it meant to solve? > > Multiple keymap inheritance as well as conditional keymaps. > > Multiple inheritance is a mess. We should avoid it if we can. But the `parent keymap' inheritance is already pretty messy. A clean way to add multiple inheritance would fix that! Stefan told me he was working on a way to support things like this, but it had a number of problems (such as unnecessary consing), so I made another proposal (which doesn't do consing), but has other implications... > > > There is no way to implement such a restriction, > > and users don't generally know which functions do consing. > > This is not intended to be a user feature, it is for package > writers. > > I know which users this feature is for. The users of Emacs Lisp > don't generally know which functions do consing. That can change. > > I didn't think we should `implement' the restriction -- simply > document it. > > No way. Ok. > > This proposal includes many aspects each of which is very undesirable. > The entire approach is wrong. We need to start by looking at the actual > problem that we actually need to solve. Ok, that's what I've tried to do all along! I've already described it several times now, so what aspects of the problem are still unclear? So, please look at the problem! You (and others) don't approve of the proposals I've made to solve this. That's ok, but then I ask you to come up with a better proposal which deals with the problem at hand. Thank you! -- Kim F. Storm <storm@cua.dk> http://www.cua.dk ^ permalink raw reply [flat|nested] 46+ messages in thread
* Re: Enhancements to "minor-mode-map-alist" functionality. 2002-04-18 23:07 ` Kim F. Storm @ 2002-04-19 13:43 ` Stefan Monnier 2002-04-19 15:36 ` Kim F. Storm 2002-04-19 18:42 ` Richard Stallman 1 sibling, 1 reply; 46+ messages in thread From: Stefan Monnier @ 2002-04-19 13:43 UTC (permalink / raw) Cc: rms, emacs-devel > I've described that several times by now -- I'm trying to find the > right approach to address the issues with complex modes which uses a > lot of keymaps (like cua and viper) and base the selection between > those keymaps on combining various state information, i.e. to provide > a more versatile keymap functionality than what is currently > available. I haven't heard any comment about my proposal to use `menu-item' bindings with a :enable setting in order to get conditional bindings (this doesn't currently work, but it should be pretty easy to make it work). Would it help you solve your problems ? Stefan ^ permalink raw reply [flat|nested] 46+ messages in thread
* Re: Enhancements to "minor-mode-map-alist" functionality. 2002-04-19 13:43 ` Stefan Monnier @ 2002-04-19 15:36 ` Kim F. Storm 2002-04-19 14:46 ` Stefan Monnier 0 siblings, 1 reply; 46+ messages in thread From: Kim F. Storm @ 2002-04-19 15:36 UTC (permalink / raw) Cc: emacs-devel "Stefan Monnier" <monnier+gnu/emacs@rum.cs.yale.edu> writes: > > I've described that several times by now -- I'm trying to find the > > right approach to address the issues with complex modes which uses a > > lot of keymaps (like cua and viper) and base the selection between > > those keymaps on combining various state information, i.e. to provide > > a more versatile keymap functionality than what is currently > > available. > > I haven't heard any comment about my proposal to use `menu-item' > bindings with a :enable setting in order to get conditional bindings > (this doesn't currently work, but it should be pretty easy to make > it work). > Would it help you solve your problems ? Considering that cua has approx 100 bindings in 7 keymaps, it seems like absolute overkill IMO to condition each of those 100 bindings individually instead of just the 7 keymaps which contain those bindings... I don't think that is a _better_ solution. -- Kim F. Storm <storm@cua.dk> http://www.cua.dk ^ permalink raw reply [flat|nested] 46+ messages in thread
* Re: Enhancements to "minor-mode-map-alist" functionality. 2002-04-19 15:36 ` Kim F. Storm @ 2002-04-19 14:46 ` Stefan Monnier 2002-04-21 17:46 ` Kim F. Storm 0 siblings, 1 reply; 46+ messages in thread From: Stefan Monnier @ 2002-04-19 14:46 UTC (permalink / raw) Cc: Stefan Monnier, emacs-devel > "Stefan Monnier" <monnier+gnu/emacs@rum.cs.yale.edu> writes: > > > > I've described that several times by now -- I'm trying to find the > > > right approach to address the issues with complex modes which uses a > > > lot of keymaps (like cua and viper) and base the selection between > > > those keymaps on combining various state information, i.e. to provide > > > a more versatile keymap functionality than what is currently > > > available. > > > > I haven't heard any comment about my proposal to use `menu-item' > > bindings with a :enable setting in order to get conditional bindings > > (this doesn't currently work, but it should be pretty easy to make > > it work). > > Would it help you solve your problems ? > > Considering that cua has approx 100 bindings in 7 keymaps, > it seems like absolute overkill IMO to condition each of those > 100 bindings individually instead of just the 7 keymaps which > contain those bindings... Is that 7*100 bindings or 7*14 bindings ? How much overlap ? How many different conditions would there be ? For the sake of describe-key, I think it's better to have fewer bindings (with the dispatch done more often in the bound function rather than in the :enable conditionals) so that the docstring can describe what happens when. Stefan ^ permalink raw reply [flat|nested] 46+ messages in thread
* Re: Enhancements to "minor-mode-map-alist" functionality. 2002-04-19 14:46 ` Stefan Monnier @ 2002-04-21 17:46 ` Kim F. Storm 2002-04-22 9:28 ` Stefan Monnier 0 siblings, 1 reply; 46+ messages in thread From: Kim F. Storm @ 2002-04-21 17:46 UTC (permalink / raw) Cc: emacs-devel "Stefan Monnier" <monnier+gnu/emacs@rum.cs.yale.edu> writes: > > "Stefan Monnier" <monnier+gnu/emacs@rum.cs.yale.edu> writes: > > > I haven't heard any comment about my proposal to use `menu-item' > > > bindings with a :enable setting in order to get conditional bindings > > > (this doesn't currently work, but it should be pretty easy to make > > > it work). > > > Would it help you solve your problems ? > > > > Considering that cua has approx 100 bindings in 7 keymaps, > > it seems like absolute overkill IMO to condition each of those > > 100 bindings individually instead of just the 7 keymaps which > > contain those bindings... > > Is that 7*100 bindings or 7*14 bindings ? It is 8 + 7 + 2 + 10 + 17 + 60 + 16 bindings... > How much overlap ? None. > How many different conditions would there be ? There are 7 different conditions. > For the sake of describe-key, I think it's better to have fewer bindings > (with the dispatch done more often in the bound function rather > than in the :enable conditionals) so that the docstring can describe what > happens when. I don't think you will see any difference whether this is done via conditions in the minor-mode-map-alist (or emulation-mode-map-alist), or by conditioning each command individually. Also, I don't see why it is better to eval the various conditions 100 times rather than just 7 times? -- Kim F. Storm <storm@cua.dk> http://www.cua.dk ^ permalink raw reply [flat|nested] 46+ messages in thread
* Re: Enhancements to "minor-mode-map-alist" functionality. 2002-04-21 17:46 ` Kim F. Storm @ 2002-04-22 9:28 ` Stefan Monnier 2002-04-22 15:15 ` Kim F. Storm 0 siblings, 1 reply; 46+ messages in thread From: Stefan Monnier @ 2002-04-22 9:28 UTC (permalink / raw) Cc: Stefan Monnier, emacs-devel > "Stefan Monnier" <monnier+gnu/emacs@rum.cs.yale.edu> writes: > > > > "Stefan Monnier" <monnier+gnu/emacs@rum.cs.yale.edu> writes: > > > > I haven't heard any comment about my proposal to use `menu-item' > > > > bindings with a :enable setting in order to get conditional bindings > > > > (this doesn't currently work, but it should be pretty easy to make > > > > it work). > > > > Would it help you solve your problems ? > > > > > > Considering that cua has approx 100 bindings in 7 keymaps, > > > it seems like absolute overkill IMO to condition each of those > > > 100 bindings individually instead of just the 7 keymaps which > > > contain those bindings... > > > > Is that 7*100 bindings or 7*14 bindings ? > > It is 8 + 7 + 2 + 10 + 17 + 60 + 16 bindings... So, more like 7*14. How many of those bindings are in submaps (rather in the toplevel maps) such that the :enable condition could be put on the prefix and thus shared ? > > How much overlap ? > None. You mean that C-x is only bound in one of those 7 keymaps ? But if there's no overlap, then the order of those maps relative to each other is irrelevant. > > How many different conditions would there be ? > There are 7 different conditions. If there's really no overlap and thus only 7 conditions, then the only difference between my proposal and yours is that in my proposition the condition is put on each binding inside the toplevel map rather than being "outside the toplevel". So the situation is very much like the use of :filter. Actually we could use :filter to get the :enable behavior without any change to the C code at all. I.e. if a binding was made like (define-key cua-foo-map key bind) and assuming that the conditional corresponding to cua-foo-map is cua-foo-predicate, the new code would simply do: (defun cua-foo-filter (b) (if (eval cua-foo-predicate) b)) (define-key cua-mode-map key '(menu-item "bla" bind :filter cua-foo-filter)) > > For the sake of describe-key, I think it's better to have fewer bindings > > (with the dispatch done more often in the bound function rather > > than in the :enable conditionals) so that the docstring can describe what > > happens when. > > I don't think you will see any difference whether this is done > via conditions in the minor-mode-map-alist (or emulation-mode-map-alist), > or by conditioning each command individually. I was assuming that there would be overlap between the maps such that C-x is bound in several of your maps, so that C-h k would point you to a different function/docstring depending on the circumstance. Whereas if the conditional is tested inside the C code, then C-h k gets you to the function that can then conveniently describe the difference circumstances and their effect. Of course, if there's no overlap, there's indeed no difference. > Also, I don't see why it is better to eval the various conditions 100 times > rather than just 7 times? I don't see why the condition should be evaluated more times with my proposal than with yours. Actually, in your proposal, 7 conditions are being evaluated for each command (they're evaluated right at the beginning, in order to know which keymaps to look up), whereas in mine only between 1 and 7 conditions would be evaluated (if there's no overlap between the 7 maps, only 1, but if the current key pressed is present in all 7 of your maps, then 7). Stefan ^ permalink raw reply [flat|nested] 46+ messages in thread
* Re: Enhancements to "minor-mode-map-alist" functionality. 2002-04-22 9:28 ` Stefan Monnier @ 2002-04-22 15:15 ` Kim F. Storm 0 siblings, 0 replies; 46+ messages in thread From: Kim F. Storm @ 2002-04-22 15:15 UTC (permalink / raw) Cc: emacs-devel "Stefan Monnier" <monnier+gnu/emacs@rum.cs.yale.edu> writes: > > "Stefan Monnier" <monnier+gnu/emacs@rum.cs.yale.edu> writes: > > > > > > "Stefan Monnier" <monnier+gnu/emacs@rum.cs.yale.edu> writes: > > > > > I haven't heard any comment about my proposal to use `menu-item' > > > > > bindings with a :enable setting in order to get conditional bindings > > > > > (this doesn't currently work, but it should be pretty easy to make > > > > > it work). > > > > > Would it help you solve your problems ? > > > > > > > > Considering that cua has approx 100 bindings in 7 keymaps, > > > > it seems like absolute overkill IMO to condition each of those > > > > 100 bindings individually instead of just the 7 keymaps which > > > > contain those bindings... > > > > > > Is that 7*100 bindings or 7*14 bindings ? > > > > It is 8 + 7 + 2 + 10 + 17 + 60 + 16 bindings... > > So, more like 7*14. > How many of those bindings are in submaps (rather in the toplevel maps) > such that the :enable condition could be put on the prefix and thus shared ? > > > > How much overlap ? > > None. > > You mean that C-x is only bound in one of those 7 keymaps ? > But if there's no overlap, then the order of those maps relative > to each other is irrelevant. Oh, sorry I don't know why I said that.... Of course there is some overlap between some of those keymaps. E.g. C-x is bound in various ways in three of the keymaps, and `kill-ring-save' is remapped differently in three other keymaps. See the completely list of bindings (with overlap) at the end of this message. > > > > How many different conditions would there be ? > > There are 7 different conditions. > > If there's really no overlap and thus only 7 conditions, then the only > difference between my proposal and yours is that in my proposition > the condition is put on each binding inside the toplevel map rather > than being "outside the toplevel". > > So the situation is very much like the use of :filter. Actually > we could use :filter to get the :enable behavior without any change > to the C code at all. I.e. if a binding was made like > > (define-key cua-foo-map key bind) > > and assuming that the conditional corresponding to cua-foo-map is > cua-foo-predicate, the new code would simply do: > > (defun cua-foo-filter (b) (if (eval cua-foo-predicate) b)) > (define-key cua-mode-map key > '(menu-item "bla" bind :filter cua-foo-filter)) Yes, I can see the potential. AFAICS, the overlap can be handled by something like this: (defun cua-krs-filter (b) (cond (cua-global-mark-active 'cua-kill-to-global-mark) (cua-rectangle 'cua-kill-rectangle) (mark-active 'cua-kill-region) (t nil))) (define-key cua-mode-map [remap kill-ring-save] '(menu-item "-" nil :filter cua-krs-filter)) But that would not be practical for cua (too much overlap). > > > > For the sake of describe-key, I think it's better to have fewer bindings > > > (with the dispatch done more often in the bound function rather > > > than in the :enable conditionals) so that the docstring can describe what > > > happens when. > > > > I don't think you will see any difference whether this is done > > via conditions in the minor-mode-map-alist (or emulation-mode-map-alist), > > or by conditioning each command individually. > > I was assuming that there would be overlap between the maps such that > C-x is bound in several of your maps, so that C-h k would point you > to a different function/docstring depending on the circumstance. > Whereas if the conditional is tested inside the C code, then C-h k > gets you to the function that can then conveniently describe the > difference circumstances and their effect. > Exactly. > Of course, if there's no overlap, there's indeed no difference. > > > Also, I don't see why it is better to eval the various conditions 100 times > > rather than just 7 times? > > I don't see why the condition should be evaluated more times with my > proposal than with yours. Actually, in your proposal, 7 conditions > are being evaluated for each command (they're evaluated right at the > beginning, in order to know which keymaps to look up), whereas in > mine only between 1 and 7 conditions would be evaluated (if there's > no overlap between the 7 maps, only 1, but if the current key pressed > is present in all 7 of your maps, then 7). I stand corrected. Again, I'm sorry about the misinformation re. overlap. But I still fail to see how this approach can address all the requirements for cua. Here is the complete list of keymaps and bindings used by cua in its current state: 1 - cua--prefix-override-keymap . 2 - cua--prefix-repeat-keymap . . 3 - cua--cua-keys-keymap . . . 4 - cua--global-mark-keymap . . . . 5 - cua--rectangle-keymap . . . . . 6 - cua--region-keymap Key binding . . . . . . 7 - cua--global-keymap (* indicates remap) . . . . . . . ----------------------------------------------------------------------------- C-x 1 (2) (3) C-c 1 (2) (3) C-x C-x (1) 2 C-x up (1) 2 C-x down (1) 2 C-x left (1) 2 C-x right (1) 2 C-x timeout (1) 3 S-C-x 3 C-c C-c (1) 2 C-c up (1) 2 C-c down (1) 2 C-c left (1) 2 C-c right (1) 2 C-c timeout (1) 3 S-C-c 3 C-z 3 C-v 3 RET 4 5 TAB 5 S-return 5 6 7 H-space 5 6 7 mouse-1 5 down-mouse-1 5 drag-mouse-1 5 mouse-3 5 down-mouse-3 5 drag-mouse-3 5 H-mouse-1 7 S-C-SPC 7 C-? 5 M-up 5 M-down 5 M-left 5 M-right 5 C-M-up 5 C-M-down 5 M-a 5 M-b 5 M-c 5 M-f 5 M-F 5 M-i 5 M-k 5 M-l 5 M-m 5 M-n 5 M-o 5 M-p 5 M-P 5 M-r 5 M-R 5 M-s 5 M-t 5 M-u 5 M-| 5 M-' 5 M-/ 5 *exchange-point-and-mark 3 *yank 4 7 *clipboard-yank 7 *yank-pop 7 *set-mark-command 5 7 *undo 7 *advertised-undo 7 *self-insert-command 4 5 6 *self-insert-iso 4 5 6 *insert-register 6 *newline-and-indent 4 6 *newline 4 6 *open-line 6 *delete-backward-char 4 5 6 *backward-delete-char 4 5 6 *backward-delete-char-untabify 4 5 6 *delete-char 4 5 6 *kill-region 4 5 6 *copy-region-as-kill 4 5 6 *kill-ring-save 4 5 6 *keyboard-escape-quit 4 6 *keyboard-quit 4 6 *forward-char 5 *backward-char 5 *next-line 5 *previous-line 5 *end-of-line 5 *beginning-of-line 5 *end-of-buffer 5 *beginning-of-buffer 5 *scroll-down 5 *scroll-up 5 -- Kim F. Storm <storm@cua.dk> http://www.cua.dk ^ permalink raw reply [flat|nested] 46+ messages in thread
* Re: Enhancements to "minor-mode-map-alist" functionality. 2002-04-18 23:07 ` Kim F. Storm 2002-04-19 13:43 ` Stefan Monnier @ 2002-04-19 18:42 ` Richard Stallman 2002-04-19 22:05 ` Kim F. Storm 1 sibling, 1 reply; 46+ messages in thread From: Richard Stallman @ 2002-04-19 18:42 UTC (permalink / raw) Cc: emacs-devel > Why do we want that? What job are you trying to do? I've described that several times by now Not specifically enough that I can try to determine whether there is another way to do the job. -- I'm trying to find the right approach to address the issues with complex modes which uses a lot of keymaps (like cua and viper) and base the selection between those keymaps on combining various state information Selecting between keymaps is one possible avenue for doing a certain job. Before we assume it should be done this way, what are the other avenues? What is the job? I have N keymaps which all make bindings starting with C-x -- and I want all of those bindings to "work". What job are these bindings supposed to *do*? Given time I could figure that out from the code you sent, but I don't have that time. If it wasn't for the problem evalling code in the current_minor_maps function [I believe there are ways to solve that], would that solution be acceptable? Not necessarily. It would still be a big extension in an area where the code is already too complex. Multiple inheritance is inherently a mess. Once it was added, it would probably require subsequent work to fix bugs or to add more features so people can "fully use" it. > Multiple inheritance is a mess. We should avoid it if we can. But the `parent keymap' inheritance is already pretty messy. That is why we should not make it any hairier. Please don't use arguments of the form "We already have this kind of problem, therefore it it doesn't matter if we add to it." That is the wrong approach for any serious problem, and I can promise you I will say no. ^ permalink raw reply [flat|nested] 46+ messages in thread
* Re: Enhancements to "minor-mode-map-alist" functionality. 2002-04-19 18:42 ` Richard Stallman @ 2002-04-19 22:05 ` Kim F. Storm 2002-04-20 17:27 ` Richard Stallman 0 siblings, 1 reply; 46+ messages in thread From: Kim F. Storm @ 2002-04-19 22:05 UTC (permalink / raw) Cc: emacs-devel Richard Stallman <rms@gnu.org> writes: > > -- I'm trying to find the > right approach to address the issues with complex modes which uses a > lot of keymaps (like cua and viper) and base the selection between > those keymaps on combining various state information > > Selecting between keymaps is one possible avenue for doing a certain > job. Before we assume it should be done this way, what are the other > avenues? What is the job? Consider C-x. Normally, it works as a prefix key for things like C-x C-f etc. Basically, with cua, if the mark is active, hitting C-x starts a 0.2 seconds timer. If the timer runs out, C-x works like C-w (kill-ring-save). If the user enters another C-x within those 0.2 seconds, the first C-x is ignored and the second C-x works like a normal prefix key. Also if the user enters another key, e.g. C-f, within those 0.2 seconds, the first C-x now works like a prefix key, i.e. as C-x C-f. [all of this was discussed a year ago as ways to let the user circumvent cua's C-x handling]. The actual interpretation of C-x is done via three of cua's 7 keymaps. To complicate things, cua also supports rectangles and a global mark, which all work using the same command set as is used for the region, e.g. you also use C-x (or C-w) to kill the rectangle (and C-y to insert it), or if the global mark is set, C-x will move the selected region or rectangle to the global mark position... To facilitate this, three more keymaps are used which selectively does command remapping of `kill-ring-save' to handle either region, rectangle, or the global mark. The final keymap is used to allow users to take advantage of cua's uniform command set for rectangles (and the global mark), but still continue to use C-w, M-w and C-y instead of C-x, C-c, and C-v (which are the normal cua bindings). Having gone through a major overhaul of the cua code, I can definitely say that basing this on multiple minor-mode keymaps is a major improvement. The primary advantage is that code is much simpler to maintain now. > > I have N keymaps which all make bindings starting with C-x -- and I want > all of those bindings to "work". > > What job are these bindings supposed to *do*? Given time I could > figure that out from the code you sent, but I don't have that time. > Ok, but considering that I've spent more than 200 hours on this project maybe you could give my views some weight -- I have tried various alternatives to the current approach, and it is by far the best approach so far!! > If it wasn't for the problem evalling code in the current_minor_maps > function [I believe there are ways to solve that], would that solution > be acceptable? > > Not necessarily. It would still be a big extension in an area where > the code is already too complex. Multiple inheritance is inherently a > mess. Once it was added, it would probably require subsequent work to > fix bugs or to add more features so people can "fully use" it. The emulation-mode-map-alist and conditioned keymaps doesn't add multiple inheritance (that was part of my other proposal, once the emulation-mode-map-alist idea was rejected). It is primarily a way for packages like cua to be able to configure its (multiple) keymaps once and for all without worrying about other packages messing them up. I don't see why this is a significant complication. And what ever errors is potentially associated with it, I feel confident I can fix. > > > Multiple inheritance is a mess. We should avoid it if we can. > > But the `parent keymap' inheritance is already pretty messy. > > That is why we should not make it any hairier. > > Please don't use arguments of the form "We already have this kind of > problem, therefore it it doesn't matter if we add to it." That is the > wrong approach for any serious problem, and I can promise you I will > say no. > Ok, since this wasn't really an issue with my initial proposal (the emulation-mode-map-alist), I will leave it to Stefan to defend any changes added for the purpose of multiple inheritance. Please do not confuse my requirements for cua with multiple inheritance issues. -- Kim F. Storm <storm@cua.dk> http://www.cua.dk ^ permalink raw reply [flat|nested] 46+ messages in thread
* Re: Enhancements to "minor-mode-map-alist" functionality. 2002-04-19 22:05 ` Kim F. Storm @ 2002-04-20 17:27 ` Richard Stallman 2002-04-21 11:08 ` Kim F. Storm 0 siblings, 1 reply; 46+ messages in thread From: Richard Stallman @ 2002-04-20 17:27 UTC (permalink / raw) Cc: emacs-devel The actual interpretation of C-x is done via three of cua's 7 keymaps. Using separate keymaps for C-x seems reasonable. I wonder, though, why simply putting all three in minor-mode-map-alist won't do the job. As I recall, if any active keymap defines a binding with a non-prefix definition, that should override all prefix definitions regardless of the precedence order of the maps. Is that not true now? If not, maybe we could make it true again. So there is no need to worry about the relative order of your maps and all other maps. If you need to condition some of these maps on some symbol's being false, then we could make the minimal extension so far proposed, which is to allow minor-mode-map-alist (or another new alist) to have conditions which are more complex than just a symbol. But you do see if you can easily get away without that. To facilitate this, three more keymaps are used which selectively does command remapping of `kill-ring-save' to handle either region, rectangle, or the global mark. It would be cleaner to define a single new command for that purpose. The final keymap is used to allow users to take advantage of cua's uniform command set for rectangles (and the global mark), but still continue to use C-w, M-w and C-y instead of C-x, C-c, and C-v (which are the normal cua bindings). Which characters does this map redefine? ^ permalink raw reply [flat|nested] 46+ messages in thread
* Re: Enhancements to "minor-mode-map-alist" functionality. 2002-04-20 17:27 ` Richard Stallman @ 2002-04-21 11:08 ` Kim F. Storm 2002-04-22 7:47 ` Richard Stallman ` (2 more replies) 0 siblings, 3 replies; 46+ messages in thread From: Kim F. Storm @ 2002-04-21 11:08 UTC (permalink / raw) Cc: emacs-devel Richard Stallman <rms@gnu.org> writes: > The actual interpretation of C-x is done via three of cua's 7 keymaps. > > Using separate keymaps for C-x seems reasonable. > > I wonder, though, why simply putting all three in minor-mode-map-alist > won't do the job. As I recall, if any active keymap defines a binding > with a non-prefix definition, that should override all prefix > definitions regardless of the precedence order of the maps. Is that > not true now? If not, maybe we could make it true again. I wasn't aware of this functionality. I'll see if it is true now. > So there is > no need to worry about the relative order of your maps and all other > maps. > There are other cases where the ordering of those maps matters, but I might be able to further limit the dependence on the ordering (by making sure only one condition is true at a time), but I would still prefer if I could just rely on having my own (separate) cua-minor-mode-map-alist (on the emulation-mode-map-alists list), and be sure that noone would mess with it. And since I've already implemented it, I know the change to add emulation-mode-map-alists is trivial! > If you need to condition some of these maps on some symbol's being > false, then we could make the minimal extension so far proposed, which > is to allow minor-mode-map-alist (or another new alist) to have > conditions which are more complex than just a symbol. But you do see > if you can easily get away without that. If we don't allow some form of simple logical expression [e.g. the functions I listed in a previous mail], I really don't see any alternative to the present code cua (and viper) which refreshes a list of state variables and fixes any ordering problems in minor-mode-map-alist after each command. > > To facilitate this, three more keymaps are used which selectively does > command remapping of `kill-ring-save' to handle either region, rectangle, > or the global mark. > > It would be cleaner to define a single new command for that purpose. I don't agree. There are many other commands which are specific for the region, rectangle, and global mark cases, and handling those in separate functions is a lot clearer (to me). Actually, the new cua package consists of three files now: cua-base.el (for the basic functionality and region handling) cua-rect.el (for rectangle commands) cua-gmrk.el (for the global mark functionality) > > The final keymap is used to allow users to take advantage of cua's > uniform command set for rectangles (and the global mark), but still > continue to use C-w, M-w and C-y instead of C-x, C-c, and C-v (which > are the normal cua bindings). > > Which characters does this map redefine? > C-z -> undo, C-v -> yank -- Kim F. Storm <storm@cua.dk> http://www.cua.dk ^ permalink raw reply [flat|nested] 46+ messages in thread
* Re: Enhancements to "minor-mode-map-alist" functionality. 2002-04-21 11:08 ` Kim F. Storm @ 2002-04-22 7:47 ` Richard Stallman 2002-04-22 13:53 ` Kim F. Storm 2002-04-22 22:36 ` Richard Stallman 2002-04-22 22:36 ` Richard Stallman 2 siblings, 1 reply; 46+ messages in thread From: Richard Stallman @ 2002-04-22 7:47 UTC (permalink / raw) Cc: emacs-devel > To facilitate this, three more keymaps are used which selectively does > command remapping of `kill-ring-save' to handle either region, rectangle, > or the global mark. > > It would be cleaner to define a single new command for that purpose. I don't agree. There are many other commands which are specific for the region, rectangle, and global mark cases, and handling those in separate functions is a lot clearer (to me). You said that the function of these maps is to remap `kill-ring-save'. I based my comment on what you said. Rather than remap `kill-ring-save', which is the usual key binding of M-w, I think it would be cleaner to bind M-w to one new command. What do these "many other commands" have to do with remapping `kill-ring-save'? I don't see the connection. Do these three maps do something else besides remap `kill-ring-save'? If so, would you please say precisely what other jobs they do? ^ permalink raw reply [flat|nested] 46+ messages in thread
* Re: Enhancements to "minor-mode-map-alist" functionality. 2002-04-22 7:47 ` Richard Stallman @ 2002-04-22 13:53 ` Kim F. Storm 0 siblings, 0 replies; 46+ messages in thread From: Kim F. Storm @ 2002-04-22 13:53 UTC (permalink / raw) Cc: emacs-devel Richard Stallman <rms@gnu.org> writes: > > To facilitate this, three more keymaps are used which selectively does > > command remapping of `kill-ring-save' to handle either region, rectangle, > > or the global mark. > > > > It would be cleaner to define a single new command for that purpose. > > I don't agree. There are many other commands which are specific for > the region, rectangle, and global mark cases, and handling those in > separate functions is a lot clearer (to me). > > You said that the function of these maps is to remap > `kill-ring-save'. I based my comment on what you said. I explained how C-x is handled as an example. > Rather than remap `kill-ring-save', which is the usual > key binding of M-w, I think it would be cleaner to bind M-w > to one new command. But the remapping is the elegant part of cua --- in each of the keymaps for the region, rectangle, and global mark I simply remap kill-ring-save to cua-kill-region, cua-kill-rectangle or cua-kill-to-global-mark ... ignoring the specific keybindings the user may be using for kill-ring-save (and copy-region-as-kill BTW). > > What do these "many other commands" have to do with remapping > `kill-ring-save'? I don't see the connection. Do these three maps do > something else besides remap `kill-ring-save'? If so, would you > please say precisely what other jobs they do? Well, they define other bindings which are specific for cua's handling of the region, rectangles, and global mark. -- Kim F. Storm <storm@cua.dk> http://www.cua.dk ^ permalink raw reply [flat|nested] 46+ messages in thread
* Re: Enhancements to "minor-mode-map-alist" functionality. 2002-04-21 11:08 ` Kim F. Storm 2002-04-22 7:47 ` Richard Stallman @ 2002-04-22 22:36 ` Richard Stallman 2002-04-23 10:58 ` Kim F. Storm 2002-04-22 22:36 ` Richard Stallman 2 siblings, 1 reply; 46+ messages in thread From: Richard Stallman @ 2002-04-22 22:36 UTC (permalink / raw) Cc: emacs-devel > If you need to condition some of these maps on some symbol's being > false, then we could make the minimal extension so far proposed, which > is to allow minor-mode-map-alist (or another new alist) to have > conditions which are more complex than just a symbol. But you do see > if you can easily get away without that. If we don't allow some form of simple logical expression [e.g. the functions I listed in a previous mail], What are the three conditions that you want to test for? Let's see what features they require. ^ permalink raw reply [flat|nested] 46+ messages in thread
* Re: Enhancements to "minor-mode-map-alist" functionality. 2002-04-22 22:36 ` Richard Stallman @ 2002-04-23 10:58 ` Kim F. Storm 0 siblings, 0 replies; 46+ messages in thread From: Kim F. Storm @ 2002-04-23 10:58 UTC (permalink / raw) Cc: emacs-devel Richard Stallman <rms@gnu.org> writes: > > If you need to condition some of these maps on some symbol's being > > false, then we could make the minimal extension so far proposed, which > > is to allow minor-mode-map-alist (or another new alist) to have > > conditions which are more complex than just a symbol. But you do see > > if you can easily get away without that. > > If we don't allow some form of simple logical expression [e.g. the > functions I listed in a previous mail], > > What are the three conditions that you want to test for? > Let's see what features they require. > Here are the keymap conditionals used by cua: (and mark-active cua-enable-cua-keys (or (eq cua-enable-cua-keys t) (not cua--explicit-region-start)) (not executing-kbd-macro) (not cua--prefix-override-timer)) (and mark-active (timerp cua--prefix-override-timer)) (or (eq cua-enable-cua-keys t) cua--last-region-shifted) (and cua--global-mark-active (not (window-minibuffer-p))) The last one calls `windows-minibuffer-p' -- that's probably not considered as `trivial' ? -- Kim F. Storm <storm@cua.dk> http://www.cua.dk ^ permalink raw reply [flat|nested] 46+ messages in thread
* Re: Enhancements to "minor-mode-map-alist" functionality. 2002-04-21 11:08 ` Kim F. Storm 2002-04-22 7:47 ` Richard Stallman 2002-04-22 22:36 ` Richard Stallman @ 2002-04-22 22:36 ` Richard Stallman 2002-04-23 11:02 ` Kim F. Storm 2 siblings, 1 reply; 46+ messages in thread From: Richard Stallman @ 2002-04-22 22:36 UTC (permalink / raw) Cc: emacs-devel > The final keymap is used to allow users to take advantage of cua's > uniform command set for rectangles (and the global mark), but still > continue to use C-w, M-w and C-y instead of C-x, C-c, and C-v (which > are the normal cua bindings). > > Which characters does this map redefine? > C-z -> undo, C-v -> yank This should be feasible with existing facilities, right? ^ permalink raw reply [flat|nested] 46+ messages in thread
* Re: Enhancements to "minor-mode-map-alist" functionality. 2002-04-22 22:36 ` Richard Stallman @ 2002-04-23 11:02 ` Kim F. Storm 2002-04-24 17:55 ` Richard Stallman 0 siblings, 1 reply; 46+ messages in thread From: Kim F. Storm @ 2002-04-23 11:02 UTC (permalink / raw) Cc: emacs-devel Richard Stallman <rms@gnu.org> writes: > > The final keymap is used to allow users to take advantage of cua's > > uniform command set for rectangles (and the global mark), but still > > continue to use C-w, M-w and C-y instead of C-x, C-c, and C-v (which > > are the normal cua bindings). > > > > Which characters does this map redefine? > > > > C-z -> undo, C-v -> yank > > This should be feasible with existing facilities, right? Yes, except that the condition on this keymap is (or (eq cua-enable-cua-keys t) cua--last-region-shifted) -- Kim F. Storm <storm@cua.dk> http://www.cua.dk ^ permalink raw reply [flat|nested] 46+ messages in thread
* Re: Enhancements to "minor-mode-map-alist" functionality. 2002-04-23 11:02 ` Kim F. Storm @ 2002-04-24 17:55 ` Richard Stallman 2002-04-26 13:44 ` Kim F. Storm 0 siblings, 1 reply; 46+ messages in thread From: Richard Stallman @ 2002-04-24 17:55 UTC (permalink / raw) Cc: emacs-devel > This should be feasible with existing facilities, right? Yes, except that the condition on this keymap is (or (eq cua-enable-cua-keys t) cua--last-region-shifted) Could you make a new variable to control this keymap, and set it from post-command-hook? Likewise, maybe you could control the other maps with variables set in post-command-hook. This would not be much more complicated and it probably would be about as fast. Perhaps faster, since the hook function could be byte-compiled, whereas if these expressions go straight into the keymap they would have to be interpreted. ^ permalink raw reply [flat|nested] 46+ messages in thread
* Re: Enhancements to "minor-mode-map-alist" functionality. 2002-04-24 17:55 ` Richard Stallman @ 2002-04-26 13:44 ` Kim F. Storm 2002-04-27 22:41 ` Richard Stallman 0 siblings, 1 reply; 46+ messages in thread From: Kim F. Storm @ 2002-04-26 13:44 UTC (permalink / raw) Cc: storm, emacs-devel Richard Stallman <rms@gnu.org> writes: > > This should be feasible with existing facilities, right? > > Yes, except that the condition on this keymap is > > (or (eq cua-enable-cua-keys t) > cua--last-region-shifted) > > Could you make a new variable to control this keymap, > and set it from post-command-hook? > > Likewise, maybe you could control the other maps > with variables set in post-command-hook. > This would not be much more complicated > and it probably would be about as fast. > Perhaps faster, since the hook function could be > byte-compiled, whereas if these expressions go straight > into the keymap they would have to be interpreted. That is exactly what I've done now. I set a total of 5 such variables in the post-command-hook to control the various cua related keymaps. The problem with this approach is that -- in some cases -- a subsequent post-command-hook function or another external event may change the state [notably clear the mark active state] so my state variables no longer contain the proper values. I still belive evalling those expressions when the keymaps are used is preferable (safer, simpler and more logical) rather than doing it in the post-command-hook. ^ permalink raw reply [flat|nested] 46+ messages in thread
* Re: Enhancements to "minor-mode-map-alist" functionality. 2002-04-26 13:44 ` Kim F. Storm @ 2002-04-27 22:41 ` Richard Stallman 2002-04-29 9:17 ` Kai Großjohann 0 siblings, 1 reply; 46+ messages in thread From: Richard Stallman @ 2002-04-27 22:41 UTC (permalink / raw) Cc: emacs-devel The problem with this approach is that -- in some cases -- a subsequent post-command-hook function or another external event may change the state [notably clear the mark active state] so my state variables no longer contain the proper values. Hmm. What sort of external event deactivates the mark? What package has a post-command-hook function that deactivates the mark? I still belive evalling those expressions when the keymaps are used is preferable (safer, simpler and more logical) rather than doing it in the post-command-hook. All in all, if the post-command-hook works, I think that is simpler. However, if making the post-command-hook work requires added complexity, that could tip the scales in favor of some other solution. ^ permalink raw reply [flat|nested] 46+ messages in thread
* Re: Enhancements to "minor-mode-map-alist" functionality. 2002-04-27 22:41 ` Richard Stallman @ 2002-04-29 9:17 ` Kai Großjohann 2002-04-30 5:18 ` Richard Stallman 0 siblings, 1 reply; 46+ messages in thread From: Kai Großjohann @ 2002-04-29 9:17 UTC (permalink / raw) Cc: kfs, emacs-devel Richard Stallman <rms@gnu.org> writes: > All in all, if the post-command-hook works, I think that is simpler. > However, if making the post-command-hook work requires added complexity, > that could tip the scales in favor of some other solution. Please note that Kim has already implemented the post-command-hook completion. And Kim has already made a suggestion for another implementation. The post-command-hook implementation requires quite complex code and is hard to maintain, he says, whereas his proposed emulation-mode-minor-map-alist leads to considerably simpler and easier to maintain code. I hope I have helped to clear this up a bit. I was feeling that there is still some misunderstanding. kai -- Silence is foo! ^ permalink raw reply [flat|nested] 46+ messages in thread
* Re: Enhancements to "minor-mode-map-alist" functionality. 2002-04-29 9:17 ` Kai Großjohann @ 2002-04-30 5:18 ` Richard Stallman 2002-04-30 21:25 ` Kim F. Storm 0 siblings, 1 reply; 46+ messages in thread From: Richard Stallman @ 2002-04-30 5:18 UTC (permalink / raw) Cc: kfs, emacs-devel What exactly is the emulation-mode-minor-map-alist suggestion? ^ permalink raw reply [flat|nested] 46+ messages in thread
* Re: Enhancements to "minor-mode-map-alist" functionality. 2002-04-30 5:18 ` Richard Stallman @ 2002-04-30 21:25 ` Kim F. Storm 2002-05-01 7:14 ` Richard Stallman 0 siblings, 1 reply; 46+ messages in thread From: Kim F. Storm @ 2002-04-30 21:25 UTC (permalink / raw) Cc: Kai.Grossjohann, emacs-devel Richard Stallman <rms@gnu.org> writes: > What exactly is the emulation-mode-minor-map-alist suggestion? The basic emulation-mode-map-alists functionality is simply a way to allow packages like cua and viper to install and manage their own keymap alists independent of minor-mode-map-alist: It is a list of alists with the same format and interpretation as minor-mode-map-alist. The documentation for emulation-mode-map-alists is as follows: List of keymap alists to use for emulations modes. It is intended for modes or packages using multiple minor-mode keymaps. Each element is a keymap alist just like `minor-mode-map-alist', and it is used the same way. The "active" keymaps in this alist are used before `minor-mode-map-alist' but after `minor-mode-overriding-map-alist'. The second - independent - part of the proposed functionality was to allow more complex expressions to select the active keymaps in the minor-mode-map-alist (and emulation-mode-map-alists): The following minor-mode-map-alist documentation describes this added functionality: Alist of keymaps to use for minor modes. Each element looks like (VARIABLE . KEYMAP); KEYMAP is used to read key sequences and look up bindings iff VARIABLE's value is non-nil. Alternatively, an element may look like (lambda . FORM) where FORM is evaluated and should return either nil or a cons (SYMBOL . KEYMAP); in this case, KEYMAP is used unconditionally and SYMBOL is displayed by `describe-bindings' as the variable controlling KEYMAP. If two active keymaps bind the same key, the keymap appearing earlier in the list takes precedence. -- Kim F. Storm <storm@cua.dk> http://www.cua.dk ^ permalink raw reply [flat|nested] 46+ messages in thread
* Re: Enhancements to "minor-mode-map-alist" functionality. 2002-04-30 21:25 ` Kim F. Storm @ 2002-05-01 7:14 ` Richard Stallman 2002-05-01 17:37 ` Kim F. Storm 0 siblings, 1 reply; 46+ messages in thread From: Richard Stallman @ 2002-05-01 7:14 UTC (permalink / raw) Cc: Kai.Grossjohann, emacs-devel It is a list of alists with the same format and interpretation as minor-mode-map-alist. Would a single added alist do the job? Alternatively, an element may look like (lambda . FORM) where FORM is evaluated and should return either nil or a cons (SYMBOL . KEYMAP); That seems kludgy and ugly. I would rather allow replacing VARIABLE with a boolean expression. Wouldn't that be enough? I think this is the sort of area where it is better to make smaller extensions, not larger ones. ^ permalink raw reply [flat|nested] 46+ messages in thread
* Re: Enhancements to "minor-mode-map-alist" functionality. 2002-05-01 7:14 ` Richard Stallman @ 2002-05-01 17:37 ` Kim F. Storm 0 siblings, 0 replies; 46+ messages in thread From: Kim F. Storm @ 2002-05-01 17:37 UTC (permalink / raw) Cc: Kai.Grossjohann, emacs-devel Richard Stallman <rms@gnu.org> writes: > It is a list of alists with the same format and interpretation as > minor-mode-map-alist. > > Would a single added alist do the job? I think a package should be able to create its own alist and link it into the -map-alists list. Then packages like cua and viper don't need to worry about each other... Having one extra alist or a list of alists doesn't make much difference for the implementation - but it makes a big difference at the lisp level. > > Alternatively, an element may look like (lambda . FORM) where FORM is > evaluated and should return either nil or a cons (SYMBOL . KEYMAP); > > That seems kludgy and ugly. I fully agree. > I would rather allow replacing VARIABLE > with a boolean expression. Wouldn't that be enough? So would I, but what symbol should describe-bindings show in case of a boolean expression? E.g. `cua--ena-cua-keys-keymap' Minor Mode Bindings: Maybe it could just be nil - in which case describe-bindings would print a heading with no specific symbol, e.g. Misc. Emulation Mode Bindings: > > I think this is the sort of area where it is better to make smaller > extensions, not larger ones. I don't think I'm advocating for large extensions here. The functionality is confined to adding one new variable, and modifying one or two functions at the C level. But I need to take care of the [potential] memory allocation problems in current_minor_maps. Either by explicitly defining (and evalling) a specific set of functions which may be used in the expression, or by inhibiting evaluation of the boolean expressions if we have run out of memory. -- Kim F. Storm <storm@cua.dk> http://www.cua.dk ^ permalink raw reply [flat|nested] 46+ messages in thread
* Re: Enhancements to "minor-mode-map-alist" functionality. 2002-04-12 18:46 ` Stefan Monnier [not found] ` <5xofgoobzr.fsf@kfs2.cua.dk> @ 2002-04-14 23:11 ` Kim F. Storm 1 sibling, 0 replies; 46+ messages in thread From: Kim F. Storm @ 2002-04-14 23:11 UTC (permalink / raw) Cc: emacs-devel "Stefan Monnier" <monnier+gnu/emacs@rum.cs.yale.edu> writes: > > > > I can easily ensure that cua-mode-map stays at the beginning of > > minor-mode-map-alist [will be simple in a post-command hook, or maybe > > by adding it to minor-mode-overriding-map-alist :-) ] > > I don't understand. In what way is it easier ? > It still seems like you need some kind of post-command-hook thingy. In any case, I would like to get cua into CVS, so I'll stick to using the existing minor-mode-map-alist (through the post-command-hook) for the time being. If and when better alternatives become available, I'll switch to using that. -- Kim F. Storm <storm@cua.dk> http://www.cua.dk ^ permalink raw reply [flat|nested] 46+ messages in thread
* Re: Enhancements to "minor-mode-map-alist" functionality. 2002-04-12 9:31 ` Kim F. Storm 2002-04-12 13:20 ` Kim F. Storm @ 2002-04-12 18:20 ` Stefan Monnier 2002-04-12 21:05 ` Kim F. Storm 2002-04-13 19:05 ` Richard Stallman 2 siblings, 1 reply; 46+ messages in thread From: Stefan Monnier @ 2002-04-12 18:20 UTC (permalink / raw) Cc: Stefan Monnier, emacs-devel > "Stefan Monnier" <monnier+gnu/emacs@rum.cs.yale.edu> writes: > > > > However, this can be dramatically simplified by two (simple) > > > enhancements to the minor-mode-map-alist functionality: > > > > > > 1) Provide a separate emulation-mode-map-alists variable where > > > modes like cua can insert their own mode-map-alist, > > > > As you probably know, I'm not too excited about this, since it shouldn't > > be necessary if we could enforce a bit more discipline in the way > > entries are added to minor-mode-map-alist. > > I doubt we can find a way to enforce that. In an ideal world, all modifications of the alist would go through either add-minor-mode or define-minor-mode, where we could enforce it. I agree that it's not realistic. > > [ Yes, I wish we had "watchers" so we could trap modifications of > > particular variables. ] > > > Which would still not ensure anything -- if multiple packages are > watching minor-mode-map-alist and rearranges it, we'd still not > be able to _ensure_ any specific ordering... Well, there would be a single watcher that provided the same functionality as your emulation alist and both viper and cua would use it. > > Also, have you contacted Michael Kifer to see if that would satisfy his > > needs for viper (I know he also had to do some funky post-command > > fiddling of the minor-mode-map-alist). > As far as I can see, it is _exactly_ the same problem (viper has 9 keymaps). That's my impression as well, but maybe he has some other idea of what the ideal solution should look like. > > > 2) Allow selection of the active keymaps in the alist to > > > be based on evaluating a form in addition to a simple variable. > > > > I generally like the idea of having the keymaps more dynamic, > > but I'd rather not add another form of dynamism that isn't quite > > good enough for everything. To be more precise, currently you can get > > the above "select the keymap dynamically" in a more generic way > > (i.e. not just for minor mode maps) by using an entry of the form: > > > > '(menu-item "foo" data :filter fun) > > > > It is mostly used for dynamic menus, but also works in other keymaps. > > Problem is, it only works for submaps because it is not itself > > a keymap and thus can't be used for a toplevel map. > > I need this at the top-level maps, so it is not applicable here. I kind of expected it :-( > But if we could support something like (keymap :filter fun ...), > it would satisfy the needs for cua. I had something like that working in the past. I don't think I have the code around any more, tho. IIRC it wasn't too difficult to add. The evaluation of the function was done in `get_keymap' (this is not to say that it was the right place to do it, but that it was my choice at the time, because it seemed simpler). Another idea I have been toying with (but it never got far enough for me to start writing any code, not even tentatively) is to use a "null event". Assuming this event is called `nil', you could replace the above dynamic keymap with: (defvar dynmap (make-sparse-keymap)) (define-key dynmap [nil] '(menu-item "foo" data :filter fun)) Ideally this would also allow multiple such "same-level submaps" which would then provide multiple keymap inheritance. > > So if the dynamism you need is only in the `command-remap' submap, > > for example, your new hack is not needed. > I don't think this is a hack! I said "hack" because I think it's more ad-hoc than it should. > ;; Neat trick from Dave Love to add more bindings in read-only mode: > (add-to-list 'minor-mode-map-alist > `(lambda . (and diff-minor-mode buffer-read-only > '(diff-minor-mode . ,diff-mode-shared-map)))) Indeed. > ;; View mode steals RET from us. > (local-set-key [remap View-scroll-line-forward] 'help-follow) That one looks completely bogus to me. Do you really want to prevent the use of View-scroll-line-forward from a help-mode buffer even if it's bound to something else than RET ? > [Actually, I think I'll install that change in any case]. Please don't. > > I'd rather not add a hack that's specific to minor-mode-map-alist > > if we could do the same for all cases instead. > > Sure. But what device do you suggest then? > (keymap :filter fun ...) ? > > I don't object to that, but it would be _less_ efficient, since > we have to search the keymap for the :filter property (like we do > for a menu-item, but that is much shorter) [unless we ensure > it stays at the head of the keymap list]. I don't care much for efficiency at this stage. > Also, the keymap lookup code would also have to be careful not to > interpret the FUN part as a binding, You can force it to be a symbol. > and when we add binding to > a map, we should be careful not to split the ":filter FUN" pair. Of course, it might need some care. Doing it in get_keymap works around the above problem, tho since the keymap that's modified is the one returned by get_keymap. > So GC-wise this only makes things marginally worse :-/ I'd rather try to make it better than to make it marginally worse. > > In other words, maybe we shouldn't evaluate the form inside this > > current_minor_maps function. > I still think it is pretty safe to do so. Despite the comment that's just above ? Do you really think the coders went to the trouble of not using xmalloc/xrealloc and of sometimes returning an incorrect result (hoping that the cause of the problem will cause something else to abort later on) just for the fun of it ? > If some packages decide to fiddle with minor-mode-map-alist when you > activate the mode the first time (rather than on load), I don't > think an after-load-hook will catch that. And if some package decides to fiddle with it from an idle-hook, the post-command-hook will fail as well. The question is not "is it theoretically safe" but "is it safe in practice" ? I believe it'd be good enough in practice because I don't see much fiddling of minor-mode-map-alist outside of toplevel expressions. Stefan ^ permalink raw reply [flat|nested] 46+ messages in thread
* Re: Enhancements to "minor-mode-map-alist" functionality. 2002-04-12 18:20 ` Stefan Monnier @ 2002-04-12 21:05 ` Kim F. Storm 2002-04-12 20:30 ` Stefan Monnier 0 siblings, 1 reply; 46+ messages in thread From: Kim F. Storm @ 2002-04-12 21:05 UTC (permalink / raw) Cc: emacs-devel "Stefan Monnier" <monnier+gnu/emacs@rum.cs.yale.edu> writes: > > > But if we could support something like (keymap :filter fun ...), > > it would satisfy the needs for cua. > > I had something like that working in the past. I don't think > I have the code around any more, tho. IIRC it wasn't too difficult > to add. The evaluation of the function was done in `get_keymap' > (this is not to say that it was the right place to do it, but that > it was my choice at the time, because it seemed simpler). I'll give it a try... > > Another idea I have been toying with (but it never got far enough > for me to start writing any code, not even tentatively) is to use > a "null event". Assuming this event is called `nil', you could > replace the above dynamic keymap with: > > (defvar dynmap (make-sparse-keymap)) > (define-key dynmap [nil] '(menu-item "foo" data :filter fun)) > > Ideally this would also allow multiple such "same-level submaps" > which would then provide multiple keymap inheritance. > This is very similar to my new proposal for nested keymaps, but it looks like a hack to use menu-item that way. > > > So if the dynamism you need is only in the `command-remap' submap, > > > for example, your new hack is not needed. > > I don't think this is a hack! > > I said "hack" because I think it's more ad-hoc than it should. > > > ;; Neat trick from Dave Love to add more bindings in read-only mode: > > (add-to-list 'minor-mode-map-alist > > `(lambda . (and diff-minor-mode buffer-read-only > > '(diff-minor-mode . ,diff-mode-shared-map)))) > > Indeed. > > > ;; View mode steals RET from us. > > (local-set-key [remap View-scroll-line-forward] 'help-follow) > > That one looks completely bogus to me. Do you really want to prevent > the use of View-scroll-line-forward from a help-mode buffer even if > it's bound to something else than RET ? No, that wasn't the intention ... I must have been sleeping... > > > [Actually, I think I'll install that change in any case]. > > Please don't. I wont. But I still think the use of the minor-mode-overriding-map-alist for this purpose is pretty obscure (although I suspect that is the purpose for which it was invented...) An alternative would be to put a keymap property on the link like this: [in CVS emacs, keymap properties take precedence over minor mode keymaps!] (defun help-xref-button (match-number type &rest args) "Make a hyperlink for cross-reference text previously matched. MATCH-NUMBER is the subexpression of interest in the last matched regexp. TYPE is the type of button to use. Any remaining arguments are passed to the button's help-function when it is invoked. See `help-make-xrefs'." ;; Don't mung properties we've added specially in some instances. (unless (button-at (match-beginning match-number)) (make-text-button (match-beginning match-number) (match-end match-number) 'type type 'help-args args 'keymap help-mode-map))) ^^^^^^^^^^^^^^^^^^^^^ > > > > I'd rather not add a hack that's specific to minor-mode-map-alist > > > if we could do the same for all cases instead. > > > > Sure. But what device do you suggest then? > > (keymap :filter fun ...) ? > > > > I don't object to that, but it would be _less_ efficient, since > > we have to search the keymap for the :filter property (like we do > > for a menu-item, but that is much shorter) [unless we ensure > > it stays at the head of the keymap list]. > > I don't care much for efficiency at this stage. Neither do I !! > > > Also, the keymap lookup code would also have to be careful not to > > interpret the FUN part as a binding, > > You can force it to be a symbol. I would prefer not to do that; an alternative would be to put a cons cell (:filter . FORM) into the keymap, causing the rest of the keymap to be ignored if FORM returns nil. Along this line, we could also add (lambda . FORM) in a keymap which will evaluate FORM to get a nested keymap. > > > and when we add binding to > > a map, we should be careful not to split the ":filter FUN" pair. > > Of course, it might need some care. Doing it in get_keymap works > around the above problem, tho since the keymap that's modified > is the one returned by get_keymap. I guess using (:filter . FORM) would make it easier to ensure this. > > > So GC-wise this only makes things marginally worse :-/ > > I'd rather try to make it better than to make it marginally worse. Sure. > > > > In other words, maybe we shouldn't evaluate the form inside this > > > current_minor_maps function. > > I still think it is pretty safe to do so. > > Despite the comment that's just above ? Do you really think the > coders went to the trouble of not using xmalloc/xrealloc and of > sometimes returning an incorrect result (hoping that the cause of > the problem will cause something else to abort later on) just > for the fun of it ? You are right. I overlooked the finer details of that comment. > > > If some packages decide to fiddle with minor-mode-map-alist when you > > activate the mode the first time (rather than on load), I don't > > think an after-load-hook will catch that. > > And if some package decides to fiddle with it from an idle-hook, the > post-command-hook will fail as well. The question is not "is it theoretically > safe" but "is it safe in practice" ? I believe it'd be good enough in practice > because I don't see much fiddling of minor-mode-map-alist outside of > toplevel expressions. I would be much easier if an element in the minor-mode-map-alist could be tagged as `keep at head of list'. IIRC we discussed this some time ago on this list, and really didn't find a way to accomplish that. But maybe such modes could simply put their map on minor-mode-overriding-map-alist instead ? Is that "legal practice"? -- Kim F. Storm <storm@cua.dk> http://www.cua.dk ^ permalink raw reply [flat|nested] 46+ messages in thread
* Re: Enhancements to "minor-mode-map-alist" functionality. 2002-04-12 21:05 ` Kim F. Storm @ 2002-04-12 20:30 ` Stefan Monnier 2002-04-12 22:08 ` Kim F. Storm 0 siblings, 1 reply; 46+ messages in thread From: Stefan Monnier @ 2002-04-12 20:30 UTC (permalink / raw) Cc: Stefan Monnier, emacs-devel > But I still think the use of the minor-mode-overriding-map-alist for > this purpose is pretty obscure (although I suspect that is the > purpose for which it was invented...) I still think it's the best solution so far. Better than a `keymap' text-property (help-follow also works on non-buttons and I care about it, since I wrote the code for it ;-). > > > Also, the keymap lookup code would also have to be careful not to > > > interpret the FUN part as a binding, > > > > You can force it to be a symbol. > > I would prefer not to do that; an alternative would be to put a > cons cell (:filter . FORM) into the keymap, causing the rest of > the keymap to be ignored if FORM returns nil. Note that if the evaluation is done inside get_keymap then there is no problem whatsoever and the map can have any shape we want (the only reason to start it with `keymap' is convenience, for instance). > I would be much easier if an element in the minor-mode-map-alist > could be tagged as `keep at head of list'. IIRC we discussed this > some time ago on this list, and really didn't find a way to > accomplish that. Indeed, it would be easy to do in add-minor-mode and define-minor-mode or with a watcher, but in the current context, it seems hopeless. Although you could of course write a general post-command-hook that does what you want and that both cua and viper could use. > But maybe such modes could simply put their map on > minor-mode-overriding-map-alist instead ? Is that "legal practice"? I don't think there's anything illegal about it, but since that variable is automatically made buffer-local, it will also require some care, although it shouldn't be too bad. Stefan ^ permalink raw reply [flat|nested] 46+ messages in thread
* Re: Enhancements to "minor-mode-map-alist" functionality. 2002-04-12 20:30 ` Stefan Monnier @ 2002-04-12 22:08 ` Kim F. Storm 0 siblings, 0 replies; 46+ messages in thread From: Kim F. Storm @ 2002-04-12 22:08 UTC (permalink / raw) Cc: emacs-devel "Stefan Monnier" <monnier+gnu/emacs@rum.cs.yale.edu> writes: > > But I still think the use of the minor-mode-overriding-map-alist for > > this purpose is pretty obscure (although I suspect that is the > > purpose for which it was invented...) > > I still think it's the best solution so far. > Better than a `keymap' text-property (help-follow also works on non-buttons > and I care about it, since I wrote the code for it ;-). What you want to accomplish is that RET runs help-follow in a help buffer. But view-mode [accidentally] has a binding for RET which shadows the help buffer's local binding of RET. Now, using the minor-mode-overriding-map-alist fixes this, but the reason I think it is obscure is that it explicitly has to mention which minor-mode is obscuring its binding... But after having discussed this with you, I now believe that the minor-mode-overriding-map-alist *is* the proper way to deal with this situation, since other minor modes may also [temporarily] rebind RET for valid reasons, so it is the view-mode binding which must be specifically overridden. As always, I appreciate the education. Thanks! -- Kim F. Storm <storm@cua.dk> http://www.cua.dk ^ permalink raw reply [flat|nested] 46+ messages in thread
* Re: Enhancements to "minor-mode-map-alist" functionality. 2002-04-12 9:31 ` Kim F. Storm 2002-04-12 13:20 ` Kim F. Storm 2002-04-12 18:20 ` Stefan Monnier @ 2002-04-13 19:05 ` Richard Stallman 2 siblings, 0 replies; 46+ messages in thread From: Richard Stallman @ 2002-04-13 19:05 UTC (permalink / raw) Cc: monnier+gnu/emacs, emacs-devel So GC-wise this only makes things marginally worse :-/ We won't install any changes that make this problem marginally worse. Please do not suggest such a thing. ^ permalink raw reply [flat|nested] 46+ messages in thread
* Re: Enhancements to "minor-mode-map-alist" functionality. 2002-04-11 22:56 Enhancements to "minor-mode-map-alist" functionality Kim F. Storm 2002-04-11 22:43 ` Stefan Monnier @ 2002-04-13 19:05 ` Richard Stallman 2002-04-13 23:30 ` Kim F. Storm 1 sibling, 1 reply; 46+ messages in thread From: Richard Stallman @ 2002-04-13 19:05 UTC (permalink / raw) Cc: emacs-devel - the new cua need a total of 7 minor mode keymaps, which must be processed in a specific order, and before all other minor mode keymaps I am surprised that the present facilities can't be used more easily. Could you explain WHY you think this is necessary? Perhaps there is already a better way. 2) Allow selection of the active keymaps in the alist to be based on evaluating a form in addition to a simple variable. Any extension to the keymap mechanism calls for careful thought. Please don't rush ahead to install any changes there before we have time to discuss this. First let's see if change is really needed. If so, then let's understand what the problem is. ^ permalink raw reply [flat|nested] 46+ messages in thread
* Re: Enhancements to "minor-mode-map-alist" functionality. 2002-04-13 19:05 ` Richard Stallman @ 2002-04-13 23:30 ` Kim F. Storm 2002-04-15 12:34 ` Stefan Monnier 2002-04-15 21:54 ` Richard Stallman 0 siblings, 2 replies; 46+ messages in thread From: Kim F. Storm @ 2002-04-13 23:30 UTC (permalink / raw) Cc: emacs-devel Richard Stallman <rms@gnu.org> writes: > - the new cua need a total of 7 minor mode keymaps, which must be > processed in a specific order, and before all other minor mode > keymaps > > I am surprised that the present facilities can't be used more easily. > Could you explain WHY you think this is necessary? Perhaps there > is already a better way. I'm pretty confiden that there isn't a _better_ way already. There are various ways to do this with the current facilities, but none of them are really satisfactory (take a look at viper mode's frequent checking of the minor-mode-map-alist to see what I mean). I'm trying to come up with a way to transparently enhance emacs' ability to "change personality" in a way that can be configured more statically. > > 2) Allow selection of the active keymaps in the alist to > be based on evaluating a form in addition to a simple variable. > > Any extension to the keymap mechanism calls for careful thought. > Please don't rush ahead to install any changes there before we > have time to discuss this. Sure! I did expect some feedback on this, and although my changes looks fairly simple, I've already been convinced that my approach isn't sufficiently generic. > > First let's see if change is really needed. If so, then let's > understand what the problem is. I've tried to explain this several times already... The fundamental problem is that some modes (like viper and cua) makes some quite fundamental changes to the way some of the standard keys works [cua remaps C-c and C-x depending on the current state of the mark (and other conditions), while viper operates in command or insert mode]. Although the current facilities are sufficient (99% at least), they _definitely_ are neither elegant, nor efficient, so I would like emacs to provide some kind of standard feature to better support such modes. E.g. for cua, I need to ensure that those 7 keymaps are in the front of minor-mode-map-alist after every command, and I need to set 7 different variables based on the current state so that the next command can be interpreted correctly... and then I have to be careful to modify that state if a timer is run which changes the state [which isn't always possible in theory, although I haven't seen the problem in practice.] I'm thinking about other ways to do this... -- Kim F. Storm <storm@cua.dk> http://www.cua.dk ^ permalink raw reply [flat|nested] 46+ messages in thread
* Re: Enhancements to "minor-mode-map-alist" functionality. 2002-04-13 23:30 ` Kim F. Storm @ 2002-04-15 12:34 ` Stefan Monnier 2002-04-17 16:03 ` Richard Stallman 2002-04-15 21:54 ` Richard Stallman 1 sibling, 1 reply; 46+ messages in thread From: Stefan Monnier @ 2002-04-15 12:34 UTC (permalink / raw) Cc: emacs-devel > The fundamental problem is that some modes (like viper and cua) makes > some quite fundamental changes to the way some of the standard keys > works [cua remaps C-c and C-x depending on the current state of the > mark (and other conditions), while viper operates in command or insert > mode]. BTW: some code in keyboard.c does something very much like function-key-map, except in a hard-coded way (drop down-mouse events if they're unbound, turn doube-clicks into single clicks if unbound, turn upper case into lower case if unbound, my own local code has added down-modifier and up-modifier events (I wanted to see if we could get a behavior similar to Windows' Alt-TAB thingy which requires catching the up-Alt event) and has correspondingly added code to drop those modifiers if they're not bound, ...). I was thinking of adding some kind of predicate binding, halfway between normal bindings and default bindings. Something like (define-key function-key-map [uppercase-p] 'map-to-lowercase) where uppercase-p is a function that takes an event and returns a boolean. In your case maybe you could save some keymap handling by doing something like (define-key cua-mode-map [conditional-control-x] 'cua-cut) where conditional-control-x returns non-nil iff the event is C-x and the mark is active. Or maybe in your specific case we could more simply reuse something existing: (define-key cua-mode-map [?\C-x] '(menu-item "cut" 'cua-cut :enable mark-active)) Making this work might be a simple matter of a few lines in get_keyelt. Stefan ^ permalink raw reply [flat|nested] 46+ messages in thread
* Re: Enhancements to "minor-mode-map-alist" functionality. 2002-04-15 12:34 ` Stefan Monnier @ 2002-04-17 16:03 ` Richard Stallman 0 siblings, 0 replies; 46+ messages in thread From: Richard Stallman @ 2002-04-17 16:03 UTC (permalink / raw) Cc: storm, emacs-devel We could consider replacing part of the command loop or the keymap lookup with Lisp code. That should make it easier to extend, and eliminate any tricky requirements about consing. On the other hand, it might cause increased storage use. ^ permalink raw reply [flat|nested] 46+ messages in thread
* Re: Enhancements to "minor-mode-map-alist" functionality. 2002-04-13 23:30 ` Kim F. Storm 2002-04-15 12:34 ` Stefan Monnier @ 2002-04-15 21:54 ` Richard Stallman 2002-04-15 23:55 ` Kim F. Storm 1 sibling, 1 reply; 46+ messages in thread From: Richard Stallman @ 2002-04-15 21:54 UTC (permalink / raw) Cc: emacs-devel > I am surprised that the present facilities can't be used more easily. > Could you explain WHY you think this is necessary? Perhaps there > is already a better way. I'm pretty confiden that there isn't a _better_ way already. Would you please explain to me why not? Before I agree that we need a new feature, I want to make sure we have not overlooked an existing good solution. Please show the reasons why (you believe) these 7 keymaps are the only way. E.g. for cua, I need to ensure that those 7 keymaps are in the front of minor-mode-map-alist after every command, The first question is why you need 7 keymaps at all. Why isn't one enough? Why can't one key binding for a given key sequence handle all the various different circumstances, through conditionals in the code? ^ permalink raw reply [flat|nested] 46+ messages in thread
* Re: Enhancements to "minor-mode-map-alist" functionality. 2002-04-15 21:54 ` Richard Stallman @ 2002-04-15 23:55 ` Kim F. Storm 0 siblings, 0 replies; 46+ messages in thread From: Kim F. Storm @ 2002-04-15 23:55 UTC (permalink / raw) Cc: emacs-devel Richard Stallman <rms@gnu.org> writes: > > I am surprised that the present facilities can't be used more easily. > > Could you explain WHY you think this is necessary? Perhaps there > > is already a better way. > > I'm pretty confiden that there isn't a _better_ way already. > > Would you please explain to me why not? > Before I agree that we need a new feature, > I want to make sure we have not overlooked an > existing good solution. Please show the reasons > why (you believe) these 7 keymaps are the only way. They are not the only way! In the CUA mode I've been promoting for the last few years I use (only) three keymaps, a pretty complicated pre-command-hook to select the proper keymap (to emulate the equivalent to the new command remapping feature!), and a very ugly/messy piece of code bound to C-c and C-x in the key-translation-map. In addition, most functions are pretty overloaded with conditionals to select the "proper action" for the current state. With the new code I've written to use the new command remapping, and the 7 keymaps, the code is _much_ simpler, as all the conditional code is now moved out of the functions and centralized around selecting the proper keymaps based on the current state. I know for sure that using 7 keymaps is a vast improvement to the old code which has been increasingly complex to maintain, so I definitely didn't want to include that code with the emacs base. > > E.g. for cua, I need to ensure that those 7 keymaps are in the front > of minor-mode-map-alist after every command, > > The first question is why you need 7 keymaps at all. Why isn't one > enough? Why can't one key binding for a given key sequence handle all > the various different circumstances, through conditionals in the code? I did that to some extent in the old version of CUA. I don't want to repeat that mistake (in this context), as it contributed significantly to the complexity of the old code. -- Kim F. Storm <storm@cua.dk> http://www.cua.dk ^ permalink raw reply [flat|nested] 46+ messages in thread
end of thread, other threads:[~2002-05-01 17:37 UTC | newest] Thread overview: 46+ messages (download: mbox.gz follow: Atom feed -- links below jump to the message on this page -- 2002-04-11 22:56 Enhancements to "minor-mode-map-alist" functionality Kim F. Storm 2002-04-11 22:43 ` Stefan Monnier 2002-04-12 9:31 ` Kim F. Storm 2002-04-12 13:20 ` Kim F. Storm 2002-04-12 18:46 ` Stefan Monnier [not found] ` <5xofgoobzr.fsf@kfs2.cua.dk> [not found] ` <200204122021.g3CKLh217680@rum.cs.yale.edu> 2002-04-14 22:32 ` Kim F. Storm 2002-04-16 20:18 ` Richard Stallman 2002-04-16 22:34 ` Kim F. Storm 2002-04-18 18:46 ` Richard Stallman 2002-04-18 23:07 ` Kim F. Storm 2002-04-19 13:43 ` Stefan Monnier 2002-04-19 15:36 ` Kim F. Storm 2002-04-19 14:46 ` Stefan Monnier 2002-04-21 17:46 ` Kim F. Storm 2002-04-22 9:28 ` Stefan Monnier 2002-04-22 15:15 ` Kim F. Storm 2002-04-19 18:42 ` Richard Stallman 2002-04-19 22:05 ` Kim F. Storm 2002-04-20 17:27 ` Richard Stallman 2002-04-21 11:08 ` Kim F. Storm 2002-04-22 7:47 ` Richard Stallman 2002-04-22 13:53 ` Kim F. Storm 2002-04-22 22:36 ` Richard Stallman 2002-04-23 10:58 ` Kim F. Storm 2002-04-22 22:36 ` Richard Stallman 2002-04-23 11:02 ` Kim F. Storm 2002-04-24 17:55 ` Richard Stallman 2002-04-26 13:44 ` Kim F. Storm 2002-04-27 22:41 ` Richard Stallman 2002-04-29 9:17 ` Kai Großjohann 2002-04-30 5:18 ` Richard Stallman 2002-04-30 21:25 ` Kim F. Storm 2002-05-01 7:14 ` Richard Stallman 2002-05-01 17:37 ` Kim F. Storm 2002-04-14 23:11 ` Kim F. Storm 2002-04-12 18:20 ` Stefan Monnier 2002-04-12 21:05 ` Kim F. Storm 2002-04-12 20:30 ` Stefan Monnier 2002-04-12 22:08 ` Kim F. Storm 2002-04-13 19:05 ` Richard Stallman 2002-04-13 19:05 ` Richard Stallman 2002-04-13 23:30 ` Kim F. Storm 2002-04-15 12:34 ` Stefan Monnier 2002-04-17 16:03 ` Richard Stallman 2002-04-15 21:54 ` Richard Stallman 2002-04-15 23:55 ` Kim F. Storm
Code repositories for project(s) associated with this public inbox https://git.savannah.gnu.org/cgit/emacs.git This is a public inbox, see mirroring instructions for how to clone and mirror all data and code used for this inbox; as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).