all messages for Emacs-related lists mirrored at yhetil.org
 help / color / mirror / code / Atom feed
* Commands with more than one keybinding in menus
@ 2013-08-13  9:33 Thorsten Jolitz
  2013-08-13 13:48 ` Michael Heerdegen
  0 siblings, 1 reply; 12+ messages in thread
From: Thorsten Jolitz @ 2013-08-13  9:33 UTC (permalink / raw)
  To: help-gnu-emacs


Hi List, 

if a command that should appear in the menu for a mode has more than one
keybinding - how do I specify which binding shows up in the menu?   

As an example, say command `demote' of 'my-mode' is bind to 'C-c C-c >'
and 'C-M-<right>', and I want the latter binding to appear in the menu
entry of 'my-mode'. Is that a matter of definition order - the binding
last defined in the mode's library is shown - or is there a way to
specify the displayed binding in the menu-map definition?

-- 
cheers,
Thorsten





^ permalink raw reply	[flat|nested] 12+ messages in thread

* Re: Commands with more than one keybinding in menus
  2013-08-13  9:33 Commands with more than one keybinding in menus Thorsten Jolitz
@ 2013-08-13 13:48 ` Michael Heerdegen
  2013-08-13 14:52   ` Thorsten Jolitz
  0 siblings, 1 reply; 12+ messages in thread
From: Michael Heerdegen @ 2013-08-13 13:48 UTC (permalink / raw)
  To: help-gnu-emacs

Thorsten Jolitz <tjolitz@gmail.com> writes:

> Hi List, 
>
> if a command that should appear in the menu for a mode has more than one
> keybinding - how do I specify which binding shows up in the menu?   
>
> As an example, say command `demote' of 'my-mode' is bind to 'C-c C-c >'
> and 'C-M-<right>', and I want the latter binding to appear in the menu
> entry of 'my-mode'. Is that a matter of definition order - the binding
> last defined in the mode's library is shown - or is there a way to
> specify the displayed binding in the menu-map definition?

Dunno about the order, but presumably you shouldn't rely on any rule.

You can specify a key binding when defining the menu explicitly - see

  (info "(elisp) Extended Menu Items")


Michael.




^ permalink raw reply	[flat|nested] 12+ messages in thread

* Re: Commands with more than one keybinding in menus
  2013-08-13 13:48 ` Michael Heerdegen
@ 2013-08-13 14:52   ` Thorsten Jolitz
  0 siblings, 0 replies; 12+ messages in thread
From: Thorsten Jolitz @ 2013-08-13 14:52 UTC (permalink / raw)
  To: help-gnu-emacs

Michael Heerdegen <michael_heerdegen@web.de> writes:

> Thorsten Jolitz <tjolitz@gmail.com> writes:
>
>> Hi List, 
>>
>> if a command that should appear in the menu for a mode has more than one
>> keybinding - how do I specify which binding shows up in the menu?   
>>
>> As an example, say command `demote' of 'my-mode' is bind to 'C-c C-c >'
>> and 'C-M-<right>', and I want the latter binding to appear in the menu
>> entry of 'my-mode'. Is that a matter of definition order - the binding
>> last defined in the mode's library is shown - or is there a way to
>> specify the displayed binding in the menu-map definition?
>
> Dunno about the order, but presumably you shouldn't rely on any rule.
>
> You can specify a key binding when defining the menu explicitly - see
>
>   (info "(elisp) Extended Menu Items")
>

thats what I needed, must have overlooked the 

,----------------------------------------------------------------------
| `:key-sequence KEY-SEQUENCE'
|      This property specifies which key sequence is likely to be bound
|      to the same command invoked by this menu item. 
`----------------------------------------------------------------------

property when searching the manual. 

Thanks.

-- 
cheers,
Thorsten




^ permalink raw reply	[flat|nested] 12+ messages in thread

* Re: Commands with more than one keybinding in menus
       [not found] <mailman.3104.1376386441.12400.help-gnu-emacs@gnu.org>
