]> git.eshelyaron.com Git - emacs.git/commitdiff
Have setopt check types
authorLars Ingebrigtsen <larsi@gnus.org>
Thu, 17 Feb 2022 11:31:12 +0000 (12:31 +0100)
committerLars Ingebrigtsen <larsi@gnus.org>
Thu, 17 Feb 2022 11:31:12 +0000 (12:31 +0100)
* doc/lispref/variables.texi (Setting Variables): Note type checking.
* lisp/cus-edit.el (setopt--set): New function to avoid having
Customize saving values, too.
(setopt): Use it.

doc/lispref/variables.texi
lisp/cus-edit.el
test/lisp/cus-edit-tests.el

index a520b3856c546fd50fb77c00ec28f8fc90cba876..d991ae9e2774bb06a6196c7b34e5013b5fa9bc74 100644 (file)
@@ -886,6 +886,10 @@ will also issue a message:
 (setopt my-var 2)
 @end example
 
+@code{setopt} also checks whether the value is valid for the user
+option.  For instance, using @code{setopt} to set a user option
+defined with a @code{number} type to a string will signal an error.
+
 The @code{setopt} macro can be used on regular, non-user option
 variables, but is much less efficient than @code{setq}.  The main use
 case for this macro is setting user options in the user's init file.
index bb7ffc1eae5ad5dc79160e5e22ce7f5d3fd5c82c..bec7348099af801ef47b4cb310791248660a4a7f 100644 (file)
@@ -1049,10 +1049,7 @@ If given a prefix (or a COMMENT argument), also prompt for a comment."
   "Set VARIABLE/VALUE pairs, and return the final VALUE.
 This is like `setq', but is meant for user options instead of
 plain variables.  This means that `setopt' will execute any
-Customize form associated with VARIABLE.
-
-If VARIABLE has a `custom-set' property, that is used for setting
-VARIABLE, otherwise `set-default' is used.
+`custom-set' form associated with VARIABLE.
 
 \(fn [VARIABLE VALUE]...)"
   (declare (debug setq))
@@ -1062,11 +1059,20 @@ VARIABLE, otherwise `set-default' is used.
     (while pairs
       (unless (symbolp (car pairs))
         (error "Attempting to set a non-symbol: %s" (car pairs)))
-      (push `(customize-set-variable ',(car pairs) ,(cadr pairs))
+      (push `(setopt--set ',(car pairs) ,(cadr pairs))
             expr)
       (setq pairs (cddr pairs)))
     (macroexp-progn (nreverse expr))))
 
+;;;###autoload
+(defun setopt--set (variable value)
+  (custom-load-symbol variable)
+  ;; Check that the type is correct.
+  (when-let ((type (get variable 'custom-type)))
+    (unless (widget-apply (widget-convert type) :match value)
+      (user-error "Value `%S' does not match type %s" value type)))
+  (funcall (or (get variable 'custom-set) #'set-default) variable value))
+
 ;;;###autoload
 (defun customize-save-variable (variable value &optional comment)
   "Set the default for VARIABLE to VALUE, and save it for future sessions.
index 01a1407dcaa8949d21063fa786b98c708f22ebf1..7a597ccf343267d7ff35c3999502843ee8022637 100644 (file)
       (customize-saved)
       (should (search-forward cus-edit-tests--obsolete-option-tag nil t)))))
 
+(ert-deftest test-setopt ()
+  (defcustom cus-edit-test-foo1 0
+    ""
+    :type 'number)
+  (should (= (setopt cus-edit-test-foo1 1) 1))
+  (should (= cus-edit-test-foo1 1))
+  (should-error (setopt cus-edit-test-foo1 :foo)))
+
 (provide 'cus-edit-tests)
 ;;; cus-edit-tests.el ends here