3

Aim

I would like to arrange for Magit's minor mode git-commit-mode to be enabled whenever a relevant Git file (e.g. COMMIT_EDITMSG) is visited, from both within Emacs (e.g. magit-commit) and without (e.g. git commit with environment variables EDITOR set to emacsclient --create-frame --no-wait and ALTERNATE_EDITOR empty).

I would, however, like the loading of git-commit.el to be deferred until such a file is visited, as loading it and its dependencies increases my Emacs startup time by nearly 100% (i.e. an extra ~0.7s).

Background

I have seen major modes usually tackle this problem by autoloading an addition to auto-mode-alist. The single autoloaded entry-point that git-commit.el defines, on the other hand, is the globalised minor mode itself, which modifies find-file-hook instead. This means that there is no way (obvious to me) to enable the mode or read the value of git-commit-filename-regexp without loading the package, its baggage and the kitchen sink.

What I have successfully done until now is add the equivalent of (cons git-commit-filename-regexp #'git-commit-mode) to auto-mode-alist (despite its being a minor mode), where I manually substitute the value of the defconst git-commit-filename-regexp as defined in the package.

Questions

  1. What effects does adding a minor mode entry to auto-mode-alist have compared to adding a major mode? Does it create a (potentially trivial) risk of breaking something, somewhere? Does this only work with git-commit-mode by chance?
  2. Is there a more elegant or idiomatic solution for autoloading git-commit-mode specifically and minor modes generally?
  3. Could git-commit.el be extended in some way to alleviate this issue?

Update

Those interested, see here for the followup discussion and patch on the project's page.

2

What effects does adding a minor mode entry to auto-mode-alist have compared to adding a major mode? Does it create a (potentially trivial) risk of breaking something, somewhere? Does this only work with git-commit-mode by chance?

You can really use any function in an auto-mode-alist entry. It needn't actually be a mode (although you might well want it to invoke one or more modes).

So you could even specify a function which calls both major and minor modes. Of course you could also define a derived mode of that major mode, and invoke the minor modes in the derived mode's body, which would seem cleaner.

(define-derived-mode my-git-commit-mode text-mode "Git Commit"
  (git-commit-mode 1))

If you don't specify (or otherwise invoke) a major mode, then the buffer will remain in fundamental-mode.

Anyhow, it's set-auto-mode-0 that ultimately handles the selected function, and it simply calls the function, whatever it is.

The potential side-effect is that if set-visited-file-name is invoked on the buffer then the specified function may be called again. Normally the function would only be called there if the detected mode differed from the current major-mode, but if the function in question is not a major mode then it will never match. If the function is a minor mode, then calling it again would tend to be fairly harmless (at least since Emacs 24; in earlier versions it would toggle the mode, which is more of a problem).

Is there a more elegant or idiomatic solution for autoloading git-commit-mode specifically and minor modes generally?

You might alternatively use find-file-hook to test the filename and call the minor mode.

I don't think the auto-mode-alist approach is a bad one, though.

And again, if you're concerned about not using a major mode, then simply define one for the purpose.

Could git-commit.el be extended in some way to alleviate this issue?

If it autoloaded the git-commit-filename-regexp variable definition, then you would have access to that (default) value without loading the library.

  • Thank you for the very informative answer and advice. What git-commit.el seems to do to avoid falling back to fundamental-mode is call normal-mode with auto-mode-alist let-bound to a mapping of the current buffer-file-name to git-commit-major-mode, a customisable variable which determines the user's preferred major mode. Here is the relevant code, in case you are interested. – Basil May 9 '17 at 23:05
  • I think I will stick with the auto-mode-alist approach and send a patch adding an autoload cookie to the package maintainers. – Basil May 9 '17 at 23:08

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.