How can I set Emacs tab settings by file type? - emacs

I need to be able to set the tab settings for the following file types:
.rb: 2 soft spaces
.css, .html.erb: 4 space tabs
I have tried the following, but none of it seems to alter my default tab settings for each of the file types.
;; js-mode-hook has also been tried
(add-hook 'javascript-mode-hook
'(lambda()
(setq tab-width 4)))
(add-hook 'css-mode-hook
'(lambda()
(setq tab-width 4)))
(add-hook 'html-mode-hook
'(lambda()
(setq tab-width 8)))
I am pretty new to emacs so my knowledge of configuration is pretty low.

In emacs each mode has it's own indentation style. The main command to indent (bound to TAB) is indent-for-tab-command.
This command calls mode specific indentation function found in the variable indent-line-function. So each mode has it's own way of doing it.
For Ruby (for my emacs 2 is a default):
(setq ruby-indent-level 2)
For CSS (again, default is 4 for me):
(setq css-indent-offset 4)
Unfortunately SGML mode (on which HTML mode is based) has a very simple indentation mechanism and apparently the level is not configurable.
See the source code of sgml-calculate-indent function.
I personally find it weird. I am not writing HTML, but you can try to modify the sgml-calculate-indent function yourself :). Learn some lisp.
I am using js2 mode, and it indents perfectly by default. For js you have to search for js-indent-level or something similar.
Cheers.

Theres a number of aspects to how Emacs does indentation. Setting the tab-width only specifics how big a tab is if a literal tab is inserted. If you don't wish to use literal tabs for indentation, then you should first disable their insertion (from the manual
):
Emacs normally uses both tabs and
spaces to indent lines. If you prefer,
all indentation can be made from
spaces only. To request this, set
indent-tabs-mode to nil. This is a
per-buffer variable, so altering the
variable affects only the current
buffer, but there is a default value
which you can change as well.which you can change as well.
However, to specify the indentation levels, you'll also need to set the c-basic-offset value variable as well:
(add-hook 'html-mode-hook
'(lambda()
(setq c-basic-offset 4)
(setq indent-tabs-mode nil))
In your case, you may only need the c-basic-offset but try a few combinations and see what works best.

js-mode uses js-indent-level so put (setq js-indent-level 4) into your ~/.emacs (shouldn't have to be in a hook, even, but if you're wondering, it's js-mode-hook, not javascript-mode-hook).
If setting tab-width doesn't change your indentation level for a certain mode, it's often simplest to just open the source for that mode. I found this variable by doing C-h f js-mode, clicking the link "js.el", then searching for "indent", second hit from the top.
However, if you collaborate a lot with other people, it's often better to put a cookie at the top of the file. I typically do // -*- tab-width: 8 -*- in the file, and then I have stuff like this in my ~/.emacs:
(defvaralias 'c-basic-offset 'tab-width)
(defvaralias 'cperl-indent-level 'tab-width)
(defvaralias 'perl-indent-level 'tab-width)
(defvaralias 'js-indent-level 'tab-width)
so that I have less variables to deal with (and don't have to get warnings about the file-local variable being unsafe or whatever if the mode-writer forgot to declare it as safe)

If you are using ELPA's css-mode.el with emacs 23.1.1, you can parametrize the global setting for tab width for CSS files for the tab width by doing the following:
1) Type M-x customize-variable ,
2) Then type css-indent-level,
3) Then after you change the variable to your liking, you do "Save for future sessions".

For HTML and erb: if you are using web-mode (the mode provided by Spacemacs) it can be as simple as:
(setq-default
web-mode-code-indent-offset 2
web-mode-markup-indent-offset 2)
where markup-indent-offset refers to the actual tags and code-indent-offset refers to embedded Ruby in ERB, etc.

Related

emacs: Want to indent with tabs (tab-size 2 or 4) allign with spaces

