9

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?

Rob Gilton
  • 221
  • 1
  • 4
  • `M-x find-library RET python RET` leads you to the elisp python package. Are you comfortable to do the necessary changes? – aadcg Nov 09 '21 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 09 '21 at 23:01
  • 1
    current version support the syntax but indentation seems to be broken – rho Sep 04 '22 at 12:42

3 Answers3

4

There is support for this in elpa 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 ELPA

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

geckos
  • 141
  • 2
3

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)
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.

bjkeefe
  • 11
  • 3