vale981 / py-vterm-interaction.el

A simple vterm-based mode for an inferior (i)Python REPL process in Emacs
GNU General Public License v3.0
23 stars 0 forks source link

-- eval: (visual-line-mode 1) --

+STARTUP: showall

[[https://melpa.org/#/py-vterm-interaction][file:https://melpa.org/packages/py-vterm-interaction-badge.svg]]

This is a port of [[https://github.com/shg/julia-vterm.el][julia-vterm.el]] with some modification to deal with python (virtual) environments and play nicely with =ipython= and the like.

Some advantages over the built-in python interaction is the ability to run ~ipython~ with it's fancy prompt and make use of ~spyder~-like code cells (see below) or running the current function.

See also [[https://github.com/shg/python-vterm.el][the original author's efforts]].

The functionalities required for typical REPL interaction have been implemented. While I would like to keep this package simple, suggestions are always welcome.

It is automatically detected whether the repl runs =ipython= or another interpreter and some functions use different functionalities based on that information. ** Installation The package is on melpa and depends on ~vterm~ and ~python.el~. The simplest way to install the package is through ~use-package~:

+begin_src elisp

(use-package py-vterm-interaction :hook (python-mode . py-vterm-interaction-mode) :config ;;; Suggested: ;; (setq-default py-vterm-interaction-repl-program "ipython") ;; (setq-default py-vterm-interaction-silent-cells t) )

+end_src

For manual installation, download =py-vterm-interaction.el= into somewhere in your local directory and use =package-install-file= command. Please make sure [[https://github.com/PythonEditorSupport/python-emacs][python-mode]] and [[https://github.com/akermu/emacs-libvterm][emacs-libvterm]] are installed and configured correctly.

Turn on =py-vterm-interaction-mode= in a =python-mode= buffer to use this package. A symbol “PY” in the mode line indicates that the python-mode buffer is ready to interact with the py-vterm-interaction REPL. Add the following line to your init file to enable =py-vterm-interaction-mode= in =python-mode= buffers automatically.

+BEGIN_SRC emacs-lisp

(add-hook 'python-mode-hook #'py-vterm-interaction-mode)

+END_SRC

By default, the command named =python= in your =PATH= is used. You can use a Python executable in any path by setting the =py-vterm-interaction-repl-program= variable to its absolute path. The variable can contain switches for the =python= command. For example, you can use a =python= executable at a certain path, with 4 threads enabled, by the line like the following.

+BEGIN_SRC emacs-lisp

(setq-default py-vterm-interaction-repl-program "ipython -i")

+END_SRC

Some commands (see below) can either paste code into the REPL verbatim or include it using ~%run -i~. If ~py-vterm-interaction-silent-cells~ is set to ~t~

+begin_src emacs-lisp

(setq-default py-vterm-interaction-silent-cells t)

+end_src

the latter option will be used.

** How to use

=M-x py-vterm-interaction-repl= (or =M-x python= if no other packages define it before py-vterm-interaction is loaded) opens an inferior Python REPL buffer.

In a python script buffer with =py-vterm-interaction-mode= on, you can open a Python REPL with =M-x py-vterm-interaction-switch-to-repl-buffer= (or =C-c C-z=). See below for other commands.

Both of the above operations open a REPL with the default session name =main=. You can specify a different session name by using the prefix argument =C-u=. A new session will be created and opened if there is no REPL with that session name.

You can also specify a session name by defining a file local variable =py-vterm-interaction-session= (or =python-session= if no other packages pre-define it). If the variable is defined, =C-c C-z= will open a REPL with that session name.

The package also contains a clone of [[https://docs.spyder-ide.org/3/editor.html#defining-code-cells][spyder]]'s code cells. Consider the following:

+begin_src python

print("block 1")

%%

print("block 2")

%%

print("block 3")

+end_src

Moving the point between any two cell markers (or between the buffer beginning/end and a marker) and executing ~py-vterm-interaction-send-current-cell~ (=C-c C-j=) will send the contents of the block to the REPL. When setting ~py-vterm-interaction-silent-cells~ to ~t~, the cell content is written to a temporary file which is then executed in the REPL with the ~%run~ magic command.

Similarly, one can load the current function into the REPL and automatically call it if it has no arguments. Consider the following:

+begin_src python

... some code

def run_some_test():

some computation

  print("hi")

+end_src

Moving the point inside of ~run_some_test~ and executing ~py-vterm-interaction-run-current-function~ (=C-c C-f=) will load the function into the REPL and execute it. For a function with arguments like

+begin_src python

... some code

def run_some_test(arg):

some computation

  print("hi")

+end_src

the function name and an opening parenthesis will be pasted into the reply.

** Key bindings

*** py-vterm-interaction-mode

+begin_example

Key Command / Description

C-c C-z py-vterm-interaction-switch-to-repl-buffer Switch to the paired REPL buffer or to the one with a specified session name. With prefix ARG, prompt for session name.

C-c C-c py-vterm-interaction-send-region-or-current-line Send the content of the region if the region is active, or send the current line.

C-c C-b py-vterm-interaction-send-buffer Send the whole content of the script buffer to the Python REPL line by line.

C-c C-j py-vterm-interaction-send-current-cell Send the current code "cell" to the Python REPL. Each block is delimited by # %% <optional name>.

        If no marker is present before the point, the cell is assumed to
        begin with the buffer. Likewise, if there is no marker after the
        point, the cell is assumed to end with the buffer.

C-c C-f py-vterm-interaction-run-current-function Send the current function the Python REPL and paste its name, ready to run. If the function has no arguments, the function call is run immediately.

C-c C-r py-vterm-interaction-send-run-buffer-file Send a line to evaluate the buffer's file using ipython %run magic.

C-c C-i Import the current buffer file like from <module> import *' in the python repl. This is especially useful with%autoload 3' in ipython.

C-c C-d py-vterm-interaction-send-cd-to-buffer-directory Send %cd function call to the Python REPL to change the current working directory of REPL to the buffer's directory.

+end_example

*** py-vterm-interaction-repl-mode

+begin_example

Key Command / Description

C-c C-z py-vterm-interaction-repl-switch-to-script-buffer Switch to the script buffer that is paired with the current Python REPL buffer.

M-k py-vterm-interaction-repl-clear-buffer Clear the content of the Python REPL buffer.

C-c C-t py-vterm-interaction-repl-copy-mode Enter copy mode.

C-c M-r py-vterm-interaction-repl-restart Restart the current inferior Python process. A new Python REPL will be opened in the same Emacs window, and the working directory and environment will be restored from the previous REPL process when possible.

+end_example

*** py-vterm-interaction-repl-mode (copy mode)

+begin_example

Key Command / Description

C-c C-t py-vterm-interaction-repl-copy-mode Exit copy mode.

py-vterm-interaction-repl-copy-mode-done Copy the region to the kill ring and exit copy mode. C-c C-r vterm-reset-cursor-point Call the vterm command that moves point to where it should be. #+end_example * Roadmap ** TODO fix the automatic return - most commands should accept a prefix that control whether the code is exectued with == or just pasted into the repl ** TODO make an =in-repl-buffer= macro ** TODO make run-current-function a bit more intelligent - detect if there are only arguments with default values