5

I would like to have a global keyboard shortcut that shows the value of a variable. However, the variable's value could change according to the current major mode in the current buffer.

I tried to add the following to my ~/.emacs:

(defun my-elisp-mode-setup ()
  (defvar-local *current-mode-var* "elisp-mode")
)
(defun my-sh-mode-setup ()
  (defvar-local *current-mode-var* "sh-mode")
)
(add-hook 'emacs-lisp-mode-hook 'my-elisp-mode-setup)
(add-hook 'sh-mode-hook 'my-sh-mode-setup)

If I now start Emacs with emacs test.sh and then type M-x describe-variable *current-mode-var* in the test.sh buffer, I get

*current-mode-var*'s value is "elisp-mode"

  Automatically becomes buffer-local when set.

Documentation:
Not documented as a variable.

while I expected to get *current-mode-var*'s value is "sh-mode"

4 Answers 4

4

The variables are evaled only at first declaration. All further declarations are skipped. You need a setq instead.

Sign up to request clarification or add additional context in comments.

5 Comments

Thanks! If I use setq how can then the variable become local?
It's buffer local after the declaration. This is something like declaring the type and assigning in C: assignment doesn't change type. So defvar-local followed by setq will not change the variable to non-local.
Ok.. Does this mean that you have to add a (defvar-local *current-mode-var* nil) in the ~/.emacs and then use setq in the mode hooks?
Yes, that should work. Or declare in each mode, and setq in each mode. Doesn't hurt to declare stuff.
In emacs 24 you can use setq-local.
3

I prefer official native package https://www.emacswiki.org/emacs/ModeLocal . It is better configurable, because you do not require add-hook

For example

(require 'mode-local)
(setq-mode-local sh-mode *current-mode-var* "sh-mode")
(setq-mode-local emacs-lisp-mode *current-mode-var* "elisp-mode")

Then by just changing mode cause changing the value of *current-mode-var*

Comments

2

If all you want to do is examine a variable to determine the major mode (which it seems is what you are doing), then just examine variable major-mode. That's what it's for.

And if you want a key/command to do that, then just create one:

(defun which-mode ()
  "Echo the current major mode in the echo area."
  (interactive)
  (message "Major mode: %s" major-mode))

Or use variable mode-name if you prefer a human-friendly major-mode name.

Comments

1

defvar-local is a macro calling defvar and make-variable-buffer-local under the hood.

defvar SYMBOL [VALUE [DOC-STRING]

... But if SYMBOL is not void, VALUE is not evaluated, and SYMBOL’s value is left unchanged...

You code should be:

(defvar-local *current-mode-var*)

(defun my-elisp-mode-setup ()
  (setq *current-mode-var* "elisp-mode"))
(add-hook 'emacs-lisp-mode-hook 'my-elisp-mode-setup)

(defun my-sh-mode-setup ()
  (setq *current-mode-var* "sh-mode"))
(add-hook 'sh-mode-hook 'my-sh-mode-setup)

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.