+ :popup -> set-popup-rule! + :popups -> set-popup-rules! + :company-backend -> set-company-backend! + :evil-state -> set-evil-initial-state! I am slowly phasing out the setting system (def-setting! and set!), starting with these. What are autodefs? These are functions that are always defined, whether or not their respective modules are enabled. However, when their modules are disabled, they are replaced with macros that no-op and don't waste time evaluating their arguments. The old set! function will still work, for a while.
135 lines
4.9 KiB
EmacsLisp
135 lines
4.9 KiB
EmacsLisp
;;; lang/python/config.el -*- lexical-binding: t; -*-
|
|
|
|
(defvar +python-pyenv-root nil
|
|
"The path to pyenv's root directory. This is automatically set when `python'
|
|
is loaded.")
|
|
|
|
(defvar +python-pyenv-versions nil
|
|
"Available versions of python in pyenv.")
|
|
|
|
(defvar-local +python-current-version nil
|
|
"The currently active pyenv version.")
|
|
|
|
|
|
;;
|
|
;; Plugins
|
|
;;
|
|
|
|
(def-package! python
|
|
:defer t
|
|
:init
|
|
(setq python-environment-directory doom-cache-dir
|
|
python-indent-guess-indent-offset-verbose nil
|
|
python-shell-interpreter "python")
|
|
:config
|
|
(add-hook! 'python-mode-hook #'(flycheck-mode highlight-numbers-mode))
|
|
|
|
(set! :env "PYTHONPATH" "PYENV_ROOT")
|
|
(set! :electric 'python-mode :chars '(?:))
|
|
(set! :repl 'python-mode #'+python/repl)
|
|
|
|
(when (executable-find "ipython")
|
|
(setq python-shell-interpreter "ipython"
|
|
python-shell-interpreter-args "-i --simple-prompt --no-color-info"
|
|
python-shell-prompt-regexp "In \\[[0-9]+\\]: "
|
|
python-shell-prompt-block-regexp "\\.\\.\\.\\.: "
|
|
python-shell-prompt-output-regexp "Out\\[[0-9]+\\]: "
|
|
python-shell-completion-setup-code
|
|
"from IPython.core.completerlib import module_completion"
|
|
python-shell-completion-string-code
|
|
"';'.join(get_ipython().Completer.all_completions('''%s'''))\n"))
|
|
|
|
;; Version management with pyenv
|
|
(defun +python|add-version-to-modeline ()
|
|
"Add version string to the major mode in the modeline."
|
|
(setq mode-name
|
|
(if +python-current-version
|
|
(format "Python %s" +python-current-version)
|
|
"Python")))
|
|
(add-hook 'python-mode-hook #'+python|add-version-to-modeline)
|
|
|
|
(if (not (executable-find "pyenv"))
|
|
(setq +python-current-version (string-trim (shell-command-to-string "python --version 2>&1 | cut -d' ' -f2")))
|
|
(setq +python-pyenv-root (string-trim (shell-command-to-string "pyenv root"))
|
|
+python-pyenv-versions (split-string (shell-command-to-string "pyenv versions --bare") "\n" t))
|
|
|
|
(defun +python|detect-pyenv-version ()
|
|
"Detect the pyenv version for the current project and set the relevant
|
|
environment variables."
|
|
(when-let* ((version-str (shell-command-to-string "python --version 2>&1 | cut -d' ' -f2")))
|
|
(setq version-str (string-trim version-str)
|
|
+python-current-version version-str)
|
|
(let ((pyenv-current-path (concat +python-pyenv-root "/versions/" version-str)))
|
|
(when (file-directory-p pyenv-current-path)
|
|
(setq pythonic-environment pyenv-current-path)))
|
|
(when (member version-str +python-pyenv-versions)
|
|
(setenv "PYENV_VERSION" version-str))))
|
|
(add-hook 'python-mode-hook #'+python|detect-pyenv-version))
|
|
|
|
(define-key python-mode-map (kbd "DEL") nil) ; interferes with smartparens
|
|
(sp-with-modes 'python-mode
|
|
(sp-local-pair "'" nil :unless '(sp-point-before-word-p sp-point-after-word-p sp-point-before-same-p))))
|
|
|
|
|
|
(def-package! anaconda-mode
|
|
:after python
|
|
:init
|
|
(setq anaconda-mode-installation-directory (concat doom-etc-dir "anaconda/")
|
|
anaconda-mode-eldoc-as-single-line t)
|
|
:config
|
|
(add-hook 'python-mode-hook #'anaconda-mode)
|
|
(add-hook 'anaconda-mode-hook #'anaconda-eldoc-mode)
|
|
(set-company-backend! 'python-mode '(company-anaconda))
|
|
(set-popup-rule! "^\\*anaconda-mode" nil '((select)))
|
|
(set! :lookup 'python-mode
|
|
:definition #'anaconda-mode-find-definitions
|
|
:references #'anaconda-mode-find-references
|
|
:documentation #'anaconda-mode-show-doc)
|
|
|
|
(defun +python|auto-kill-anaconda-processes ()
|
|
"Kill anaconda processes if this buffer is the last python buffer."
|
|
(when (and (eq major-mode 'python-mode)
|
|
(not (delq (current-buffer)
|
|
(doom-buffers-in-mode 'python-mode (buffer-list)))))
|
|
(anaconda-mode-stop)))
|
|
(add-hook! 'python-mode-hook
|
|
(add-hook 'kill-buffer-hook #'+python|auto-kill-anaconda-processes nil t))
|
|
|
|
(map! :map anaconda-mode-map
|
|
:localleader
|
|
:prefix "f"
|
|
:nv "d" #'anaconda-mode-find-definitions
|
|
:nv "h" #'anaconda-mode-show-doc
|
|
:nv "a" #'anaconda-mode-find-assignments
|
|
:nv "f" #'anaconda-mode-find-file
|
|
:nv "u" #'anaconda-mode-find-references))
|
|
|
|
|
|
(def-package! nose
|
|
:commands nose-mode
|
|
:preface
|
|
(defvar nose-mode-map (make-sparse-keymap))
|
|
:init
|
|
(associate! nose-mode :match "/test_.+\\.py$" :modes (python-mode))
|
|
:config
|
|
(set-popup-rule! "^\\*nosetests" '((size . 0.4)) '((select)))
|
|
(set! :yas-minor-mode 'nose-mode)
|
|
(map! :map nose-mode-map
|
|
:localleader
|
|
:prefix "t"
|
|
:n "r" #'nosetests-again
|
|
:n "a" #'nosetests-all
|
|
:n "s" #'nosetests-one
|
|
:n "v" #'nosetests-module
|
|
:n "A" #'nosetests-pdb-all
|
|
:n "O" #'nosetests-pdb-one
|
|
:n "V" #'nosetests-pdb-module))
|
|
|
|
|
|
;;
|
|
;; Evil integration
|
|
;;
|
|
|
|
(when (featurep! :feature evil +everywhere)
|
|
(add-hook! '(anaconda-mode-hook nose-mode-hook)
|
|
#'evil-normalize-keymaps))
|