ChatGPT解决这个技术问题 Extra ChatGPT

Set 4 Space Indent in Emacs in Text Mode

I've been unsuccessful in getting Emacs to switch from 8 space tabs to 4 space tabs when pressing the TAB in buffers with the major mode text-mode. I've added the following to my .emacs:

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

;;; And I have tried
(setq indent-tabs-mode nil)
(setq tab-width 4)

No matter how I change my .emacs file (or my buffer's local variables) the TAB button always does the same thing.

If there is no text above, indent 8 spaces If there is text on the previous line, indent to the beginning of the second word

As much as I love Emacs this is getting annoying. Is there a way to make Emacs to at least indent 4 space when there's not text in the previous line?

For a mode line C++ or csharp-mode I added (setq tab-width 4) (setq c-basic-offset 4) to the end of (defun csharp-mode () ... ) and it did the trick to make (1) tabs show as 4 instead of 8 characters and (2) when I press tab I get 4 spaces on a new line.
Very late, but I just realized that using (setq tab-width 4) does not work, but if you use (setq-default tab-width 4) you don't need to do anything else.
See my answer if you want to use spaces but go to tab stops.
Note to others that have found this question: (setq-default tab-width 4) is NOT the same thing as (setq tab-width 4) be sure you didn't miss the "-default"!
I cannot believe this is so difficult to do.

a
alcortes

Short answer:

The key point is to tell emacs to insert whatever you want when indenting, this is done by changing the indent-line-function. It is easier to change it to insert a tab and then change tabs into 4 spaces than change it to insert 4 spaces. The following configuration will solve your problem:

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

Explanation:

From Indentation Controlled by Major Mode @ emacs manual:

An important function of each major mode is to customize the key to indent properly for the language being edited. [...] The indent-line-function variable is the function to be used by (and various commands, like when calling indent-region) to indent the current line. The command indent-according-to-mode does no more than call this function. [...] The default value is indent-relative for many modes.

From indent-relative @ emacs manual:

Indent-relative Space out to under next indent point in previous nonblank line. [...] If the previous nonblank line has no indent points beyond the column point starts at, `tab-to-tab-stop' is done instead.

Just change the value of indent-line-function to the insert-tab function and configure tab insertion as 4 spaces.


I have the same problem as the OP, your solution does not work for me.
your confuguration inserts 8 spaces for me.
I am using emacs version 23.3.1 and the short answer doesn't change it to spaces. this answer is misleading.
@BruceBarnett I am in text mode and these instructions still don't work.
For those who don't know... Add the lines from the code block shown above to ~/.emacs. If you don't have the file, you can just create it.
p
phils

Update: Since Emacs 24.4:

tab-stop-list is now implicitly extended to infinity. Its default value is changed to nil which means a tab stop every tab-width columns.

which means that there's no longer any need to be setting tab-stop-list in the way shown below, as you can keep it set to nil.

Original answer follows...

It always pains me slightly seeing things like (setq tab-stop-list 4 8 12 ................) when the number-sequence function is sitting there waiting to be used.

(setq tab-stop-list (number-sequence 4 200 4))

or

(defun my-generate-tab-stops (&optional width max)
  "Return a sequence suitable for `tab-stop-list'."
  (let* ((max-column (or max 200))
         (tab-width (or width tab-width))
         (count (/ max-column tab-width)))
    (number-sequence tab-width (* tab-width count) tab-width)))

(setq tab-width 4)
(setq tab-stop-list (my-generate-tab-stops))

This is the only answer that I could get to work on my system.
emacs indent customize page says tab list "implicitly extends to infinity through repetition of the last step" - which means a list (4 8) ought to be good enough, without explicit number-sequence
@JamesWaldby-jwpat7 Indeed, that happened in 24.4 (2014). NEWS says: "tab-stop-list is now implicitly extended to infinity. Its default value is changed to nil which means a tab stop every tab-width columns." -- so in fact you can just use the default value of nil.
Indent seems 4 in but still emacs applies 2 spaces in between \begin{tikzpicture} and \end{tikzpicture}
@alper: Indentation functionality can vary hugely from mode to mode -- different languages can have extremely different rules and requirements. You'll have to do some reading about how Emacs does LaTeX (I presume) indentation specifically.
s
skrueger

Do not confuse variable tab-width with variable tab-stop-list. The former is used for the display of literal TAB characters. The latter controls what characters are inserted when you press the TAB character in certain modes.

-- GNU Emacs Manual

(customize-variable (quote tab-stop-list))

or add tab-stop-list entry to custom-set-variables in .emacs file:

