From be94fe93ea947e18723a99c9e28fe3c9c070493b Mon Sep 17 00:00:00 2001 From: Gerard Vermeulen Date: Sun, 13 Feb 2022 15:10:23 +0100 Subject: [PATCH] Program the pyenv-mode facilities myself --- README.org | 109 ++++++++++++++++++++++++++++++++++++++++++++--------- 1 file changed, 92 insertions(+), 17 deletions(-) diff --git a/README.org b/README.org index 08e618b..29b40b5 100644 --- a/README.org +++ b/README.org @@ -219,7 +219,6 @@ the ~custom-file~ as [[info:emacs#Saving Customizations][saving customizations ( orderless ; Emacs completion style pdf-tools ; interactive docview replacement pdf-view-restore ; add view history to pdf-tools - pyenv-mode ; Python environment selector quelpa ; install Emacs packages from source rainbow-mode ; set background color to color string sly ; Sylvester the Cat's Common Lisp IDE @@ -2240,7 +2239,17 @@ server, before plunging into the configuring steps: :CUSTOM_ID: sec:python-mode :END: Listing [[lst:configure-python]] tells the Python shell to disregard its environment -variables (in particular =PYTHONSTARTUPFILE=). +variables (in particular =PYTHONSTARTUPFILE=). The [[https://github.com/pythonic-emacs/pythonic#readme][pythonic]] and [[https://github.com/jorgenschaefer/pyvenv#readme][pyvenv]] packages +provide support to handle Python virtual environments within Emacs. The [[https://github.com/pyenv/pyenv][pyenv]] +package provides support to work with [[https://github.com/pyenv/pyenv#readme][pyenv]] (eventually with [[https://github.com/pyenv/pyenv-virtualenv#readme][pyenv-virtualenv]]) +to select between different python versions (eventually each with different +environments). In the end, all those packages do is to set +=python-shell-virtualenv-root= (in case of [[https://github.com/pyenv/pyenv#readme][pyenv]] and [[https://github.com/pythonic-emacs/pythonic#readme][pythonic]]) and tweak the +environment variables and restart the relevant Python child processes (in case +of [[https://github.com/jorgenschaefer/pyvenv#readme][pyvenv]]). Therefore, this setup replaces those packages with listing +[[lst:manage-pyenv]] to manage [[https://github.com/pyenv/pyenv#readme][pyenv]] from within Emacs and listing +[[lst:setting-python-shell-virtualenv-root]] to set +=python-shell-virtualenv-root=. #+caption[Configure =python=]: #+caption: Configure =python=. @@ -2252,22 +2261,88 @@ variables (in particular =PYTHONSTARTUPFILE=). '(python-shell-interpreter-args "-i -E"))) #+end_src -*** [[https://github.com/pyenv/pyenv][Pyenv]] -:PROPERTIES: -:CUSTOM_ID: sec:pyenv -:END: -Listing [[lst:enable-pyenv-mode]] configures and enables =pyenv-mode=. - -#+caption[Enable =pyenv-mode=]: -#+caption: Enable =pyenv-mode=. -#+name: lst:enable-pyenv-mode +#+caption[Manage =pyenv=]: +#+caption: Manage =pyenv=. +#+name: lst:manage-pyenv #+begin_src emacs-lisp - (when (and (executable-find "pyenv") - (require 'pyenv-mode nil 'noerror)) - (pyenv-mode +1) - (pyenv-mode-set "3.9.10/envs/python-3.9.10") - ;; Stop shadowing the org-mode-map "C-c C-s" binding. - (define-key pyenv-mode-map (kbd "C-c C-s") nil)) + (when (executable-find "pyenv") + (defun pyenv-full-path (version) + "Return the full path for VERSION." + (unless (string= version "system") + (concat (pyenv-root) (file-name-as-directory "versions") version))) + + (defun pyenv-root () + "Return \"pyenv root\" as a directory." + (cl-destructuring-bind (exit-code output) + (shell-command-with-exit-code "pyenv" "root") + (if (= 0 exit-code) (file-name-as-directory (string-trim output)) + (error "%s" (string-trim output))))) + + (defun pyenv-version-name () + "Return \"pyenv version-name\"." + (cl-destructuring-bind (exit-code output) + (shell-command-with-exit-code "pyenv" "version-name") + (if (= 0 exit-code) (string-trim output) + (error "%s" (string-trim output))))) + + (defun pyenv-versions () + "Return \"pyenv versions --bare --skip-aliases\" as a list. + Complete the result with \"system\"." + (cl-destructuring-bind (exit-code output) + (shell-command-with-exit-code + "pyenv" "versions" "--bare" "--skip-aliases") + (if (= 0 exit-code) (cons "system" (split-string output)) + (error "%s" (string-trim output))))) + + (defun pyenv-virtualenvs () + "Return \"pyenv virtualenvs --bare --skip-aliases\" as a list." + (cl-destructuring-bind (exit-code output) + (shell-command-with-exit-code + "pyenv" "virtualenvs" "--bare" "--skip-aliases") + (if (= 0 exit-code) (split-string output) + (error "%s" (string-trim output)))))) +#+end_src + +#+caption[Setting =python-shell-virtualenv-root=]: +#+caption: Setting =python-shell-virtualenv-root=. +#+name: lst:setting-python-shell-virtualenv-root +#+begin_src emacs-lisp + (with-eval-after-load 'python + (when (cl-every #'fboundp '(pyenv-full-path + pyenv-version-name + pyenv-versions + pyenv-virtualenvs)) + (setq python-shell-virtualenv-root + (pyenv-full-path (or (car (pyenv-virtualenvs)) + (car (pyenv-versions))))) + (message "Now `python-shell-virtualenv-root' equals \"%s\"" + python-shell-virtualenv-root) + + (defun set-python-shell-virtualenv-root-to-pyenv-version () + "Set `python-shell-virtual-env-root' to a pyenv version." + (interactive) + (let* ((version-name (pyenv-version-name)) + (prompt (format "pyenv version (%s): " version-name)) + (choices (pyenv-versions)) + (version (completing-read prompt choices nil 'require-match))) + (unless (string= version-name version) + (setq python-shell-virtualenv-root (pyenv-full-path version)) + (setenv "PYENV_VERSION" version)) + (message "Now `python-shell-virtualenv-root' equals \"%s\"" + python-shell-virtualenv-root))) + + (defun set-python-shell-virtualenv-root-to-pyenv-virtualenv () + "Set `python-shell-virtual-env-root' to a pyenv virtualenv." + (interactive) + (let* ((version-name (pyenv-version-name)) + (prompt (format "pyenv virtualenv (%s): " version-name)) + (choices (pyenv-virtualenvs)) + (version (completing-read prompt choices nil 'require-match))) + (unless (string= version-name version) + (setq python-shell-virtualenv-root (pyenv-full-path version)) + (setenv "PYENV_VERSION" version)) + (message "Now `python-shell-virtualenv-root' equals \"%s\"" + python-shell-virtualenv-root))))) #+end_src *** [[https://github.com/joaotavora/eglot][Eglot]]