I think this is possible in Common Lisp (through overloading setf
), but not sure about Emacs Lisp.
What I want to do would be something like:
(setf (local variable) value)
where the form (local ...)
would call some code I've written and return the symbol to use for setting its value slot.
EDIT: From looking at gv.el it seems like advising gv-get
would do the job, but maybe there's a better procedure for it?
EDIT2: Tried the suggestion from Stefan, close, but not good :(
(gv-define-setter local (value varname &optional buffer)
`(with-current-buffer (or ,buffer (current-buffer))
(setq ,varname ,value)))
which expands to:
(let* ((v bar))
(with-current-buffer (or nil (current-buffer))
(setq v 42)))
Obviously, not what I wanted. I was trying to do it with advising as mentioned above and with gv-define-expander
, but there's just too much quoting going on, and I can't find a way to loose the let
part of the expression with the redundant substitution.
EDIT3:
OK, unless I messed something seriously in the scope or the evaluation sequence of the value the variable will be set to, this seems to work:
(gv-define-expander local
(lambda (do &rest args)
(let ((varname (first args))
(buffer (or (second args) '(current-buffer)))
(value (funcall do nil #'identity)))
`(with-current-buffer ,buffer
(setq ,varname ,value)))))
There's gv-define-expander
, gv-define-setter
, and gv-define-simple-setter
(in order of growing simplicity of use).
You might want to try the 100% guaranteed untested code (note how I pass the with-current-buffer+setq
to do
rather than calling do
with dummy arguments, so that this things has a chance to work when used with push
).
(gv-define-expander local
(lambda (do &rest varname &optional buffer)
(macroexp-let2 nil b buffer
(funcall do `(buffer-local-value ',varname ,b)
(lambda (value)
`(with-current-buffer ,b
(setq ,varname ,value)))))))