11

By design, the fundamental-mode is bare bones as other major modes are supposed to derive from this one.

From the info page (elisp) Major Modes, we have:

This is the major mode command for Fundamental mode. Unlike other mode commands, it does not run any mode hooks (*note Major Mode Conventions::), since you are not supposed to customize this mode.

For that reason,

  • We do not have a fundamental-mode-hook.
  • Also my-minor-mode does not get enabled ONLY in this major mode buffers inspite of having (global-my-minor-mode 1) in my config.

Below would work but only if I manually typed M-x fundamental-mode:

(add-hook 'after-change-major-mode-hook #'my-minor-mode)

It does not help in the below case where a fundamental-mode buffer (*abcd*) is created by default:

(with-current-buffer (get-buffer-create "*abcd*")
  (insert "Hello world"))

Why I want to enable a minor mode in fundamental-mode?

I like to keep my custom key bindings in my minor mode map. I have this minor mode enabled globally (but it does not get enabled only in fundamental-mode buffers).

Here's a use case that made this ask this question here. On doing M-x esup (esup package), it creates an *esup-log* buffer with fundamental-mode as its major mode. But each time I need to enable my minor mode manually in it to use my convenient bindings.

I'd like to enable my-minor-mode in a truly global fashion, fundamental-mode or not.

Update 1:

Here is my minor mode definition: modi-mode.

Update 2:

Based on @npostavs' comment, I reviewed what's different between my minor mode modi-mode and override-global-mode in use-package/bind-key.el. And it turns out that the init value of my mode is nil and that of override-global-mode is t.

If I change the init value of my mode to t, it too gets enabled in the fundamental-mode buffers! But the act of (global-modi-mode 1) does not end with the same result. Is that odd? Probably a bug?

Kaushal Modi
  • 25,203
  • 3
  • 74
  • 179
  • A similar custom key binding mode does get enabled in `fundamental-mode` buffers for me, so perhaps the problem is in your mode's definition. [`override-global-mode`](https://github.com/jwiegley/use-package/blob/4b7917cc276b33cd7daff96ef764f4626baf0a5c/bind-key.el#L123-L125) – npostavs Sep 17 '15 at 14:03
  • @npostavs Thanks. I will review how `use-package` implements that. – Kaushal Modi Sep 17 '15 at 14:08
  • @npostavs Please check the updated question.. turns out I am facing this problem simply because the init value of my mode is `nil`; but I do enable it globally. – Kaushal Modi Sep 17 '15 at 14:56
  • If you are creating a global minor mode, I suggest you just use the `:global` option from `definie-minor-mode` instead of creating a global and local variant if you are always going to use it globally. – Jordon Biondo Sep 17 '15 at 15:07
  • @JordonBiondo I toggle this mode locally at times. So I have kept both the variants. – Kaushal Modi Sep 17 '15 at 15:08
  • The function for `fundamental-mode` is just a few lines of code in `simple.el` -- modify it to suit your needs, but be aware that other modes use it. Or do like me, create your own -- I call it `fm-mode`. – lawlist Sep 17 '15 at 15:32
  • @lawlist Apparently that function is not called when calling `get-buffer-create`. I derived so because I did not see the effects of `(run-mode-hooks)` (which is called in the `fundamental-mode` function). As I noted in the question, `M-x fundamental-mode` works fine but I then need to do that manually in each buffer generated with `fundamental-mode`. – Kaushal Modi Sep 17 '15 at 15:40
  • 1
    In `buffer.c`, it looks like `get-buffer-create` runs the `buffer-list-update-hook` at the very end of its function, perhaps you could attach your own function with conditions to that hook? – lawlist Sep 17 '15 at 15:47
  • @lawlist I think that will be a good answer. Can you please add that as an answer? Thanks! – Kaushal Modi Sep 17 '15 at 15:54
  • 1
    Emacs uses "internal" temporary buffers for all kinds of purposes (e.g. doing coding-system conversion for I/O to/from a file or process may use a tempoary buffer). These buffers use fundamental-mode and I think it's right that they don't enable your minor-mode. As for other buffers, the rule for me is that: if you ever want to see this buffer (other than for debugging purposes) then it should probably not use fundamental-mode. – Stefan Sep 20 '15 at 01:42
  • @Stefan I am confused because enabling the minor mode globally did not work but setting the init value of the minor mode to t in its definition or by force (setq-default) worked. – Kaushal Modi Sep 20 '15 at 03:34
  • @kaushalmodi: setting it to t only works if "enabling" the mode amounts to setting the variable. If there is anything else that needs to be done (e.g. do `add-hook` or set some other buffer-local variables) then the variable will be non-nil but the mode will not have been properly enabled (because the minor mode function will not have been called). – Stefan Sep 20 '15 at 13:04

3 Answers3

5

The only way I can get a minor mode enabled by default in fundamental-mode buffers is to set the init value of that minor mode to t.

(define-minor-mode my-minor-mode
 "My minor mode"
 :init-value t)

Note that simply toggling ON a globalized minor mode (see C-h i g (elisp) Defining Minor Modes) with init value nil does not do the same thing. In this case, a fundamental-mode buffer will be created with this minor mode disabled.