(custom-set-variables
  ;; custom-set-variables was added by Custom.
  ;; If you edit it by hand, you could mess it up, so be careful.
  ;; Your init file should contain only one such instance.
  ;; If there is more than one, they won't work right.
 '(tab-stop-list (quote (4 8 12 16 20 24 28 32 36 40 44 48 52 56 60 64 68 72 76 80 84 88 92 96 100 104 108 112 116 120))))

Another way to edit the tab behavior is with with M-x edit-tab-stops.

See the GNU Emacs Manual on Tab Stops for more information on edit-tab-stops.


Both tab-width and tab-stop-list are needed. tab-width is used when DISPLAYING tabs, while tab-stop-list is needed to determine tab stops when you ADD tabs.
Is there really nothing shorter than '(tab-stop-list (quote (4 8 12 16 20 24 28 32 36 40 44 48 52 56 60 64 68 72 76 80 84 88 92 96 100 104 108 112 116 120)))? Well, as long as it works I guess... :P
According to the documentation, you don't need all those positions. Just do 4 8 12 and the it will extend to all the others (keep adding 4). Apparently if you just use 1 or 2 elements instead of 3, it will just use tab-width as the last step. So theoretically, if I wanted to tab by four spaces, and my tab-width was set to 4. I could write '(tab-stop-list (quote (4))).
@NicholasPeterson thank you for noticing that! It would seem though, that in practice quote needs two numbers to continue the sequence ad infinitum. See: stackoverflow.com/a/42148697/2662028
D
Dave Webb

You may find it easier to set up your tabs as follows:

M-x customize-group

At the Customize group: prompt enter indent.

You'll see a screen where you can set all you indenting options and set them for the current session or save them for all future sessions.

If you do it this way you'll want to set up a customisations file.


I need to remember M-x customize-group - very handy shortcut!
Indent seems 4 but still it applies 2 in between \begin{tikzpicture} and \end{tikzpicture}
佚名
(setq tab-width 4)
(setq tab-stop-list '(4 8 12 16 20 24 28 32 36 40 44 48 52 56 60 64 68 72 76 80))
(setq indent-tabs-mode nil)

a
alecxe
(setq-default indent-tabs-mode nil)
(setq-default tab-width 4)
(setq indent-line-function 'insert-tab)
(setq c-default-style "linux") 
(setq c-basic-offset 4) 
(c-set-offset 'comment-intro 0)

this works for C++ code and the comment inside too


Late to the party, but thank you. I can't fathom why emacs would need specific instructions to apply its indentation rules to C/C++ code as well. I'll be eyeing vim in the future...
I want to ask this question myself JUST SO I CAN ACCEPT THIS ANSWER. I'd give it a bounty if I could. I was very, very upset that a change made emacs unwilling to tab at 4, was going through all the solutions on this page, and you have saved me a tremendous amount of work!
l
lawlist
(defun my-custom-settings-fn ()
  (setq indent-tabs-mode t)
  (setq tab-stop-list (number-sequence 2 200 2))
  (setq tab-width 2)
  (setq indent-line-function 'insert-tab))

(add-hook 'text-mode-hook 'my-custom-settings-fn)

This worked for me when others on this page did not.
Works in emacs 26.3
佚名

This problem isn't caused by missing tab stops; it's that emacs has a (new?) tab method called indent-relative that seems designed to line up tabular data. The TAB key is mapped to the method indent-for-tab-command, which calls whatever method the variable indent-line-function is set to, which is indent-relative method for text mode. I havn't figured out a good way to override the indent-line-function variable (text mode hook isn't working, so maybe it is getting reset after the mode-hooks run?) but one simple way to get rid of this behavior is to just chuck the intent-for-tab-command method by setting TAB to the simpler tab-to-tab-stop method:

(define-key text-mode-map (kbd "TAB") 'tab-to-tab-stop)


g
gigilibala

You can add these lines of code to your .emacs file. It adds a hook for text mode to use insert-tab instead of indent-relative.

(custom-set-variables
 '(indent-line-function 'insert-tab)
 '(indent-tabs-mode t)
 '(tab-width 4))
(add-hook 'text-mode-hook
      (lambda() (setq indent-line-function 'insert-tab)))

I hope it helps.


c
cjm

Try this:

(add-hook 'text-mode-hook
  (function
   (lambda ()
     (setq tab-width 4)
     (define-key text-mode-map "\C-i" 'self-insert-command)
     )))

That will make TAB always insert a literal TAB character with tab stops every 4 characters (but only in Text mode). If that's not what you're asking for, please describe the behavior you'd like to see.


I think the OP wants spaces instead of tabs (so hitting Tab inserts 4 spaces).
In conjunction with Aquamacs 2.4, this particular answer gives me characters in another language instead of a tab: 렔. If the tab key is pressed more than one time, the result is: 렔렔 (without any separation). And the same holds true for each successive tab press.
d
dividebyzero

Just changing the style with c-set-style was enough for me.


q
qwerty9967

Add this to your .emacs file:

This will set the width that a tab is displayed to 2 characters (change the number 2 to whatever you want)

(setq default-tab-width 2)

To make sure that emacs is actually using tabs instead of spaces:

(global-set-key (kbd "TAB") 'self-insert-command)

As an aside, the default for emacs when backspacing over a tab is to convert it to spaces and then delete a space. This can be annoying. If you want it to just delete the tab, you can do this:

(setq c-backspace-function 'backward-delete-char)

Enjoy!


Does not meet the at least 4 spaces ask in the question.
Y
Yary

Customizations can shadow (setq tab width 4) so either use setq-default or let Customize know what you're doing. I also had issues similar to the OP and fixed it with this alone, did not need to adjust tab-stop-list or any insert functions:

(custom-set-variables
 '(tab-width 4 't)
 )

Found it useful to add this immediately after (a tip from emacsWiki):

(defvaralias 'c-basic-offset 'tab-width)
(defvaralias 'cperl-indent-level 'tab-width)

This just lets me switch something that is already indented back to left alignment. 2nd time tab brings it back to the start indentation. Pressing tab on a left aligned text does nothing at all.
And M+i as it is mentioned and working with 4 spaces in this answer has the 8 spaces here instead.
can this (last two lines) be done with modelines, at the individual file level. For it it might be enough to define one variable as the same value of the other but i don’t know how to do that in a modeline.
r
ryanpcmcquen

This is the only solution that keeps a tab from ever getting inserted for me, without a sequence or conversion of tabs to spaces. Both of those seemed adequate, but wasteful:

(setq-default
    indent-tabs-mode nil
    tab-width 4
    tab-stop-list (quote (4 8))
)

Note that quote needs two numbers to work (but not more!).

Also, in most major modes (Python for instance), indentation is automatic in Emacs. If you need to indent outside of the auto indent, use:

M-i


The M+i trick works with 4 spaces. The tab just lets me switch something that is already indented back to left alignment. 2nd time tab brings it back to the start indentation. Anything aligned left is not changed. I am in a Python file, probably this happens as automatic alignment as said here. But this answer uses tab-stop-list which is not a good way, it should be number-sequence instead, see this highly upvoted answer.
This is recommended with number-sequence instead: bash (setq-default indent-tabs-mode nil tab-width 4 tab-stop-list (number-sequence 4 200 4) )
@questionto42, why? Wouldn't that stop indentation consistency at 200+?
@questionto42 it is a limit as I suggested. Why use that when my solution automatically expands to infinity?
@questionto42 that comment is criticizing code that doesn't use a sequence, but my code uses a more efficient sequence than the one provided there.
j
josliber

The best answers did not work for until I wrote this in the .emacs file:

(global-set-key (kbd "TAB") 'self-insert-command)

Yes, this makes the tab a real tab, no matter whether it makes sense or not. The normal tab looks whether a tab fits into the code. Something that is left aligned will not get indented by the tab when in the code, this tab would make no sense. This is to help with auto-aligning, but most of the time you will rather use a code editor and not emacs for code formatting. And then in emacs, you often rather just want the tab in any case. This code here makes 8 spaces whenever you press tab. Combine this with this answer to make 4 spaces on M+i.
佚名

Have you tried

(setq  tab-width  4)

They have this in their question, so yes, it is safe to assume that they tried it.
D
Dason
(setq-default tab-width 4)
(setq-default indent-tabs-mode nil)

f
flyrain

By the way, for C-mode, I add (setq-default c-basic-offset 4) to .emacs. See http://www.emacswiki.org/emacs/IndentingC for details.


S
Stefan

From my init file, different because I wanted spaces instead of tabs:

(add-hook 'sql-mode-hook
          (lambda ()
             (progn
               (setq-default tab-width 4)
               (setq indent-tabs-mode nil)
               (setq indent-line-function 'tab-to-tab-stop) 
               (modify-syntax-entry ?_ "w")       ; now '_' is not considered a word-delimiter
               (modify-syntax-entry ?- "w")       ; now '-' is not considered a word-delimiter 
               )))

S
Saurabh

Modified this answer without any hook:

(setq-default
  indent-tabs-mode t
  tab-stop-list (number-sequence 4 200 4)
  tab-width 4
  indent-line-function 'insert-tab)

Strange, when I add this to ~/.emacs, the tab does not work at all, as soon as I press it, the line gets left aligned, that is all. Probably my mistake, new to emacs. Pressing tab on a left aligned text does nothing at all.
To get a further indentation of 4 spaces works here when using M+i as mentioned in this answer. Probably my tab tests were dominated by the automatic alignments of emacs for my Python file, also explained in that answer.
a
alex_1948511

To make in text-mode pressing Tab does indent then tabbing/spacing by fixed values (NOT by previous line words)

see also: indent-relative-first-indent-point, tab-width indent-tabs-mode

(add-hook 'text-mode-hook
 (lambda()
   (progn
     (setq tab-always-indent nil) 
     ;(setq electric-indent-mode nil)
     (setq indent-line-function 
           (lambda()
             (indent-relative 't)   
             )
           ) 
     (setq tab-always-indent nil)
     )))

When I press tab on an indented row, I get a left alignment, 2nd time it jumps back to the start indentation. Pressing tab on a left aligned text does nothing at all.
And M+i as it is mentioned and working with 4 spaces in this answer has the 8 spaces here instead.