;;; python-settings.el --- Python settings -*- mode: emacs-lisp; lexical-binding: t -*- ;;; Commentary: ;; Requirements: ;; program: python ;; Emacs packages: anaconda-mode company-anaconda sphinx-doc ;;; Code: (use-package python :delight (python-mode "🅟") ;; "Py " :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: Can’t 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)))) ) (use-package anaconda-mode ;; works with company-mode via company-anaconda :after python :delight (anaconda-mode "Ⓐ") ;; Ⓐ 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 "Ⓢ") ;; Ⓢ s :hook (python-mode . sphinx-doc-mode)) (provide 'python-settings) ;;; python-settings.el ends here