aboutsummaryrefslogtreecommitdiff
path: root/helpful.el
diff options
context:
space:
mode:
authorWilfred Hughes <me@wilfred.me.uk>2019-03-16 16:39:24 +0000
committerWilfred Hughes <me@wilfred.me.uk>2019-03-16 16:39:24 +0000
commitd5b0eb78731df41a9f20ebf4f3c2d15e8a3d22d8 (patch)
tree5e968a409be9eadb0e78f70906abcbefa43b470e /helpful.el
parent9f1d08c3d4292f778b14838da35701714ea0e231 (diff)
Don't interpret "`foo'" as a symbol reference
This requires `foo' to be handled as part of the loop in `helpful--format-command-keys' rather than a separate function. Helps with #197
Diffstat (limited to 'helpful.el')
-rw-r--r--helpful.el139
1 files changed, 76 insertions, 63 deletions
diff --git a/helpful.el b/helpful.el
index 64200df..3907861 100644
--- a/helpful.el
+++ b/helpful.el
@@ -757,51 +757,34 @@ blank line afterwards."
(-cons* first-line "" (cdr lines)))
docstring)))
-(defun helpful--propertize-keywords (docstring)
- "Propertize quoted keywords in docstrings."
- (replace-regexp-in-string
- ;; Replace all text of the form `foo'.
- (rx "`"
- (group ":"
- symbol-start
- (+? (or (syntax word) (syntax symbol)))
- symbol-end)
- "'")
- (lambda (it)
- (propertize (match-string 1 it)
- 'face 'font-lock-builtin-face))
- docstring
- t t))
-
-(defun helpful--propertize-quoted (docstring)
- "Convert `foo' in docstrings to buttons (if bound) or else highlight."
- (replace-regexp-in-string
- ;; Replace all text of the form `foo'.
- (rx (? "\\=") "`" (+? (not (any "`" "'"))) "'")
- (lambda (it)
- (let* ((sym-name
- (s-chop-prefix "`" (s-chop-suffix "'" it)))
- (sym (intern sym-name)))
- (cond
- ;; If the quote is escaped, don't modify it.
- ((s-starts-with-p "\\=" it)
- it)
- ;; Only create a link if this is a symbol that is bound as a
- ;; variable or callable.
- ((or (boundp sym) (fboundp sym))
- (helpful--button
- sym-name
- 'helpful-describe-button
- 'symbol sym))
- ;; If this is already a button, don't modify it.
- ((get-text-property 0 'button sym-name)
- sym-name)
- ;; Highlight the quoted string.
- (t
- (propertize sym-name
- 'face 'font-lock-constant-face)))))
- docstring
- t t))
+(defun helpful--propertize-sym-ref (sym-name)
+ "Given a symbol name from a docstring, convert to a button (if
+bound) or else highlight."
+ (let* ((sym (intern sym-name)))
+ (cond
+ ;; Highlight keywords.
+ ((s-matches-p
+ (rx ":"
+ symbol-start
+ (+? (or (syntax word) (syntax symbol)))
+ symbol-end)
+ sym-name)
+ (propertize sym-name
+ 'face 'font-lock-builtin-face))
+ ;; Only create a link if this is a symbol that is bound as a
+ ;; variable or callable.
+ ((or (boundp sym) (fboundp sym))
+ (helpful--button
+ sym-name
+ 'helpful-describe-button
+ 'symbol sym))
+ ;; If this is already a button, don't modify it.
+ ((get-text-property 0 'button sym-name)
+ sym-name)
+ ;; Highlight the quoted string.
+ (t
+ (propertize sym-name
+ 'face 'font-lock-constant-face)))))
(defun helpful--propertize-info (docstring)
"Convert info references in docstrings to buttons."
@@ -949,13 +932,35 @@ vector suitable for `key-description', and COMMAND is a smbol."
;; inherited bindings last. Sort so that we group by prefix.
(s-join "\n" (-sort #'string< lines))))
+(defun helpful--format-commands (str keymap)
+ "Replace all the \\[ references in STR with buttons."
+ (replace-regexp-in-string
+ ;; Text of the form \\[foo-command]
+ (rx "\\[" (group (+ (not (in "]")))) "]")
+ (lambda (it)
+ (let* ((symbol-name (match-string 1 it))
+ (symbol (intern symbol-name))
+ (key (where-is-internal symbol keymap t))
+ (key-description
+ (if key
+ (key-description key)
+ (format "M-x %s" symbol-name))))
+ (helpful--button
+ key-description
+ 'helpful-describe-exactly-button
+ 'symbol symbol
+ 'callable-p t)))
+ str
+ t
+ t))
+
(defun helpful--format-command-keys (docstring)
"Convert command key references and keymap references
in DOCSTRING to buttons.
Emacs uses \\= to escape \\[ references, so replace that
unescaping too."
- ;; Based on `substitute-command-keys', but converts command
+ ;; Loosely based on `substitute-command-keys', but converts
;; references to buttons.
(let ((keymap nil))
(with-temp-buffer
@@ -981,6 +986,29 @@ unescaping too."
(delete-region (point) (+ (point) 2))
(forward-char 1))
((looking-at
+ ;; Text of the form `foo'
+ (rx "`"))
+ (let* ((start-pos (point))
+ (end-pos (search-forward "'" nil t))
+ (contents
+ (when end-pos
+ (buffer-substring (1+ start-pos) (1- end-pos)))))
+ (cond
+ ((null contents)
+ ;; If there's no closing ' to match the opening `, just
+ ;; leave it.
+ (goto-char (1+ start-pos)))
+ ((s-contains-p "`" contents)
+ ;; If we have repeated backticks `foo `bar', leave the
+ ;; first one.
+ (goto-char (1+ start-pos)))
+ ((s-contains-p "\\[" contents)
+ (delete-region start-pos end-pos)
+ (insert (helpful--format-commands contents keymap)))
+ (t
+ (delete-region start-pos end-pos)
+ (insert (helpful--propertize-sym-ref contents))))))
+ ((looking-at
;; Text of the form \\<foo-keymap>
(rx "\\<" (group (+ (not (in ">")))) ">"
(? "\n")))
@@ -1016,18 +1044,7 @@ unescaping too."
(delete-region (point)
(+ (point) (length symbol-with-parens)))
;; Add a button.
- (let* ((symbol (intern symbol-name))
- (key (where-is-internal symbol keymap t))
- (key-description
- (if key
- (key-description key)
- (format "M-x %s" symbol-name))))
- (insert
- (helpful--button
- key-description
- 'helpful-describe-exactly-button
- 'symbol symbol
- 'callable-p t)))))
+ (insert (helpful--format-commands symbol-with-parens keymap))))
;; Don't modify other characters.
(t
(forward-char 1))))
@@ -1042,10 +1059,6 @@ unescaping too."
(helpful--propertize-info)
(helpful--propertize-links)
(helpful--propertize-bare-links)
- (helpful--propertize-keywords)
- (helpful--propertize-quoted)
- ;; This needs to happen after we've replaced quoted chars, so we
- ;; don't confuse \\=` with `.
(helpful--format-command-keys)
(s-trim)))
@@ -2307,7 +2320,7 @@ For example, \"(some-func FOO &optional BAR)\"."
(defun helpful--format-obsolete-info (sym callable-p)
(-let [(use _ date) (helpful--obsolete-info sym callable-p)]
- (helpful--propertize-quoted
+ (helpful--format-docstring
(s-word-wrap
70
(format "This %s is obsolete%s%s"