2

By default I want all indentation (when I hit the tab key) to be 2 spaces.

However, when I am editing certain Python files (where I can not mix tabs and spaces) I would like to use whatever the existing indentation is.

Every time I open a file I see Can’t guess python-indent-offset, using defaults: 4

That warning and answers like these make me think that Emacs can guess the offset. However, when I just edited a file that uses all tabs, pressing the tab key resulted in 4 spaces.

In my init file I do have the following:

(setq-default indent-tabs-mode nil)

Can somebody tell me if I really need to install guess style mode in order to switch between tabs and spaces based on what exists in the file?

Is there another way to allow tabs (even though I have disabled them by default)?

1 Answer 1

10

By default I want all indentation (when I hit the tab key) to be 2 spaces.

This can be achieved for many modes with settings such as

(setq-default indent-tabs-mode nil
              tab-stop-list    ()
              tab-width        2)

Every time I open a file I see Can’t guess python-indent-offset, using defaults: 4

The default indentation offset for python.el can be configured via the customisable variable python-indent-offset.

Whether python.el tries to guess the indentation offset can be controlled by the customisable variable python-indent-guess-indent-offset.

Whether python.el prints this message after guessing the indentation offset can be controlled by the customisable variable python-indent-guess-indent-offset-verbose.

That warning and answers like these make me think that Emacs can guess the offset. However, when I just edited a file that uses all tabs, pressing the tab key resulted in 4 spaces.

This is probably because python-mode and inferior-python-mode from python.el set indent-tabs-mode to nil by default.

Note that "guessing the offset" and "inserting tabs or spaces" are not the same thing. Emacs (more specifically, python.el) can indeed do the former, but the latter does not seem like a very easy task to me and I am not familiar with a built-in means of achieving this. I suggest you consider the following options for setting indent-tabs-mode:

  • Define your own convenience function which toggles indent-tabs-mode. For example:

    (defun my-toggle-indent-tabs-mode ()
      "Toggle `indent-tabs-mode'."
      (interactive)
      (setq-local indent-tabs-mode (not indent-tabs-mode)))
    

    You can even bind this to a convenient key.

  • Install python-mode.el. It is more customisable than python.el and provides indent-tabs-mode-toggling commands like the one above.

  • Use file-local variables to determine and, to an extent, enforce the desired style in certain files.

  • Similarly with directory-local variables. See also here.

  • Add a custom function to python-mode-hook with your own logic for setting indent-tabs-mode, e.g. based on file name or contents.

  • Install a third-party package which detects indentation style based on customisable heuristics, such as dtrt-indent. See also this related question.

[do] I really need to install guess style mode

Yes, for the reasons outlined above I think you need to install a third-party package for automatic tab/space detection.

No, I would not recommend guess-style, as it seems to be cc-mode-specific, and newer versions of cc-mode come with built-in style guessing.

4
  • Great answer. dtrt-indent was a good solution for me.
    – Startec
    May 20, 2017 at 8:22
  • 1
    wow answer. I was looking for the ...-verbose variable, to silence the warnings. Many thanks. (reposted to stackoverflow.com/a/51966682/1449460) Aug 22, 2018 at 12:15
  • Does any of these packages implement caching of detected offset associated with a given source file? At least when that file hasn't changed since it was last edited in Emacs.
    – Nordlöw
    Apr 26, 2021 at 17:44
  • @Nordlöw The built-in python-mode conditionally tries to detect indentation whenever the mode is enabled. I don't know about the others.
    – Basil
    Apr 26, 2021 at 18:25

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

Not the answer you're looking for? Browse other questions tagged or ask your own question.