From: Eshel Yaron Date: Wed, 14 Feb 2024 12:51:29 +0000 (+0100) Subject: Improve prompting 'customize-toggle-option' X-Git-Url: http://git.eshelyaron.com/gitweb/?a=commitdiff_plain;h=6ce5bb47abf4c4986d0ac6ce332423cb85a4436d;p=emacs.git Improve prompting 'customize-toggle-option' * lisp/cus-edit.el (customize-option-history): New variable. (custom-variable-prompt): Use it. (customize-read-boolean-option): New function. (customize-toggle-option): Use it. * etc/NEWS: Refine announcement. --- diff --git a/etc/NEWS b/etc/NEWS index f7dae2e8a2c..7f540312fde 100644 --- a/etc/NEWS +++ b/etc/NEWS @@ -1455,7 +1455,7 @@ This command pops up a buffer to edit the settings in ".dir-locals.el". --- ** New command 'customize-toggle-option'. -This command can toggle boolean options for the duration of a session. +This command toggles the value of a boolean (nil/non-nil) option. ** Calc diff --git a/lisp/cus-edit.el b/lisp/cus-edit.el index 8fad51dc116..004cd2de995 100644 --- a/lisp/cus-edit.el +++ b/lisp/cus-edit.el @@ -474,6 +474,9 @@ IF REGEXP is not a string, return it unchanged." (split-string regexp "\\\\|") regexp)) +(defvar customize-option-history nil + "History of minibuffer inputs for `customize-option' and similar commands.") + (defun custom-variable-prompt () "Prompt for a custom variable, defaulting to the variable at point. Return a list suitable for use in `interactive'." @@ -482,7 +485,8 @@ Return a list suitable for use in `interactive'." (enable-recursive-minibuffers t) val) (setq val (completing-read (format-prompt "Customize variable" default) - obarray 'custom-variable-p t nil nil default)) + obarray 'custom-variable-p t nil + 'customize-option-history default)) (list (if (equal val "") (if (symbolp v) v nil) (intern val))))) @@ -1227,37 +1231,37 @@ If OTHER-WINDOW is non-nil, display in another window." (unless (eq symbol basevar) (message "`%s' is an alias for `%s'" symbol basevar)))) +(defun customize-read-boolean-option (&optional any) + "Read a boolean user option and return its name as a symbol. + +By default, accept only options of type `boolean'. If optional argument +ANY is non-nil, accept any user option instead, regardless of its type." + (let* ((v (symbol-at-point)) + (pred (if any #'custom-variable-p + (lambda (sym) + (eq (get (indirect-variable sym) 'custom-type) 'boolean)))) + (default (when (funcall pred v) (symbol-name v))) + (val (completing-read + (format-prompt "Toggle option" default) + (completion-table-with-metadata + obarray '(metadata (category . boolean-option))) + pred t nil 'customize-option-history default))) + (when (string-empty-p val) (user-error "You didn't specify an option")) + (intern val))) + ;;;###autoload (defun customize-toggle-option (symbol) - "Toggle the value of boolean option SYMBOL for this session." - (interactive (let ((prompt "Toggle boolean option: ") opts) - (mapatoms - (lambda (sym) - (when (eq (get sym 'custom-type) 'boolean) - (push sym opts)))) - (list (intern (completing-read prompt opts nil nil nil nil - (symbol-at-point)))))) - (let* ((setter (or (get symbol 'custom-set) #'set-default)) - (getter (or (get symbol 'custom-get) #'symbol-value)) - (value (condition-case nil - (funcall getter symbol) - (void-variable (error "`%s' is not bound" symbol)))) - (type (get symbol 'custom-type))) - (cond - ((eq type 'boolean)) - ((and (null type) - (yes-or-no-p - (format "`%s' doesn't have a type, and has the value %S. \ -Proceed to toggle?" symbol value)))) - ((yes-or-no-p - (format "`%s' is of type %s, and has the value %S. \ -Proceed to toggle?" - symbol type value))) - ((error "Abort toggling of option `%s'" symbol))) - (message "%s user options `%s'." - (if (funcall setter symbol (not value)) - "Enabled" "Disabled") - symbol))) + "Toggle boolean user option SYMBOL. + +Interactively, prompt for SYMBOL, with completion. Normally, completion +candidates include only option with custom type `boolean'. With a +prefix argument, completion candidates include all user options instead." + (interactive (list (customize-read-boolean-option current-prefix-arg))) + (let* ((set (or (get symbol 'custom-set) #'set-default)) + (get (or (get symbol 'custom-get) #'symbol-value)) + (new (not (funcall get symbol)))) + (funcall set symbol new) + (message "`%s' is now %s." symbol (if new "ON" "OFF")))) ;;;###autoload (defalias 'toggle-option #'customize-toggle-option)