summaryrefslogtreecommitdiff
path: root/lisp/help.el
diff options
context:
space:
mode:
Diffstat (limited to 'lisp/help.el')
-rw-r--r--lisp/help.el593
1 files changed, 477 insertions, 116 deletions
diff --git a/lisp/help.el b/lisp/help.el
index c276c1dc280..ac5c2f1311b 100644
--- a/lisp/help.el
+++ b/lisp/help.el
@@ -101,6 +101,7 @@
(define-key map "p" 'finder-by-keyword)
(define-key map "P" 'describe-package)
(define-key map "r" 'info-emacs-manual)
+ (define-key map "R" 'info-display-manual)
(define-key map "s" 'describe-syntax)
(define-key map "t" 'help-with-tutorial)
(define-key map "w" 'where-is)
@@ -131,7 +132,6 @@ This is a list
(WINDOW . quit-window) do quit-window, then select WINDOW.
(WINDOW BUF START POINT) display BUF at START, POINT, then select WINDOW.")
-(define-obsolete-function-alias 'print-help-return-message 'help-print-return-message "23.2")
(defun help-print-return-message (&optional function)
"Display or return message saying how to restore windows after help command.
This function assumes that `standard-output' is the help buffer.
@@ -224,6 +224,7 @@ o SYMBOL Display the given function or variable's documentation and value.
p TOPIC Find packages matching a given topic keyword.
P PACKAGE Describe the given Emacs Lisp package.
r Display the Emacs manual in Info mode.
+R Prompt for a manual and then display it in Info mode.
s Display contents of current syntax table, plus explanations.
S SYMBOL Show the section for the given symbol in the Info manual
for the programming language used in this buffer.
@@ -365,7 +366,7 @@ With argument, display info only for the selected version."
(sort (delete-dups res) #'string>)))
(current (car all-versions)))
(setq version (completing-read
- (format "Read NEWS for the version (default %s): " current)
+ (format-prompt "Read NEWS for the version" current)
all-versions nil nil nil nil current))
(if (integerp (string-to-number version))
(setq version (string-to-number version))
@@ -459,6 +460,7 @@ the variable `message-log-max'."
"Display last few input keystrokes and the commands run.
For convenience this uses the same format as
`edit-last-kbd-macro'.
+See `lossage-size' to update the number of recorded keystrokes.
To record all your input, use `open-dribble-file'."
(interactive)
@@ -534,12 +536,9 @@ If INSERT (the prefix arg) is non-nil, insert the message in the buffer."
(let ((fn (function-called-at-point))
(enable-recursive-minibuffers t)
val)
- (setq val (completing-read
- (if fn
- (format "Where is command (default %s): " fn)
- "Where is command: ")
- obarray 'commandp t nil nil
- (and fn (symbol-name fn))))
+ (setq val (completing-read (format-prompt "Where is command" fn)
+ obarray 'commandp t nil nil
+ (and fn (symbol-name fn))))
(list (unless (equal val "") (intern val))
current-prefix-arg)))
(unless definition (error "No command"))
@@ -879,114 +878,6 @@ current buffer."
(princ ", which is ")
(describe-function-1 defn)))))))
-(defun describe-mode (&optional buffer)
- "Display documentation of current major mode and minor modes.
-A brief summary of the minor modes comes first, followed by the
-major mode description. This is followed by detailed
-descriptions of the minor modes, each on a separate page.
-
-For this to work correctly for a minor mode, the mode's indicator
-variable \(listed in `minor-mode-alist') must also be a function
-whose documentation describes the minor mode.
-
-If called from Lisp with a non-nil BUFFER argument, display
-documentation for the major and minor modes of that buffer."
- (interactive "@")
- (unless buffer (setq buffer (current-buffer)))
- (help-setup-xref (list #'describe-mode buffer)
- (called-interactively-p 'interactive))
- ;; For the sake of help-do-xref and help-xref-go-back,
- ;; don't switch buffers before calling `help-buffer'.
- (with-help-window (help-buffer)
- (with-current-buffer buffer
- (let (minor-modes)
- ;; Older packages do not register in minor-mode-list but only in
- ;; minor-mode-alist.
- (dolist (x minor-mode-alist)
- (setq x (car x))
- (unless (memq x minor-mode-list)
- (push x minor-mode-list)))
- ;; Find enabled minor mode we will want to mention.
- (dolist (mode minor-mode-list)
- ;; Document a minor mode if it is listed in minor-mode-alist,
- ;; non-nil, and has a function definition.
- (let ((fmode (or (get mode :minor-mode-function) mode)))
- (and (boundp mode) (symbol-value mode)
- (fboundp fmode)
- (let ((pretty-minor-mode
- (if (string-match "\\(\\(-minor\\)?-mode\\)?\\'"
- (symbol-name fmode))
- (capitalize
- (substring (symbol-name fmode)
- 0 (match-beginning 0)))
- fmode)))
- (push (list fmode pretty-minor-mode
- (format-mode-line (assq mode minor-mode-alist)))
- minor-modes)))))
- ;; Narrowing is not a minor mode, but its indicator is part of
- ;; mode-line-modes.
- (when (buffer-narrowed-p)
- (push '(narrow-to-region "Narrow" " Narrow") minor-modes))
- (setq minor-modes
- (sort minor-modes
- (lambda (a b) (string-lessp (cadr a) (cadr b)))))
- (when minor-modes
- (princ "Enabled minor modes:\n")
- (make-local-variable 'help-button-cache)
- (with-current-buffer standard-output
- (dolist (mode minor-modes)
- (let ((mode-function (nth 0 mode))
- (pretty-minor-mode (nth 1 mode))
- (indicator (nth 2 mode)))
- (save-excursion
- (goto-char (point-max))
- (princ "\n\f\n")
- (push (point-marker) help-button-cache)
- ;; Document the minor modes fully.
- (insert-text-button
- pretty-minor-mode 'type 'help-function
- 'help-args (list mode-function)
- 'button '(t))
- (princ (format " minor mode (%s):\n"
- (if (zerop (length indicator))
- "no indicator"
- (format "indicator%s"
- indicator))))
- (princ (help-split-fundoc (documentation mode-function)
- nil 'doc)))
- (insert-button pretty-minor-mode
- 'action (car help-button-cache)
- 'follow-link t
- 'help-echo "mouse-2, RET: show full information")
- (newline)))
- (forward-line -1)
- (fill-paragraph nil)
- (forward-line 1))
-
- (princ "\n(Information about these minor modes follows the major mode info.)\n\n"))
- ;; Document the major mode.
- (let ((mode mode-name))
- (with-current-buffer standard-output
- (let ((start (point)))
- (insert (format-mode-line mode nil nil buffer))
- (add-text-properties start (point) '(face bold)))))
- (princ " mode")
- (let* ((mode major-mode)
- (file-name (find-lisp-object-file-name mode nil)))
- (when file-name
- (princ (format-message " defined in `%s'"
- (file-name-nondirectory file-name)))
- ;; Make a hyperlink to the library.
- (with-current-buffer standard-output
- (save-excursion
- (re-search-backward (substitute-command-keys "`\\([^`']+\\)'")
- nil t)
- (help-xref-button 1 'help-function-def mode file-name)))))
- (princ ":\n")
- (princ (help-split-fundoc (documentation major-mode) nil 'doc)))))
- ;; For the sake of IELM and maybe others
- nil)
-
(defun search-forward-help-for-help ()
"Search forward \"help window\"."
(interactive)
@@ -1082,6 +973,476 @@ is currently activated with completion."
minor-modes nil)
(setq minor-modes (cdr minor-modes)))))
result))
+
+
+(defun substitute-command-keys (string)
+ "Substitute key descriptions for command names in STRING.
+Each substring of the form \\\\=[COMMAND] is replaced by either a
+keystroke sequence that invokes COMMAND, or \"M-x COMMAND\" if COMMAND
+is not on any keys.
+
+Each substring of the form \\\\={MAPVAR} is replaced by a summary of
+the value of MAPVAR as a keymap. This summary is similar to the one
+produced by ‘describe-bindings’. The summary ends in two newlines
+(used by the helper function ‘help-make-xrefs’ to find the end of the
+summary).
+
+Each substring of the form \\\\=<MAPVAR> specifies the use of MAPVAR
+as the keymap for future \\\\=[COMMAND] substrings.
+
+Each grave accent \\=` is replaced by left quote, and each apostrophe \\='
+is replaced by right quote. Left and right quote characters are
+specified by ‘text-quoting-style’.
+
+\\\\== quotes the following character and is discarded; thus, \\\\==\\\\== puts \\\\==
+into the output, \\\\==\\[ puts \\[ into the output, and \\\\==\\=` puts \\=` into the
+output.
+
+Return the original STRING if no substitutions are made.
+Otherwise, return a new string (without any text properties)."
+ (when (not (null string))
+ ;; KEYMAP is either nil (which means search all the active
+ ;; keymaps) or a specified local map (which means search just that
+ ;; and the global map). If non-nil, it might come from
+ ;; overriding-local-map, or from a \\<mapname> construct in STRING
+ ;; itself.
+ (let ((keymap overriding-local-map)
+ (inhibit-modification-hooks t)
+ (orig-buf (current-buffer)))
+ (with-temp-buffer
+ (insert string)
+ (goto-char (point-min))
+ (while (< (point) (point-max))
+ (let ((orig-point (point))
+ end-point active-maps
+ close generate-summary)
+ (cond
+ ;; 1. Handle all sequences starting with "\"
+ ((= (following-char) ?\\)
+ (ignore-errors
+ (forward-char 1))
+ (cond
+ ;; 1A. Ignore \= at end of string.
+ ((and (= (+ (point) 1) (point-max))
+ (= (following-char) ?=))
+ (forward-char 1))
+ ;; 1B. \= quotes the next character; thus, to put in \[
+ ;; without its special meaning, use \=\[.
+ ((= (following-char) ?=)
+ (goto-char orig-point)
+ (delete-char 2)
+ (ignore-errors
+ (forward-char 1)))
+ ;; 1C. \[foo] is replaced with the keybinding.
+ ((and (= (following-char) ?\[)
+ (save-excursion
+ (prog1 (search-forward "]" nil t)
+ (setq end-point (- (point) 2)))))
+ (goto-char orig-point)
+ (delete-char 2)
+ (let* ((fun (intern (buffer-substring (point) (1- end-point))))
+ (key (with-current-buffer orig-buf
+ (where-is-internal fun keymap t))))
+ ;; If this a command remap, we need to follow it.
+ (when (and (vectorp key)
+ (> (length key) 1)
+ (eq (aref key 0) 'remap)
+ (symbolp (aref key 1)))
+ (setq fun (aref key 1))
+ (setq key (with-current-buffer orig-buf
+ (where-is-internal fun keymap t))))
+ (if (not key)
+ ;; Function is not on any key.
+ (progn (insert "M-x ")
+ (goto-char (+ end-point 3))
+ (delete-char 1))
+ ;; Function is on a key.
+ (delete-char (- end-point (point)))
+ (insert (key-description key)))))
+ ;; 1D. \{foo} is replaced with a summary of the keymap
+ ;; (symbol-value foo).
+ ;; \<foo> just sets the keymap used for \[cmd].
+ ((and (or (and (= (following-char) ?{)
+ (setq close "}")
+ (setq generate-summary t))
+ (and (= (following-char) ?<)
+ (setq close ">")))
+ (or (save-excursion
+ (prog1 (search-forward close nil t)
+ (setq end-point (- (point) 2))))))
+ (goto-char orig-point)
+ (delete-char 2)
+ (let* ((name (intern (buffer-substring (point) (1- end-point))))
+ this-keymap)
+ (delete-char (- end-point (point)))
+ ;; Get the value of the keymap in TEM, or nil if
+ ;; undefined. Do this in the user's current buffer
+ ;; in case it is a local variable.
+ (with-current-buffer orig-buf
+ ;; This is for computing the SHADOWS arg for
+ ;; describe-map-tree.
+ (setq active-maps (current-active-maps))
+ (when (boundp name)
+ (setq this-keymap (and (keymapp (symbol-value name))
+ (symbol-value name)))))
+ (cond
+ ((null this-keymap)
+ (insert "\nUses keymap "
+ (substitute-command-keys "`")
+ (symbol-name name)
+ (substitute-command-keys "'")
+ ", which is not currently defined.\n")
+ (unless generate-summary
+ (setq keymap nil)))
+ ((not generate-summary)
+ (setq keymap this-keymap))
+ (t
+ ;; Get the list of active keymaps that precede this one.
+ ;; If this one's not active, get nil.
+ (let ((earlier-maps (cdr (memq this-keymap (reverse active-maps)))))
+ (describe-map-tree this-keymap t (nreverse earlier-maps)
+ nil nil t nil nil t))))))))
+ ;; 2. Handle quotes.
+ ((and (eq (text-quoting-style) 'curve)
+ (or (and (= (following-char) ?\`)
+ (prog1 t (insert "‘")))
+ (and (= (following-char) ?')
+ (prog1 t (insert "’")))))
+ (delete-char 1))
+ ((and (eq (text-quoting-style) 'straight)
+ (= (following-char) ?\`))
+ (insert "'")
+ (delete-char 1))
+ ;; 3. Nothing to do -- next character.
+ (t (forward-char 1)))))
+ (buffer-string)))))
+
+(defvar help--keymaps-seen nil)
+(defun describe-map-tree (startmap partial shadow prefix title no-menu
+ transl always-title mention-shadow)
+ "Insert a description of the key bindings in STARTMAP.
+This is followed by the key bindings of all maps reachable
+through STARTMAP.
+
+If PARTIAL is non-nil, omit certain uninteresting commands
+\(such as `undefined').
+
+If SHADOW is non-nil, it is a list of maps; don't mention keys
+which would be shadowed by any of them.
+
+If PREFIX is non-nil, mention only keys that start with PREFIX.
+
+If TITLE is non-nil, is a string to insert at the beginning.
+TITLE should not end with a colon or a newline; we supply that.
+
+If NOMENU is non-nil, then omit menu-bar commands.
+
+If TRANSL is non-nil, the definitions are actually key
+translations so print strings and vectors differently.
+
+If ALWAYS_TITLE is non-nil, print the title even if there are no
+maps to look through.
+
+If MENTION_SHADOW is non-nil, then when something is shadowed by
+SHADOW, don't omit it; instead, mention it but say it is
+shadowed.
+
+Any inserted text ends in two newlines (used by
+`help-make-xrefs')."
+ (let* ((amaps (accessible-keymaps startmap prefix))
+ (orig-maps (if no-menu
+ (progn
+ ;; Delete from MAPS each element that is for
+ ;; the menu bar.
+ (let* ((tail amaps)
+ result)
+ (while tail
+ (let ((elem (car tail)))
+ (when (not (and (>= (length (car elem)) 1)
+ (eq (elt (car elem) 0) 'menu-bar)))
+ (setq result (append result (list elem)))))
+ (setq tail (cdr tail)))
+ result))
+ amaps))
+ (maps orig-maps)
+ (print-title (or maps always-title)))
+ ;; Print title.
+ (when print-title
+ (insert (concat (if title
+ (concat title
+ (if prefix
+ (concat " Starting With "
+ (key-description prefix)))
+ ":\n"))
+ "key binding\n"
+ "--- -------\n")))
+ ;; Describe key bindings.
+ (setq help--keymaps-seen nil)
+ (while (consp maps)
+ (let* ((elt (car maps))
+ (elt-prefix (car elt))
+ (sub-shadows (lookup-key shadow elt-prefix t)))
+ (when (if (natnump sub-shadows)
+ (prog1 t (setq sub-shadows nil))
+ ;; Describe this map iff elt_prefix is bound to a
+ ;; keymap, since otherwise it completely shadows this
+ ;; map.
+ (or (keymapp sub-shadows)
+ (null sub-shadows)
+ (and (consp sub-shadows)
+ (keymapp (car sub-shadows)))))
+ ;; Maps we have already listed in this loop shadow this map.
+ (let ((tail orig-maps))
+ (while (not (equal tail maps))
+ (when (equal (car (car tail)) elt-prefix)
+ (setq sub-shadows (cons (cdr (car tail)) sub-shadows)))
+ (setq tail (cdr tail))))
+ (describe-map (cdr elt) elt-prefix transl partial
+ sub-shadows no-menu mention-shadow)))
+ (setq maps (cdr maps)))
+ (when print-title
+ (insert "\n"))))
+
+(defun help--shadow-lookup (keymap key accept-default remap)
+ "Like `lookup-key', but with command remapping.
+Return nil if the key sequence is too long."
+ ;; Converted from shadow_lookup in keymap.c.
+ (let ((value (lookup-key keymap key accept-default)))
+ (cond ((and (fixnump value) (<= 0 value)))
+ ((and value remap (symbolp value))
+ (or (command-remapping value nil keymap)
+ value))
+ (t value))))
+
+(defvar help--previous-description-column 0)
+(defun help--describe-command (definition)
+ ;; Converted from describe_command in keymap.c.
+ ;; If column 16 is no good, go to col 32;
+ ;; but don't push beyond that--go to next line instead.
+ (let* ((column (current-column))
+ (description-column (cond ((> column 30)
+ (insert "\n")
+ 32)
+ ((or (> column 14)
+ (and (> column 10)
+ (= help--previous-description-column 32)))
+ 32)
+ (t 16))))
+ (indent-to description-column 1)
+ (setq help--previous-description-column description-column)
+ (cond ((symbolp definition)
+ (insert (symbol-name definition) "\n"))
+ ((or (stringp definition) (vectorp definition))
+ (insert "Keyboard Macro\n"))
+ ((keymapp definition)
+ (insert "Prefix Command\n"))
+ (t (insert "??\n")))))
+
+(defun help--describe-translation (definition)
+ ;; Converted from describe_translation in keymap.c.
+ (indent-to 16 1)
+ (cond ((symbolp definition)
+ (insert (symbol-name definition) "\n"))
+ ((or (stringp definition) (vectorp definition))
+ (insert (key-description definition nil) "\n"))
+ ((keymapp definition)
+ (insert "Prefix Command\n"))
+ (t (insert "??\n"))))
+
+(defun help--describe-map-compare (a b)
+ (let ((a (car a))
+ (b (car b)))
+ (cond ((and (fixnump a) (fixnump b)) (< a b))
+ ;; ((and (not (fixnump a)) (fixnump b)) nil) ; not needed
+ ((and (fixnump a) (not (fixnump b))) t)
+ ((and (symbolp a) (symbolp b))
+ ;; Sort the keystroke names in the "natural" way, with (for
+ ;; instance) "<f2>" coming between "<f1>" and "<f11>".
+ (string-version-lessp (symbol-name a) (symbol-name b)))
+ (t nil))))
+
+(defun describe-map (map prefix transl partial shadow nomenu mention-shadow)
+ "Describe the contents of keymap MAP.
+Assume that this keymap itself is reached by the sequence of
+prefix keys PREFIX (a string or vector).
+
+TRANSL, PARTIAL, SHADOW, NOMENU, MENTION-SHADOW are as in
+`describe-map-tree'."
+ ;; Converted from describe_map in keymap.c.
+ (let* ((suppress (and partial 'suppress-keymap))
+ (map (keymap-canonicalize map))
+ (tail map)
+ (first t)
+ (describer (if transl
+ #'help--describe-translation
+ #'help--describe-command))
+ done vect)
+ (while (and (consp tail) (not done))
+ (cond ((or (vectorp (car tail)) (char-table-p (car tail)))
+ (help--describe-vector (car tail) prefix describer partial
+ shadow map mention-shadow))
+ ((consp (car tail))
+ (let ((event (caar tail))
+ definition this-shadowed)
+ ;; Ignore bindings whose "prefix" are not really
+ ;; valid events. (We get these in the frames and
+ ;; buffers menu.)
+ (and (or (symbolp event) (fixnump event))
+ (not (and nomenu (eq event 'menu-bar)))
+ ;; Don't show undefined commands or suppressed
+ ;; commands.
+ (setq definition (keymap--get-keyelt (cdr (car tail)) nil))
+ (or (not (symbolp definition))
+ (null (get definition suppress)))
+ ;; Don't show a command that isn't really
+ ;; visible because a local definition of the
+ ;; same key shadows it.
+ (or (not shadow)
+ (let ((tem (help--shadow-lookup shadow (vector event) t nil)))
+ (cond ((null tem) t)
+ ;; If both bindings are keymaps,
+ ;; this key is a prefix key, so
+ ;; don't say it is shadowed.
+ ((and (keymapp definition) (keymapp tem)) t)
+ ;; Avoid generating duplicate
+ ;; entries if the shadowed binding
+ ;; has the same definition.
+ ((and mention-shadow (not (eq tem definition)))
+ (setq this-shadowed t))
+ (t nil))))
+ (eq definition (lookup-key tail (vector event) t))
+ (push (list event definition this-shadowed) vect))))
+ ((eq (car tail) 'keymap)
+ ;; The same keymap might be in the structure twice, if
+ ;; we're using an inherited keymap. So skip anything
+ ;; we've already encountered.
+ (let ((tem (assq tail help--keymaps-seen)))
+ (if (and (consp tem)
+ (equal (car tem) prefix))
+ (setq done t)
+ (push (cons tail prefix) help--keymaps-seen)))))
+ (setq tail (cdr tail)))
+ ;; If we found some sparse map events, sort them.
+ (let ((vect (sort vect 'help--describe-map-compare)))
+ ;; Now output them in sorted order.
+ (while vect
+ (let* ((elem (car vect))
+ (start (car elem))
+ (definition (cadr elem))
+ (shadowed (caddr elem))
+ (end start))
+ (when first
+ (setq help--previous-description-column 0)
+ (insert "\n")
+ (setq first nil))
+ ;; Find consecutive chars that are identically defined.
+ (when (fixnump start)
+ (while (and (cdr vect)
+ (let ((this-event (caar vect))
+ (this-definition (cadar vect))
+ (this-shadowed (caddar vect))
+ (next-event (caar (cdr vect)))
+ (next-definition (cadar (cdr vect)))
+ (next-shadowed (caddar (cdr vect))))
+ (and (eq next-event (1+ this-event))
+ (equal next-definition this-definition)
+ (eq this-shadowed next-shadowed))))
+ (setq vect (cdr vect))
+ (setq end (caar vect))))
+ ;; Now START .. END is the range to describe next.
+ ;; Insert the string to describe the event START.
+ (insert (key-description (vector start) prefix))
+ (when (not (eq start end))
+ (insert " .. " (key-description (vector end) prefix)))
+ ;; Print a description of the definition of this character.
+ ;; Called function will take care of spacing out far enough
+ ;; for alignment purposes.
+ (if transl
+ (help--describe-translation definition)
+ (help--describe-command definition))
+ ;; Print a description of the definition of this character.
+ ;; elt_describer will take care of spacing out far enough for
+ ;; alignment purposes.
+ (when shadowed
+ (goto-char (max (1- (point)) (point-min)))
+ (insert "\n (this binding is currently shadowed)")
+ (goto-char (min (1+ (point)) (point-max)))))
+ ;; Next item in list.
+ (setq vect (cdr vect))))))
+
+;;;; This Lisp version is 100 times slower than its C equivalent:
+;;
+;; (defun help--describe-vector
+;; (vector prefix transl partial shadow entire-map mention-shadow)
+;; "Insert in the current buffer a description of the contents of VECTOR.
+;;
+;; PREFIX a prefix key which leads to the keymap that this vector is
+;; in.
+;;
+;; If PARTIAL, it means do not mention suppressed commands
+;; (that assumes the vector is in a keymap).
+;;
+;; SHADOW is a list of keymaps that shadow this map. If it is
+;; non-nil, look up the key in those maps and don't mention it if it
+;; is defined by any of them.
+;;
+;; ENTIRE-MAP is the vector in which this vector appears.
+;; If the definition in effect in the whole map does not match
+;; the one in this vector, we ignore this one."
+;; ;; Converted from describe_vector in keymap.c.
+;; (let* ((first t)
+;; (idx 0))
+;; (while (< idx (length vector))
+;; (let* ((val (aref vector idx))
+;; (definition (keymap--get-keyelt val nil))
+;; (start-idx idx)
+;; this-shadowed
+;; found-range)
+;; (when (and definition
+;; ;; Don't mention suppressed commands.
+;; (not (and partial
+;; (symbolp definition)
+;; (get definition 'suppress-keymap)))
+;; ;; If this binding is shadowed by some other map,
+;; ;; ignore it.
+;; (not (and shadow
+;; (help--shadow-lookup shadow (vector start-idx) t nil)
+;; (if mention-shadow
+;; (prog1 nil (setq this-shadowed t))
+;; t)))
+;; ;; Ignore this definition if it is shadowed by an earlier
+;; ;; one in the same keymap.
+;; (not (and entire-map
+;; (not (eq (lookup-key entire-map (vector start-idx) t)
+;; definition)))))
+;; (when first
+;; (insert "\n")
+;; (setq first nil))
+;; (when (and prefix (> (length prefix) 0))
+;; (insert (format "%s" prefix)))
+;; (insert (key-description (vector start-idx) prefix))
+;; ;; Find all consecutive characters or rows that have the
+;; ;; same definition.
+;; (while (equal (keymap--get-keyelt (aref vector (1+ idx)) nil)
+;; definition)
+;; (setq found-range t)
+;; (setq idx (1+ idx)))
+;; ;; If we have a range of more than one character,
+;; ;; print where the range reaches to.
+;; (when found-range
+;; (insert " .. ")
+;; (when (and prefix (> (length prefix) 0))
+;; (insert (format "%s" prefix)))
+;; (insert (key-description (vector idx) prefix)))
+;; (if transl
+;; (help--describe-translation definition)
+;; (help--describe-command definition))
+;; (when this-shadowed
+;; (goto-char (1- (point)))
+;; (insert " (binding currently shadowed)")
+;; (goto-char (1+ (point))))))
+;; (setq idx (1+ idx)))))
+
(declare-function x-display-pixel-height "xfns.c" (&optional terminal))
(declare-function x-display-pixel-width "xfns.c" (&optional terminal))