1
0
mirror of https://git.savannah.gnu.org/git/emacs.git synced 2024-11-23 07:19:15 +00:00

Allow editing variable values in *Help* buffers

* lisp/help-fns.el (help-enable-variable-value-editing): New user
option.
(describe-variable): Tag values for editing.
(help-fns--editable-variable, help-fns-edit-variable): New
functions (bug#36826).
(help-fns--edit-value-mode-map, help-fns--edit-value-mode)
(help-fns-edit-mode-done): New mode and commands.
This commit is contained in:
Lars Ingebrigtsen 2022-04-17 18:59:59 +02:00
parent b49cca7012
commit 01282cbd80
3 changed files with 83 additions and 5 deletions

View File

@ -405,6 +405,12 @@ command also works for non-Emoji characters.)
** Help
---
*** New user option 'help-enable-variable-value-editing'.
If enabled, 'e' on a value in *Help* will pop you to a new buffer
where you can edit the value. This is not enabled by default, because
it's easy to make an edit that yields an invalid result.
---
*** 'C-h b' uses outlining by default.
Set 'describe-bindings-outline' to nil to get the old behavior.

View File

@ -133,6 +133,14 @@ with the current prefix. The files are chosen according to
:group 'help
:version "26.3")
(defcustom help-enable-variable-value-editing nil
"If non-nil, allow editing values in *Help* buffers.
Values that aren't readable by the Emacs Lisp reader can't be
edited even if this option is enabled."
:type 'boolean
:group 'help
:version "29.1")
(defcustom help-enable-symbol-autoload nil
"Perform autoload if docs are missing from autoload objects."
:type 'boolean
@ -1167,10 +1175,11 @@ it is displayed along with the global value."
(let ((rep
(let ((print-quoted t)
(print-circle t))
(cl-prin1-to-string val))))
(if (and (symbolp val) (not (booleanp val)))
(cl-prin1-to-string val))))
(if (and (symbolp val) (not (booleanp val)))
(format-message "`%s'" rep)
rep))))
rep)))
(start (point)))
(if (< (+ (length print-rep) (point) (- line-beg)) 68)
(insert " " print-rep)
(terpri)
@ -1185,6 +1194,8 @@ it is displayed along with the global value."
(insert-buffer-substring pp-buffer)))))
;; Remove trailing newline.
(and (= (char-before) ?\n) (delete-char -1)))
(help-fns--editable-variable start (point)
variable val buffer)
(let* ((sv (get variable 'standard-value))
(origval (and (consp sv)
(condition-case nil
@ -1204,6 +1215,8 @@ it is displayed along with the global value."
(save-restriction
(narrow-to-region from (point))
(save-excursion (pp-buffer)))
(help-fns--editable-variable from (point)
variable origval buffer)
(if (< (point) (+ from 20))
(delete-region (1- from) from)))))))
(terpri)
@ -1236,7 +1249,9 @@ it is displayed along with the global value."
;; See previous comment for this function.
;; (help-xref-on-pp from (point))
(if (< (point) (+ from 20))
(delete-region (1- from) from)))))))
(delete-region (1- from) from))
(help-fns--editable-variable
from (point) variable global-val buffer))))))
(terpri))
;; If the value is large, move it to the end.
@ -1286,6 +1301,62 @@ it is displayed along with the global value."
;; Return the text we displayed.
(buffer-string))))))))
(defun help-fns--editable-variable (start end variable value buffer)
(when (and (readablep value) help-enable-variable-value-editing)
(add-text-properties
start end
(list 'help-echo "`e' to edit the value"
'help-fns--edit-variable (list variable value buffer
(current-buffer))
'keymap (define-keymap
"e" #'help-fns-edit-variable)))))
(defvar help-fns--edit-variable)
(put 'help-fns-edit-variable 'disabled t)
(defun help-fns-edit-variable ()
"Edit the variable under point."
(interactive)
(declare (completion ignore))
(let ((var (get-text-property (point) 'help-fns--edit-variable)))
(unless var
(error "No variable under point"))
(pop-to-buffer-same-window (format "*edit %s*" (nth 0 var)))
(prin1 (nth 1 var) (current-buffer))
(pp-buffer)
(goto-char (point-min))
(insert (format ";; Edit the `%s' variable.\n" (nth 0 var))
";; C-c C-c to update the value and exit.\n\n")
(help-fns--edit-value-mode)
(setq-local help-fns--edit-variable var)))
(defvar-keymap help-fns--edit-value-mode-map
"C-c C-c" #'help-fns-edit-mode-done)
(define-derived-mode help-fns--edit-value-mode emacs-lisp-mode "Elisp"
:interactive nil)
(defun help-fns-edit-mode-done (&optional kill)
"Update the value of the variable and kill the buffer.
If KILL (the prefix), don't update the value, but just kill the
current buffer."
(interactive "P" help-fns--edit-value-mode)
(unless help-fns--edit-variable
(error "Invalid buffer"))
(goto-char (point-min))
(cl-destructuring-bind (variable _ buffer help-buffer)
help-fns--edit-variable
(unless (buffer-live-p buffer)
(error "Original buffer is gone; can't update"))
(unless kill
(let ((value (read (current-buffer))))
(with-current-buffer buffer
(set variable value))))
(kill-buffer (current-buffer))
(when (buffer-live-p help-buffer)
(with-current-buffer help-buffer
(revert-buffer)))))
(defun help-fns--run-describe-functions (functions &rest args)
(with-current-buffer standard-output
(unless (bolp)

View File

@ -393,7 +393,8 @@ The format is (FUNCTION ARGS...).")
;;;###autoload
(define-derived-mode help-mode special-mode "Help"
"Major mode for viewing help text and navigating references in it.
Entry to this mode runs the normal hook `help-mode-hook'.
Also see the `help-enable-editing' variable.
Commands:
\\{help-mode-map}"
(setq-local revert-buffer-function