{"id":21291680,"url":"https://github.com/jdtsmith/python-mls","last_synced_at":"2025-03-15T16:34:29.172Z","repository":{"id":45344360,"uuid":"410340020","full_name":"jdtsmith/python-mls","owner":"jdtsmith","description":"Multi-line Shell Commands for Python REPLs in Emacs","archived":false,"fork":false,"pushed_at":"2024-06-21T21:14:40.000Z","size":213,"stargazers_count":40,"open_issues_count":0,"forks_count":3,"subscribers_count":4,"default_branch":"main","last_synced_at":"2025-01-22T06:24:07.017Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":null,"language":null,"has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"agpl-3.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/jdtsmith.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2021-09-25T17:35:44.000Z","updated_at":"2024-06-21T21:14:43.000Z","dependencies_parsed_at":"2024-06-22T12:47:10.083Z","dependency_job_id":"16f6a38e-0623-4fb6-ad92-2ac121b0408f","html_url":"https://github.com/jdtsmith/python-mls","commit_stats":null,"previous_names":[],"tags_count":10,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/jdtsmith%2Fpython-mls","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/jdtsmith%2Fpython-mls/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/jdtsmith%2Fpython-mls/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/jdtsmith%2Fpython-mls/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/jdtsmith","download_url":"https://codeload.github.com/jdtsmith/python-mls/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":243760576,"owners_count":20343655,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2024-11-21T13:39:10.333Z","updated_at":"2025-03-15T16:34:29.146Z","avatar_url":"https://github.com/jdtsmith.png","language":null,"funding_links":[],"categories":[],"sub_categories":[],"readme":"# python-MLS: multi-line Python shell commands in Emacs\n\n\u003cimg src=\"https://user-images.githubusercontent.com/93749/134784188-7ac9ee9d-8e29-4c7f-82d7-2881e96d4bd2.gif\"\u003e\n\nPython-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.\n\n# Features:\n\n- Works with both python and ipython.\n- Arbitrary command lengths.\n- Auto-detects and handles native continuation prompts.\n- Auto-indents multi-line commands.\n- Normal emacs and python editing commands work (e.g. tab to cycle indent).\n- Replaces python-mode's external buffer fontifications with in-buffer\n  fontification for signficant speedup on long multi-line input statements.\n- Up/Down arrow history browsing with and without block movement\n  (try shift arrow, or `C-S-n/p`).\n- Saves and restore (multi-line) command history, per interpreter.\n- Directly kill and yank multi-line code blocks to \u0026 from Python\n  buffers, websites, etc..\n  \n# Installation\n\nSimply 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.:\n\n```elisp\n(use-package python-mls\n  ;; :custom\n  ;; (python-mls-multiline-history-modifier '(meta shift))\n  :hook\n  (inferior-python-mode . python-mls-mode))\n```\n\n---\n\u003e **_NOTE:_** The `python-mls-setup` function is no longer necessary, and was removed in v0.2.\n---\n\nYou 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.\n\n# Usage\n\nUsing 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. \n\nYou can disable python-MLS for _future_ shells in one Emacs session with `M-x python-mls-mode` in an enabled shell buffer. \n\n# Keys\n\n- `Up`/`Down` (or `C-p`/`C-n`): when on the last line in that direction, navigate history, otherwise move _within_ multi-line statements. \n-  `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`. \n- `S-Ret` or `M-Ret`: send a multi-line statement from anywhere within it.\n-  `Ret` after _two_ blank lines at statement end: send the multi-line statement.\n- `C-j`: break an initial line into a multi-line command anywhere. \n- `C-r`/`C-s`: Search backward/forward through command history. \n- `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. \n- `C-d`: send EOF, if at a prompt at the end of the buffer. \n\n# Config\n\nA 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`. \n\n# FAQs\n\n- **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.\n\n- **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:\n  ```\n  \u003e\u003e\u003e x=1[C-j]\n  ... y=2[C-j]\n  ... z=3[S-Ret]\n  ```\n\n- **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.\n\n- **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: \n\n  1. iPython evaluates each line of a multi-line statement as it gets inputed, and checks for syntax errors line by line, whereas python-MLS lets you edit and then sends the complete block _en masse_ at the end, so any errors will appear at that point.  \n  3. Python-MLS lets you move and edit right across lines using normal emacs commands (even python navigation commands), whereas iPython treats each line as a separate entity you can access via up/down arrow _only_.  As a result, editing python-MLS multi-line commands feels just about like editing code in a source buffer. \n\n- **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`).\n\n- **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.\n\n- **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](https://melpa.org/#/python-mode).  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.  \n\n- **Any other tips?**  \n   - Get to know the useful commands provided by `comint` (which most Emacs inferior shells use): \n     - `C-c C-u`: `comint-kill-input`\n     - `C-c C-o`: `comint-kill-output`\n     - `C-c M-o`: `comint-clear-buffer`\n     - and more.\n   - Python-MLS binds a few keyboard shortcuts for python navigation for use after the prompt. See `python-mls-import-python-nav-command-list` to add more. \n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fjdtsmith%2Fpython-mls","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fjdtsmith%2Fpython-mls","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fjdtsmith%2Fpython-mls/lists"}