Files
emacs/settings/python-settings.el
2024-05-06 16:50:56 +02:00

219 lines
8.9 KiB
EmacsLisp
Raw Blame History

This file contains invisible Unicode characters
This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
;;; python-settings.el --- Python settings -*- mode: emacs-lisp; lexical-binding: t -*-
;;; Commentary:
;; Requirements:
;; program: python
;; Emacs packages: anaconda-mode company-anaconda sphinx-doc
;; Language Server Support, Emacs built-in package `eglot'
;; https://github.com/joaotavora/eglot
;; connects to LSP
;; activate with `eglot'
;; after changing configurations run `eglot-reconnect'
;; follow documentation at point `eldoc-doc-buffer'
;; Language Server Protocol (LSP), python package `python-lsp-server'
;; https://github.com/python-lsp/python-lsp-server
;; install via: pip install "python-lsp-server[all]"
;; arch linux: extra/python-lsp-server
;; - pycodestyle (formerly called pep8) - Python style guide checker
;; https://pycodestyle.pycqa.org/en/latest/
;; arch linux: extra/python-pycodestyle
;; to ignore a check in a code line use # noqa
;; config via ~/.config/pycodestyle
;; - pylsp-mypy: pylsp plugin, type checking for Python >=3.8
;; https://mypy-lang.org/
;; pip install pylsp-mypy
;; arch linux: aur/python-pylsp-mypy
;; Syntax Checking, Emacs built-in package `flymake'
;;; Code:
(use-package python
:delight (python-mode "Py") ;; "Py " "\u1F15F"
:commands (python-mode)
:bind (:map python-mode-map
;; swap C-u C-c C-c with C-c C-c, so C-c C-c sends __main__
("C-c C-c" . my-python-shell-send-buffer-w-main)
("C-u C-c C-c" . my-python-shell-send-buffer)
("M-m m c c" . my-python-execute-file)
("M-m m c C" . my-python-execute-file-switch)
("M-m m s b" . my-python-shell-send-buffer-w-main))
:config
(setq python-indent-offset 2) ; python-indent is obsolete since 24.3; use python-indent-offset instead.
(setq python-indent-guess-indent-offset nil) ; default t. nil to use the config value python-indent-offset
(setq python-indent-guess-indent-offset-verbose nil) ; hide message like: Cant guess python-indent-offset, using defaults: 2
;;(setq python-shell-interpreter "ipython")
;;(setq python-shell-interpreter-args "-i")
(defun my-pyenv-executable-find (command)
"Find executable taking pyenv shims into account.
If the executable is a system executable and not in the same path
as the pyenv version then also return nil. This works around https://github.com/pyenv/pyenv-which-ext
"
(if (executable-find "pyenv")
(progn
(let ((pyenv-string (shell-command-to-string (concat "pyenv which " command)))
(pyenv-version-names (split-string (string-trim (shell-command-to-string "pyenv version-name")) ":"))
(executable nil)
(i 0))
(if (not (string-match "not found" pyenv-string))
(while (and (not executable)
(< i (length pyenv-version-names)))
(if (string-match (elt pyenv-version-names i) (string-trim pyenv-string))
(setq executable (string-trim pyenv-string)))
(if (string-match (elt pyenv-version-names i) "system")
(setq executable (string-trim (executable-find command))))
(setq i (1+ i))))
executable))
(executable-find command)))
(defun my-python-execute-file (arg)
"Execute a python script in a shell."
(interactive "P")
;; set compile command to buffer-file-name
;; universal argument put compile buffer in comint mode
(let ((universal-argument t)
(compile-command (format "%s %s"
(my-pyenv-executable-find python-shell-interpreter)
(shell-quote-argument (file-name-nondirectory buffer-file-name)))))
(if arg
(call-interactively 'compile)
(compile compile-command t)
(with-current-buffer (get-buffer "*compilation*")
(inferior-python-mode)))))
(defun my-python-execute-file-switch (arg)
"Execute a python script in a shell and switch to the shell buffer in `insert state'."
(interactive "P")
(my-python-execute-file arg)
(switch-to-buffer-other-window "*compilation*")
(end-of-buffer)
(evil-insert-state))
(defun my-python-shell-send-buffer (&optional send-main)
"Send buffer content to shell."
(interactive)
(let ((python-mode-hook nil)) ;; TODO: why?
(python-shell-send-buffer send-main)))
(defun my-python-shell-send-buffer-w-main ()
"Send buffer content to shell with main."
(interactive)
(my-python-shell-send-buffer t))
(defadvice run-python
(after my-advice-run-python activate)
"set flag to allow exit without query on any active python
process."
(set-process-query-on-exit-flag ad-return-value nil))
(defun my-python-shell-send-buffer-w-args (args)
"Send buffer content to shell with main and arguments."
(interactive "sPython arguments: ")
(let ((source-buffer (current-buffer)))
(with-temp-buffer
(insert "import sys; sys.argv = '''" args "'''.split()\n")
(insert-buffer-substring source-buffer)
(my-python-shell-send-buffer-w-main))))
)
;; needs system package python-jedi
;; (use-package anaconda-mode ;; works with company-mode via company-anaconda
;; :after python
;; :delight (anaconda-mode "A") ;; \u24B6 a
;; :bind (([remap anaconda-mode-show-doc] . my-anaconda-mode-show-doc)) ;; M-?
;; :hook (python-mode
;; (python-mode . anaconda-eldoc-mode)) ;; if cursor is between function's parenthesis show parameter in echo area
;; :config
;; (setq anaconda-mode-installation-directory (concat user-cache-directory "anaconda-mode"))
;; ;; compared to `anaconda-mode-show-doc' using `my-anaconda-mode-show-doc-callback'
;; (defun my-anaconda-mode-show-doc ()
;; "Show documentation for context at point."
;; (interactive)
;; ;;(anaconda-mode-call "show_doc" 'anaconda-mode-show-doc-callback) ;; removed
;; (anaconda-mode-call "show_doc" 'my-anaconda-mode-show-doc-callback) ;; instead
;; )
;; ;; compared to `anaconda-mode-show-doc-callback' no change of focus
;; (defun my-anaconda-mode-show-doc-callback (result)
;; "Process view doc RESULT."
;; (if (> (length result) 0)
;; (if (and anaconda-mode-use-posframe-show-doc
;; (require 'posframe nil 'noerror)
;; (posframe-workable-p))
;; (anaconda-mode-documentation-posframe-view result)
;; ;;(pop-to-buffer (anaconda-mode-documentation-view result) t) ;; removed
;; (anaconda-mode-documentation-view result) ;; instead
;; )
;; (message "No documentation available")))
;; )
;; (use-package company-anaconda
;; :after (python anaconda-mode company)
;; :bind (([remap anaconda-mode-complete] . company-anaconda))
;; :config
;; (add-to-list 'company-backends '(company-anaconda :with company-capf))) ;; to see anaconda-mode completions together with ones comes from inferior python process
;; https://melpa.org/#/sphinx-doc
;; https://github.com/naiquevin/sphinx-doc.el
;; enable the sphinx-doc-mode and bind the interactive function sphinx-doc to C-c M-d.
(use-package sphinx-doc
:delight (sphinx-doc-mode "Sph") ;; \u24C8 s
:hook (python-mode . sphinx-doc-mode))
;; jupyter repl
;; optional markdown-mode
;; optional company-mode
;; emacs-websocket
;; simple-httpd
;; zmq
(use-package jupyter
:commands (;; launch a new local kernel and displays a REPL buffer
jupyter-run-repl
;; connect to an existing kernel using the kernels connection
;; file, which is supplied by the user, and displays a REPL buffer
jupyter-connect-repl
;; associate the buffer to an existing emacs-jupyter REPL or create a new one choosing the appropriate Jupyter kernel
jupyter-repl-associate-buffer)
:init
(setq jupyter-use-zmq nil)
:config
(add-to-list 'org-structure-template-alist '("py" . "src jupyter-python"))
;; emacs-jupyter will always use the Python kernel found on startup
(defun my-jupyter-refresh-kernelspecs ()
"Refresh Jupyter kernelspecs"
(interactive)
(jupyter-available-kernelspecs t))
)
;; https://github.com/astoff/code-cells.el
;; .ipynb
(use-package code-cells
:commands (code-cells-mode code-cells-convert-ipynb)
;;:mode ("\\.ipynb\\'" . code-cells-mode)
:hook (code-cells-mode . code-cells-convert-ipynb)
:config
(setq code-cells-convert-ipynb-style '(("pandoc" "--to" "ipynb" "--from" "org")
("pandoc" "--to" "org" "--from" "ipynb")
(lambda () #'org-mode)))
)
(use-package ox-ipynb
:after ox)
;; https://millejoh.github.io/emacs-ipython-notebook/
;; requires: anaphora dash deferred polymode request websocket with-editor
(use-package ein
:commands (ein:run ein:jupyter-server-start ein:notebooklist-open)
:config
(require 'ein-jupyter)
(require 'ein-notebook)
(setq ein:output-area-inlined-images t))
(provide 'python-settings)
;;; python-settings.el ends here