在Emacs的文本模式下设置四个空格缩进

181

当在主模式text-mode的缓冲区中按下TAB键时,我无法成功使Emacs从8空格制表符切换到4空格制表符。我已经将以下内容添加到我的.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)

无论我如何更改我的.emacs文件(或者我的缓冲区的本地变量),TAB按钮总是做同样的事情。

  1. 如果上面没有文本,则缩进8个空格
  2. 如果前一行有文本,则缩进到第二个单词的开头

尽管我很喜欢Emacs,但这很烦人。是否有一种方法可以让Emacs在上一行没有文本时至少缩进4个空格?


针对C++或csharp-mode模式,我在(defun csharp-mode ()...)的结尾处添加了(setq tab-width 4)和(setq c-basic-offset 4),这使得(1)制表符显示为4个字符而不是8个字符,(2)当我按tab键时在新行上会出现4个空格。 - Jared Updike
非常晚了,但我刚意识到使用(setq tab-width 4)不起作用,但如果你使用(setq-default tab-width 4),你就不需要做任何其他事情。 - Sambatyon
如果您想使用空格,但是要转到制表位,请查看我的答案。 - forkandwait
注意:对于那些发现这个问题的人,请注意:(setq-default tab-width 4) 不等同于 (setq tab-width 4),一定不要漏掉 "-default"! - zachaysan
16
我不敢相信这么做很难。 - jds
21个回答

153

简短回答:

关键点是告诉emacs在缩进时插入想要的内容,这可以通过更改indent-line-function来实现。将其更改为插入制表符,然后将制表符转换为4个空格比直接更改为插入4个空格更容易。以下配置将解决您的问题:

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

说明:

来自 Emacs手册中的Major Mode控制缩进:

每个主要模式最重要的功能之一是为了编辑的语言定制合适的按键缩进。

[...]

indent-line-function变量是当前行进行缩进时(例如调用indent-region)所使用的函数。命令indent-according-to-mode不过就是调用此函数。

[...]

许多模式的默认值是indent-relative。

来自于indent-relative @ Emacs手册:

Indent-relative: 在前一非空白行向下对齐到下一个缩进点。

[...]

如果前一非空白行没有缩进点超出列点开始的位置,则执行'tab-to-tab-stop'。

只需将indent-line-function变量的值更改为insert-tab函数并配置tab插入为4个空格即可。


13
我和原帖作者有同样的问题,你的解决方法对我不起作用。 - Gauthier
4
你的配置对我来说插入了8个空格。 - Vladimir Mihailenco
4
我使用的是Emacs版本23.3.1,短答案无法将其转换为空格,这个答案是误导性的。 - VNarasimhaM
2
@BruceBarnett 我现在处于文本模式,但这些指令仍然无效。 - sunny
2
对于那些不知道的人...请将上面代码块中的行添加到~/.emacs中。如果你没有这个文件,可以直接创建它。 - spencer.sm
显示剩余4条评论

67
更新:自Emacs 24.4起:

tab-stop-list现在会自动延伸到无限大。它的默认值已更改为nil,这意味着每tab-width个字符就有一个制表位。

这意味着不再需要像下面所示的设置tab-stop-list,因为可以将其保持为nil
原回答如下...
当看到像(setq tab-stop-list 4 8 12 ................)时,总会让我感到些许痛心,因为number-sequence函数正等待被使用。
(setq tab-stop-list (number-sequence 4 200 4))

或者
(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))

这是我在我的系统上能够得到的唯一可行的答案。 - Karpov
1
Emacs缩进自定义页面说tab列表“通过重复最后一步隐含地无限扩展”,这意味着一个列表(4 8)应该足够好,不需要显式的数字序列。 - James Waldby - jwpat7
缩进似乎是4个空格,但是emacs在\begin{tikzpicture}和\end{tikzpicture}之间仍然应用了2个空格。 - alper
@alper:缩进功能在不同的模式下可能会有很大的差异 - 不同的语言可能具有极其不同的规则和要求。您需要阅读一些关于Emacs如何进行LaTeX(我推测)缩进的内容。 - phils
你有一个入门指南可以开始阅读吗?我刚刚尝试在这里的示例代码片段(https://tex.stackexchange.com/q/585896/127048)上应用4个空格缩进;但是我尝试了这个线程中的所有答案,无论如何都只有2个空格。 - alper
显示剩余4条评论

34
不要将变量tab-width与变量tab-stop-list混淆。前者用于显示字面值TAB字符,而后者控制在某些模式下按下TAB字符时插入的字符。-- GNU Emacs手册
(customize-variable (quote tab-stop-list))

或者在.emacs文件中的custom-set-variables中添加tab-stop-list条目:
(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))))

编辑标签行为的另一种方法是使用M-x edit-tab-stops

