Custom indentation mode with tabs for Emacs

1

1

I love Emacs, but my customization powers are weak, and I would appreciate any help on this.

My default settings are to never use literal tab stops (indent-tabs-mode nil). However, for one particular project I do need to use tab stops, and I need to display tabs with spacing 4 (not the default 8), and I want the tab-stop-list to be 4, 8, 12, ....

Now the question: How can I define (in my ~/.emacs.d) a single function that I can M-x invoke from within any mode I might already be in so that these particular settings are overridden to those requirements? Alternatively, how can I make these settings a minor mode that I can activate optionally inside a given major mode (say some fictitious PHP-mode (which I haven't found yet))?

Kerrek SB

Posted 2011-09-04T11:04:10.757

Reputation: 811

Answers

5

(setq-default 
          tab-width 4                                     ; Set tab stops
          tab-stop-list '(4 8 12 16 20 24 28 32 36 40 44
                            48 52 56 60 64 68 72 76 80 84)
          )

put this in your .emacs.d/init.el and use M-i to go to next tab position

UPDATE:

(defun my-tab-width ()
  "set tab-width as local variable"
  (interactive)
  (progn
    (set (make-local-variable 'tab-width) 4)
     (set (make-local-variable 'tab-stop-list)
     '(4 8 12 16 20 24 28 32 36 40 44 48 52 56 60 64 68 72 76 80 84))))

call this function iteratively with M-x or put a hook to your desired mode to load automatically

(add-hook 'php-mode-hook 'my-tab-width)

kindahero

Posted 2011-09-04T11:04:10.757

Reputation: 1 088

No no, I don't want this to happen by default - rather, I only want to enable this behaviour in very particular situations, so I'd like a command that I call in those situations and that only changes the local settings for that one buffer. – Kerrek SB – 2011-09-04T12:08:44.617

updated the answere – kindahero – 2011-09-04T12:27:19.610

Great, this is already working well in fundamental mode. But now, say, I finally do find a PHP mode which already defines everything, how can I make the command override the mode's settings? – Kerrek SB – 2011-09-04T12:38:25.677

doesn't it make local variables if you call the function in the buffer?? – kindahero – 2011-09-04T12:48:29.793

I just tested it in C++ mode, where it doesn't override the mode's indentation settings :-( – Kerrek SB – 2011-09-04T12:50:53.457

did you try using M-i which runs the command tab-to-tab-stop. check your variable values using C-h v tab-width RET in your cpp buffer – kindahero – 2011-09-04T13:00:46.950

Well, M-i does advance, but it inserts spaces, while I expressly want tabs -- I did add indent-tabs-mode t to your command, and it does work in fundamental mode, but it just gets overwritten by the C++ major mode, it seeems. – Kerrek SB – 2011-09-04T13:02:37.743

Together with php-mode in "java" indentation style as a basis, this function implements my requirements on demand, perfect. Thank you!

– Kerrek SB – 2011-09-04T16:06:16.300

2

You probably don't need to create a mode. You only want to set variables (indent-tabs-mode, tab-width and tab-stop-list) for one or multiple files.

That has also been asked in this Stack Overflow question.

My suggestion: Create a ".dir-locals.el" file in that project's directory with these contents:

((nil . ((tab-width . 4)
         (indent-tabs-mode . t)
         (tab-stop-list . (4 8 12 16 20 24 28 32 36 40 44 48 52 56 60 64 68 72 76 80 84)))))

That will set those three variables for all files in that folder.

But you need to make sure that your mode/file hooks don't also set these variables. Setting them directly that way will always take priority no matter what you configure.

And remember that these variables only affect pure text indentation. Programming modes usually have their own variables for indentation (e.g. c-basic-offset).

nschum

Posted 2011-09-04T11:04:10.757

Reputation: 290

Can I somehow turn that into a command? I don't want to have to copy a configuration file into random parts of a large source tree... but thanks for the idea! (I already managed to set my working buffer to have the right behaviour, I just want to be able to activate this behaviour with a single command somehow.) – Kerrek SB – 2011-09-04T13:00:09.387

You don't need to put it into random parts of the source tree. You can put it at the project root and/or specify a folder instead of nil. See http://www.gnu.org/software/libtool/manual/emacs/Directory-Variables.html for details. Why use a single command when zero commands will work? Why write code when the code already exists?

– nschum – 2011-09-04T13:15:48.393

That's true, but it does create this non-local dependency... the point is that I don't always have the exact same source tree, I might be checking it out in random places on random machines - but I always have my ~/.emacs :-) – Kerrek SB – 2011-09-04T13:20:17.310

I did try it, though, but I get lots of "Wrong type argument: number-or-marker-p, quote" errors when I press tab... – Kerrek SB – 2011-09-04T13:24:23.650

Fixed by removing the apostrophe. I would still prefer to copy a file when checking out rather than activating a mode every time I open a file. But anyhow, this answer might not be for you then. :) Maybe it will help future visitors. – nschum – 2011-09-04T14:54:10.760

I certainly appreciate the answer, and I'm trying it out. Now something weird happens: If I press tab three or more times, I get tabs. But if I press it only once or twice, I get spaces! (In Fundamental mode.) – Kerrek SB – 2011-09-04T14:57:22.890

Sounds like something else is at play there. Try emacs -Q. (But I think that's not something we can troubleshoot in the comments section.) – nschum – 2011-09-04T15:09:32.857

Ahh, thank you, with -Q it behaves as expected! So is it just something else in my config file that interferes? I can go and chase that up if that's the case. Thanks again! – Kerrek SB – 2011-09-04T15:12:12.900

Yes, something in your .emacs or site-start.el – nschum – 2011-09-04T15:44:33.767

Witha combination of php-mode in "java" indentation style and your directory override I believe I have now set up a working environment that implements the tabbing requirements. Thank you!

– Kerrek SB – 2011-09-04T16:05:41.443

Upvoted for mention of .dir-locals.el, which I didn't previously know about. Thanks! – Aaron Miller – 2013-09-23T15:16:56.850

0

I'm no eLISP expert, but you could add something like

(add-hook 'your-minor-mode '(set-variable 'tab-width 4))

to your .emacs

Jaap Eldering

Posted 2011-09-04T11:04:10.757

Reputation: 7 596

How would I activate the mode? If I just put this in, I don't seem to get the new minor mode. – Kerrek SB – 2011-09-04T11:52:58.573