I use emacs now for a while and like it in most cases (useful on ssh, syntax highlight, ...).
But when it comes to indentation and justification (alignment) of code, I don't get clear with emacs.
I want in all my code (SQL, C, Java, ECMAScript, HTML, PHP, CSS, ...) that a press of the "TAB" key realy makes a TAB character (which I usually have a size of 2 spaces, but 4 or 6 are good as well). [I agree, that TABs in Code are evil when it comes to alignment, but spaces are evil as well, when it comes to indentation!] You can have a look, how I want to have it in my HTML template:
https://github.com/pheek/HTMLTemplate/blob/master/template.html
On the other hand I always align with spaces, so other programmers have all the equal signs properly aligned in my code. This works fine, except for 2 exceptions:
To enter a TAB-Char I always have to press "CTRL-q TAB", which is annoying.
Different programming languages are configured in emacs to use different TAB sizes. For myself, I always want to behave a TAB to be the size of 2 spaces.
How can I achieve that
a) a press of the TAB-Key always inserts a TAB-Char?
b) TABs are in all emacs-modes (c, java, html, php, css, ecmascript, ...) 2 chars wide?
As #lawlist says, it's different for every major mode. Each one usually has its own indent-line-function, and settings like tab-width are buffer local.
There's a smart-tabs package (https://github.com/jcsalomon/smarttabs) that works well for me, but I only use it for C-like modes (which is not to say it doesn't work for others, I just haven't tried).
(use-package smart-tabs-mode
:commands (smart-tabs-mode)
:init
(add-hook 'c-mode-common-hook #'smart-tabs-mode)
:config
(smart-tabs-advice c-indent-line c-basic-offset)
(smart-tabs-advice c-indent-region c-basic-offset)
)
tab-width should be set to your preferred width globally, and can be changed in major mode hooks to be different in some modes.
(setq-default tab-width 2)
(defun jpk/c-mode-common-hook ()
(setq tab-width 4))
(add-hook 'c-mode-common-hook #'jpk/c-mode-common-hook)
a) Set the value of indent-tabs-mode to non-nil in your emacs configuration file.
(setq-default indent-tabs-mode t) should do the trick.
https://www.gnu.org/software/emacs/manual/html_node/emacs/Indentation.html
b) Similarly, set the value of tab-width to the desired width.
(setq-default tab-width 2) in your case.
https://www.gnu.org/software/emacs/manual/html_node/efaq/Changing-the-length-of-a-Tab.html

Tab indentation in CoffeeScript using Emacs

