From 997dd86a9f6a253e4542d65b17dfec6af2f4e8fd Mon Sep 17 00:00:00 2001 From: Lars Ingebrigtsen Date: Sun, 13 Feb 2022 16:29:26 +0100 Subject: [PATCH] Add a new macro `setopt' * doc/emacs/custom.texi (Examining): Mention it. (Init Syntax): Ditto. * doc/emacs/windows.texi (Window Choice): Adjust example. * doc/lispref/windows.texi (Choosing Window Options): Adjust examples. * doc/lispref/variables.texi (Setting Variables): Document setopt. * doc/misc/eudc.texi (Emacs-only Configuration): Adjust examples. * lisp/cus-edit.el (setopt): New macro. --- doc/emacs/custom.texi | 21 +++++++++++++++++--- doc/emacs/windows.texi | 12 ++++++------ doc/lispref/variables.texi | 27 +++++++++++++++++++++++++ doc/lispref/windows.texi | 40 +++++++++++++++++++------------------- doc/misc/eudc.texi | 36 +++++++++++++++++----------------- etc/NEWS | 5 +++++ lisp/cus-edit.el | 23 ++++++++++++++++++++++ 7 files changed, 117 insertions(+), 47 deletions(-) diff --git a/doc/emacs/custom.texi b/doc/emacs/custom.texi index b2dd5eb6980..c4f112d6683 100644 --- a/doc/emacs/custom.texi +++ b/doc/emacs/custom.texi @@ -844,6 +844,21 @@ otherwise stated, affects only the current Emacs session. The only way to alter the variable in future sessions is to put something in your initialization file (@pxref{Init File}). + If you're setting a customizable variable in your initialization +file, and you don't want to use the Customize interface, you can use +the @code{setopt} macro. For instance: + +@findex setopt +@example +(setopt fill-column 75) +@end example + +This works the same as @code{setq}, but if the variable has any +special setter functions, they will be run automatically when using +@code{setopt}. You can also use @code{setopt} on other, +non-customizable variables, but this is less efficient than using +@code{setq}. + @node Hooks @subsection Hooks @cindex hook @@ -2338,8 +2353,8 @@ mode when you set them with Customize, but ordinary @code{setq} won't do that; to enable the mode in your init file, call the minor mode command. Finally, a few customizable user options are initialized in complex ways, and these have to be set either via the customize -interface (@pxref{Customization}) or by using -@code{customize-set-variable} (@pxref{Examining}). +interface (@pxref{Customization}), or by using +@code{customize-set-variable}/@code{setopt} (@pxref{Examining}). The second argument to @code{setq} is an expression for the new value of the variable. This can be a constant, a variable, or a @@ -2492,7 +2507,7 @@ Change the coding system used when using the clipboard (@pxref{Communication Coding}). @example -(customize-set-variable 'selection-coding-system 'utf-8) +(setopt selection-coding-system 'utf-8) @end example @item diff --git a/doc/emacs/windows.texi b/doc/emacs/windows.texi index 4a3862562c2..4537f8157e8 100644 --- a/doc/emacs/windows.texi +++ b/doc/emacs/windows.texi @@ -442,8 +442,8 @@ selected window write: @example @group -(customize-set-variable - 'display-buffer-alist +(setopt + display-buffer-alist '(("\\*scratch\\*" (display-buffer-same-window)))) @end group @end example @@ -468,8 +468,8 @@ Lisp Reference Manual}) as follows: @example @group -(customize-set-variable - 'display-buffer-base-action +(setopt + display-buffer-base-action '((display-buffer-reuse-window display-buffer-pop-up-frame) (reusable-frames . 0))) @end group @@ -535,8 +535,8 @@ the following form in your initialization file (@pxref{Init File}): @example @group -(customize-set-variable - 'display-buffer-alist +(setopt + display-buffer-alist '(("\\*Completions\\*" display-buffer-below-selected))) @end group @end example diff --git a/doc/lispref/variables.texi b/doc/lispref/variables.texi index b9de92a29eb..8b5f50562e7 100644 --- a/doc/lispref/variables.texi +++ b/doc/lispref/variables.texi @@ -861,6 +861,33 @@ error is signaled. @end example @end defun +@defmac setopt [symbol form]@dots{} +This is like @code{setq} (see above), but meant for user options. +This macro uses the Customize machinery to set the variable(s). In +particular, @code{setopt} will run the setter function associated with +the variable. For instance, if you have: + +@example +(defcustom my-var 1 + "My var." + :type 'number + :set (lambda (var val) + (set-default var val) + (message "We set %s to %s" var val))) +@end example + +Then the following, in addition to setting @code{my-var} to @samp{2}, +will also issue a message: + +@example +(setop my-var 2) +@end example + +@code{setopt} 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. +@end defmac + @node Watching Variables @section Running a function when a variable is changed. @cindex variable watchpoints diff --git a/doc/lispref/windows.texi b/doc/lispref/windows.texi index bbf8988e5c4..43f222d57ff 100644 --- a/doc/lispref/windows.texi +++ b/doc/lispref/windows.texi @@ -3377,8 +3377,8 @@ functions it should try instead as, for example: @example @group -(customize-set-variable - 'display-buffer-base-action +(setopt + display-buffer-base-action '((display-buffer-reuse-window display-buffer-same-window display-buffer-in-previous-window display-buffer-use-some-window))) @@ -3392,8 +3392,8 @@ Instead of customizing this variable to @code{t}, customize @example @group -(customize-set-variable - 'display-buffer-base-action +(setopt + display-buffer-base-action '((display-buffer-reuse-window display-buffer-pop-up-frame) (reusable-frames . 0))) @end group @@ -3409,8 +3409,8 @@ specifying the action function @code{display-buffer-same-window}. @example @group -(customize-set-variable - 'display-buffer-alist +(setopt + display-buffer-alist (cons '("\\*foo\\*" (display-buffer-same-window)) display-buffer-alist)) @end group @@ -3483,8 +3483,8 @@ another frame. Such a user might provide the following customization: @example @group -(customize-set-variable - 'display-buffer-base-action +(setopt + display-buffer-base-action '((display-buffer-reuse-window display-buffer-pop-up-frame) (reusable-frames . 0))) @end group @@ -3529,8 +3529,8 @@ In fact, this: @example @group -(customize-set-variable - 'display-buffer-base-action +(setopt + display-buffer-base-action '(display-buffer-pop-up-frame (reusable-frames . 0))) @end group @end example @@ -3586,8 +3586,8 @@ by customizing the option @code{display-buffer-alist} as follows: @example @group -(customize-set-variable - 'display-buffer-alist +(setopt + display-buffer-alist '(("\\*foo\\*" (display-buffer-reuse-window display-buffer-pop-up-frame)))) @end group @@ -3609,8 +3609,8 @@ we would have to specify that separately, however: @example @group -(customize-set-variable - 'display-buffer-alist +(setopt + display-buffer-alist '(("\\*foo\\*" (display-buffer-reuse-window display-buffer-pop-up-frame) (reusable-frames . visible)))) @@ -3716,8 +3716,8 @@ written that as @example @group -(customize-set-variable - 'display-buffer-alist +(setopt + display-buffer-alist '(("\\*foo\\*" (display-buffer-reuse-window display-buffer-pop-up-frame) (inhibit-same-window . t) @@ -3860,8 +3860,8 @@ follows: @example @group -(customize-set-variable - 'display-buffer-alist +(setopt + display-buffer-alist '(("\\*foo\\*" (display-buffer-below-selected display-buffer-at-bottom) (inhibit-same-window . t) @@ -3874,8 +3874,8 @@ To add a customization for a second buffer one would then write: @example @group -(customize-set-variable - 'display-buffer-alist +(setopt + display-buffer-alist '(("\\*foo\\*" (display-buffer-below-selected display-buffer-at-bottom) (inhibit-same-window . t) diff --git a/doc/misc/eudc.texi b/doc/misc/eudc.texi index e9cf4cfade9..7c37ae55055 100644 --- a/doc/misc/eudc.texi +++ b/doc/misc/eudc.texi @@ -286,14 +286,14 @@ LDAP: @lisp (with-eval-after-load "message" (define-key message-mode-map (kbd "TAB") 'eudc-expand-inline)) -(customize-set-variable 'eudc-server-hotlist - '(("" . bbdb) - ("ldaps://ldap.gnu.org" . ldap))) -(customize-set-variable 'ldap-host-parameters-alist - '(("ldaps://ldap.gnu.org" - base "ou=people,dc=gnu,dc=org" - binddn "gnu\\emacsuser" - passwd ldap-password-read))) +(setopt eudc-server-hotlist + '(("" . bbdb) + ("ldaps://ldap.gnu.org" . ldap))) +(setopt 'ldap-host-parameters-alist + '(("ldaps://ldap.gnu.org" + base "ou=people,dc=gnu,dc=org" + binddn "gnu\\emacsuser" + passwd ldap-password-read))) @end lisp @findex ldap-password-read @@ -342,12 +342,12 @@ configure EUDC for LDAP: @lisp (with-eval-after-load "message" (define-key message-mode-map (kbd "TAB") 'eudc-expand-inline)) -(customize-set-variable 'eudc-server-hotlist - '(("" . bbdb) - ("ldaps://ldap.gnu.org" . ldap))) -(customize-set-variable 'ldap-host-parameters-alist - '(("ldaps://ldap.gnu.org" - auth-source t))) +(setopt 'eudc-server-hotlist + '(("" . bbdb) + ("ldaps://ldap.gnu.org" . ldap))) +(setopt 'ldap-host-parameters-alist + '(("ldaps://ldap.gnu.org" + auth-source t))) @end lisp For this example where we only care about one server, the server name @@ -371,10 +371,10 @@ and the @file{.emacs} expressions become: @lisp (with-eval-after-load "message" (define-key message-mode-map (kbd "TAB") 'eudc-expand-inline)) -(customize-set-variable 'eudc-server-hotlist - '(("" . bbdb) ("" . ldap))) -(customize-set-variable 'ldap-host-parameters-alist - '(("" auth-source t))) +(setopt 'eudc-server-hotlist + '(("" . bbdb) ("" . ldap))) +(setopt 'ldap-host-parameters-alist + '(("" auth-source t))) @end lisp @node Troubleshooting diff --git a/etc/NEWS b/etc/NEWS index 6f5edfafc5a..0f956f18a20 100644 --- a/etc/NEWS +++ b/etc/NEWS @@ -1092,6 +1092,11 @@ functions. * Lisp Changes in Emacs 29.1 ++++ +** New macro 'setopt'. +This is like 'setq', but uses 'customize-set-variable' to set the +variable(s). + +++ ** New utility predicate 'mode-line-window-selected-p'. This is meant to be used from ':eval' mode line constructs to create diff --git a/lisp/cus-edit.el b/lisp/cus-edit.el index ff70f6724a8..bb7ffc1eae5 100644 --- a/lisp/cus-edit.el +++ b/lisp/cus-edit.el @@ -1044,6 +1044,29 @@ If given a prefix (or a COMMENT argument), also prompt for a comment." (put variable 'customized-variable-comment comment))) value) +;;;###autoload +(defmacro setopt (&rest pairs) + "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. + +\(fn [VARIABLE VALUE]...)" + (declare (debug setq)) + (unless (zerop (mod (length pairs) 2)) + (error "PAIRS must have an even number of variable/value members")) + (let ((expr nil)) + (while pairs + (unless (symbolp (car pairs)) + (error "Attempting to set a non-symbol: %s" (car pairs))) + (push `(customize-set-variable ',(car pairs) ,(cadr pairs)) + expr) + (setq pairs (cddr pairs))) + (macroexp-progn (nreverse expr)))) + ;;;###autoload (defun customize-save-variable (variable value &optional comment) "Set the default for VARIABLE to VALUE, and save it for future sessions. -- 2.39.5