10

Python 3.10 added a match statement. When I try and type one in emacs 27.2, it does not indent it correctly, presumably because it does not yet have support for it. How do I get python-mode to indent the match statement correctly?

3
  • M-x find-library RET python RET leads you to the elisp python package. Are you comfortable to do the necessary changes?
    – aadcg
    Nov 9, 2021 at 19:29
  • Please clarify what you mean by "support" the match statement. If you mean only support indenting it properly, the say so.
    – Drew
    Nov 9, 2021 at 23:01
  • 1
    current version support the syntax but indentation seems to be broken
    – rho
    Sep 4, 2022 at 12:42

3 Answers 3

5

There is support for this in melpa python-mode but in my case the emacs was loading the builtin python mode which does not support the match statement.

You can tell that you are loading the builtin python-mode in two ways.

  1. The status line shows Python instead of Py
  2. If you do C-h f python-mode RET, then you move the cursor to the python.el, RET and look the folder for the file (M-: (buffer-file-name) RET). In my case I'm using Mac and I get this path /Applications/Emacs.app/Contents/Resources/lisp/progmodes/python.el.gz

To fix this install the package python-mode from MELPA

M-x package-refresh-contents
M-x package-install python-mode RET

Then add (require 'python-mode) to your .emacs file. And restart emacs. To verify that it is working open a python file, you should see Py instead of Python

I hope this helps

--- update ---

Just for reference, this is the python-mode source code that I'm talking about: https://gitlab.com/python-mode-devs/python-mode, https://melpa.org/#/python-mode

4
  • thanks, that did the trick for me! :)
    – lupl
    Jul 29, 2023 at 5:33
  • 1
    python-mode is in MELPA, not ELPA; it's a package unrelated to the built-in python mode.
    – jirassimok
    Nov 16, 2023 at 17:52
  • Fixed, thanks @jirassimok
    – geckos
    Nov 17, 2023 at 23:51
  • This didn't work for indentation of the match statement for me, in the end I did a M-x package-delete python-mode to get back to the built-in python mode and used Levin's answer. Apr 16 at 16:20
4

I am also using 27.2. What worked for me, clued by this question

  1. Update python.el to 28 (probably not necessary)
  2. M-x find-library, "python"
  3. Add "match" and case" in this section:
(defmacro python-rx (&rest regexps)
  "Python mode specialized rx macro.
This variant of `rx' supports common Python named REGEXPS."
  `(rx-let ((block-start       (seq symbol-start
                                    (or "def" "class" "if" "elif" "else" "try"
                                        "except" "finally" "for" "while" "with"
                                        ;; added by me for python 3.10
                                        "match" "case"
                                        ;; Python 3.5+ PEP492
                                        (and "async" (+ space)
                                             (or "def" "for" "with")))

and this section:

(defvar python-font-lock-keywords-level-2
  `(,@python-font-lock-keywords-level-1
    ,(rx symbol-start
         (or
          "and" "del" "from" "not" "while" "as" "elif" "global" "or" "with"
          "assert" "else" "if" "pass" "yield" "break" "except" "import" "class"
          "in" "raise" "continue" "finally" "is" "return" "def" "for" "lambda"
          "try" "match" "case"
  1. Finally I deleted python.elc which was in same directory as python.el (because the unchanged .elc file will be used in preference to the .el file)
2
  • 1
    What about emacs v28? When I run "find-library" "python" I get: "Can't find library: python"
    – Endlisnis
    Dec 21, 2022 at 2:17
  • This worked for me, but I had to be root to edit python.el (and delete python.elc, of course), otherwise it would open as read-only. Apr 16 at 16:19
1

I followed the answer given by Levin Magruder. I am using Emacs 26.3. I found that, in my copy of python.el, there was only one block which corresponded with what Levin's answer showed. So, here is what that block looked like after I made the changes:

(eval-and-compile
  (defconst python-rx-constituents
    `((block-start          . ,(rx symbol-start
                                   (or "def" "class" "if" "elif" "else" "try"
                                       "except" "finally" "for" "while" "with"
                                       ;; added by bjk for Python 3.10
                                       "match" "case"
                                       ;; Python 3.5+ PEP492
                                       (and "async" (+ space)
                                            (or "def" "for" "with")))
                                   symbol-end))
  [...]

Seems to work just fine. Thanks, Levin. Sorry that I don't yet have enough reputation on this SE to upvote your answer.

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.