Configure Emacs

Procedure 9.1. Set up the editor virtual environment.

In this configuration, we use two virtual enviromnents. The one we are creating in this chapter is semi-permanent; it's for emacs python and should be usable for editing most python files regardless of their host project. We'll make another virtualenv specific to the project for running the project's code. That way, the packages and python version required for different projects do not conflict while editing, because editing uses a dedicated virtualenv. Note that this approach may break mypy typing, and will make it harder to run code directly from emacs, so figure that out next.

  1. Install system packages

    sudo apt install python3-venv python3-pip python3-gpg

  2. Create the editor's virtual environment

    python -m venv ~/.config/venv/emacs_python_ide source ~/.config/venv/emacs_python_ide/bin/activate

  3. Install IDE python software

    pip install ruff

  4. Install tree-sitter python

    As of 2025-09-18, tree-sitter-python is broken: because current emacsen—30.1 and 30.2—use ABI 14, but current py-tree-sitter—version 0.25—uses ABI 15. This breaks the built-in install method of M-x treesit-install-language-grammar.

    Manually compile and install version tree-sitter-python grammar 0.23.6. git clone https://github.com/tree-sitter/py-tree-sitter.git cd tree-sitter-python/ git fetch --tags git checkout refs/tags/v0.23.6 python setup.py build make cp libtree-sitter-python.so ~/.emacs.d/tree-sitter/libtree-sitter-python.so

  5. Verify treesit setup

    M-x ielm (treesit-language-available-p 'python)

    It should return t.

    Open python file and activate treesitter mode with M-x python-ts-mode RET

  6. Make treesit fontlock everything it can.

    Try M-X customize-variable treesit-font-lock-level to 4. If this is good, move this to init.el

  7. pip install ruff black

  8. Put this in .emacs.d/init.el:

    (add-hook 'python-mode-hook 'eglot-ensure)
                  (with-eval-after-load 'eglot
                  (add-to-list 'eglot-server-programs
                  '(python-mode . ("ruff" "server"))))