I hope this is within the reasonable scope of this site and not too trivial, this is my first post. I am new to Emacs and am trying to set up the environment so that when I start a new line in coffee-mode the automatic indentation is in the form of tabs. As I understood the documentation of coffee-mode all I need to do is set coffee-indent-tabs-mode to t. I've appended my init file with the code below:
(custom-set-variables
'(coffee-tab-width 2)
'(coffee-indent-tabs-mode t))
However when I start Emacs and open a .coffee file, though it gets the tab width right, when I press enter it indents with spaces. Quibbles about whether I need to indent with tabs aside, what am I doing wrong?
In the coffee-mode I find in GNU ELPA, there is no coffee-indent-tabs-mode. I recommend you simply do:
(add-hook 'coffee-mode-hook
(lambda ()
(set (make-local-variable 'tab-width) 2)
(set (make-local-variable 'indent-tabs-mode) t)))
This should work for pretty much any major mode.

Emacs global configuration of tabs

I'm attempting to switch from Vim to Emacs, but I'm tearing my hair out trying to configure it to treat tabs how I wish. I require:
Inserted "tabs" to be expanded into two spaces. Emacs stubbornly sticks to eight, no matter what I do.
Tabs (i.e. real \t characters) to be represented on screen by two spaces.
Pressing TAB should insert a tab at the cursor rather than indent the entire line. Currently, I press TAB anywhere and Emacs destroys all whitespace at the start of the line; this is the most infuriating thing so far.
My current ~/.emacs reads
(setq standard-indent 2)
(setq-default indent-tabs-mode nil)
but I have tried no end of suggested configurations from the web, none of which have done what they said they would. (Does the API constantly change? I'm using GNU Emacs 23.1.1, apparently.)
Emacs has extremely flexible support for handling indentation. Generally the mode that you are in dictates how they work - so if you're working on a C file then the way that pressing tab works will be different than if you're working on a Python file.
So it does depend which mode you're working in, which will limit the answers you get. In most cases I would recommend that you don't fight against it - for me the indentation behaviour is one of the best features of emacs. However, you do need to spend the time to customize it for yourself.
To change the way that tabs are displayed you need to set tab-width to 2. If you're editing Java or C style code then it sounds like you want to turn off all the nice indentation features by these to NIL:
c-tab-always-indent
c-syntactic-indentation
indent-tabs-mode
I suggest you set these through the customization interface. If you use "M-x customize-group RET C" then you can see the various settings for C mode.
If you're editting different types of files then the instructions will be different.
Perhaps emacs is in the wrong mode for your file. You could try doing "M-x fundamental-mode" to see if you prefer the behaviour there.
;; * Inserted "tabs" to be expanded into two spaces. Emacs stubbornly
;; sticks to eight, no matter what I do.
;; * Tabs (i.e. real \t characters) to be represented on screen by two
;; spaces.
(setq-default tab-width 2)
;; * Pressing TAB should insert a tab at the cursor rather than indent
;; the entire line. Currently, I press TAB anywhere and Emacs
;; destroys all whitespace at the start of the line; this is the
;; most infuriating thing so far.
(setq-default indent-tabs-mode t)
(mapcar (lambda (hooksym)
(add-hook hooksym
(lambda ()
(kill-local-variable 'indent-tabs-mode)
(kill-local-variable 'tab-width)
(local-set-key (kbd "TAB") 'self-insert-command))))
'(
c-mode-common-hook
;; add other hook functions here, one for each mode you use :-(
))
;; How to know the name of the hook function? Well ... visit a file
;; in that mode, and then type C-h v major-mode RET. You'll see the
;; mode's name in the *Help* buffer (probably on the second line).
;; Then type (e.g.) C-h f python-mode; you'll see blather about the
;; mode, and (hopefully) somewhere in there you'll see (again e.g.)
;; "This mode runs the hook `python-mode-hook', as the final step
;; during initialization."
This should get you most of what you want. You'll probably have to customize some other programming modes you commonly use.
(defun insert-tab ()
"self-insert-command doesn't seem to work for tab"
(interactive)
(insert "\t"))
(setq indent-line-function 'insert-tab) ;# for many modes
(define-key c-mode-base-map [tab] 'insert-tab) ;# for c/c++/java/etc.
(setq-default tab-width 2)

completely lucid tabs and spaces in emacs?

The title of my question is a reference to sane tabs in emacs.
Basically what I want is to globally set tabs and indention to work in
some uniform way. I feel like emacs is so much better than TextMate
or BBEdit but really the way they handle indention is simple and great
for my purposes. In emacs if you use some tab/space scheme that's
different than the scheme enforced by a minor mode you use you're in
trouble.
When I press enter I'd like to be moved to the next line indented to
the right place using tabs. If I can have my cake and eat it too I'd
like to be indented using spaces if the rest of the file is composed
that way.
I've tried these also:
doing tabs in emacs
force emacs to use tabs
Thanks to anyone who can help me achieve this.
-Mike
Perhaps (global-set-key (kbd "RET") 'newline-and-indent) is what you want?
(Or reindent-then-newline-and-indent if that's available, or you could just hit C-j instead of the Enter key.)
For this part of your question:
If I can have my cake and eat it too I'd like to be indented using spaces if the rest of
the file is composed that way.
does this do what you want?
(defun dtrt-indent ()
(setq indent-tabs-mode
(save-excursion
(goto-char (point-min))
(search-forward "\t" nil t))))
(add-hook 'text-mode-hook #'dtrt-indent)
(add-hook 'c-mode-hook #'dtrt-indent)
; etc for all modes you care about
So if there's a tab anywhere in the buffer, indent using tabs; if there is no tab, indent using spaces.
if you do your setup as described:
(setq indent-tabs-mode t)
(setq-default indent-tabs-mode t)
(setq tab-width 4) ;; 8 is way too many
(setq default-tab-width 4) ;; 8 is way too many
(global-set-key (kbd "RET") 'newline-and-indent)
The indent-tabs-mode thing will tell emacs to create your indentation by using TABS and SPACES to make up the desired indentation (defined by the individual mode). This means, if you want to have a TAB inserted instead of TABS/SPACES you need to configure your mode to use tab-width as indentation.
For example if you use c-mode and select cc-mode as indentation style (select with C-c .) which uses 4 as indentation value, newline-and-indent will insert spaces.
To conclude:
Check that your mode uses tab-width as indentation
Check that your mode doesn't overwride indent-tabs-mode (python-mode seems to do this)
Although I personally don't like TABS good luck on your journey :)
The best strategy is to convince your programming mode of choice to
indent things the way you like. This is generally very easy; I am
picky about indentation and my emacs always does the right thing
automatically. (That means that "indent-region" also always does
what I want, which is very convenient.)

Removing tab inconsistencies in Emacs

To set tabs in emacs I have this line in my .emacs:
(global-set-key (kbd "TAB") 'tab-to-tab-stop)
I'm looking for some way to make all modes show tabs in emacs as 4 spaces and have emacs save the tabs as tab characters (instead of saving them as spaces).
If I'm using c-mode that .emacs line will make tabs look like 8 spaces and save them as a tab character. But in ada-mode enter will auto-indent (which I'm ok with) and it will appear as 4 spaces in emacs and save as four spaces.
Does anyone know how to universally set tabs to insert one tab (and no spaces) when the tab key is pressed and have it appear on emacs as four spaces?
I've also tried:
(setq tab-width 4)
but I still had the same problem with ada-mode.
You can't really do it for all modes as there are mode-specific indentation variables, but you can set it it for all of the languages you care about. For C, something akin to the following in your .emacs should work for what you describe:
(add-hook 'c-mode-common-hook`
(lambda ()
(setq c-basic-offset 4)
(setq tab-width 4)
(setq standard-indent 4)
(setq c-tab-always-indent t)
)
)
That will set up tab stops at 4 characters and make 4 the default indentation level for all C-style modes. For other languages and their respective modes, you have to look up their indentation variables and set them accordingly in that mode's common hook. Some examples include 'sh-indentation, 'tcl-indent-level, and 'perl-indent-level. The easiest way to figure out what needs to be set is to run:
M-x describe-key [TAB]
That should send you down the rabbit hole.
Cheers!
Sean