Disable semantic in derived modes - emacs

How can I stop semantic-mode from clobbering buffer-local variables in derived modes? In my case I want semantic in C/C++, but I don't want it to setup in modes derived from these. Currently, I use semantic for the following
(setq semantic-new-buffer-setup-functions
'((c-mode . semantic-default-c-setup)
(c++-mode . semantic-default-c-setup)
(srecode-template-mode . srecode-template-setup-parser)))
and attempt to disable it with
(add-to-list 'semantic-inhibit-functions
(lambda () (not (memq major-mode '(c-mode c++-mode srecode-template-mode)))))
However, if I enter a derived mode, like bison-mode, semantic still runs its setup since it is hooked into c/c++, clobbering any variables I set in my bison-mode-hook, in this case imenu-create-index-function. How can I stop semantic from setting up derived modes?

Related

In Emacs, how to disable auto-fill-paragraph mode when in php-mode?

Normally, I need to enable the auto-fill-mode, so I have it turned on in .emacs. But when editting PHP in php-mode, I'd like to not use auto-fill-mode. Is there way to set it in .emacs such that when I'm in PHP mode, the auto-fill-paragraph mode is automatically turned off and when I leave php-mode, it's automatically turned on, barring other overriding?
Update: a closer examination of the .emacs revealed that auto-fill is set up by
(custom-set-variables
;; custom-set-variables was added by Custom.
;; If you edit it by hand, you could mess it up, so be careful.
;; Your init file should contain only one such instance.
;; If there is more than one, they won't work right.
'(column-number-mode t)
...
'(text-mode-hook (quote (turn-on-auto-fill text-mode-hook-identify)))
...)
Some major-modes inherit certain settings from other modes (e.g., text-mode is used by many popular major modes). The following code snippet can be used to disable a feature for a particular major-mode using its mode hook:
(add-hook 'php-mode-hook (lambda ()
(auto-fill-mode -1) ))
It is sometimes helpful to check and see whether a particular feature has been enabled globally or locally, which in turn can give a clue as to whether that feature has been inherited by a major mode. In this case, the documentation for auto-fill-mode states as follows -- https://www.gnu.org/software/emacs/manual/html_node/emacs/Auto-Fill.html:
"Auto Fill mode is a buffer-local minor mode (see Minor Modes) in which lines are broken automatically when they become too wide. Breaking happens only when you type a <SPC> or <RET>."

How to keep dir-local variables when switching major modes?

I'm committing to a project where standard indentations and tabs are 3-chars wide, and it's using a mix of HTML, PHP, and JavaScript. Since I use Emacs for everything, and only want the 3-char indentation for this project, I set up a ".dir-locals.el" file at the root of the project to apply to all files/all modes under it:
; Match projets's default indent of 3 spaces per level- and don't add tabs
(
(nil .
(
(tab-width . 3)
(c-basic-offset . 3)
(indent-tabs-mode . nil)
))
)
Which works fine when I first open a file. The problem happens when switching major modes- for example to work on a chunk of literal HTML inside of a PHP file. Then I lose all the dir-local variables.
I've also tried explicitly stating all of the modes I use in ".dir-locals.el", and adding to my .emacs file "dir-locals-set-class-variables / dir-locals-set-directory-class". I'm glad to say they all behave consistently, initially setting the dir-local variables, and then losing them as I switch the major mode.
I'm using GNU Emacs 24.3.1.
What's an elegant way of reloading dir-local variables upon switching a buffer's major-mode?
-- edit -- Thanks for the excellent answers and commentary both Aaron and phils! After posting here, I thought it "smelled" like a bug, so entered a report to GNU- will send them a reference to these discussions.
As per comments to Aaron Miller's answer, here is an overview of what happens when a mode function is called (with an explanation of derived modes); how calling a mode manually differs from Emacs calling it automatically; and where after-change-major-mode-hook and hack-local-variables fit into this, in the context of the following suggested code:
(add-hook 'after-change-major-mode-hook 'hack-local-variables)
After visiting a file, Emacs calls normal-mode which "establishes the proper major mode and buffer-local variable bindings" for the buffer. It does this by first calling set-auto-mode, and immediately afterwards calling hack-local-variables, which determines all the directory-local and file-local variables for the buffer, and sets their values accordingly.
For details of how set-auto-mode chooses the mode to call, see C-hig (elisp) Auto Major Mode RET. It actually involves some early local-variable interaction (it needs to check for a mode variable, so there's a specific look-up for that which happens before the mode is set), but the 'proper' local variable processing happens afterwards.
When the selected mode function is actually called, there's a clever sequence of events which is worth detailing. This requires us to understand a little about "derived modes" and "delayed mode hooks"...
Derived modes, and mode hooks
The majority of major modes are defined with the macro define-derived-mode. (Of course there's nothing stopping you from simply writing (defun foo-mode ...) and doing whatever you want; but if you want to ensure that your major mode plays nicely with the rest of Emacs, you'll use the standard macros.)
When you define a derived mode, you must specify the parent mode which it derives from. If the mode has no logical parent, you still use this macro to define it (in order to get all the standard benefits), and you simply specify nil for the parent. Alternatively you could specify fundamental-mode as the parent, as the effect is much the same as for nil, as we shall see momentarily.
define-derived-mode then defines the mode function for you using a standard template, and the very first thing that happens when the mode function is called is:
(delay-mode-hooks
(PARENT-MODE)
,#body
...)
or if no parent is set:
(delay-mode-hooks
(kill-all-local-variables)
,#body
...)
As fundamental-mode itself calls (kill-all-local-variables) and then immediately returns when called in this situation, the effect of specifying it as the parent is equivalent to if the parent were nil.
Note that kill-all-local-variables runs change-major-mode-hook before doing anything else, so that will be the first hook which is run during this whole sequence (and it happens while the previous major mode is still active, before any of the code for the new mode has been evaluated).
So that's the first thing that happens. The very last thing that the mode function does is to call (run-mode-hooks MODE-HOOK) for its own MODE-HOOK variable (this variable name is literally the mode function's symbol name with a -hook suffix).
So if we consider a mode named child-mode which is derived from parent-mode which is derived from grandparent-mode, the whole chain of events when we call (child-mode) looks something like this:
(delay-mode-hooks
(delay-mode-hooks
(delay-mode-hooks
(kill-all-local-variables) ;; runs change-major-mode-hook
,#grandparent-body)
(run-mode-hooks 'grandparent-mode-hook)
,#parent-body)
(run-mode-hooks 'parent-mode-hook)
,#child-body)
(run-mode-hooks 'child-mode-hook)
What does delay-mode-hooks do? It simply binds the variable delay-mode-hooks, which is checked by run-mode-hooks. When this variable is non-nil, run-mode-hooks just pushes its argument onto a list of hooks to be run at some future time, and returns immediately.
Only when delay-mode-hooks is nil will run-mode-hooks actually run the hooks. In the above example, this is not until (run-mode-hooks 'child-mode-hook) is called.
For the general case of (run-mode-hooks HOOKS), the following hooks run in sequence:
change-major-mode-after-body-hook
delayed-mode-hooks (in the sequence in which they would otherwise have run)
HOOKS (being the argument to run-mode-hooks)
after-change-major-mode-hook
So when we call (child-mode), the full sequence is:
(run-hooks 'change-major-mode-hook) ;; actually the first thing done by
(kill-all-local-variables) ;; <-- this function
,#grandparent-body
,#parent-body
,#child-body
(run-hooks 'change-major-mode-after-body-hook)
(run-hooks 'grandparent-mode-hook)
(run-hooks 'parent-mode-hook)
(run-hooks 'child-mode-hook)
(run-hooks 'after-change-major-mode-hook)
Back to local variables...
Which brings us back to after-change-major-mode-hook and using it to call hack-local-variables:
(add-hook 'after-change-major-mode-hook 'hack-local-variables)
We can now see clearly that if we do this, there are two possible sequences of note:
We manually change to foo-mode:
(foo-mode)
=> (kill-all-local-variables)
=> [...]
=> (run-hooks 'after-change-major-mode-hook)
=> (hack-local-variables)
We visit a file for which foo-mode is the automatic choice:
(normal-mode)
=> (set-auto-mode)
=> (foo-mode)
=> (kill-all-local-variables)
=> [...]
=> (run-hooks 'after-change-major-mode-hook)
=> (hack-local-variables)
=> (hack-local-variables)
Is it a problem that hack-local-variables runs twice? Maybe, maybe not. At minimum it's slightly inefficient, but that's probably not a significant concern for most people. For me, the main thing is that I wouldn't want to rely upon this arrangement always being fine in all situations, as it's certainly not the expected behaviour.
(Personally I do actually cause this to happen in certain specific cases, and it works just fine; but of course those cases are easily tested -- whereas doing this as standard means that all cases are affected, and testing is impractical.)
So I would propose a small tweak to the technique, so that our additional call to the function does not happen if normal-mode is executing:
(defvar my-hack-local-variables-after-major-mode-change t
"Whether to process local variables after a major mode change.
Disabled by advice if the mode change is triggered by `normal-mode',
as local variables are processed automatically in that instance.")
(defadvice normal-mode (around my-do-not-hack-local-variables-twice)
"Prevents `after-change-major-mode-hook' from processing local variables.
See `my-after-change-major-mode-hack-local-variables'."
(let ((my-hack-local-variables-after-major-mode-change nil))
ad-do-it))
(ad-activate 'normal-mode)
(add-hook 'after-change-major-mode-hook
'my-after-change-major-mode-hack-local-variables)
(defun my-after-change-major-mode-hack-local-variables ()
"Callback function for `after-change-major-mode-hook'."
(when my-hack-local-variables-after-major-mode-change
(hack-local-variables)))
Disadvantages to this?
The major one is that you can no longer change the mode of a buffer which sets its major mode using a local variable. Or rather, it will be changed back immediately as a result of the local variable processing.
That's not impossible to overcome, but I'm going to call it out of scope for the moment :)
Be warned that I have not tried this, so it may produce undesired results ranging from your dir-local variables not being applied, to Emacs attempting to strangle your cat; by any sensible definition of how Emacs should behave, this is almost certainly cheating. On the other hand, it's all in the standard library, so it can't be that much of a sin. (I hope.)
Evaluate the following:
(add-hook 'after-change-major-mode-hook
'hack-dir-local-variables-non-file-buffer)
From then on, when you change major modes, dir-local variables should (I think) be reapplied immediately after the change.
If it doesn't work or you don't like it, you can undo it without restarting Emacs by replacing 'add-hook' with 'remove-hook' and evaluating the form again.
My take on this:
(add-hook 'after-change-major-mode-hook #'hack-local-variables)
and either
(defun my-normal-mode-advice
(function &rest ...)
(let ((after-change-major-mode-hook
(remq #'hack-local-variables after-change-major-mode-hook)))
(apply function ...)))
if you can live with the annoying
Making after-change-major-mode-hook buffer-local while locally let-bound!
message or
(defun my-normal-mode-advice
(function &rest ...)
(remove-hook 'after-change-major-mode-hook #'hack-local-variables)
(unwind-protect
(apply function ...)
(add-hook 'after-change-major-mode-hook #'hack-local-variables)))
otherwise and finally
(advice-add #'normal-mode :around #'my-normal-mode-advice)

What is the difference of tex-mode and latex-mode and LaTeX-mode in emacs

I am configuring AUCTeX in emacs.
Most of the configurations are put in a LaTeX-mode-hook. When I open a main.tex file, I notice that the major mode is latex-mode and my hooked configurations are not activated. I have to M-x Tex-latex-mode to activate them. But the major-mode is still latex-mode.
(add-hook 'LaTeX-mode-hook
(lambda ()
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; auctex
(setq TeX-auto-save t)
(setq TeX-parse-self t)
))
So I would like to know what is the difference of these modes and how can I turn on AUCTeX automatically when I open a *.tex file.
The modes provided by AUCTeX are listed at https://www.gnu.org/software/auctex/manual/auctex.html#Modes-and-Hooks and they are
plain-TeX-mode
LaTeX-mode
ams-TeX-mode
ConTeXt-mode
Texinfo-mode
docTeX-mode
Instead,
tex-mode
plain-tex-mode
latex-mode
slitex-mode
doctex-mode
(note the different capitalization) are the major modes provided by the TeX mode package shipped with Emacs.
If you want to open all *.tex files with AUCTeX LaTeX mode add this to your .emacs:
(add-to-list 'auto-mode-alist '("\\.tex$" . LaTeX-mode))
Actually, this shouldn't be necessary, because AUCTeX defines the tex-mode.el mode names as alias of its own modes.
TLDR: Use latex-mode or LaTeX-mode (they mean the same thing), no need to change auto-mode-alist, and use LaTeX-mode-hook for hooking into AucTeX.
Setting up AucTeX can be quite confusing, because it uses advice to override Emacs' built-in support for TeX and friends.
So, after installing AucTeX from ELPA, you should see the following in C-h f latex-mode:
This function has :override advice: ‘TeX-latex-mode’.
Same for all the other tex modes, though the list of modes that AucTeX overrides depends on the value of the TeX-modes variable.
The function LaTeX-mode is not defined in AucTeX (any more?): it's defined in core Emacs, with a cryptic comment about compatibility:
;; The following three autoloaded aliases appear to conflict with
;; AUCTeX. However, even though AUCTeX uses the mixed case variants
;; for all mode relevant variables and hooks, the invocation function
;; and setting of `major-mode' themselves need to be lowercase for
;; AUCTeX to provide a fully functional user-level replacement. So
;; these aliases should remain as they are, in particular since AUCTeX
;; users are likely to use them.
;; Note from Stef: I don't understand the above explanation, the only
;; justification I can find to keep those confusing aliases is for those
;; users who may have files annotated with -*- LaTeX -*- (e.g. because they
;; received them from someone using AUCTeX).
;;;###autoload
(defalias 'TeX-mode #'tex-mode)
;;;###autoload
(defalias 'plain-TeX-mode #'plain-tex-mode)
;;;###autoload
(defalias 'LaTeX-mode #'latex-mode)
What this all means is that, at least in 2021, you do not need to change auto-mode-alist to use AucTeX; just installing it is enough for it to override Emacs' builtin functionality.
Unfortunately, there's one last source of confusion. Even though LaTeX-mode is now mostly just a useless alias for latex-mode, it turns out that code in AucTeX that overrides latex-mode does not call latex-mode-hook (it calls LaTeX-mode-hook, which is different. So the LaTeX- variables, which are the AucTeX ones (as opposed to the lowercase ones that are builtin with Emacs), are still useful.

how to change buffer-local variable for a major mode in Emacs?

Generally, how can I customize the value of a buffer-local variable in Emacs? For example, the variable w3m-lnum-mode is buffer-local, if I set (setq w3m-lnum-mode t) in .emacs, its value in a w3m mode buffer is still nil. How could I set it to t in w3m major mode?
Major modes have a hook variable for this sort of thing. Look for w3m-mode-hook.
(defun my-w3m-hook nil
(setq w3m-lnum-mode t))
(add-hook 'w3m-mode-hook #'my-w3m-hook)
The indirection to hook a separate function is not absolutely necessary, but simplifies the management of the hook functionality (otherwise you'd have to restart Emacs or jump through several hoops to add something to an existing hook; now all you need to do is evaluate a new defun of the function called from the hook).
You can set a default like so:
(setq-default w3m-lnum-mode t)
For fine-grained control, use a hook as RNAer suggests. As far as I can tell though, this is not a normal local variable but a minor mode variable. You actually probably want to do (w3m-lnum-mode 1).

How to minify .emacs configuration file?

I was wondering if anyone can provide me with some help on minifying my .emacs file.
Currently I have it set up where each language I use have a custom tab, for example, if I have a hook for Java, it would look like this.
;; Java Hook
(defun e-java-mode-hook ()
(setq tab-width 4)
(setq indent-tabs-mode t)
(define-key java-mode-map (kbd "") 'java-insert-tab))
(defun java-insert-tab (&optional arg)
(interactive "P")
(insert-tab arg))
(add-hook 'java-mode-hook 'e-java-mode-hook)
And if I were to add another language like CSS or JavaScript, I would add another hook for CSS and another hook for JavaScript. So I was wondering if there's a global way of setting it so it would apply to any and all language?
I am currently running GNU Emacs 23.2.1 on Windows 7.
I agree with Tyler; although it's a bit complicated, you would be better off in the long run if you try to understand and customize the default indentation features. The Emacs Wiki has good resources, and there are other relevant Q&As here on Stack Overflow.
Binding the tab key to insert-tab means you completely lose the benefit of the likes of indent-region, and any other intelligent behaviour that a major mode might offer.
To address your specific questions regardless, however:
1) If you are defining (java-insert-tab) and (css-insert-tab) and (javascript-insert-tab) etc, and they all do exactly the same thing... well, hopefully you can see that you don't actually need more than one of those functions. Just give it a more generic name, and re-use it.
2) (local-set-key ...) does the same thing as (define-key (current-local-map) ...), which means you can also have a single generic function to override the tab keybinding, regardless of the major mode.
(defun my-coding-config ()
(setq tab-width 4)
(setq indent-tabs-mode t)
(local-set-key (kbd "<tab>") 'my-insert-tab))
(defun my-insert-tab (&optional arg)
(interactive "P")
(insert-tab arg))
Then you just need to add my-coding-config to each applicable mode hook variable. If there are a lot of them, you might wrap it up in a list like this:
;; Use my coding hook for all programming modes
(mapcar
(lambda (language-mode-hook)
(add-hook language-mode-hook 'my-coding-config))
'(java-mode-hook
javascript-mode-hook
css-mode-hook
...))
3) If you look at C-h v tab-width RET and likewise for indent-tabs-mode, you'll notice that they both say "Automatically becomes buffer-local when set in any fashion."
As an alternative to the customize interface already mentioned, you can use (set-default 'indent-tabs-mode t) to establish the default value for such variables. In the absence of code which sets a buffer-local value, all of your buffers will use the default, which might help you to avoid writing unnecessary mode hooks.
I'm not sure what you're trying to do. If you want to set the tab-width to 4 spaces globally, then you can do that using the customize command:
M-x customize-variable tab-width <ret>
Any changes you make to tab-width in customize will be applied globally. So you won't need to set it individually for each mode with hooks.
If you have different settings you want to apply to different modes, you will necessarily have to have code specific for each mode in your .emacs.
More generally, it looks like you're trying to build your own custom tab insertion commands - does the built-in indentation not do what you need? I think it will be easier to customize the indentation settings in Emacs than to manually insert tabs where you want them.
If you haven't already, take a look at the manual section on indentation and see if you might be able to do what you need without a lot of extra hooks:
C-h r m Indentation
(that is: h-elp, r-ead the manual, m-enu item Indentation)
or:
(info "(emacs)Indentation")
espect.el is doing exactly what you want.
From the docs:
This mode makes it easy to configure settings for individual
buffers with a concice and extensible mini-language. It abstracts
away common configuration selection tasks, like checking the mode
or filename, into a simple declarative syntax. Declare conditions;
run a function when the new buffer matches them. This makes it
easy to do things like turn on flyspell-prog-mode for your favorite
programming languages, or make all text-mode buffers ending in .mkn
have special properties.