2

I've been searching most of the day for an answer to this basic question, but I can't find an answer for the noise.

If you search for, say, "configuring indentation in emacs," there's lots of results of various forms, like

(setq-default indent-tabs-mode nil)
(setq-default tab-width 4)

(setq indent-tabs-mode nil)
(setq tab-width 4)

(setq indent-line-function 'insert-tab)

Of course, different major modes treat indentation differently, so in general I don't want a given piece of configuration to affect all major modes, I want it to affect one major mode. Nothing I've found explains how to do this.

How do I put permanent configuration into .emacs in a way that only applies to a specific major mode? Say javascript-mode for the sake of concreteness.

I've only been using Emacs for about 15 years, so I understand very little of it and will benefit from small words and overexplanation.

5
  • 3
    Search for [hooks] mode hook on this site. The Emacs manual contains an excellent introduction: [Hooks ](gnu.org/software/emacs/manual/html_node/emacs/Hooks.html), as does the "Programming in Emacs Lisp" book,
    – NickD
    Commented Oct 13, 2022 at 22:10
  • That is not an "excellent introduction", that is godawful writing. At no point does the author bother to specify what the arguments to add-hook are, so after reading it I'm still left with no clue how I'm supposed to use it to configure a major mode's indentation. The second link goes to a table of contents, none of the entries of which have anything obvious to do with either major modes or hooks, so I'm not sure what I'm supposed to get from that.
    – JonahHuron
    Commented Oct 14, 2022 at 13:55
  • Did you see the example that starts with "Here is a more complex example, showing how to use a hook to customize the indentation of C code: "? It is an almost complete answer to what you are asking. As for the second link, you are supposed to read all of it.
    – NickD
    Commented Oct 14, 2022 at 14:05
  • Quoting from that page of the manual: "the recommended way to add a function to a hook ... is to use add-hook ... See Hooks in The Emacs Lisp Reference Manual, for details." which is a link to the "Hooks" node in the elisp manual, which in turn links to the "Setting Hooks" node, which describes the arguments to add-hook.
    – phils
    Commented Oct 17, 2022 at 22:55
  • Configuring "a major mode's indentation" is a complex topic, as it heavily depends on the major mode in question. I would always start with M-x customize-group RET <group> for the major mode's group (which is often the name of that mode).
    – phils
    Commented Oct 17, 2022 at 22:57

2 Answers 2

0

You define a function that does what you want and add that function to the major mode hook.

E.g. javascript-mode has a major mode hook called javascript-mode-hook. If you want to set the tab-width to 2 in javascript-mode, you write a function that does that:

(defun my/set-tab-width ()
   (setq tab-width 2))

and add it to the hook:

(add-hook 'javascript-mode-hook 'my/set-tab-width)

This code goes into your initialization file (~/.emacs or ~/.emacs.d/init.el or another possibility - check the Emacs manual for what the possibilities are).

When you start Emacs, the init file is evaluated, defining the function and setting the hook. When subsequently you open a javascript file, the major-mode function javascript-mode runs automatically. One of the things it does is to execute each function in the major mode hook, javascript-mode-hook in this case. That's what gets your function to run and set the tab width (or whatever...). tab-width is a buffer-local variable, so each buffer can have its own value.

If you have questions about a function, you can ask Emacs about it, e.g. C-h f add-hook will give you the information about add-hook. Similarly, you can ask about a variable, e.g. C-h v tab-width.

Now, maybe you can go back and read the docs and they might make more sense.

0

Configuring a major mode in Emacs requires understanding hooks in Lisp. A hook is a Lisp list whose elements are functions that are executed at a certain triggering event. Every major mode features a built-in hook whose triggering event is the activation of that mode and whose name is constructed as {MODE NAME}-hook. For instance, the Python mode hook is python-mode-hook, the shell mode hook is sh-mode-hook, the Java mode hook is java-mode-hook, and so on.

You do not have to construct a hook in order to configure a major mode; rather, you write your desired configuration as a Lisp function, and then you add that function to the major mode's hook using the add-hook Lisp function.

Like many things in open source programming, the add-hook method is dumbly named: when using it, you're not adding a hook variable to anything, as the name would imply; rather, you're adding an element to an already-existing hook list. Mentally replacing add-hook with add-to-hook as you read Emacs configuration will make a great deal of it more comprehensible. Its usage is

(add-hook '{EXISTING HOOK} '{FUNCTION TO ADD TO EXISTING HOOK})

where

  • {EXISTING HOOK} is the name of an existing hook, and
  • {FUNCTION TO ADD TO EXISTING HOOK} is the name of the function you'd like to add to that hook.

Note the use of the single-apostrophe ' shortcut for quote() with both arguments; add-hook is written to allow either argument to be a function that returns the name of the hook or of the function to be added, so the shortcuts are needed to indicate to add-hook that we're supplying these names as literals instead.

Since the elements of a hook are functions, using add-hook to insert your desired configuration directives into a major mode's hook requires you to define that configuration as a function. In principle this requires nontrivial knowledge of how to define functions in Lisp, but in practice it isn't too hard as long as the configuration you're adding is a basic series of self-contained expressions.

Lisp functions are defined by the defun ("define function") function, which has the form

(defun {NAME} {ARGUMENT LIST} {BODY})

where

  • {NAME} is the name you give your function, which can be any normal variable name, like "my-config,"
  • {ARGUMENT LIST} is a Lisp list (including parentheses) of variables representing input arguments, and
  • {BODY} is the series of expressions to be executed whenever the function is executed, called the "body" of the function.

Typically you won't have arguments to your configuration function (if you do, it's most likely that you're doing something complex enough that either you already know what you're doing or that this guide won't help you with if you don't), so you'll use an empty list (), and the body is where your configuration expressions will go.

Putting this all together, Emacs configuration that you might find suggested in a blog post or on a forum, like

(setq indent-tabs-mode nil)
(setq tab-width 4)
(setq indent-line-function 'insert-tab)

can be added to the .emacs configuration of a particular major mode -- say, javascript-mode -- like so:

;; Define the configuration function
(defun shell-indent-config ()
    ;; Your configuration directives go here
    (setq indent-tabs-mode nil)
    (setq tab-width 4)
    (setq indent-line-function 'insert-tab)
)

;; Add the configuration function to the JavaScript mode hook
(add-hook 'javascript-mode-hook 'shell-indent-config)

Your Answer

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

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