Python-MLS (multi-line shell) is an Emacs minor mode for working directly with multi-line Python commands in the REPL. It builds on and automatically extends python-mode's inferior shell capabilities.
C-S-n/p
).Simply install python-MLS from this repository or MELPA, and use require
or use-package
to load it. To enable, arrange to have python-mls-mode
called on the inferior-python-mode
hook, e.g.:
(use-package python-mls
;; :custom
;; (python-mls-multiline-history-modifier '(meta shift))
:hook
(inferior-python-mode . python-mls-mode))
NOTE: The
python-mls-setup
function is no longer necessary, and was removed in v0.2.
You can start your shell however you normally do (e.g. C-c C-p
in a Python buffer, or M-x run-python
), and Python-MLS will activate.
Using python-MLS is simple: just enter the first of a multi-line statement at the (i)Python prompt, then editing as you would in a python buffer. Or hit C-j
to "build your own" multi-line statement. Hit S-Ret
or enter two final blank lines to send to python. Add shift to your up/down commands to skip through history multi-line blocks at a time.
You can disable python-MLS for future shells in one Emacs session with M-x python-mls-mode
in an enabled shell buffer.
Up
/Down
(or C-p
/C-n
): when on the last line in that direction, navigate history, otherwise move within multi-line statements. S-Up
/S-Down
(or C-S-p
/C-S-n
): skip through multi-line statements in command history without navigating inside them. To configure the modifier used, see python-mls-multiline-history-modifier
. S-Ret
or M-Ret
: send a multi-line statement from anywhere within it.Ret
after two blank lines at statement end: send the multi-line statement.C-j
: break an initial line into a multi-line command anywhere. C-r
/C-s
: Search backward/forward through command history. M-a
/M-e
/C-M-u
: (by default) python-nav bindings for backward-, forward-block and up-list are brought over from python mode. See python-mls-import-python-nav-command-list
to add more. C-d
: send EOF, if at a prompt at the end of the buffer. A few options are available for configuration, including whether and where to save multi-line command history, whether to kill the window after the Python process quits, and which navigation commands to bring over from python-mode. To configure, use M-x customize-group [Ret] python-mls
.
How does Python-MLS work? It looks for the normal continuation prompt (e.g. ...
) in (i)Python's output, and if found, quietly interrupts the process, removes the partial command from the history, and starts a "native" emacs continued statement. On continued lines, it uses a computed line prefix which matches your prompt. Importantly, the prefixes added are only decoration, and are not in the actual text, so it is easy to select, navigate, kill, yank and operate on multi-line statements just as you would in a normal python-mode buffer.
How else can you make a multi-line statement? You can break any line at any time with C-j
. So a multi line-statement like the following is perfectly allowable:
>>> x=1[C-j]
... y=2[C-j]
... z=3[S-Ret]
Copy and paste? Just try it. Python-MLS configures python-mode to strip out the ...
decorative line prefixes on yank, and it adds them back in automatically when copying text from elsewhere into the shell.
How does this differ from iPython's native multi-line input capability? iPython's multi-line input was a source of inspiration for python-MLS, but it differs in a few ways:
How do you skip over entire multi-line statements in history without having to move all the way through them? Try holding Shift: S-up
,S-down
(or C-S-n/p
).
Why does python-MLS do fontification? By default, inferior-python-mode copies the full input text at the prompt back and forth from the inferior shell to a hidden Python buffer, and fully refontifies it there after every keypress. With short, single-line statements this isn't such a problem, but with long multi-line input this becomes highly inefficient. Python-MLS replaces this method entirely with a special in-buffer fontification function, that does double duty, both adding the continuation line prefix decorations (e.g. ...
) and performing default python-mode fontification on just the input, all in one efficient pass. This also increases performance and saves the creation of random fontification buffers.
My py-XXX functions aren't working! There are two popular packages providing python-mode for source buffers and the shell. python-MLS makes use of the built-in python.el version, as opposed to the MELPA package. Either can be used in the python buffer with python-MLS. But if you use the non-builtin python-mode, you'll have to ensure the python.el shell is run.
Any other tips?
comint
(which most Emacs inferior shells use):
C-c C-u
: comint-kill-input
C-c C-o
: comint-kill-output
C-c M-o
: comint-clear-buffer
python-mls-import-python-nav-command-list
to add more.