Subject: bug#73991: EditorConfig bundled with Emacs 30 does not set tab-width

From: Stefan Monnier <[email-masked]>
Date: Fri, 25 Oct 2024 13:25:23 -0400

>> You can get the same behavior with
>>
>>    indent_size = tab
>>    tab_width = 4
>
> The settings mean the same thing,

Do they?  If so, why prefer the above formulation?

Also they don't seem to mean quite the same thing to me.  The way I read
it, the above really says that an indent step should be a TAB since
that's what the first line says quite literally, whereas:

    indent_size = 4
    indent_style = tab

only says that an indentation step should span 4 columns, and that the
spacing inserted when indenting use TAB chars rather than spaces to move
from a the `N1 * tab_width` column to the `N2 * tab_width` column.

I think the two interpretations can only be mistaken as equivalent if
you ignore situations like

    x.bar(arg1,
          somefunctionwithalongname
              (arg2))

where you can't align `somefunction` with TABs of width 4 (or 8 for that
matter), nor can you then properly indent `(arg2)` 4 columns further
with only TABs.

[ Admittedly, the spec of EditorConfig around `tab_width`,
  `indent_size`, and `indent_style` is quite vague and hard to
  interpret.  OT1H it tends to conflate several notions of "TAB" and
  "indentation steps" (like you're doing when you claim that both
  settings mean the same), yet OTOH it goes through the trouble of
  providing 3 different variables, thus recognizing that there is more
  to it.  ]

This said, I guess we could meet halfway and set `tab-width` to
`indent_size` when `indent_style = tab`, as in the patch below.

        Stefan

diff --git a/lisp/editorconfig.el b/lisp/editorconfig.el
index c21e12559a6..83e4ea36731 100644
--- a/lisp/editorconfig.el
+++ b/lisp/editorconfig.el
@@ -434,8 +434,10 @@ editorconfig--get-indentation
   (let ((style (gethash 'indent_style props))
         (size (gethash 'indent_size props))
         (tab_width (gethash 'tab_width props)))
-    (when tab_width
-      (setq tab_width (string-to-number tab_width)))
+    (cond
+     (tab_width (setq tab_width (string-to-number tab_width)))
+     ((and (equal style "tab") (editorconfig-string-integer-p size))
+      (setq tab_width (string-to-number size))))
 
     (setq size
           (cond ((editorconfig-string-integer-p size)