@ 2013-08-13 14:57 ` Stefan Monnier
  2013-08-13 21:13   ` Thorsten Jolitz
       [not found]   ` <mailman.3163.1376428457.12400.help-gnu-emacs@gnu.org>
  0 siblings, 2 replies; 12+ messages in thread
From: Stefan Monnier @ 2013-08-13 14:57 UTC (permalink / raw)
  To: help-gnu-emacs

> if a command that should appear in the menu for a mode has more than one
> keybinding - how do I specify which binding shows up in the menu?

(put 'my-command :advertised-binding [C-M-right])


        Stefan


^ permalink raw reply	[flat|nested] 12+ messages in thread

* Re: Commands with more than one keybinding in menus
  2013-08-13 14:57 ` Stefan Monnier
@ 2013-08-13 21:13   ` Thorsten Jolitz
  2013-08-14 12:36     ` Michael Heerdegen
       [not found]   ` <mailman.3163.1376428457.12400.help-gnu-emacs@gnu.org>
  1 sibling, 1 reply; 12+ messages in thread
From: Thorsten Jolitz @ 2013-08-13 21:13 UTC (permalink / raw)
  To: help-gnu-emacs

Stefan Monnier <monnier@iro.umontreal.ca> writes:

>> if a command that should appear in the menu for a mode has more than one
>> keybinding - how do I specify which binding shows up in the menu?
>
> (put 'my-command :advertised-binding [C-M-right])

I completely refactored the old menu and keybinding code in
'outshine.el', that was mostly inherited from older libraries
'outline-magic' and 'out-xtra', giving outshine its own menu entry while
getting rid of the "Outline" entry with its countless specialised
outline commands (many of them kind of obsolete due to a few more
powerful commands introduced in 'outline-magic' and
'outline-mode-easy-bindings').

Its looks good so far, but I could not make easy-menu to show the
advertised keybindings. The whole thing looks like this:

,-----------------------------------------------------------------------
| ;; ** Menus
| ;; *** Advertise Bindings
|
| (put 'outline-cycle :advertised-binding [TAB])
| (put 'outshine-cycle-buffer :advertised-binding [BACKTAB])
| (put 'outline-promote :advertised-binding [M-S-left])
| (put 'outline-demote :advertised-binding [M-S-right])
| [...snip...]
| (put 'outline-up-heading :advertised-binding [M-\# M-u])
| (put 'outorg-edit-as-org :advertised-binding [M-\# M-\#])
|
| ;; *** Define Menu
|
| (easy-menu-define outshine-menu outline-minor-mode-map "Outshine menu"
|   '("Outshine"
|      ["Cycle Subtree" outline-cycle
|       :active (outline-on-heading-p)]
|       [...snip...]
|      ["Up Heading" outline-up-heading t]
|     "--"
|      ["Edit As Org" outorg-edit-as-org t]))
|
| ;; add "Outshine" menu item
| (easy-menu-add outshine-menu outline-minor-mode-map)
| ;; get rid of "Outline" menu item
| (define-key outline-minor-mode-map [menu-bar outline] 'undefined)
`-----------------------------------------------------------------------

but the advertised bindings don't appear in the menu, either the
alternative bindings or no bindings at all show up.

I should mention that I use a specialised macro to define keybindings
conditional on point position, in order to not mess with user setting
(this is a minor-mode). Am I doing the advertising the wrong way?

--
cheers,
Thorsten




^ permalink raw reply	[flat|nested] 12+ messages in thread

* Re: Commands with more than one keybinding in menus
  2013-08-13 21:13   ` Thorsten Jolitz
@ 2013-08-14 12:36     ` Michael Heerdegen
  2013-08-14 13:25       ` Thorsten Jolitz
       [not found]       ` <mailman.3200.1376486779.12400.help-gnu-emacs@gnu.org>
  0 siblings, 2 replies; 12+ messages in thread
From: Michael Heerdegen @ 2013-08-14 12:36 UTC (permalink / raw)
  To: help-gnu-emacs

Thorsten Jolitz <tjolitz@gmail.com> writes:

