mirror of https://github.com/Wilfred/difftastic/
270 lines
9.3 KiB
EmacsLisp
270 lines
9.3 KiB
EmacsLisp
;;; helpful.el --- a better *help* buffer -*- lexical-binding: t; -*-
|
|
|
|
;; Copyright (C) 2017-2018 Wilfred Hughes
|
|
|
|
(defun helpful-update ()
|
|
"Update the current *Helpful* buffer to the latest
|
|
state of the current symbol."
|
|
(interactive)
|
|
(cl-assert (not (null helpful--sym)))
|
|
(unless (buffer-live-p helpful--associated-buffer)
|
|
(setq helpful--associated-buffer nil))
|
|
(-let* ((inhibit-read-only t)
|
|
(start-line (line-number-at-pos))
|
|
(start-column (current-column))
|
|
(primitive-p (helpful--primitive-p helpful--sym helpful--callable-p))
|
|
(look-for-src (or (not primitive-p)
|
|
find-function-C-source-directory))
|
|
((buf pos opened)
|
|
(if look-for-src
|
|
(helpful--definition helpful--sym helpful--callable-p)
|
|
'(nil nil nil)))
|
|
(source (when look-for-src
|
|
(helpful--source helpful--sym helpful--callable-p buf pos)))
|
|
(source-path (when buf
|
|
(buffer-file-name buf)))
|
|
(references (helpful--calculate-references
|
|
helpful--sym helpful--callable-p
|
|
source-path)))
|
|
|
|
(erase-buffer)
|
|
|
|
(insert (helpful--summary helpful--sym helpful--callable-p buf pos))
|
|
|
|
(when (and helpful--callable-p
|
|
(not (helpful--kbd-macro-p helpful--sym)))
|
|
(helpful--insert-section-break)
|
|
(insert
|
|
(helpful--heading "Signature")
|
|
(helpful--syntax-highlight (helpful--signature helpful--sym))))
|
|
|
|
(when (not helpful--callable-p)
|
|
(helpful--insert-section-break)
|
|
(let* ((sym helpful--sym)
|
|
(val (helpful--sym-value sym helpful--associated-buffer))
|
|
(multiple-views-p
|
|
(or (stringp val)
|
|
(keymapp val)
|
|
(and (s-ends-with-p "-hook" (symbol-name sym))
|
|
(consp val)))))
|
|
(insert
|
|
(helpful--heading
|
|
(cond
|
|
;; Buffer-local variable and we're looking at the value in
|
|
;; a specific buffer.
|
|
((and
|
|
helpful--associated-buffer
|
|
(local-variable-p sym helpful--associated-buffer))
|
|
(format "Value in %s"
|
|
(helpful--button
|
|
(format "#<buffer %s>" (buffer-name helpful--associated-buffer))
|
|
'helpful-buffer-button
|
|
'buffer helpful--associated-buffer
|
|
'position pos)))
|
|
;; Buffer-local variable but default/global value.
|
|
((local-variable-if-set-p sym)
|
|
"Global Value")
|
|
;; This variable is not buffer-local.
|
|
(t "Value")))
|
|
(cond
|
|
(helpful--view-literal
|
|
(helpful--syntax-highlight (helpful--pretty-print val)))
|
|
;; Allow strings to be viewed with properties rendered in
|
|
;; Emacs, rather than as a literal.
|
|
((stringp val)
|
|
val)
|
|
;; Allow keymaps to be viewed with keybindings shown and
|
|
;; links to the commands bound.
|
|
((keymapp val)
|
|
(helpful--format-keymap val))
|
|
((and (s-ends-with-p "-hook" (symbol-name sym))
|
|
(consp val))
|
|
(helpful--format-hook val))
|
|
(t
|
|
(helpful--pretty-print val)))
|
|
"\n\n")
|
|
(when multiple-views-p
|
|
(insert (helpful--make-toggle-literal-button) " "))
|
|
|
|
(when (local-variable-if-set-p sym)
|
|
(insert
|
|
(helpful--button
|
|
"Buffer values"
|
|
'helpful-associated-buffer-button
|
|
'symbol sym
|
|
'prompt-p t)
|
|
" "
|
|
(helpful--button
|
|
"Global value"
|
|
'helpful-associated-buffer-button
|
|
'symbol sym
|
|
'prompt-p nil)
|
|
" "))
|
|
(when (memq (helpful--sym-value helpful--sym helpful--associated-buffer) '(nil t))
|
|
(insert (helpful--make-toggle-button helpful--sym helpful--associated-buffer) " "))
|
|
(insert (helpful--make-set-button helpful--sym helpful--associated-buffer))
|
|
(when (custom-variable-p helpful--sym)
|
|
(insert " " (helpful--make-customize-button helpful--sym)))))
|
|
|
|
(-when-let (docstring (helpful--docstring helpful--sym helpful--callable-p))
|
|
(helpful--insert-section-break)
|
|
(insert
|
|
(helpful--heading "Documentation")
|
|
(helpful--format-docstring docstring))
|
|
(when (helpful--in-manual-p helpful--sym)
|
|
(insert "\n\n")
|
|
(insert (helpful--make-manual-button helpful--sym))))
|
|
|
|
;; Show keybindings.
|
|
;; TODO: allow users to conveniently add and remove keybindings.
|
|
(when (commandp helpful--sym)
|
|
(helpful--insert-section-break)
|
|
(insert
|
|
(helpful--heading "Key Bindings")
|
|
(helpful--format-keys helpful--sym)))
|
|
|
|
(helpful--insert-section-break)
|
|
|
|
(insert
|
|
(helpful--heading "References")
|
|
(let ((src-button
|
|
(when source-path
|
|
(helpful--navigate-button
|
|
(file-name-nondirectory source-path)
|
|
source-path
|
|
(or pos
|
|
0)))))
|
|
(cond
|
|
((and source-path references)
|
|
(format "References in %s:\n%s"
|
|
src-button
|
|
(helpful--format-position-heads references source-path)))
|
|
((and source-path primitive-p)
|
|
(format
|
|
"Finding references in a .%s file is not supported."
|
|
(f-ext source-path)))
|
|
(source-path
|
|
(format "%s is unused in %s."
|
|
helpful--sym
|
|
src-button))
|
|
((and primitive-p (null find-function-C-source-directory))
|
|
"C code is not yet loaded.")
|
|
(t
|
|
"Could not find source file.")))
|
|
"\n\n"
|
|
(helpful--make-references-button helpful--sym helpful--callable-p))
|
|
|
|
(when (and helpful--callable-p source (not primitive-p))
|
|
(insert
|
|
" "
|
|
(helpful--make-callees-button helpful--sym source)))
|
|
|
|
(when (helpful--advised-p helpful--sym)
|
|
(helpful--insert-section-break)
|
|
(insert
|
|
(helpful--heading "Advice")
|
|
(format "This %s is advised."
|
|
(if (macrop helpful--sym) "macro" "function"))))
|
|
|
|
(let ((can-edebug
|
|
(helpful--can-edebug-p helpful--sym helpful--callable-p buf pos))
|
|
(can-trace
|
|
(and (symbolp helpful--sym)
|
|
helpful--callable-p
|
|
;; Tracing uses advice, and you can't apply advice to
|
|
;; primitive functions that are replaced with special
|
|
;; opcodes. For example, `narrow-to-region'.
|
|
(not (plist-get (symbol-plist helpful--sym) 'byte-opcode))))
|
|
(can-disassemble
|
|
(and helpful--callable-p (not primitive-p)))
|
|
(can-forget
|
|
(and (not (special-form-p helpful--sym))
|
|
(not primitive-p))))
|
|
(when (or can-edebug can-trace can-disassemble can-forget)
|
|
(helpful--insert-section-break)
|
|
(insert (helpful--heading "Debugging")))
|
|
(when can-edebug
|
|
(insert
|
|
(helpful--make-edebug-button helpful--sym)))
|
|
(when can-trace
|
|
(when can-edebug
|
|
(insert " "))
|
|
(insert
|
|
(helpful--make-tracing-button helpful--sym)))
|
|
|
|
(when (and
|
|
(or can-edebug can-trace)
|
|
(or can-disassemble can-forget))
|
|
(insert "\n"))
|
|
|
|
(when can-disassemble
|
|
(insert (helpful--make-disassemble-button helpful--sym)))
|
|
|
|
(when can-forget
|
|
(when can-disassemble
|
|
(insert " "))
|
|
(insert (helpful--make-forget-button helpful--sym helpful--callable-p))))
|
|
|
|
(let ((aliases (helpful--aliases helpful--sym helpful--callable-p)))
|
|
(when aliases
|
|
(helpful--insert-section-break)
|
|
(insert
|
|
(helpful--heading "Aliases")
|
|
(s-join "\n" (--map (helpful--format-alias it helpful--callable-p)
|
|
aliases)))))
|
|
|
|
(helpful--insert-section-break)
|
|
|
|
(insert
|
|
(helpful--heading "Source Code")
|
|
(cond
|
|
(source-path
|
|
(concat
|
|
(propertize (format "%s Defined in " (if primitive-p "//" ";;"))
|
|
'face 'font-lock-comment-face)
|
|
(helpful--navigate-button
|
|
(f-abbrev source-path)
|
|
source-path
|
|
pos)
|
|
"\n"))
|
|
(primitive-p
|
|
(concat
|
|
(propertize
|
|
"C code is not yet loaded."
|
|
'face 'font-lock-comment-face)
|
|
"\n\n"
|
|
(helpful--button
|
|
"Set C source directory"
|
|
'helpful-c-source-directory)))
|
|
(t
|
|
"")))
|
|
(when source
|
|
(insert
|
|
(cond
|
|
((stringp source)
|
|
(helpful--syntax-highlight source (if primitive-p 'c-mode)))
|
|
((and (consp source) (eq (car source) 'closure))
|
|
(helpful--syntax-highlight
|
|
(concat ";; Closure converted to defun by helpful.\n"
|
|
(helpful--pretty-print
|
|
(helpful--format-closure helpful--sym source)))))
|
|
(t
|
|
(helpful--syntax-highlight
|
|
(concat
|
|
";; Source file is unknown, showing raw function object.\n"
|
|
(helpful--pretty-print source)))))))
|
|
|
|
(helpful--insert-section-break)
|
|
|
|
(-when-let (formatted-props (helpful--format-properties helpful--sym))
|
|
(insert
|
|
(helpful--heading "Symbol Properties")
|
|
formatted-props))
|
|
|
|
(goto-char (point-min))
|
|
(forward-line (1- start-line))
|
|
(forward-char start-column)
|
|
|
|
(when opened
|
|
(kill-buffer buf))))
|