]> git.eshelyaron.com Git - emacs.git/commitdiff
Improve prompting 'customize-toggle-option'
authorEshel Yaron <me@eshelyaron.com>
Wed, 14 Feb 2024 12:51:29 +0000 (13:51 +0100)
committerEshel Yaron <me@eshelyaron.com>
Wed, 14 Feb 2024 14:23:57 +0000 (15:23 +0100)
* 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.

etc/NEWS
lisp/cus-edit.el

index f7dae2e8a2cf0f1b794afed41cf0a898ad533f0f..7f540312fde007de5cf6ed2aeb0f6b15b1ff068c 100644 (file)
--- 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
 
index 8fad51dc1166c7ddced32b4698f05903ba1204ad..004cd2de9951180a0d8bb7015fca30e6e7b7f931 100644 (file)
@@ -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)