@@ -186,7 +186,10 @@ Can be toggled at any time with `\\[cider-debug-toggle-locals]'."
186186 (?n " next" " next" )
187187 (?i " in" " in" )
188188 (?o " out" " out" )
189- (?O " force-out" nil )
189+ ; ; Force-out is not a distinct middleware command: it's `out' sent with a
190+ ; ; `force?' flag, which `cider-debug-mode-send-reply' adds because the key
191+ ; ; is uppercase.
192+ (?O " out" nil )
190193 (?h " here" " here" )
191194 (?e " eval" " eval" )
192195 (?p " inspect" " inspect" )
@@ -394,31 +397,60 @@ In order to work properly, this mode must be activated by
394397 (setq cider-debug-prompt value)
395398 (cider--debug-mode-redisplay))
396399
400+ ; ; The command catalog is the single source of truth for both the menu-bar
401+ ; ; menu (`cider-debug-mode-menu' ) and the transient menu (`cider-debug-menu' ),
402+ ; ; so the two can no longer drift apart. It is wrapped in `eval-and-compile'
403+ ; ; because the transient prefix is generated from it at macroexpansion time.
404+ (eval-and-compile
405+ (defconst cider--debug-commands
406+ '((?n cider-debug-next " Next step" stepping)
407+ (?i cider-debug-in " Step in" stepping)
408+ (?o cider-debug-out " Step out" stepping)
409+ (?O cider-debug-force-out " Step out (skip breakpoints)" stepping)
410+ (?h cider-debug-move-here " Continue to point" stepping)
411+ (?c cider-debug-continue " Continue" stepping)
412+ (?C cider-debug-continue-all " Continue non-stop" stepping)
413+ (?e cider-debug-eval " Eval in debug scope" values)
414+ (?j cider-debug-inject " Inject value" values)
415+ (?p cider-debug-inspect " Inspect current value" values)
416+ (?P cider-debug-inspect-expr " Inspect expression" values)
417+ (?l cider-debug-locals " Inspect locals" values)
418+ (?L cider-debug-toggle-locals " Toggle locals display" values)
419+ (?s cider-debug-stacktrace " Show stacktrace" session)
420+ (?t cider-debug-trace " Trace (continue, printing values)" session)
421+ (?q cider-debug-quit " Quit session" session))
422+ " Catalog of the debugger's user-facing commands.
423+ Each entry is (KEY FUNCTION DESCRIPTION GROUP), where KEY is the character
424+ that invokes FUNCTION during a session, DESCRIPTION is the label shown in
425+ the menus, and GROUP is one of `stepping' , `values' , or `session' ." )
426+
427+ (defun cider--debug-commands-in-group (group )
428+ " Return the `cider--debug-commands' entries belonging to GROUP."
429+ (seq-filter (pcase-lambda (`(,_key ,_fn ,_desc ,g )) (eq g group))
430+ cider--debug-commands)))
431+
432+ (defun cider--debug-menu-items (group )
433+ " Return `easy-menu' items for the debugger commands in GROUP."
434+ (mapcar (pcase-lambda (`(,key ,fn ,desc ,_group ))
435+ (vector desc fn :keys (string key)))
436+ (cider--debug-commands-in-group group)))
437+
397438(easy-menu-define cider-debug-mode-menu cider--debug-mode-map
398439 " Menu for CIDER debug mode."
399- `(" CIDER Debugger"
400- [" Next step" (cider-debug-mode-send-reply " :next" ) :keys " n" ]
401- [" Continue" (cider-debug-mode-send-reply " :continue" ) :keys " c" ]
402- [" Continue non-stop" (cider-debug-mode-send-reply " :continue-all" ) :keys " C" ]
403- [" Move out of sexp" (cider-debug-mode-send-reply " :out" ) :keys " o" ]
404- [" Forced move out of sexp" (cider-debug-mode-send-reply " :out" nil t ) :keys " O" ]
405- [" Move to current position" (cider-debug-mode-send-reply " :here" ) :keys " h" ]
406- [" Quit" (cider-debug-mode-send-reply " :quit" ) :keys " q" ]
407- " --"
408- [" Evaluate in current scope" (cider-debug-mode-send-reply " :eval" ) :keys " e" ]
409- [" Inject value" (cider-debug-mode-send-reply " :inject" ) :keys " i" ]
410- [" Inspect current value" (cider-debug-mode-send-reply " :inspect" ) :keys " p" ]
411- [" Inspect expression" (cider-debug-mode-send-reply " :inspect-prompt" ) :keys " P" ]
412- [" Inspect local variables" (cider-debug-mode-send-reply " :locals" ) :keys " l" ]
413- " --"
414- (" Configure keys prompt"
415- [" Don't show keys" (cider--debug-set-prompt nil ) :style toggle :selected (eq cider-debug-prompt nil )]
416- [" Show in minibuffer" (cider--debug-set-prompt 'minibuffer ) :style toggle :selected (eq cider-debug-prompt 'minibuffer )]
417- [" Show above function" (cider--debug-set-prompt 'overlay ) :style toggle :selected (eq cider-debug-prompt 'overlay )]
418- [" Show in both places" (cider--debug-set-prompt t ) :style toggle :selected (eq cider-debug-prompt t )]
419- " --"
420- [" List locals" cider-debug-toggle-locals :style toggle :selected cider-debug-display-locals])
421- [" Customize" (customize-group 'cider-debug )]))
440+ (append
441+ '(" CIDER Debugger" )
442+ (cider--debug-menu-items 'stepping )
443+ '(" --" )
444+ (cider--debug-menu-items 'values )
445+ '(" --" )
446+ (cider--debug-menu-items 'session )
447+ '(" --" )
448+ '((" Configure keys prompt"
449+ [" Don't show keys" (cider--debug-set-prompt nil ) :style toggle :selected (eq cider-debug-prompt nil )]
450+ [" Show in minibuffer" (cider--debug-set-prompt 'minibuffer ) :style toggle :selected (eq cider-debug-prompt 'minibuffer )]
451+ [" Show above function" (cider--debug-set-prompt 'overlay ) :style toggle :selected (eq cider-debug-prompt 'overlay )]
452+ [" Show in both places" (cider--debug-set-prompt t ) :style toggle :selected (eq cider-debug-prompt t )])
453+ [" Customize" (customize-group 'cider-debug )])))
422454
423455; ; Named commands for the debugger replies, so they can be invoked outside
424456; ; the single-key session bindings (M-x, the transient menu below, etc.).
@@ -493,33 +525,30 @@ In order to work properly, this mode must be activated by
493525 (interactive )
494526 (cider-debug-mode-send-reply " :quit" ))
495527
496- (transient-define-prefix cider-debug-menu ()
497- " Transient menu for the CIDER debugger.
528+ (eval-and-compile
529+ (defun cider--debug-transient-column (title group )
530+ " Build a transient column vector titled TITLE for GROUP.
531+ The suffixes are derived from `cider--debug-commands' ."
532+ (apply #'vector title
533+ (mapcar (pcase-lambda (`(,key ,fn ,desc ,_group ))
534+ (list (string key) desc fn))
535+ (cider--debug-commands-in-group group)))))
536+
537+ (defmacro cider--debug-define-menu ()
538+ " Define the `cider-debug-menu' transient from `cider--debug-commands' ."
539+ `(transient-define-prefix cider-debug-menu ()
540+ " Transient menu for the CIDER debugger.
498541It groups and labels the debugger's single-key commands, so they can be
499542discovered without memorizing the key prompt. The sub-keys match the
500543session bindings, so this menu is purely additive."
501- [[" Stepping"
502- (" n" " Next step" cider-debug-next)
503- (" i" " Step in" cider-debug-in)
504- (" o" " Step out" cider-debug-out)
505- (" O" " Step out (skip breakpoints)" cider-debug-force-out)
506- (" h" " Continue to point" cider-debug-move-here)
507- (" c" " Continue" cider-debug-continue)
508- (" C" " Continue non-stop" cider-debug-continue-all)]
509- [" Values"
510- (" e" " Eval in debug scope" cider-debug-eval)
511- (" j" " Inject value" cider-debug-inject)
512- (" p" " Inspect current value" cider-debug-inspect)
513- (" P" " Inspect expression" cider-debug-inspect-expr)
514- (" l" " Inspect locals" cider-debug-locals)
515- (" L" " Toggle locals display" cider-debug-toggle-locals)]
516- [" Session"
517- (" s" " Show stacktrace" cider-debug-stacktrace)
518- (" t" " Trace (continue, printing values)" cider-debug-trace)
519- (" q" " Quit session" cider-debug-quit)]]
520- ; ; Uppercase `here' , preserving the H binding's forced variant.
521- [:hide (lambda () t )
522- (" H" " Continue to point (forced)" cider-debug-move-here)])
544+ [,(cider--debug-transient-column " Stepping" 'stepping )
545+ ,(cider--debug-transient-column " Values" 'values )
546+ ,(cider--debug-transient-column " Session" 'session )]
547+ ; ; Uppercase `here' , preserving the H binding's forced variant.
548+ [:hide (lambda () t )
549+ (" H" " Continue to point (forced)" cider-debug-move-here)]))
550+
551+ (cider--debug-define-menu)
523552
524553(defun cider--uppercase-command-p ()
525554 " Return non-nil if the last command was uppercase letter."
0 commit comments