Add Qt startup crash breadcrumbs

ober

9a564a71402d3d9557adc74a22f8611b2be497b6

diff --git a/lib/jerboa-emacs/qt/app.sls b/lib/jerboa-emacs/qt/app.sls
index 30fd00a..7eea3eb 100644
--- a/lib/jerboa-emacs/qt/app.sls
+++ b/lib/jerboa-emacs/qt/app.sls
@@ -757,595 +757,618 @@
                           (sci-send ed SCI_SETXOFFSET 0)
                           (qt-widget-set-updates-enabled! ed #t)))
                       (loop (cdr wins))))))])))
-  (def (qt-do-init! qt-app args) (init-jemacs-log!)
-       (init-verbose-log!)
-       (verbose-log! "jemacs-qt verbose mode ON")
-       (define-standard-faces!)
-       (let-values ([(saved-theme saved-font-family saved-font-size)
-                     (theme-settings-load!)])
-         (when (and saved-theme (theme-get saved-theme))
-           (set! *current-theme* saved-theme))
-         (when (and saved-font-family
-                    (not (string-empty? saved-font-family)))
-           (set! *default-font-family* saved-font-family))
-         (when (and saved-font-size
-                    (>= saved-font-size 6)
-                    (<= saved-font-size 72))
-           (set! *default-font-size* saved-font-size)))
-       (load-theme! *current-theme*) (custom-faces-load!)
-       (qt-app-set-style-sheet! qt-app (theme-stylesheet))
-       (let* ([win (qt-main-window-create)]
-              [central (qt-widget-create win)]
-              [layout (qt-vbox-layout-create central)]
-              [tab-bar (qt-widget-create central)]
-              [tab-layout (qt-hbox-layout-create tab-bar)]
-              [splitter (qt-splitter-create QT_VERTICAL central)]
-              [_ (begin
-                   (qt-splitter-set-handle-width! splitter 3)
-                   (qt-widget-set-style-sheet!
-                     splitter
-                     "QSplitter::handle { background: #51afef; }"))]
-              [echo-label (qt-label-create "" central)]
-              [fr (qt-frame-init! win splitter)]
-              [app (new-app-state fr)])
-         (qt-widget-set-minimum-height! tab-bar 26)
-         (qt-widget-set-style-sheet!
-           tab-bar
-           "background: #1e1e1e; border-bottom: 1px solid #383838;")
-         (qt-layout-set-margins! tab-layout 2 2 2 2)
-         (qt-layout-set-spacing! tab-layout 2)
-         (set! *tab-bar-layout* tab-layout)
-         (set! *tab-bar-widget* tab-bar)
-         (qt-widget-set-minimum-height! echo-label 28)
-         (let ([font-css (string-append " font-family: " *default-font-family*
-                           "; font-size: "
-                           (number->string *default-font-size*) "pt;")])
-           (qt-widget-set-style-sheet!
-             echo-label
-             (string-append
-               "color: #d8d8d8; background: #1e1e1e;"
-               font-css
-               " padding: 4px 6px; border-top: 1px solid #484848;")))
-         (qt-layout-add-widget! layout tab-bar)
-         (qt-layout-add-widget! layout splitter)
-         (qt-layout-add-widget! layout echo-label)
-         (qt-layout-set-stretch-factor! layout tab-bar 0)
-         (qt-layout-set-stretch-factor! layout splitter 1)
-         (qt-layout-set-stretch-factor! layout echo-label 0)
-         (qt-widget-set-size-policy!
-           tab-bar
-           QT_SIZE_PREFERRED
-           QT_SIZE_FIXED)
-         (qt-widget-set-size-policy!
-           echo-label
-           QT_SIZE_PREFERRED
-           QT_SIZE_FIXED)
-         (qt-layout-set-margins! layout 0 0 0 0)
-         (qt-layout-set-spacing! layout 0)
-         (qt-minibuffer-init! echo-label qt-app layout)
-         (set! *qt-app-ptr* qt-app)
-         (qt-window-set-app-ptr! qt-app)
-         (setup-default-bindings!)
-         (setup-command-docs!)
-         (qt-register-all-commands!)
-         (jemacs-log!
-           "commands registered: "
-           (number->string (hash-length *all-commands*))
-           " total")
-         (let ([image-key-installed (make-hash-table-eq)])
-           (add-hook!
-             'post-buffer-attach-hook
-             (lambda (editor buf)
-               (with-catch
-                 (lambda (e)
-                   (verbose-log!
-                     "post-buffer-attach-hook ERROR: "
-                     (with-output-to-string
-                       (lambda () (display-exception e)))))
-                 (lambda ()
-                   (cond
-                     [(hash-get *terminal-widget-map* buf) =>
-                      (lambda (session)
-                        (let ([win (hash-get *editor-window-map* editor)])
-                          (when win
-                            (let* ([container (qt-edit-window-container
-                                                win)]
-                                   [view (terminal-ensure-view!
-                                           app
-                                           buf
-                                           session
-                                           container)])
-                              (qt-stacked-widget-set-current-widget!
-                                container
-                                view)
-                              (when (eq? win
-                                         (qt-current-window
-                                           (app-state-frame app)))
-                                (qt-terminal-view-focus! view))))))]
-                     [(image-buffer? buf)
-                      (qt-show-image-buffer! editor buf)
-                      (let ([win (hash-get *editor-window-map* editor)])
-                        (when (and win (qt-edit-window-image-scroll win))
-                          (let ([scroll (qt-edit-window-image-scroll win)])
-                            (unless (hash-get image-key-installed scroll)
-                              ((app-state-key-handler app) scroll)
-                              (hash-put! image-key-installed scroll #t))
-                            (qt-widget-set-focus! scroll))))]
-                     [else
-                      (qt-hide-image-buffer! editor)
-                      (qt-reapply-highlighting! editor buf)
-                      (qt-widget-set-focus! editor)]))))))
-         (recent-files-load!)
-         (bookmarks-load! app)
-         (custom-keys-load!)
-         (abbrevs-load!)
-         (savehist-load!)
-         (save-place-load!)
-         (gsh-history-load!)
-         (load-init-file!)
-         (init-file-load!)
-         (qt-setup-menubar! app win)
-         (let* ([ed (qt-current-editor fr)]
-                [saved (scratch-restore!)]
-                [text (or saved
-                          (string-append ";; Jemacs — *scratch*\n" ";;\n"
-                            ";; Key Bindings:\n"
-                            ";;   C-x C-f   Find file        C-x C-s   Save buffer\n"
-                            ";;   C-x b     Switch buffer     C-x k     Kill buffer\n"
-                            ";;   C-x C-r   Recent files      M-x       Extended command\n"
-                            ";;   C-s       Search forward    M-%       Query replace\n"
-                            ";;   C-x 2     Split window      C-x o     Other window\n"
-                            ";;   C-h f     Describe command   C-h k     Describe key\n"
-                            ";;\n"
-                            ";; This buffer is for Jerboa Scheme evaluation.\n"
-                            ";; Type expressions and use M-x eval-buffer to evaluate.\n\n"))])
-           (qt-plain-text-edit-set-text! ed text)
-           (qt-text-document-set-modified!
-             (buffer-doc-pointer (qt-current-buffer fr))
-             #f)
-           (qt-plain-text-edit-set-cursor-position! ed 0)
-           (scratch-update-text! text))
-         (run-hooks! 'after-init-hook app)
-         (let ([key-handler (lambda ()
-                              (when (not *minibuffer-active?*)
-                                (let* ([code (qt-last-key-code)]
-                                       [mods (normalize-qt-mods
-                                               (qt-last-key-modifiers))]
-                                       [raw-text (qt-last-key-text)]
-                                       [autorepeat? (qt-last-key-autorepeat?)]
-                                       [text (if (= (string-length
-                                                      raw-text)
-                                                    1)
-                                                 (string
-                                                   (key-translate-char
-                                                     (string-ref
-                                                       raw-text
-                                                       0)))
-                                                 raw-text)])
-                                  (let ([ks (qt-key-event->string
-                                              code
-                                              mods
-                                              text)])
-                                    (when ks
-                                      (key-lossage-record! app ks)
-                                      (verbose-log! "KEY " ks " code="
-                                        (number->string code) " mods="
-                                        (number->string mods))))
-                                  (cond
-                                    [*isearch-active*
-                                     (let ([handled (isearch-handle-key!
-                                                      app
-                                                      code
-                                                      mods
-                                                      text)])
-                                       (qt-update-visual-decorations!
-                                         (qt-current-editor
-                                           (app-state-frame app)))
-                                       (qt-modeline-update! app)
-                                       (qt-echo-draw!
-                                         (app-state-echo app)
-                                         echo-label)
-                                       (when (not handled)
-                                         (let-values ([(action data new-state)
-                                                       (qt-key-state-feed!
-                                                         (app-state-key-state
-                                                           app)
-                                                         code
-                                                         mods
-                                                         text)])
-                                           (app-state-key-state-set!
-                                             app
-                                             new-state)
-                                           (when (eq? action 'command)
-                                             (execute-command!
-                                               app
-                                               data)))))]
-                                    [*qreplace-active*
-                                     (qreplace-handle-key!
-                                       app
-                                       code
-                                       mods
-                                       text)
-                                     (qt-modeline-update! app)
-                                     (qt-echo-draw!
-                                       (app-state-echo app)
-                                       echo-label)]
-                                    [*snake-active*
-                                     (snake-handle-key!
+  (def (qt-startup-trace msg)
+       (display "TRACE qt-do-init: " (current-error-port))
+       (display msg (current-error-port))
+       (display "\n" (current-error-port))
+       (flush-output-port (current-error-port)))
+  (def (qt-do-init! qt-app args) (qt-startup-trace "enter")
+   (init-jemacs-log!) (init-verbose-log!)
+   (qt-startup-trace "logs ready")
+   (verbose-log! "jemacs-qt verbose mode ON")
+   (qt-startup-trace "faces begin") (define-standard-faces!)
+   (qt-startup-trace "faces done")
+   (qt-startup-trace "theme settings begin")
+   (let-values ([(saved-theme saved-font-family saved-font-size)
+                 (theme-settings-load!)])
+     (when (and saved-theme (theme-get saved-theme))
+       (set! *current-theme* saved-theme))
+     (when (and saved-font-family
+                (not (string-empty? saved-font-family)))
+       (set! *default-font-family* saved-font-family))
+     (when (and saved-font-size
+                (>= saved-font-size 6)
+                (<= saved-font-size 72))
+       (set! *default-font-size* saved-font-size)))
+   (qt-startup-trace "theme settings done")
+   (qt-startup-trace "load theme begin")
+   (load-theme! *current-theme*)
+   (qt-startup-trace "load theme done")
+   (qt-startup-trace "custom faces begin") (custom-faces-load!)
+   (qt-startup-trace "custom faces done")
+   (qt-startup-trace "stylesheet begin")
+   (qt-app-set-style-sheet! qt-app (theme-stylesheet))
+   (qt-startup-trace "stylesheet done")
+   (qt-startup-trace "frame create begin")
+   (let* ([win (qt-main-window-create)]
+          [central (qt-widget-create win)]
+          [layout (qt-vbox-layout-create central)]
+          [tab-bar (qt-widget-create central)]
+          [tab-layout (qt-hbox-layout-create tab-bar)]
+          [splitter (qt-splitter-create QT_VERTICAL central)]
+          [_ (begin
+               (qt-splitter-set-handle-width! splitter 3)
+               (qt-widget-set-style-sheet!
+                 splitter
+                 "QSplitter::handle { background: #51afef; }"))]
+          [echo-label (qt-label-create "" central)]
+          [fr (qt-frame-init! win splitter)]
+          [app (new-app-state fr)])
+     (qt-startup-trace "frame create done")
+     (qt-startup-trace "layout setup begin")
+     (qt-widget-set-minimum-height! tab-bar 26)
+     (qt-widget-set-style-sheet!
+       tab-bar
+       "background: #1e1e1e; border-bottom: 1px solid #383838;")
+     (qt-layout-set-margins! tab-layout 2 2 2 2)
+     (qt-layout-set-spacing! tab-layout 2)
+     (set! *tab-bar-layout* tab-layout)
+     (set! *tab-bar-widget* tab-bar)
+     (qt-widget-set-minimum-height! echo-label 28)
+     (let ([font-css (string-append " font-family: " *default-font-family*
+                       "; font-size: " (number->string *default-font-size*)
+                       "pt;")])
+       (qt-widget-set-style-sheet!
+         echo-label
+         (string-append
+           "color: #d8d8d8; background: #1e1e1e;"
+           font-css
+           " padding: 4px 6px; border-top: 1px solid #484848;")))
+     (qt-layout-add-widget! layout tab-bar)
+     (qt-layout-add-widget! layout splitter)
+     (qt-layout-add-widget! layout echo-label)
+     (qt-layout-set-stretch-factor! layout tab-bar 0)
+     (qt-layout-set-stretch-factor! layout splitter 1)
+     (qt-layout-set-stretch-factor! layout echo-label 0)
+     (qt-widget-set-size-policy!
+       tab-bar
+       QT_SIZE_PREFERRED
+       QT_SIZE_FIXED)
+     (qt-widget-set-size-policy!
+       echo-label
+       QT_SIZE_PREFERRED
+       QT_SIZE_FIXED)
+     (qt-layout-set-margins! layout 0 0 0 0)
+     (qt-layout-set-spacing! layout 0)
+     (qt-startup-trace "layout setup done")
+     (qt-startup-trace "minibuffer begin")
+     (qt-minibuffer-init! echo-label qt-app layout)
+     (qt-startup-trace "minibuffer done")
+     (set! *qt-app-ptr* qt-app)
+     (qt-window-set-app-ptr! qt-app)
+     (qt-startup-trace "app pointers set")
+     (qt-startup-trace "commands begin")
+     (setup-default-bindings!)
+     (setup-command-docs!)
+     (qt-register-all-commands!)
+     (jemacs-log!
+       "commands registered: "
+       (number->string (hash-length *all-commands*))
+       " total")
+     (qt-startup-trace "commands done")
+     (let ([image-key-installed (make-hash-table-eq)])
+       (add-hook!
+         'post-buffer-attach-hook
+         (lambda (editor buf)
+           (with-catch
+             (lambda (e)
+               (verbose-log!
+                 "post-buffer-attach-hook ERROR: "
+                 (with-output-to-string
+                   (lambda () (display-exception e)))))
+             (lambda ()
+               (cond
+                 [(hash-get *terminal-widget-map* buf) =>
+                  (lambda (session)
+                    (let ([win (hash-get *editor-window-map* editor)])
+                      (when win
+                        (let* ([container (qt-edit-window-container win)]
+                               [view (terminal-ensure-view!
                                        app
-                                       code
-                                       mods
-                                       text)]
-                                    [else
-                                     (letrec ([terminal-pty-intercept? (lambda (code
-                                                                                mods
-                                                                                text)
-                                                                         (and (null?
-                                                                                (key-state-prefix-keys
-                                                                                  (app-state-key-state
-                                                                                    app)))
-                                                                              (let* ([ctrl? (not (zero?
-                                                                                                   (bitwise-and
-                                                                                                     mods
-                                                                                                     QT_MOD_CTRL)))]
-                                                                                     [alt? (not (zero?
-                                                                                                  (bitwise-and
-                                                                                                    mods
-                                                                                                    QT_MOD_ALT)))]
-                                                                                     [buf (qt-current-buffer
-                                                                                            (app-state-frame
-                                                                                              app))])
-                                                                                (and (not (and ctrl?
-                                                                                               (not alt?)
-                                                                                               (or (= code
-                                                                                                      (+ QT_KEY_A
-                                                                                                         23))
-                                                                                                   (= code
-                                                                                                      (+ QT_KEY_A
-                                                                                                         6)))))
-                                                                                     (not (and alt?
-                                                                                               (not ctrl?)
+                                       buf
+                                       session
+                                       container)])
+                          (qt-stacked-widget-set-current-widget!
+                            container
+                            view)
+                          (when (eq? win
+                                     (qt-current-window
+                                       (app-state-frame app)))
+                            (qt-terminal-view-focus! view))))))]
+                 [(image-buffer? buf)
+                  (qt-show-image-buffer! editor buf)
+                  (let ([win (hash-get *editor-window-map* editor)])
+                    (when (and win (qt-edit-window-image-scroll win))
+                      (let ([scroll (qt-edit-window-image-scroll win)])
+                        (unless (hash-get image-key-installed scroll)
+                          ((app-state-key-handler app) scroll)
+                          (hash-put! image-key-installed scroll #t))
+                        (qt-widget-set-focus! scroll))))]
+                 [else
+                  (qt-hide-image-buffer! editor)
+                  (qt-reapply-highlighting! editor buf)
+                  (qt-widget-set-focus! editor)]))))))
+     (qt-startup-trace "post-buffer-attach hook installed")
+     (qt-startup-trace "recent files begin")
+     (recent-files-load!)
+     (qt-startup-trace "recent files done")
+     (qt-startup-trace "bookmarks begin")
+     (bookmarks-load! app)
+     (qt-startup-trace "bookmarks done")
+     (qt-startup-trace "custom keys begin")
+     (custom-keys-load!)
+     (qt-startup-trace "custom keys done")
+     (qt-startup-trace "abbrevs begin")
+     (abbrevs-load!)
+     (qt-startup-trace "abbrevs done")
+     (qt-startup-trace "savehist begin")
+     (savehist-load!)
+     (qt-startup-trace "savehist done")
+     (qt-startup-trace "save place begin")
+     (save-place-load!)
+     (qt-startup-trace "save place done")
+     (qt-startup-trace "gsh history begin")
+     (gsh-history-load!)
+     (qt-startup-trace "gsh history done")
+     (qt-startup-trace "legacy init begin")
+     (load-init-file!)
+     (qt-startup-trace "legacy init done")
+     (qt-startup-trace "init file begin")
+     (init-file-load!)
+     (qt-startup-trace "init file done")
+     (qt-startup-trace "menubar begin")
+     (qt-setup-menubar! app win)
+     (qt-startup-trace "menubar done")
+     (qt-startup-trace "scratch begin")
+     (let* ([ed (qt-current-editor fr)]
+            [saved (scratch-restore!)]
+            [text (or saved
+                      (string-append ";; Jemacs — *scratch*\n" ";;\n"
+                        ";; Key Bindings:\n"
+                        ";;   C-x C-f   Find file        C-x C-s   Save buffer\n"
+                        ";;   C-x b     Switch buffer     C-x k     Kill buffer\n"
+                        ";;   C-x C-r   Recent files      M-x       Extended command\n"
+                        ";;   C-s       Search forward    M-%       Query replace\n"
+                        ";;   C-x 2     Split window      C-x o     Other window\n"
+                        ";;   C-h f     Describe command   C-h k     Describe key\n"
+                        ";;\n"
+                        ";; This buffer is for Jerboa Scheme evaluation.\n"
+                        ";; Type expressions and use M-x eval-buffer to evaluate.\n\n"))])
+       (qt-plain-text-edit-set-text! ed text)
+       (qt-text-document-set-modified!
+         (buffer-doc-pointer (qt-current-buffer fr))
+         #f)
+       (qt-plain-text-edit-set-cursor-position! ed 0)
+       (scratch-update-text! text))
+     (qt-startup-trace "scratch done")
+     (qt-startup-trace "after-init hook begin")
+     (run-hooks! 'after-init-hook app)
+     (qt-startup-trace "after-init hook done")
+     (qt-startup-trace "key handler setup begin")
+     (let ([key-handler (lambda ()
+                          (when (not *minibuffer-active?*)
+                            (let* ([code (qt-last-key-code)]
+                                   [mods (normalize-qt-mods
+                                           (qt-last-key-modifiers))]
+                                   [raw-text (qt-last-key-text)]
+                                   [autorepeat? (qt-last-key-autorepeat?)]
+                                   [text (if (= (string-length raw-text) 1)
+                                             (string
+                                               (key-translate-char
+                                                 (string-ref raw-text 0)))
+                                             raw-text)])
+                              (let ([ks (qt-key-event->string
+                                          code
+                                          mods
+                                          text)])
+                                (when ks
+                                  (key-lossage-record! app ks)
+                                  (verbose-log! "KEY " ks " code="
+                                    (number->string code) " mods="
+                                    (number->string mods))))
+                              (cond
+                                [*isearch-active*
+                                 (let ([handled (isearch-handle-key!
+                                                  app
+                                                  code
+                                                  mods
+                                                  text)])
+                                   (qt-update-visual-decorations!
+                                     (qt-current-editor
+                                       (app-state-frame app)))
+                                   (qt-modeline-update! app)
+                                   (qt-echo-draw!
+                                     (app-state-echo app)
+                                     echo-label)
+                                   (when (not handled)
+                                     (let-values ([(action data new-state)
+                                                   (qt-key-state-feed!
+                                                     (app-state-key-state
+                                                       app)
+                                                     code
+                                                     mods
+                                                     text)])
+                                       (app-state-key-state-set!
+                                         app
+                                         new-state)
+                                       (when (eq? action 'command)
+                                         (execute-command! app data)))))]
+                                [*qreplace-active*
+                                 (qreplace-handle-key! app code mods text)
+                                 (qt-modeline-update! app)
+                                 (qt-echo-draw!
+                                   (app-state-echo app)
+                                   echo-label)]
+                                [*snake-active*
+                                 (snake-handle-key! app code mods text)]
+                                [else
+                                 (letrec ([terminal-pty-intercept? (lambda (code
+                                                                            mods
+                                                                            text)
+                                                                     (and (null?
+                                                                            (key-state-prefix-keys
+                                                                              (app-state-key-state
+                                                                                app)))
+                                                                          (let* ([ctrl? (not (zero?
+                                                                                               (bitwise-and
+                                                                                                 mods
+                                                                                                 QT_MOD_CTRL)))]
+                                                                                 [alt? (not (zero?
+                                                                                              (bitwise-and
+                                                                                                mods
+                                                                                                QT_MOD_ALT)))]
+                                                                                 [buf (qt-current-buffer
+                                                                                        (app-state-frame
+                                                                                          app))])
+                                                                            (and (not (and ctrl?
+                                                                                           (not alt?)
+                                                                                           (or (= code
+                                                                                                  (+ QT_KEY_A
+                                                                                                     23))
                                                                                                (= code
                                                                                                   (+ QT_KEY_A
-                                                                                                     23))))
-                                                                                     (let ([send! (cond
-                                                                                                    [(terminal-buffer?
-                                                                                                       buf)
-                                                                                                     (let ([ts (hash-get
-                                                                                                                 *terminal-state*
-                                                                                                                 buf)])
-                                                                                                       (and ts
-                                                                                                            (terminal-pty-busy?
-                                                                                                              ts)
-                                                                                                            (lambda (s)
-                                                                                                              (terminal-send-input!
-                                                                                                                ts
-                                                                                                                s))))]
-                                                                                                    [(shell-buffer?
-                                                                                                       buf)
-                                                                                                     (let ([ss (hash-get
-                                                                                                                 *shell-state*
-                                                                                                                 buf)])
-                                                                                                       (and ss
-                                                                                                            (shell-pty-busy?
-                                                                                                              ss)
-                                                                                                            (lambda (s)
-                                                                                                              (shell-send-input!
-                                                                                                                ss
-                                                                                                                s))))]
-                                                                                                    [else
-                                                                                                     #f])])
-                                                                                       (and send!
-                                                                                            (cond
-                                                                                              [(and ctrl?
-                                                                                                    (not alt?)
-                                                                                                    (>= code
-                                                                                                        QT_KEY_A)
-                                                                                                    (<= code
-                                                                                                        QT_KEY_Z))
-                                                                                               (send!
-                                                                                                 (string
-                                                                                                   (integer->char
-                                                                                                     (+ 1
-                                                                                                        (- code
-                                                                                                           QT_KEY_A)))))
-                                                                                               #t]
-                                                                                              [(= code
-                                                                                                  QT_KEY_UP)
-                                                                                               (send!
-                                                                                                 "\x1B;[A")
-                                                                                               #t]
-                                                                                              [(= code
-                                                                                                  QT_KEY_DOWN)
-                                                                                               (send!
-                                                                                                 "\x1B;[B")
-                                                                                               #t]
-                                                                                              [(= code
-                                                                                                  QT_KEY_RIGHT)
-                                                                                               (send!
-                                                                                                 "\x1B;[C")
-                                                                                               #t]
-                                                                                              [(= code
-                                                                                                  QT_KEY_LEFT)
-                                                                                               (send!
-                                                                                                 "\x1B;[D")
-                                                                                               #t]
-                                                                                              [(or (= code
-                                                                                                      QT_KEY_RETURN)
-                                                                                                   (= code
-                                                                                                      QT_KEY_ENTER))
-                                                                                               (send!
-                                                                                                 "\r")
-                                                                                               #t]
-                                                                                              [(= code
-                                                                                                  QT_KEY_BACKSPACE)
-                                                                                               (send!
-                                                                                                 (string
-                                                                                                   (integer->char
-                                                                                                     127)))
-                                                                                               #t]
-                                                                                              [(= code
-                                                                                                  QT_KEY_DELETE)
-                                                                                               (send!
-                                                                                                 "\x1B;[3~")
-                                                                                               #t]
-                                                                                              [(= code
-                                                                                                  QT_KEY_TAB)
-                                                                                               (send!
-                                                                                                 "\t")
-                                                                                               #t]
-                                                                                              [(= code
-                                                                                                  QT_KEY_ESCAPE)
-                                                                                               (send!
-                                                                                                 "\x1B;")
-                                                                                               #t]
-                                                                                              [(= code
-                                                                                                  QT_KEY_HOME)
-                                                                                               (send!
-                                                                                                 "\x1B;[H")
-                                                                                               #t]
-                                                                                              [(= code
-                                                                                                  QT_KEY_END)
-                                                                                               (send!
-                                                                                                 "\x1B;[F")
-                                                                                               #t]
-                                                                                              [(= code
-                                                                                                  QT_KEY_PAGE_UP)
-                                                                                               (send!
-                                                                                                 "\x1B;[5~")
-                                                                                               #t]
-                                                                                              [(= code
-                                                                                                  QT_KEY_PAGE_DOWN)
-                                                                                               (send!
-                                                                                                 "\x1B;[6~")
-                                                                                               #t]
-                                                                                              [(and (= (string-length
-                                                                                                         text)
-                                                                                                       1)
-                                                                                                    (> (char->integer
-                                                                                                         (string-ref
-                                                                                                           text
-                                                                                                           0))
-                                                                                                       31))
-                                                                                               (send!
-                                                                                                 text)
-                                                                                               #t]
-                                                                                              [else
-                                                                                               #f])))))))]
-                                              [do-normal-key! (lambda (code
-                                                                       mods
-                                                                       text)
-                                                                (unless (terminal-pty-intercept?
+                                                                                                     6)))))
+                                                                                 (not (and alt?
+                                                                                           (not ctrl?)
+                                                                                           (= code
+                                                                                              (+ QT_KEY_A
+                                                                                                 23))))
+                                                                                 (let ([send! (cond
+                                                                                                [(terminal-buffer?
+                                                                                                   buf)
+                                                                                                 (let ([ts (hash-get
+                                                                                                             *terminal-state*
+                                                                                                             buf)])
+                                                                                                   (and ts
+                                                                                                        (terminal-pty-busy?
+                                                                                                          ts)
+                                                                                                        (lambda (s)
+                                                                                                          (terminal-send-input!
+                                                                                                            ts
+                                                                                                            s))))]
+                                                                                                [(shell-buffer?
+                                                                                                   buf)
+                                                                                                 (let ([ss (hash-get
+                                                                                                             *shell-state*
+                                                                                                             buf)])
+                                                                                                   (and ss
+                                                                                                        (shell-pty-busy?
+                                                                                                          ss)
+                                                                                                        (lambda (s)
+                                                                                                          (shell-send-input!
+                                                                                                            ss
+                                                                                                            s))))]
+                                                                                                [else
+                                                                                                 #f])])
+                                                                                   (and send!
+                                                                                        (cond
+                                                                                          [(and ctrl?
+                                                                                                (not alt?)
+                                                                                                (>= code
+                                                                                                    QT_KEY_A)
+                                                                                                (<= code
+                                                                                                    QT_KEY_Z))
+                                                                                           (send!
+                                                                                             (string
+                                                                                               (integer->char
+                                                                                                 (+ 1
+                                                                                                    (- code
+                                                                                                       QT_KEY_A)))))
+                                                                                           #t]
+                                                                                          [(= code
+                                                                                              QT_KEY_UP)
+                                                                                           (send!
+                                                                                             "\x1B;[A")
+                                                                                           #t]
+                                                                                          [(= code
+                                                                                              QT_KEY_DOWN)
+                                                                                           (send!
+                                                                                             "\x1B;[B")
+                                                                                           #t]
+                                                                                          [(= code
+                                                                                              QT_KEY_RIGHT)
+                                                                                           (send!
+                                                                                             "\x1B;[C")
+                                                                                           #t]
+                                                                                          [(= code
+                                                                                              QT_KEY_LEFT)
+                                                                                           (send!
+                                                                                             "\x1B;[D")
+                                                                                           #t]
+                                                                                          [(or (= code
+                                                                                                  QT_KEY_RETURN)
+                                                                                               (= code
+                                                                                                  QT_KEY_ENTER))
+                                                                                           (send!
+                                                                                             "\r")
+                                                                                           #t]
+                                                                                          [(= code
+                                                                                              QT_KEY_BACKSPACE)
+                                                                                           (send!
+                                                                                             (string
+                                                                                               (integer->char
+                                                                                                 127)))
+                                                                                           #t]
+                                                                                          [(= code
+                                                                                              QT_KEY_DELETE)
+                                                                                           (send!
+                                                                                             "\x1B;[3~")
+                                                                                           #t]
+                                                                                          [(= code
+                                                                                              QT_KEY_TAB)
+                                                                                           (send!
+                                                                                             "\t")
+                                                                                           #t]
+                                                                                          [(= code
+                                                                                              QT_KEY_ESCAPE)
+                                                                                           (send!
+                                                                                             "\x1B;")
+                                                                                           #t]
+                                                                                          [(= code
+                                                                                              QT_KEY_HOME)
+                                                                                           (send!
+                                                                                             "\x1B;[H")
+                                                                                           #t]
+                                                                                          [(= code
+                                                                                              QT_KEY_END)
+                                                                                           (send!
+                                                                                             "\x1B;[F")
+                                                                                           #t]
+                                                                                          [(= code
+                                                                                              QT_KEY_PAGE_UP)
+                                                                                           (send!
+                                                                                             "\x1B;[5~")
+                                                                                           #t]
+                                                                                          [(= code
+                                                                                              QT_KEY_PAGE_DOWN)
+                                                                                           (send!
+                                                                                             "\x1B;[6~")
+                                                                                           #t]
+                                                                                          [(and (= (string-length
+                                                                                                     text)
+                                                                                                   1)
+                                                                                                (> (char->integer
+                                                                                                     (string-ref
+                                                                                                       text
+                                                                                                       0))
+                                                                                                   31))
+                                                                                           (send!
+                                                                                             text)
+                                                                                           #t]
+                                                                                          [else
+                                                                                           #f])))))))]
+                                          [do-normal-key! (lambda (code
+                                                                   mods
+                                                                   text)
+                                                            (unless (terminal-pty-intercept?
+                                                                      code
+                                                                      mods
+                                                                      text)
+                                                              (let* ([prefix-keys (key-state-prefix-keys
+                                                                                    (app-state-key-state
+                                                                                      app))]
+                                                                     [is-prefix-autorepeat? (and (pair?
+                                                                                                   prefix-keys)
+                                                                                                 (let* ([last-prefix (car (reverse
+                                                                                                                            prefix-keys))]
+                                                                                                        [ks (qt-key-event->string
+                                                                                                              code
+                                                                                                              mods
+                                                                                                              text)])
+                                                                                                   (and ks
+                                                                                                        (or (string=?
+                                                                                                              ks
+                                                                                                              last-prefix)
+                                                                                                            (and (zero?
+                                                                                                                   (bitwise-and
+                                                                                                                     mods
+                                                                                                                     QT_MOD_CTRL))
+                                                                                                                 (zero?
+                                                                                                                   (bitwise-and
+                                                                                                                     mods
+                                                                                                                     QT_MOD_ALT))
+                                                                                                                 (>= (string-length
+                                                                                                                       last-prefix)
+                                                                                                                     3)
+                                                                                                                 (string=?
+                                                                                                                   ks
+                                                                                                                   (substring
+                                                                                                                     last-prefix
+                                                                                                                     (- (string-length
+                                                                                                                          last-prefix)
+                                                                                                                        1)
+                                                                                                                     (string-length
+                                                                                                                       last-prefix))))))))])
+                                                                (if is-prefix-autorepeat?
+                                                                    (begin
+                                                                      (verbose-log!
+                                                                        "PREFIX-AUTOREPEAT ignored key="
+                                                                        (qt-key-event->string
                                                                           code
                                                                           mods
                                                                           text)
-                                                                  (let* ([prefix-keys (key-state-prefix-keys
+                                                                        " prefix="
+                                                                        (car (reverse
+                                                                               prefix-keys)))
+                                                                      (void))
+                                                                    (if (and (active-repeat-map)
+                                                                             (let* ([ks (qt-key-event->string
+                                                                                          code
+                                                                                          mods
+                                                                                          text)]
+                                                                                    [repeat-cmd (and ks
+                                                                                                     (repeat-map-lookup
+                                                                                                       ks))])
+                                                                               (if repeat-cmd
+                                                                                   (begin
+                                                                                     (execute-command!
+                                                                                       app
+                                                                                       repeat-cmd)
+                                                                                     #t)
+                                                                                   (begin
+                                                                                     (clear-repeat-map!)
+                                                                                     #f))))
+                                                                        (void)
+                                                                        (let-values ([(action data new-state)
+                                                                                      (qt-key-state-feed!
                                                                                         (app-state-key-state
-                                                                                          app))]
-                                                                         [is-prefix-autorepeat? (and (pair?
-                                                                                                       prefix-keys)
-                                                                                                     (let* ([last-prefix (car (reverse
-                                                                                                                                prefix-keys))]
-                                                                                                            [ks (qt-key-event->string
-                                                                                                                  code
-                                                                                                                  mods
-                                                                                                                  text)])
-                                                                                                       (and ks
-                                                                                                            (or (string=?
-                                                                                                                  ks
-                                                                                                                  last-prefix)
-                                                                                                                (and (zero?
-                                                                                                                       (bitwise-and
-                                                                                                                         mods
-                                                                                                                         QT_MOD_CTRL))
-                                                                                                                     (zero?
-                                                                                                                       (bitwise-and
-                                                                                                                         mods
-                                                                                                                         QT_MOD_ALT))
-                                                                                                                     (>= (string-length
-                                                                                                                           last-prefix)
-                                                                                                                         3)
-                                                                                                                     (string=?
-                                                                                                                       ks
-                                                                                                                       (substring
-                                                                                                                         last-prefix
-                                                                                                                         (- (string-length
-                                                                                                                              last-prefix)
-                                                                                                                            1)
-                                                                                                                         (string-length
-                                                                                                                           last-prefix))))))))])
-                                                                    (if is-prefix-autorepeat?
-                                                                        (begin
-                                                                          (verbose-log!
-                                                                            "PREFIX-AUTOREPEAT ignored key="
-                                                                            (qt-key-event->string
-                                                                              code
-                                                                              mods
-                                                                              text)
-                                                                            " prefix="
-                                                                            (car (reverse
-                                                                                   prefix-keys)))
-                                                                          (void))
-                                                                        (if (and (active-repeat-map)
-                                                                                 (let* ([ks (qt-key-event->string
-                                                                                              code
-                                                                                              mods
-                                                                                              text)]
-                                                                                        [repeat-cmd (and ks
-                                                                                                         (repeat-map-lookup
-                                                                                                           ks))])
-                                                                                   (if repeat-cmd
-                                                                                       (begin
-                                                                                         (execute-command!
-                                                                                           app
-                                                                                           repeat-cmd)
-                                                                                         #t)
-                                                                                       (begin
-                                                                                         (clear-repeat-map!)
-                                                                                         #f))))
-                                                                            (void)
-                                                                            (let-values ([(action data new-state)
-                                                                                          (qt-key-state-feed!
-                                                                                            (app-state-key-state
-                                                                                              app)
-                                                                                            code
-                                                                                            mods
-                                                                                            text)])
-                                                                              (app-state-key-state-set!
-                                                                                app
-                                                                                new-state)
-                                                                              (when (and *which-key-timer*
-                                                                                         (not (eq? action
-                                                                                                   'prefix)))
-                                                                                (qt-timer-stop!
-                                                                                  *which-key-timer*)
-                                                                                (set! *which-key-pending-keymap*
-                                                                                  #f))
-                                                                              (if (and *qt-describe-key-pending*
-                                                                                       (not (eq? action
-                                                                                                 'prefix)))
-                                                                                  (let ([ks (qt-key-event->string
-                                                                                              code
-                                                                                              mods
-                                                                                              text)])
-                                                                                    (qt-describe-key-result!
-                                                                                      app
-                                                                                      ks
-                                                                                      action
-                                                                                      data))
-                                                                                  (if *qt-quoted-insert-pending*
-                                                                                      (qt-quoted-insert-handle!
-                                                                                        app
-                                                                                        (if (and text
-                                                                                                 (> (string-length
-                                                                                                      text)
-                                                                                                    0))
-                                                                                            text
-                                                                                            (qt-key-event->string
-                                                                                              code
-                                                                                              mods
-                                                                                              text)))
-                                                                                      (case action
-                                                                                        [(command)
-                                                                                         (when (and (app-state-macro-recording
-                                                                                                      app)
-                                                                                                    (not (memq
-                                                                                                           data
-                                                                                                           '(start-kbd-macro
-                                                                                                              end-kbd-macro
-                                                                                                              call-last-kbd-macro
-                                                                                                              call-named-kbd-macro
-                                                                                                              name-last-kbd-macro
-                                                                                                              list-kbd-macros
-                                                                                                              save-kbd-macros
-                                                                                                              load-kbd-macros))))
-                                                                                           (app-state-macro-recording-set!
+                                                                                          app)
+                                                                                        code
+                                                                                        mods
+                                                                                        text)])
+                                                                          (app-state-key-state-set!
+                                                                            app
+                                                                            new-state)
+                                                                          (when (and *which-key-timer*
+                                                                                     (not (eq? action
+                                                                                               'prefix)))
+                                                                            (qt-timer-stop!
+                                                                              *which-key-timer*)
+                                                                            (set! *which-key-pending-keymap*