4

I have a project where I want to disable format-all-mode for all my python files. I can do this manually by running M-x format-all-mode every time I open up a python file for that project.

I tried automating this by setting my .dir-locals.el to this:

((python-mode
  (eval . (progn
          (make-local-variable 'format-all-mode)
          (setq format-all-mode nil)))
))

I've also tried:

((python-mode
  (eval . (progn
         (format-all-mode nil)))
))

but format-all-mode continues to be t every time I open a python file. I've confirmed that my .dir-locals.el settings are otherwise working, because when I add something like (setq blah "asdf") inside the progn function, I see that variable in my buffer.

What am I missing in order to configure the buffer-local format-all-mode variable?

Here are the docs when I describe this format-all-mode variable:

format-all-mode is a buffer-local variable defined in format-all.el.

Value in #<buffer my-file.py>
t

Buffer values Global value Toggle Set

Documentation
Non-nil if Format-All mode is enabled.

Use the command format-all-mode to change this variable.

Key Bindings
This command is not in any keymaps.

References
References in format-all.el:
(define-minor-mode format-all-mode ...) 2 references

Find all references

Update

I should've mentioned that I'm using Doom emacs, which has modified the format-all-mode so that it cannot be disabled with the usual (format-all-mode -1).

I followed these instructions: https://docs.doomemacs.org/latest/modules/editor/format/

and got it working with the following value in my .dir-locals.el:

((python-mode
  (eval . (progn
        ;; this doesn't work, because we're using doom emacs:
        ;; (format-all-mode -1)
        ;;
        ;; https://docs.doomemacs.org/latest/modules/editor/format/
        ;; TODO: add python-mode to the list, instead of overwriting the whole list
        (setq +format-on-save-enabled-modes
          '(not python-mode sql-mode org-mode emacs-lisp-mode))
  ))
))

It's a hack though, since +format-on-save-enabled-modes isn't buffer local. I'm not sure if there's a better way - any help is appreciated!

5
  • 1
    To disable a minor mode, you call it with a negative argument, so try ((python-mode (eval . (format-all-mode -1)))). I didn't check the syntax though.
    – NickD
    Commented May 11, 2023 at 18:20
  • Hmm I tried that, but it's still not working... Note that the docs mention Non-nil if Format-All mode is enabled. (I referenced the output above)
    – modulitos
    Commented May 11, 2023 at 18:35
  • 4
    You need to call the function format-all-mode with a negative argument. If the mode is disabled, then the variable format-all-mode should automatically be set to nil. Setting the variable does not disable the mode in general. So try this: open a python file, check the variable (which should be t if the mode is automatically enabled); then do M-: (format-all-mode -1) to disable the mode and check the variable again: it should now be nil. If that's all as it should be, then you have to make sure that the syntax of your entry in the .dir-locals.el file is correct.
    – NickD
    Commented May 11, 2023 at 18:49
  • @NickD Thanks for the tips! You are correct. This helped me narrow down the issue, which I detailed at the bottom of my updated post. Looks like there's some complications due to me using Doom emacs, and while I have a workaround as described, it's pretty hacky.
    – modulitos
    Commented May 11, 2023 at 23:57
  • Just to update this thread, philz answer below provides an elegant solution to make this work with Doom emacs!
    – modulitos
    Commented May 12, 2023 at 7:27

1 Answer 1

2

The real question is about disabling a minor mode, but just to answer the stated question of setting a buffer-local variable, it's as simple as this:

((python-mode . ((format-all-mode . nil))))

I.e. giving variables buffer-local values is what the most basic syntax of .dir-locals.el is for. There is no need to complicate anything with eval.

Note that if you ever use (eval . (setq VAR VALUE)) in a .dir-locals.el file and VAR is not already/automatically buffer-local, then you are setting the global value. I would suggest using setq-local as standard in that situation.

In your case, and per the quoted docs, you need to:

Use the command format-all-mode to change this variable.

Where the command is the function itself, which is interactively callable via M-x.

(Because changing the variable is not the real goal; the variable is merely intended to be a reflection of whether or not certain other functionality is active, and the function controls that functionality.)

So you would use eval if you needed this to be a buffer-local thing, but you'd do that to call the function:

((python-mode . ((eval . (format-all-mode 0)))))

n.b. I'm also assuming that format-all-mode is a buffer-local minor mode. If it's a global mode, then the above would disable its behaviour globally as soon as you visited a python file under that directory. (Global modes need to be handled on a case-by-case basis, as how they operate can be highly variable.)


Edit: From the comments, this particular case needed something different again, but a working solution turns out to be:

((python-mode . ((+format-on-save-enabled-modes . nil))))

I.e. in python-mode buffers, for files under the dir-locals directory, we give +format-on-save-enabled-modes the buffer-local value of nil. Testing has confirmed that this has the desired effect of preventing the format-on-save behaviour for those files.

6
  • 1
    I don't use doom or this mode, but looking at your update, you might try ((python-mode . ((+format-on-save-enabled-modes . (not python-mode))))) -- whether that works would very much depend on the manner in which +format-on-save-enabled-modes is used, but it seems worth a try.
    – phils
    Commented May 12, 2023 at 1:33
  • 1
    Or maybe ((python-mode . ((+format-on-save-enabled-modes . nil)))) is a slightly cleaner option. I don't know anything about this variable though, so that's purely a guess.
    – phils
    Commented May 12, 2023 at 3:28
  • 1
    Amazing! Your suggestion above works perfectly: ((python-mode . ((+format-on-save-enabled-modes . nil)))) I'm still wrapping my head around buffer-local variables, but it seems like setting +format-on-save-enabled-modes in this manner is specific to python-mode and correctly uses the default for all other modes. This is exactly what I needed. I should probably read up on how this actually works, but for now, I'm thrilled to have this working as expected :D
    – modulitos
    Commented May 12, 2023 at 7:26
  • 1
    I'm glad that worked. My guess is that the format-on-save functionality is triggered in before-save-hook for the specific buffer being saved, checks the value of +format-on-save-enabled-modes at that point in time, sees the buffer-local value, and therefore does nothing.
    – phils
    Commented May 12, 2023 at 9:06
  • 1
    You've correctly understood the .dir-locals.el behaviour -- the buffer-local value is being set only for file buffers which are in python-mode; other buffers are unaffected.
    – phils
    Commented May 12, 2023 at 9:12

Your Answer

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

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