144 lines
6.2 KiB
EmacsLisp
144 lines
6.2 KiB
EmacsLisp
;;; 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
|
||
:load-path (lambda() (concat config-dir "lisp/anaconda-mode"))
|
||
: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
|