feat(python): add treesit support

This commit is contained in:
Henrik Lissner
2025-05-07 18:15:51 -04:00
parent f2678b3ea2
commit a372eba7cd
4 changed files with 47 additions and 20 deletions

View File

@ -7,7 +7,7 @@
;;;###autoload
(defun +python-pyenv-mode-set-auto-h ()
"Set pyenv-mode version from buffer-local variable."
(when (eq major-mode 'python-mode)
(when (memq major-mode '(python-mode python-ts-mode))
(when (not (local-variable-p '+pyenv--version))
(make-local-variable '+pyenv--version)
(setq +pyenv--version (+python-pyenv-read-version-from-file)))

View File

@ -14,28 +14,38 @@
;;; Packages
(use-package! python
:mode ("[./]flake8\\'" . conf-mode)
:mode ("/Pipfile\\'" . conf-mode)
:mode ("/\\(?:Pipfile\\|\\.?flake8\\)\\'" . conf-mode)
:init
(setq python-environment-directory doom-cache-dir
python-indent-guess-indent-offset-verbose nil)
(when (modulep! +tree-sitter)
(set-tree-sitter! 'python-mode 'python-ts-mode
'((python :url "https://github.com/tree-sitter/tree-sitter-python"))))
:config
;; HACK: `python-base-mode' (and `python-ts-mode') don't exist on pre-29
;; versions of Emacs, Rather than litter this module with conditionals, I
;; shim the keymap in.
(unless (boundp 'python-base-mode-map)
(defvaralias 'python-base-mode-map 'python-mode-map))
(when (modulep! +lsp)
(add-hook 'python-mode-local-vars-hook #'lsp! 'append)
(add-hook 'python-ts-mode-local-vars-hook #'lsp! 'append)
;; Use "mspyls" in eglot if in PATH
(when (executable-find "Microsoft.Python.LanguageServer")
(set-eglot-client! 'python-mode '("Microsoft.Python.LanguageServer"))))
(set-eglot-client! '(python-mode python-ts-mode) '("Microsoft.Python.LanguageServer"))))
(when (modulep! +tree-sitter)
(add-hook 'python-mode-local-vars-hook #'tree-sitter! 'append))
:config
(set-repl-handler! 'python-mode #'+python/open-repl
(set-repl-handler! '(python-mode python-ts-mode) #'+python/open-repl
:persist t
:send-region #'python-shell-send-region
:send-buffer #'python-shell-send-buffer)
(set-docsets! '(python-mode inferior-python-mode) "Python 3" "NumPy" "SciPy" "Pandas")
(set-ligatures! 'python-mode
(set-docsets! '(python-mode python-ts-mode inferior-python-mode)
"Python 3" "NumPy" "SciPy" "Pandas")
(set-ligatures! '(python-mode python-ts-mode)
;; Functional
:def "def"
:lambda "lambda"
@ -62,7 +72,7 @@
(string= python-shell-interpreter "python"))
(setq python-shell-interpreter "python3"))
(add-hook! 'python-mode-hook
(add-hook! '(python-mode-hook python-ts-mode-hook)
(defun +python-use-correct-flycheck-executables-h ()
"Use the correct Python executables for Flycheck."
(let ((executable python-shell-interpreter))
@ -86,14 +96,25 @@
(advice-add #'pythonic-activate :after-while #'+modeline-update-env-in-all-windows-h)
(advice-add #'pythonic-deactivate :after #'+modeline-clear-env-in-all-windows-h))
(setq-hook! 'python-mode-hook tab-width python-indent-offset))
;; HACK: `python-mode' doesn't update `tab-width' to reflect
;; `python-indent-offset', causing issues anywhere `tab-width' is respected.
(setq-hook! '(python-mode-hook python-ts-mode-hook) tab-width python-indent-offset)
;; HACK: `python-ts-mode' changes `auto-mode-alist' and
;; `interpreter-mode-alist' every time the mode is activated, which runs the
;; risk of overwriting user (or Doom) entries.
;; REVIEW: Should be addressed upstream.
(defadvice! +python--undo-ts-side-effects-a (fn &rest args)
:around #'python-ts-mode
(let (auto-mode-alist interpreter-mode-alist)
(apply fn args))))
(use-package! pyimport
:defer t
:init
(map! :after python
:map python-mode-map
:map python-base-mode-map
:localleader
:prefix ("i" . "imports")
:desc "Insert missing imports" "i" #'pyimport-insert-missing
@ -105,12 +126,13 @@
:defer t
:init
(map! :after python
:map python-mode-map
:map python-base-mode-map
:localleader
(:prefix ("i" . "imports")
:desc "Sort imports" "s" #'py-isort-buffer
:desc "Sort region" "r" #'py-isort-region)))
(use-package! nose
:commands nose-mode
:preface (defvar nose-mode-map (make-sparse-keymap))
@ -138,7 +160,7 @@
:init
(map! :after python
:localleader
:map python-mode-map
:map python-base-mode-map
:prefix ("t" . "test")
"a" #'python-pytest
"f" #'python-pytest-file-dwim
@ -157,7 +179,7 @@
:hook (python-mode . pipenv-mode)
:init (setq pipenv-with-projectile nil)
:config
(set-eval-handler! 'python-mode
(set-eval-handler! '(python-mode python-ts-mode)
'((:command . (lambda () python-shell-interpreter))
(:exec (lambda ()
(if-let* ((bin (executable-find "pipenv" t))
@ -165,7 +187,7 @@
(format "PIPENV_MAX_DEPTH=9999 %s run %%c %%o %%s %%a" bin)
"%c %o %s %a")))
(:description . "Run Python script")))
(map! :map python-mode-map
(map! :map python-base-mode-map
:localleader
:prefix ("e" . "pipenv")
:desc "activate" "a" #'pipenv-activate
@ -185,7 +207,8 @@
(add-hook 'pyvenv-post-activate-hooks #'+modeline-update-env-in-all-windows-h)
(add-hook 'pyvenv-pre-deactivate-hooks #'+modeline-clear-env-in-all-windows-h))
:config
(add-hook 'python-mode-local-vars-hook #'pyvenv-track-virtualenv)
(add-hook! '(python-mode-local-vars-hook python-ts-mode-local-vars-hook)
#'pyvenv-track-virtualenv)
(add-to-list 'global-mode-string
'(pyvenv-virtual-env-name (" venv:" pyvenv-virtual-env-name " "))
'append))
@ -199,7 +222,8 @@
(when (executable-find "pyenv")
(pyenv-mode +1)
(add-to-list 'exec-path (expand-file-name "shims" (or (getenv "PYENV_ROOT") "~/.pyenv"))))
(add-hook 'python-mode-local-vars-hook #'+python-pyenv-mode-set-auto-h)
(add-hook! '(python-mode-local-vars-hook python-ts-mode-local-vars-hook)
#'+python-pyenv-mode-set-auto-h)
(add-hook 'doom-switch-buffer-hook #'+python-pyenv-mode-set-auto-h))

View File

@ -8,6 +8,10 @@
(modulep! :tools tree-sitter))
"This module requires (:tools tree-sitter)")
(assert! (or (not (modulep! +tree-sitter))
(fboundp 'python-ts-mode))
"Can't find `python-ts-mode'; Emacs 29.1+ is required")
(if (not (or (executable-find "python")
(executable-find "python3")))
(error! "Couldn't find python in your PATH")

View File

@ -48,7 +48,6 @@
(org "https://github.com/milisims/tree-sitter-org" nil nil nil nil)
(perl "https://github.com/ganezdragon/tree-sitter-perl" nil nil nil nil)
(proto "https://github.com/mitchellh/tree-sitter-proto" nil nil nil nil)
(python "https://github.com/tree-sitter/tree-sitter-python" nil nil nil nil)
(r "https://github.com/r-lib/tree-sitter-r" nil nil nil nil)
(ruby "https://github.com/tree-sitter/tree-sitter-ruby" nil nil nil nil)
(rust "https://github.com/tree-sitter/tree-sitter-rust" nil nil nil nil)