有关edit-tab-stops的更多信息,请参阅GNU Emacs手册上的标签停止


10
需要使用“tab-width”和“tab-stop-list”两个参数。当显示制表位时,必须使用“tab-width”参数,而在添加制表位时需要使用“tab-stop-list”参数来确定制表位的位置。请注意不改变原意。 - Michael Ratanapintha
3
请注意:https://dev59.com/RHVD5IYBdhLWcg3wJIIK - phils
7
'(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))) 没有比它更短的了吗?好吧,只要它有效,我想这样就可以了... :P - HelloGoodbye
6
根据文档,您不需要所有这些位置。只需使用4、8、12,它就会扩展到所有其他位置(每次增加4)。显然,如果您只使用1或2个元素而不是3个,它将仅使用tab-width作为最后一步。因此从理论上讲,如果我想要用四个空格进行制表,而我的tab-width设置为4,我可以写'(tab-stop-list (quote (4))) - Nicholas Peterson
2
@NicholasPeterson 谢谢您注意到这个问题!然而,在实践中,quote需要两个数字才能无限延续序列。请参见:https://dev59.com/RHVD5IYBdhLWcg3wJIIK#42148697 - ryanpcmcquen
显示剩余2条评论

21

您可能会发现按照以下方式设置选项卡更容易:

M-x customize-group

在“自定义组:”提示处输入“indent”。

您将看到一个屏幕,可以在其中设置所有缩进选项并将它们设置为当前会话或保存为所有未来的会话。

如果您以这种方式进行操作,您将需要设置一个自定义文件


我需要记住 M-x customize-group - 非常方便的快捷方式! - Nick Bolton
1
缩进似乎是4,但在\begin{tikzpicture}\end{tikzpicture}之间仍然应用2。 - alper

12
(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)

这适用于C++代码以及注释内部。


晚来一步,但还是谢谢。我无法理解为什么emacs需要特定的指令来将其缩进规则应用于C/C++代码。将来我会关注vim... - MegaWidget
我想问这个问题只是为了能够接受这个答案。如果可以的话,我会给它一个赏金。当一个改变使emacs不愿意在4个空格上缩进时,我非常非常沮丧,正在查看此页面上的所有解决方案,而您已经为我节省了大量的工作! - Topological Sort

11
(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)

10
(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)

这个方法对我有效,而其他页面上的方法则无效。 - Michael Terry
适用于emacs 26.3 - Saurabh
@Saurabh 在哪个系统上?在我这里,Win10 64位,没有任何效果。这些解决方案都没有用。Emacs 26.4。C++ - 总是2个空格,没有例外。 - Chuckk Hubbard
@ChuckkHubbard -- 我相信你没有使用text-mode-hook来尝试更改主模式以编辑C++文件的行为?此外,像cc-mode等主模式可能需要根据正在使用的变量进行略微不同的处理...键入C-h m以查看有关主模式的信息。 - lawlist
@lawlist 嗯,我明白了;虽然我实际上想要所有语言的相同设置,但我猜我得为每个语言单独设置。如果其他人有我的烦恼:M-x customize-groups emacs-Programming-Languages-C-C basic offset = override style settings 这个命令对我很有用。 - Chuckk Hubbard
@ChuckkHubbard - 当我将2改为4时,这在macOS上运行正常。如果有与C++主模式冲突的问题,则可能会出现问题。 - Saurabh

8
这个问题不是由于缺少制表位引起的;而是 Emacs 有一个(新的?)称为 indent-relative 的制表方法,似乎旨在对齐表格数据。TAB 键映射到 indent-for-tab-command 方法,该方法调用变量 indent-line-function 设置的任何方法,文本模式下的 indent-relative 方法。我还没有找到一个好的方法来覆盖 indent-line-function 变量(文本模式钩子不起作用,所以也许它在模式钩子运行后被重置了?)但是消除这种行为的一种简单方法是通过将 TAB 设置为更简单的 tab-to-tab-stop 方法来取消 indent-for-tab-command 方法:
(define-key text-mode-map (kbd "TAB") 'tab-to-tab-stop)

7
您可以将以下代码添加到您的.emacs文件中。 它为文本模式添加了一个钩子,以使用insert-tab而不是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)))

我希望这有所帮助。

6

试试这个:

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

这将使TAB键始终插入一个字面上的制表符,每4个字符有一个制表位(但仅在文本模式下)。如果这不是您要求的,请描述您想要看到的行为。


4
我认为OP希望用空格代替制表符(因此按下Tab键会插入4个空格)。 - mipadi
与Aquamacs 2.4配合使用,这个特定的答案给我提供了另一种语言的字符而不是制表符:렔。如果按下制表键超过一次,则结果为:렔렔(没有任何分隔符)。对于每个连续的制表键按下都是如此。 - lawlist

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接