Function: substitute-command-keys
substitute-command-keys is a byte-compiled function defined in
help.el.gz.
Signature
(substitute-command-keys STRING &optional NO-FACE INCLUDE-MENUS)
Documentation
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. Keybindings will use the face help-key-binding,
unless the optional argument NO-FACE is non-nil.
Each substring of the form \`KEYBINDING' will be replaced by
KEYBINDING and use the help-key-binding face.
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. This will normally
exclude menu bindings, but if the optional INCLUDE-MENUS argument
is non-nil, also include menu 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(var)/text-quoting-style(fun).
\= 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.
Probably introduced at or before Emacs version 16.
Source Code
;; Defined in /usr/src/emacs/lisp/help.el.gz
(defun substitute-command-keys (string &optional no-face include-menus)
"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. Keybindings will use the face `help-key-binding',
unless the optional argument NO-FACE is non-nil.
Each substring of the form \\\\=`KEYBINDING' will be replaced by
KEYBINDING and use the `help-key-binding' face.
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'. This will normally
exclude menu bindings, but if the optional INCLUDE-MENUS argument
is non-nil, also include menu 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."
(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. \`f' is replaced with a fontified f.
((and (= (following-char) ?`)
(save-excursion
(prog1 (search-forward "'" nil t)
(setq end-point (1- (point))))))
(let ((k (buffer-substring-no-properties (+ orig-point 2)
end-point)))
(when (or (key-valid-p k)
(string-match-p "\\`mouse-[1-9]" k)
(string-match-p "\\`M-x " k))
(goto-char orig-point)
(delete-char 2)
(goto-char (- end-point 2)) ; nb. take deletion into account
(delete-char 1)
(unless no-face
(add-text-properties orig-point (point)
'( face help-key-binding
font-lock-face help-key-binding))))))
;; 1D. \[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
(and keymap
(list keymap))
t))))
;; If we're looking in a particular keymap which has
;; no binding, then we need to redo the lookup, with
;; the global map as well this time.
(when (and (not key) keymap)
(setq key (with-current-buffer orig-buf
(where-is-internal fun keymap t))))
(if (not key)
;; Function is not on any key.
(let ((op (point)))
(insert "M-x ")
(goto-char (+ end-point 3))
(or no-face
(add-text-properties
op (point)
'( face help-key-binding
font-lock-face help-key-binding)))
(delete-char 1))
;; Function is on a key.
(delete-char (- end-point (point)))
(insert
(if no-face
(key-description key)
(let ((key (help--key-description-fontified key)))
(if (and help-link-key-to-documentation
help-buffer-under-preparation
(functionp fun))
;; The `fboundp' fixes bootstrap.
(if (fboundp 'help-mode--add-function-link)
(help-mode--add-function-link key fun)
key)
key)))))))
;; 1E. \{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-quotes "`")
(symbol-name name)
(substitute-quotes "'")
", 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 (not include-menus)
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)))))