mirror of
git://git.sv.gnu.org/emacs.git
synced 2026-06-14 12:31:25 +00:00
Set user options in file/directory locals like 'setopt-local' (bug#81120)
This ensures defcustom ':set' functions are invoked. The new user option 'setopt-local-type-mismatch' can prompt users to accept or discard type-mismatched values or to always accept or discard such values. * lisp/cus-edit.el (setopt-local-type-mismatch): New defcustom. (setopt--set-local): Consult setopt-local-type-mismatch. * lisp/files.el (hack-one-local-variable): Detect a custom variable and call 'setopt--set-local'. * etc/NEWS: Announce the change.
This commit is contained in:
parent
6e67ac222b
commit
725120ca3d
3 changed files with 71 additions and 11 deletions
22
etc/NEWS
22
etc/NEWS
|
|
@ -49,6 +49,28 @@ behavior.
|
|||
If this variable is nil, 'tty-cursor-movement-use-TAB-BS' has no effect,
|
||||
and Emacs will never use TABs for any cursor-movement sequences.
|
||||
|
||||
---
|
||||
** File- and directory-locals respect user option setters.
|
||||
Values of variables that are user options mentioned in file-local
|
||||
variable properties and directory-locals via ".dir-locals.el" are now
|
||||
set similarly to 'setopt-local'; i.e., if a user option has a defcustom
|
||||
':set' function, that function will be invoked.
|
||||
|
||||
---
|
||||
** New user option 'setopt-local-type-mismatch'.
|
||||
This option controls what 'setopt-local' does when it detects a type
|
||||
mismatch between the specified value and the 'defcustom' of its user
|
||||
option. Its backward-compatible default is nil which emits a warning
|
||||
and accepts the type-mismatched value. If you customize it to non-nil,
|
||||
you will be prompted to accept or ignore the value. If it is the symbol
|
||||
'accept', warnings are inhibited and type-mismatched values are
|
||||
accepted. If 'discard', warnings are inhibited and type-mismatched
|
||||
values are discarded.
|
||||
|
||||
*** Specifying a minor mode as a local variables enables that mode,
|
||||
unconditionally. The previous behavior, toggling the mode, was
|
||||
neither reliable nor generally desirable.
|
||||
|
||||
|
||||
* Editing Changes in Emacs 32.1
|
||||
|
||||
|
|
|
|||
|
|
@ -1104,6 +1104,22 @@ even if it doesn't match the type.)
|
|||
(put variable 'custom-check-value (list value))
|
||||
(funcall (or (get variable 'custom-set) #'set-default) variable value))
|
||||
|
||||
;;;###autoload
|
||||
(defcustom setopt-local-type-mismatch nil
|
||||
"Behavior of `setopt-local’ if value's type mismatches its definition.
|
||||
If nil, emit a warning and assign the value.
|
||||
If non-nil, prompt to accept or discard the value.
|
||||
If the symbol `accept', ignore type mismatch warning and assign the value.
|
||||
If the symbol `discard', ignore warning and discard the mismatched value.
|
||||
Note: Accepting mismatched values may result in unexpected behavior."
|
||||
:type '(choice (const :tag "Emit a warning and accept the type value" nil)
|
||||
(const :tag "Prompt to accept or discard the value" t)
|
||||
(const :tag "Ignore the warning and accept the value" accept)
|
||||
(const :tag "Ignore the warning and discard the value" discard))
|
||||
:version "32.1"
|
||||
:safe #'symbolp
|
||||
:group 'customize)
|
||||
|
||||
;;;###autoload
|
||||
(defmacro setopt-local (&rest pairs)
|
||||
"Set buffer local VARIABLE/VALUE pairs, and return the final VALUE.
|
||||
|
|
@ -1135,17 +1151,37 @@ Signal an error if a `custom-set' form does not support the
|
|||
|
||||
;;;###autoload
|
||||
(defun setopt--set-local (variable value)
|
||||
"Set a buffer local VARIABLE to VALUE.
|
||||
Consult `setopt-local-type-mismatch'."
|
||||
(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)
|
||||
(warn "Value does not match %S's type `%S': %S" variable type value)))
|
||||
(condition-case _
|
||||
(funcall (or (get variable 'custom-set)
|
||||
(lambda (x v &optional _) (set-local x v)))
|
||||
variable value 'buffer-local)
|
||||
(wrong-number-of-arguments
|
||||
(error "The setter of %S does not support setopt-local" variable))))
|
||||
(let ((accept t))
|
||||
;; Check that the type is correct.
|
||||
(when-let* ((type (get variable 'custom-type)))
|
||||
(unless (widget-apply (widget-convert type) :match value)
|
||||
(let ((msg (format-message
|
||||
"Value does not match %S's type `%S': %S"
|
||||
variable type value)))
|
||||
(cond
|
||||
;; Fall through and try anyway.
|
||||
((eq setopt-local-type-mismatch 'accept))
|
||||
;; Silently discard the mismatched value.
|
||||
((eq setopt-local-type-mismatch 'discard)
|
||||
(setq accept nil))
|
||||
;; Prompt to accept or discard the value.
|
||||
(setopt-local-type-mismatch
|
||||
(setq accept (eq ?a (car
|
||||
(read-multiple-choice msg
|
||||
'((?a "accept" "Accept")
|
||||
(?d "discard" "Discard")))))))
|
||||
(t
|
||||
(warn msg))))))
|
||||
(when accept
|
||||
(condition-case _
|
||||
(funcall (or (get variable 'custom-set)
|
||||
(lambda (x v &optional _) (set-local x v)))
|
||||
variable value 'buffer-local)
|
||||
(wrong-number-of-arguments
|
||||
(error "The setter of %S does not support setopt-local" variable))))))
|
||||
|
||||
;;;###autoload
|
||||
(defun customize-save-variable (variable value &optional comment)
|
||||
|
|
|
|||
|
|
@ -4623,7 +4623,9 @@ already the major mode."
|
|||
;; so it is risky to put them on with a local variable list.
|
||||
(if (stringp val)
|
||||
(set-text-properties 0 (length val) nil val))
|
||||
(set (make-local-variable var) val))))
|
||||
(if (custom-variable-p var)
|
||||
(setopt--set-local var val)
|
||||
(set (make-local-variable var) val)))))
|
||||
|
||||
;;; Handling directory-local variables, aka project settings.
|
||||
|
||||
|
|
|
|||
Loading…
Reference in a new issue