While trying to re-implement ltktest with Celtk (+ Cells Ltk) I got stumped by why Alt-Q worked for ltktest "classic" but not for me. Then I noticed:
(bind **tk** "<Alt-q>" (lambda (event) (declare (ignore event)) (setf ** exit-mainloop** t)))
Not sure how well that scales to other menu items. Not an issue here, but for one thing it fails to check whether the menu item being faked is enabled. And at any rate it requires duplicating the code associated with a menu item (tho here the menu item command was simply "exit"). Anyway...
I found something in one of my Tk books and did:
(defobserver accelerator :around ((self menu-entry-usable) new-value old-value old-value-bound-p) (call-next-method) (with-integrity (:client '(:bind nil)) (when new-value (tk-format-now "bind . ~a {~a invoke ~a}" new-value (path (upper self menu)) (index self)))))
(forget most of that, but the idea is a general solution to menu accelerators via TCL "invoke").
Only tested for the same alt-q accelerator, but it could handle any accelerator for any menu item. The TCL invoke, btw, does nothing if the menu item is disabled.
Confession: since defobserver is an on-change handler, it really should be looking for the odd case in which an accelerator got */removed/* (?!) and then clear the binding.
ken