A variable is either buffer-local or not. If it's buffer-local then the value isn't shared with other buffers. There's no built-in feature to directly have a variable that's shared between buffers. So you'll need to do something where accessing the value of the variable isn't just my-variable
and setting isn't just (setq my-variable some-value)
.
One possibility that makes lookup time quasi-constant is to define a variable with a different name for each mode, and compute the name. For example, I call the value of foo
in Python mode mode-local:foo:python-mode
.
(defun make-variable-mode-local (var &optional default)
"Make VAR eligible for mode-local use.
When VAR hasn't been set in a mode, it will have the value DEFAULT."
(set var default))
(defun mode-local-variable (var &optional mode)
"Return the mode-local variable symbol for VAR in the current major mode.
If MODE is specified, return the symbol for that major mode."
(intern (concat "mode-local:" var ":" (symbol-name (or mode major-mode)))))
(defun mode-local-variable-value (var &optional mode)
"Return the mode-local value of VAR in the current major mode.
If MODE is specified, return the value for that major mode."
(let ((mlv (mode-local-variable var mode)))
(symbol-value (if (boundp mlv) mlv var))))
(defun mode-local-variable-set (var new-value &optional mode)
"Set the mode-local value of VAR to NEW-VALUE the current major mode.
If MODE is specified, return the value for that major mode."
(let ((mlv (mode-local-variable var (or mode major-mode))))
(set mlv new-value)))
(defun mode-local-variable-default-value (var)
"Get the default value of the mode-local variable VAR."
(symbol-value var))
(defun mode-local-variable-set-default (var new-value)
"Set the default value of the mode-local variable VAR to VALUE."
(set var new-value))
(mode-local-variable-set 'answer 42)
(message (mode-local-variable-get 'answer))
(Warning: untested code.)
Another possibility is to keep the data in a single global variable's value, arranged as an association list from mode symbols to values. This can be slow if a variable is set in a lot of major modes.
(defun make-variable-mode-local (var &optional default)
"Make VAR eligible for mode-local use.
When VAR hasn't been set in a mode, it will have the value DEFAULT."
(set var (cons default nil)))
(defun mode-local-variable-value (var &optional mode)
"Return the mode-local value of VAR in the current major mode.
If MODE is specified, return the value for that major mode."
(or mode (setq mode major-mode))
(let ((cell (assq mode (cdr var))))
(if cell
(cdr cell)
(car var))))
(defun mode-local-variable-set (var new-value &optional mode)
"Set the mode-local value of VAR to NEW-VALUE the current major mode.
If MODE is specified, return the value for that major mode."
(or mode (setq mode major-mode))
(let ((cell (assq mode (cdr var))))
(if cell
(setcdr cell new-value)
(setcdr var (cons (cons mode new-value) (cdr var))))))
(defun mode-local-variable-default-value (var)
"Get the default value of the mode-local variable VAR."
(car var))
(defun mode-local-variable-set-default (var new-value)
"Set the default value of the mode-local variable VAR to VALUE."
(setcar var new-value))