> Its looks good so far, but I could not make easy-menu to show the
> advertised keybindings. The whole thing looks like this:
>
> ,-----------------------------------------------------------------------
> | ;; ** Menus
> | ;; *** Advertise Bindings
> |
> | (put 'outline-cycle :advertised-binding [TAB])
> | (put 'outshine-cycle-buffer :advertised-binding [BACKTAB])
> | (put 'outline-promote :advertised-binding [M-S-left])
> | (put 'outline-demote :advertised-binding [M-S-right])
> | [...snip...]
> | (put 'outline-up-heading :advertised-binding [M-\# M-u])
> | (put 'outorg-edit-as-org :advertised-binding [M-\# M-\#])
> |
> | ;; *** Define Menu
> |
> | (easy-menu-define outshine-menu outline-minor-mode-map "Outshine menu"
> |   '("Outshine"
> |      ["Cycle Subtree" outline-cycle
> |       :active (outline-on-heading-p)]
> |       [...snip...]
> |      ["Up Heading" outline-up-heading t]
> |     "--"
> |      ["Edit As Org" outorg-edit-as-org t]))
> |
> | ;; add "Outshine" menu item
> | (easy-menu-add outshine-menu outline-minor-mode-map)
> | ;; get rid of "Outline" menu item
> | (define-key outline-minor-mode-map [menu-bar outline] 'undefined)
> `-----------------------------------------------------------------------
>
> but the advertised bindings don't appear in the menu, either the
> alternative bindings or no bindings at all show up.

Looks ok to me.  But presumably Emacs doesn't match your actual bindings
with the advertised bindings.

I wonder how the actual bindings are compared with the
:advertised-binding property - equal? (Stefan?)

> I should mention that I use a specialised macro to define keybindings
> conditional on point position, in order to not mess with user setting
> (this is a minor-mode).

Please post the according code.


Michael.




^ permalink raw reply	[flat|nested] 12+ messages in thread

* Re: Commands with more than one keybinding in menus
  2013-08-14 12:36     ` Michael Heerdegen
@ 2013-08-14 13:25       ` Thorsten Jolitz
       [not found]       ` <mailman.3200.1376486779.12400.help-gnu-emacs@gnu.org>
  1 sibling, 0 replies; 12+ messages in thread
From: Thorsten Jolitz @ 2013-08-14 13:25 UTC (permalink / raw)
  To: help-gnu-emacs

Michael Heerdegen <michael_heerdegen@web.de> writes:

> Thorsten Jolitz <tjolitz@gmail.com> writes:
>
>> Its looks good so far, but I could not make easy-menu to show the
>> advertised keybindings. The whole thing looks like this:
>>
>> ,-----------------------------------------------------------------------
>> | ;; ** Menus
>> | ;; *** Advertise Bindings
>> |
>> | (put 'outline-cycle :advertised-binding [TAB])
>> | (put 'outshine-cycle-buffer :advertised-binding [BACKTAB])
>> | (put 'outline-promote :advertised-binding [M-S-left])
>> | (put 'outline-demote :advertised-binding [M-S-right])
>> | [...snip...]
>> | (put 'outline-up-heading :advertised-binding [M-\# M-u])
>> | (put 'outorg-edit-as-org :advertised-binding [M-\# M-\#])
>> |
>> | ;; *** Define Menu
>> |
>> | (easy-menu-define outshine-menu outline-minor-mode-map "Outshine menu"
>> |   '("Outshine"
>> |      ["Cycle Subtree" outline-cycle
>> |       :active (outline-on-heading-p)]
>> |       [...snip...]
>> |      ["Up Heading" outline-up-heading t]
>> |     "--"
>> |      ["Edit As Org" outorg-edit-as-org t]))
>> |
>> | ;; add "Outshine" menu item
>> | (easy-menu-add outshine-menu outline-minor-mode-map)
>> | ;; get rid of "Outline" menu item
>> | (define-key outline-minor-mode-map [menu-bar outline] 'undefined)
>> `-----------------------------------------------------------------------
>>
>> but the advertised bindings don't appear in the menu, either the
>> alternative bindings or no bindings at all show up.
>
> Looks ok to me.  But presumably Emacs doesn't match your actual bindings
> with the advertised bindings.
>
> I wonder how the actual bindings are compared with the
> :advertised-binding property - equal? (Stefan?)
>
>> I should mention that I use a specialised macro to define keybindings
>> conditional on point position, in order to not mess with user setting
>> (this is a minor-mode).
>
> Please post the according code.

Here is the macro (everything that follows is from
[[https://github.com/tj64/outshine/blob/master/outshine.el][outshine.el]]):

#+begin_src emacs-lisp
(defmacro outshine-define-key-with-fallback
  (keymap key def condition &optional mode)
  "Define key with fallback.
Binds KEY to definition DEF in keymap KEYMAP, the binding is
active when the CONDITION is true. Otherwise turns MODE off and
re-enables previous definition for KEY. If MODE is nil, tries to
recover it by stripping off \"-map\" from KEYMAP name."
  `(define-key
     ,keymap
     ,key
     (lambda (&optional arg)
       (interactive "P")
       (if ,condition ,def
         (let* ((,(if mode mode
                    (let* ((keymap-str (symbol-name keymap))
                           (mode-name-end
                            (- (string-width keymap-str) 4)))
                      (if (string=
                           "-map"
                           (substring keymap-str mode-name-end))
                          (intern (substring keymap-str 0 mode-name-end))
                        (message
                         "Could not deduce mode name from keymap name")
                        (intern "dummy-sym"))
                      )) nil)
                (original-func (key-binding ,key)))
           (condition-case nil
               (call-interactively original-func)
             (error nil)))))))
#+end_src

Here are the principal keybindings (those I want to advertise):

#+begin_src emacs-lisp
(let ((map outline-minor-mode-map))
  ;; Visibility Cycling
  (outshine-define-key-with-fallback
   map (kbd "TAB") (outline-cycle arg) (outline-on-heading-p))
  (define-key
    map (kbd "<backtab>") 'outshine-cycle-buffer)
  (outshine-define-key-with-fallback
   map (kbd "M-<left>") (outline-hide-more) (outline-on-heading-p))
  (outshine-define-key-with-fallback
   map (kbd "M-<right>") (outline-show-more) (outline-on-heading-p))
  ;; Headline Insertion
  (outshine-define-key-with-fallback
   map (kbd "M-RET") (outshine-insert-heading) (outline-on-heading-p))
  ;; Structure Editing
  (outshine-define-key-with-fallback
   map (kbd "M-S-<left>") (outline-promote) (outline-on-heading-p))
  (outshine-define-key-with-fallback
   map (kbd "M-S-<right>") (outline-demote) (outline-on-heading-p))
  (outshine-define-key-with-fallback
   map (kbd "M-S-<up>") (outline-move-subtree-up) (outline-on-heading-p))
  (outshine-define-key-with-fallback
   map (kbd "M-S-<down>") (outline-move-subtree-down) (outline-on-heading-p))
  ;; Motion
  (define-key
    map (kbd "M-<up>") 'outline-previous-visible-heading)
  (define-key
    map (kbd "M-<down>") 'outline-next-visible-heading))
#+end_src

and here an excerpt from the 'alternative' keybindings:

#+begin_src emacs-lisp
;; Set the outline-minor-mode-prefix key in your init-file
;; before loading outline-mode
(let ((map (lookup-key outline-minor-mode-map outline-minor-mode-prefix)))
  [...]
  (define-key map (kbd "I") 'outline-previous-visible-heading)
  (define-key map (kbd "K") 'outline-next-visible-heading)
  ;; for use with 'C-c' prefix
  (define-key map "\C-t" 'hide-body)
  (define-key map "\C-a" 'show-all)
  [...]
  ;; for use with 'M-#' prefix
  (define-key map "\M-t" 'hide-body)
  (define-key map "\M-a" 'show-all)
  [...]
#+end_src

I don't know how to copy the actual appearance of the "Outshine" menu item,
but it looks like this (with 'M-#' being my `outline-minor-mode-prefix' set in
my init file):

,----------------------------------
| Previous Visible Heading    M-# I
| Next Visible Heading        M-# K
`----------------------------------

and should look somehow like this when advertising works:

,----------------------------------
| Previous Visible Heading    M-<up>
| Next Visible Heading        M-<down>
`----------------------------------


--
cheers,
Thorsten




^ permalink raw reply	[flat|nested] 12+ messages in thread

* Re: Commands with more than one keybinding in menus
       [not found]   ` <mailman.3163.1376428457.12400.help-gnu-emacs@gnu.org>
@ 2013-08-14 14:09     ` Stefan Monnier
  0 siblings, 0 replies; 12+ messages in thread
From: Stefan Monnier @ 2013-08-14 14:09 UTC (permalink / raw)
  To: help-gnu-emacs

> | (put 'outline-cycle :advertised-binding [TAB])
                                            ^^^^^
There's no such binding.  You probably meant [?\t].

> | (put 'outshine-cycle-buffer :advertised-binding [BACKTAB])
                                                    ^^^^^^^^^
                                                    [backtab]

> | (put 'outline-promote :advertised-binding [M-S-left])
> | (put 'outline-demote :advertised-binding [M-S-right])

These look OK.

> | (put 'outline-up-heading :advertised-binding [M-\# M-u])
                                                 ^^^^^^^^^^
                                                 [?\M-# ?\M-u]

> | (put 'outorg-edit-as-org :advertised-binding [M-\# M-\#])
                                                 ^^^^^^^^^^^
                                                 [?\M-# ?\M-#]

> I should mention that I use a specialised macro to define keybindings
> conditional on point position, in order to not mess with user setting
> (this is a minor-mode).

Without seeing this macro and/or its use, it's hard to tell.


        Stefan


^ permalink raw reply	[flat|nested] 12+ messages in thread

* Re: Commands with more than one keybinding in menus
       [not found]       ` <mailman.3200.1376486779.12400.help-gnu-emacs@gnu.org>
@ 2013-08-14 14:12         ` Stefan Monnier
  2013-08-14 15:40           ` Thorsten Jolitz
       [not found]           ` <mailman.3205.1376494881.12400.help-gnu-emacs@gnu.org>
  0 siblings, 2 replies; 12+ messages in thread
From: Stefan Monnier @ 2013-08-14 14:12 UTC (permalink / raw)
  To: help-gnu-emacs

> (defmacro outshine-define-key-with-fallback
>   (keymap key def condition &optional mode)

You don't actually bind KEY to DEF but to another command that (may) end
up running DEF, so it's no wonder Emacs doesn't tell you that KEY is the
binding of DEF.


        Stefan


^ permalink raw reply	[flat|nested] 12+ messages in thread

* Re: Commands with more than one keybinding in menus
  2013-08-14 14:12         ` Stefan Monnier
@ 2013-08-14 15:40           ` Thorsten Jolitz
       [not found]           ` <mailman.3205.1376494881.12400.help-gnu-emacs@gnu.org>
  1 sibling, 0 replies; 12+ messages in thread
From: Thorsten Jolitz @ 2013-08-14 15:40 UTC (permalink / raw)
  To: help-gnu-emacs

Stefan Monnier <monnier@iro.umontreal.ca> writes:

>> (defmacro outshine-define-key-with-fallback
>>   (keymap key def condition &optional mode)
>
> You don't actually bind KEY to DEF but to another command that (may) end
> up running DEF, so it's no wonder Emacs doesn't tell you that KEY is the
> binding of DEF.

Your syntax corrections from the other post did fix some cases, and the
macro seems to be the root cause of the remaining cases. 

The macro was offered by a user of outshine, I only fiddled around with
it until it worked without errors. It serves its purpose, because
without it a minor-mode, unconditionally defining 'M-[S-]<arrow-key>'
bindings, runs a high risk of breaking major-mode or user settings - I
would not want to do without it.

Since all the menu entries work anyway and can thus be used with the
mouse or keyboard, I rather live with the suboptimal situation that some
entries don't show a keybinding and others only show the second best
keybinding - until a solution is found some day. 

When using `outshine.el', the new "Outshine" menu is still better than
the old "Outline" menu that showed all those not so popular specialised
outline commands instead of the more powerfull outline-magic (Org-mode)
versions.

Thanks for the help.

-- 
cheers,
Thorsten




^ permalink raw reply	[flat|nested] 12+ messages in thread

* Re: Commands with more than one keybinding in menus
       [not found]           ` <mailman.3205.1376494881.12400.help-gnu-emacs@gnu.org>
@ 2013-08-14 16:23             ` Stefan Monnier
  2013-08-14 16:55               ` Thorsten Jolitz
  0 siblings, 1 reply; 12+ messages in thread
From: Stefan Monnier @ 2013-08-14 16:23 UTC (permalink / raw)
  To: help-gnu-emacs

> The macro was offered by a user of outshine, I only fiddled around with
> it until it worked without errors. It serves its purpose, because
> without it a minor-mode, unconditionally defining 'M-[S-]<arrow-key>'
> bindings, runs a high risk of breaking major-mode or user settings - I
> would not want to do without it.

There are a few ways to have your cake and eat it too:
- Move the conditional test into the command, so the menu entries are
  bound to the same command as the keys.  If you want the menu-entries
  to skip the test, then you can do that by checking the event(s) that
  triggered the command.
- You can use ":keys STRING" in the menu.  This will show "STRING" as
  the shortcut without checking if it indeed runs the same command.
- You can use dynamic key-bindings, i.e. instead of binding your key to
  (lambda () (interactive) (if foo (CMD))), bind it to
  (menu-item "" CMD :filter (lambda (cmd) (if foo cmd))).


        Stefan


^ permalink raw reply	[flat|nested] 12+ messages in thread

* Re: Commands with more than one keybinding in menus
  2013-08-14 16:23             ` Stefan Monnier
@ 2013-08-14 16:55               ` Thorsten Jolitz
  0 siblings, 0 replies; 12+ messages in thread
From: Thorsten Jolitz @ 2013-08-14 16:55 UTC (permalink / raw)
  To: help-gnu-emacs

Stefan Monnier <monnier@iro.umontreal.ca> writes:

>> The macro was offered by a user of outshine, I only fiddled around with
>> it until it worked without errors. It serves its purpose, because
>> without it a minor-mode, unconditionally defining 'M-[S-]<arrow-key>'
>> bindings, runs a high risk of breaking major-mode or user settings - I
>> would not want to do without it.
>
> There are a few ways to have your cake and eat it too:
> - Move the conditional test into the command, so the menu entries are
>   bound to the same command as the keys.  If you want the menu-entries
>   to skip the test, then you can do that by checking the event(s) that
>   triggered the command.
> - You can use ":keys STRING" in the menu.  This will show "STRING" as
>   the shortcut without checking if it indeed runs the same command.

I quickly applied this as an immediate "solution", it solves most cases
where keybindings were missing in the menu, otherwise the :keys property
is overwritten by the alternative keybindings (that do not involve the
macro). 

> - You can use dynamic key-bindings, i.e. instead of binding your key to
>   (lambda () (interactive) (if foo (CMD))), bind it to
>   (menu-item "" CMD :filter (lambda (cmd) (if foo cmd))).

I will have a look at the other option later, thanks for the hints.

-- 
cheers,
Thorsten




^ permalink raw reply	[flat|nested] 12+ messages in thread

end of thread, other threads:[~2013-08-14 16:55 UTC | newest]

Thread overview: 12+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2013-08-13  9:33 Commands with more than one keybinding in menus Thorsten Jolitz
2013-08-13 13:48 ` Michael Heerdegen
2013-08-13 14:52   ` Thorsten Jolitz
     [not found] <mailman.3104.1376386441.12400.help-gnu-emacs@gnu.org>
2013-08-13 14:57 ` Stefan Monnier
2013-08-13 21:13   ` Thorsten Jolitz
2013-08-14 12:36     ` Michael Heerdegen
2013-08-14 13:25       ` Thorsten Jolitz
     [not found]       ` <mailman.3200.1376486779.12400.help-gnu-emacs@gnu.org>
2013-08-14 14:12         ` Stefan Monnier
2013-08-14 15:40           ` Thorsten Jolitz
     [not found]           ` <mailman.3205.1376494881.12400.help-gnu-emacs@gnu.org>
2013-08-14 16:23             ` Stefan Monnier
2013-08-14 16:55               ` Thorsten Jolitz
     [not found]   ` <mailman.3163.1376428457.12400.help-gnu-emacs@gnu.org>
2013-08-14 14:09     ` Stefan Monnier

Code repositories for project(s) associated with this external index

	https://git.savannah.gnu.org/cgit/emacs.git
	https://git.savannah.gnu.org/cgit/emacs/org-mode.git

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.