The above, of course, will work only if you control the minor mode source. For all other minor modes that come with different packages, if you'd like to enable a minor mode by default in fundamental-mode buffers, you would need to do

(setq-default the-minor-mode t)
Kaushal Modi
  • 25,203
  • 3
  • 74
  • 179
  • 1
    I think for other minor modes you could do `(setq-default 'the-minor-mode t)` to get the same effect. – npostavs Sep 17 '15 at 15:38
  • Good point! I will update the answer (removed that single quote). Thanks! – Kaushal Modi Sep 17 '15 at 15:45
  • If you added `(setq-default modi-mode 1)` to the function `turn-on-modi-mode` and `(setq-default modi-mode nil) to the function `turn-off-modi-mode`, then you would be one step closer to *actually* globally enabling and disabling the mode. – nispio Apr 16 '16 at 23:09
  • @nispio That's a good point. I haven't yet needed to do this. But now I know what I need to do if I need to toggle my minor mode in a fundamental-mode buffer. – Kaushal Modi Apr 17 '16 at 00:25
3

Do not use fundamental-mode -- at least not interactively. You rarely want to be in fundamental-mode. There is almost always something better.

The whole point of fundamental-mode is to not have the usual major-mode handling (hooks etc.). You can think of fundamental-mode as kind of like an abstract class.

If some package puts you in a buffer that is in fundamental-mode then do what you need to do to prevent this -- use some other mode for it.

Consider customizing major-mode so that it defaults to something other than fundamental-mode. (I use indented-text-mode.)


Formerly there was default-major-mode for this, which I think was a bit clearer, but they decided to deprecate that (it still works, of course).

default-major-mode is a variable defined in `C source code`.
Its value is indented-text-mode

  This variable is obsolete since 23.2;
  use `major-mode' instead.

Documentation:
Value of `major-mode` for new buffers.
Drew
  • 75,699
  • 9
  • 109
  • 225
  • 2
    I am not using the `fundamental-mode`. The crux of the matter is that when any package uses `get-buffer-create` to generate a temporary buffer, that buffer gets created with `fundamental-mode` as the major mode. In those buffers, my minor mode won't be enabled by default (because its init value is nil; even though I enabled it globally). – Kaushal Modi Sep 17 '15 at 15:43
  • Few such packages I can list: [`esup`](https://github.com/jschaf/esup), [`keyfreq`](https://github.com/dacap/keyfreq) – Kaushal Modi Sep 17 '15 at 15:45
  • A package that just calls `get-buffer-create` does not do anything to establish the major mode (or any minor mode). *Should* it (for the package in question)? If it should, consider contacting the package maintainer. If not, consider turning on your preferred major or minor mode yourself. IOW, if it's about what *you* want, and not what the package *should* set up generally, then it's up to you to set it up the way you want. – Drew Sep 17 '15 at 22:43
  • I'd be curious to know why this was downvoted. – Drew Apr 13 '16 at 22:57
  • 1
    @Drew because it does not address the issue. The OP explicitly states that other modes are creating buffers in fundamental mode, and your proposed solution is to not use fundamental mode. – nispio Apr 15 '16 at 17:51
  • @nispio: Sigh. See Stefan's comments as well. And my answer was not only to not use `fundamental-mode`. I said that if some package is forcing `fundamental-mode` on you then (1) work around that to not use `fundamental-mode`, and (2) contact the package author, to ask for a behavior change in the package (i.e., a fix). The OP claimed that `fundamental-mode` was coming from `get-buffer-create`, but it does not do that. I suggested that the OP set the mode he wants, and not just stick with fundamental mode as served up by a (broken) package. – Drew Apr 15 '16 at 21:02
  • **"The OP claimed that fundamental-mode was coming from get-buffer-create, but it does not do that."** `emacs -Q --eval '(progn (setq-default major-mode (quote indented-text-mode)) (switch-to-buffer (get-buffer-create "*foo*")))'` This lands me in fundamental mode on emacs 24.5 – nispio Apr 16 '16 at 23:00
  • @nispio: It is `switch-to-buffer` that is doing that, not `get-buffer-create`. `M-: (get-buffer-create "*foo"*)`. `get-buffer-create` does not change the current buffer, and it does not change the current mode. – Drew Apr 17 '16 at 04:50
  • Very pedantic. The point is that `get-buffer-create` creates a new buffer which does not have a major mode associated with it and therefore puts me in fundamental mode when I visit it. This happens *despite* having set `major-mode` to default to `indented-text-mode` – nispio Apr 18 '16 at 17:25
  • `get-buffer-create` creates a new buffer that does not have a major mode associated with it - correct. It is **visiting** a buffer that associates it with a major mode. **It is the code that visits the buffer that needs to be corrected.** That's the point. The right thing to do (while working around it locally temporarily) is to request that the library maintainer fix the code properly - it *should not use fundamental mode*. – Drew Apr 18 '16 at 20:18
0

The function get-buffer-create is defined in buffer.c, and at the very end of that function it calls the buffer-list-update-hook. Such a hook could be used to run a custom function, but certain conditions may need to be added to prevent the custom function from firing at inopportune moments whenever that hook is called by other functions.

lawlist
  • 18,826
  • 5
  • 37
  • 118