Skip to content

Commit

Permalink
Avoid intermediate hash-table when generating keymap docs
Browse files Browse the repository at this point in the history
  • Loading branch information
greghendershott committed Nov 4, 2024
1 parent 04bdadf commit 69dd900
Showing 1 changed file with 28 additions and 22 deletions.
50 changes: 28 additions & 22 deletions doc/generate.el
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,9 @@
;; The reference.org file is included by racket-mode.org as its last,
;; "Reference" section. Then racket-mode.org is used to create both
;; Info and HTML format documentation.
;;
;; Note that this file is /not/ loaded when running Racket Mode --
;; just used as part of the build process.

(require 'racket-mode)
(require 'racket-debug)
Expand Down Expand Up @@ -388,7 +391,7 @@ unescaping too."
(buffer-string))))

(defun racket-generate--insert-keymap (km)
"Insert org table for keymap KM.
"Insert org table describing keymap KM.
Filter \"noise\" like bindings for `negative-argument' and
`digit-argument'.
Expand All @@ -397,9 +400,17 @@ Insert sorted by command name.
When multiple key-bindings for a command, group into one row of
table, sorted shortest first."
(let ((result (make-hash-table)))
;; Accumulate nested keymaps into a flat association list. Each key
;; is a command symbol. Each value is a list of lists of keys
;; (potentially more than one key sequence bound for each command).
(let ((alist nil))
(cl-labels
((keymap (v prefix-keys)
((add (sym keys)
(let ((cell (assq sym alist)))
(if cell
(setcdr cell (push keys (cdr cell)))
(push (cons sym (list keys)) alist))))
(keymap (v prefix-keys)
(dolist (v (cdr v))
(pcase v
(`(,(and key (pred numberp)) . ,(and km (pred keymapp)))
Expand All @@ -410,26 +421,21 @@ table, sorted shortest first."
(unless (member sym '(negative-argument
digit-argument
describe-mode))
(puthash sym
(cons (reverse (cons key prefix-keys))
(gethash sym result))
result)))))))
(add sym (reverse (cons key prefix-keys)))))))))
;; Recursively mutate `alist'.
(keymap km nil)
(let* ((alist nil)
(_ (maphash (lambda (sym keys)
(push (cons sym keys) alist))
result)))
(dolist (v (seq-sort-by (lambda (v) (symbol-name (car v)))
#'string<
alist))
(let* ((command-str (racket-generate--ref-or-code (car v)))
(keys-strs (seq-map (lambda (binding)
(format "{{{kbd(%s)}}}"
(racket-generate--key-description binding)))
(cdr v)))
(keys-str (string-join (seq-sort-by #'length #'< keys-strs)
", ")))
(insert "|" keys-str "|" command-str "|\n")))))))
;; Navigate `alist' sorted by command.
(dolist (v (seq-sort-by (lambda (v) (symbol-name (car v)))
#'string<
alist))
(let* ((command-str (racket-generate--ref-or-code (car v)))
(keys-strs (seq-map (lambda (binding)
(format "{{{kbd(%s)}}}"
(racket-generate--key-description binding)))
(cdr v)))
(keys-str (string-join (seq-sort-by #'length #'< keys-strs)
", ")))
(insert "|" keys-str "|" command-str "|\n"))))))

(defun racket-generate--key-description (xs)
"Like `key-description' but escapes some chars for our \"KBD\" texi macro."
Expand Down

0 comments on commit 69dd900

Please sign in to comment.