helpful

a fork of Wilfred's helpful
git clone https://git.trogloxene.org/helpful.git
Log | Files | Refs | README

commit 27373703625fdf86fe0f71500767802a28350b9f
parent b0e937fff71dc0a5d34066bfd25310e76f284621
Author: Wilfred Hughes <me@wilfred.me.uk>
Date:   Tue, 22 Sep 2020 23:18:34 -0700

Detect docstring symbol references that are unambiguous

If we see "function `foo'" or "variable `foo'", it's clear what we
should link to.

Fixes #243

Diffstat:
MCHANGELOG.md | 2++
Mhelpful.el | 38+++++++++++++++++++++++++++++++++++---
2 files changed, 37 insertions(+), 3 deletions(-)

diff --git a/CHANGELOG.md b/CHANGELOG.md @@ -8,6 +8,8 @@ Fixed a crash on assigning byte-compiled objects to keybindings. Fixed an issue with advice being shown in docstrings on Emacs 27+. +Symbol links in docstrings are now smarter in cases like "function `foo'". + # v0.17 Fixed a minor docstring formatting issue when keymap references were diff --git a/helpful.el b/helpful.el @@ -758,7 +758,7 @@ blank line afterwards." (-cons* first-line "" (cdr lines))) docstring))) -(defun helpful--propertize-sym-ref (sym-name) +(defun helpful--propertize-sym-ref (sym-name before-txt after-txt) "Given a symbol name from a docstring, convert to a button (if bound) or else highlight." (let* ((sym (intern sym-name))) @@ -772,6 +772,20 @@ bound) or else highlight." sym-name) (propertize sym-name 'face 'font-lock-builtin-face)) + ((and (boundp sym) (s-ends-with-p "variable " before-txt)) + (helpful--button + sym-name + 'helpful-describe-exactly-button + 'symbol sym + 'callable-p nil)) + ((and (fboundp sym) (or + (s-starts-with-p " command" after-txt) + (s-ends-with-p "function " before-txt))) + (helpful--button + sym-name + 'helpful-describe-exactly-button + 'symbol sym + 'callable-p t)) ;; Only create a link if this is a symbol that is bound as a ;; variable or callable. ((or (boundp sym) (fboundp sym)) @@ -964,6 +978,20 @@ vector suitable for `key-description', and COMMAND is a smbol." t t)) +(defun helpful--chars-before (pos n) + "Return up to N chars before POS in the current buffer. +The string may be shorter than N or empty if out-of-range." + (buffer-substring + (max (point-min) (- pos n)) + pos)) + +(defun helpful--chars-after (pos n) + "Return up to N chars after POS in the current buffer. +The string may be shorter than N or empty if out-of-range." + (buffer-substring + pos + (min (point-max) (+ pos n)))) + (defun helpful--format-command-keys (docstring) "Convert command key references and keymap references in DOCSTRING to buttons. @@ -1019,9 +1047,13 @@ unescaping too." ((s-contains-p "\\[" contents) (delete-region start-pos end-pos) (insert (helpful--format-commands contents keymap))) + ;; Highlight a normal `foo', extracting the surrounding + ;; text so we can detect e.g. "function `foo'". (t - (delete-region start-pos end-pos) - (insert (helpful--propertize-sym-ref contents)))))) + (let ((before (helpful--chars-before start-pos 10)) + (after (helpful--chars-after end-pos 10))) + (delete-region start-pos end-pos) + (insert (helpful--propertize-sym-ref contents before after))))))) ((looking-at ;; Text of the form \\<foo-keymap> (rx "\\<" (group (+ (not (in ">")))) ">"