{"id":23100753,"url":"https://github.com/p3r7/with-shell-interpreter","last_synced_at":"2025-08-16T14:31:58.406Z","repository":{"id":92560041,"uuid":"235450967","full_name":"p3r7/with-shell-interpreter","owner":"p3r7","description":":shell: Helper for Emacs shell command APIs","archived":false,"fork":false,"pushed_at":"2023-09-16T14:22:27.000Z","size":43,"stargazers_count":9,"open_issues_count":0,"forks_count":1,"subscribers_count":2,"default_branch":"master","last_synced_at":"2025-08-16T03:51:09.573Z","etag":null,"topics":["emacs-lisp","shell","terminal-emulator","tramp"],"latest_commit_sha":null,"homepage":"","language":"Emacs Lisp","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/p3r7.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":"2020-01-21T22:06:01.000Z","updated_at":"2023-09-16T14:21:31.000Z","dependencies_parsed_at":"2024-12-16T23:35:29.496Z","dependency_job_id":"661a5482-6570-405c-b924-7318d6884bdc","html_url":"https://github.com/p3r7/with-shell-interpreter","commit_stats":null,"previous_names":[],"tags_count":7,"template":false,"template_full_name":null,"purl":"pkg:github/p3r7/with-shell-interpreter","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/p3r7%2Fwith-shell-interpreter","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/p3r7%2Fwith-shell-interpreter/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/p3r7%2Fwith-shell-interpreter/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/p3r7%2Fwith-shell-interpreter/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/p3r7","download_url":"https://codeload.github.com/p3r7/with-shell-interpreter/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/p3r7%2Fwith-shell-interpreter/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":270723213,"owners_count":24634339,"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","status":"online","status_checked_at":"2025-08-16T02:00:11.002Z","response_time":91,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"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":["emacs-lisp","shell","terminal-emulator","tramp"],"created_at":"2024-12-16T23:35:03.096Z","updated_at":"2025-08-16T14:31:58.322Z","avatar_url":"https://github.com/p3r7.png","language":"Emacs Lisp","funding_links":[],"categories":[],"sub_categories":[],"readme":"# with-shell-interpreter [![MELPA](https://melpa.org/packages/with-shell-interpreter-badge.svg)](https://melpa.org/#/with-shell-interpreter) [![MELPA Stable](https://stable.melpa.org/packages/with-shell-interpreter-badge.svg)](https://stable.melpa.org/#/with-shell-interpreter)\n\n\nHelper for Emacs shell command APIs, making implicit argument as explicit keyword arguments.\n\nThis package is a library and does not provide any command.\n\nIt is inspired by the `eval-after-load` / `with-eval-after-load` functions.\n\nIt does the heavy lifting behind packages [friendly-shell-command](https://github.com/p3r7/friendly-shell) and [friendly-shell](https://github.com/p3r7/friendly-shell).\n\nFor more context, read the [accompanying blog post](https://www.eigenbahn.com/2020/01/19/painless-emacs-shell-commands).\n\n\n## Installation\n\nThe package is available on [Melpa](https://melpa.org/).\n\nWith `use-package`:\n\n```el\n(use-package with-shell-interpreter)\n```\n\nManually:\n\n    M-x package-install with-shell-interpreter\n\n\n## Usage\n\nWe recommend using the macro `with-shell-interpreter`. It's a more convenient version of `with-shell-interpreter-eval` that prevents having to quote _:form_ and wrap it in a `progn`.\n\n| keyword argument    | implicit var being let-bound                   | mandatory?         | description                                                                       |\n|---------------------|------------------------------------------------|--------------------|-----------------------------------------------------------------------------------|\n| _:form_             | n/a                                            | :heavy_check_mark: | The s-expressions to eval.                                                        |\n| _:path_             | `default-directory`                            | :x:                | The path from which to eval.                                                      |\n| _:interpreter_      | `explicit-shell-file-name` / `shell-file-name` | :x:                | Name or absolute path of shell interpreter executable.                            |\n| _:interpreter-args_ | `explicit-INTEPRETER-args`                     | :x:                | Login args to call interpreter with for login.                                    |\n| _:command-switch_   | `shell-command-switch`                         | :x:                | Command switch arg for asking interpreter to run a shell command.                 |\n| _:w32-arg-quote_    | `w32-quote-process-args`                       | :x:                | Character to use for quoting shell arguments (only on the Windows build of Emacs) |\n| _:allow-local-vars_ | n/a                                            | :x:                | Whether to allow buffer-local and/or connection-local values                      |\n\n_:form_ is expected to contain calls to functions relying on the Emacs shell APIs (e.g. `shell`, `shell-command`, `async-shell-command` and `shell-command-to-string`).\n\nSetting _:path_ to a remote location (with TRAMP format, i.e. `/\u003cmethod\u003e:\u003cuser\u003e@\u003chost\u003e:\u003clocalname\u003e`) allows running form with interpreter of remote server.\n\n_:interpreter-args_ is only usefull for interactive shells (from package shell-mode).\n\n_:command-switch_ is only usefull for single shell commands (from package simple).\n\n_:allow-local-vars_ can take the following values:\n\n - _'buffer_: allow buffer-local vars values_\n - _'connection_: allow connection-local values\n - _'both_: allow both types of local values\n - _'none_: ignore all local values\n\nIf left empty, here are the default values being used:\n\n| keyword argument    | fallback value (local path)       | fallback value (remote path)                           |\n|---------------------|-----------------------------------|--------------------------------------------------------|\n| _:path_             | current `default-directory`       | current `default-directory`                            |\n| _:interpreter_      | `shell-file-name`                 | `with-shell-interpreter-default-remote`                |\n| _:interpreter-args_ | `explicit-INTEPRETER-args` if set | `with-shell-interpreter-default-remote-args`           |\n| _:command-switch_   | `shell-command-switch`            | `with-shell-interpreter-default-remote-command-switch` |\n| _:w32-arg-quote_    | `w32-quote-process-args`          | `w32-quote-process-args`                               |\n| _:allow-local-vars_ | _nil_                             | _'connection_                                          |\n\n\n## Examples\n\nGetting the temperature from a Raspberry Pi:\n\n```el\n(with-shell-interpreter\n   :path \"/ssh:pi@raspberry:/~\"\n   :interpreter \"bash\"\n   :form\n   (shell-command-to-string \"vcgencmd measure_temp\"))\n```\n\nUnder Microsoft Windows, launching an interactive shell with the git-bash interpreter:\n\n```el\n(with-shell-interpreter\n  :path \"~\"                            ; ensure local path\n  :interpreter \"C:/Program Files/Git/bin/bash.exe\"\n  :form\n  (let (current-prefix-arg '(4))       ; don't prompt user for interpreter\n    (shell)))\n```\n\nFor more practical examples, have a look at packages [friendly-shell-command](https://github.com/p3r7/friendly-shell) and [friendly-shell](https://github.com/p3r7/friendly-shell) ([examples](https://github.com/p3r7/friendly-shell/blob/master/examples.md)).\n\n\n## Configuration\n\n### Per connection default configuration\n\nWe generally want to have different values for remote connection as the user might have redefined the value of `shell-file-name` with something exotic (e.g. zsh) and we would want a safer default for remote servers.\n\nFurthermore, under Microsoft Windows, `shell-file-name` defaults to _cmdproxy.exe_ which is OK for local shells but sucks for remote ones...\n\nWe can of course use the _:interpreter_, _:interpreter-args_ and _:command-switch_ keyword parameters but it's cumbersome to define a function for each remote connection with a custom configuration.\n\nInstead, the preferred way is to rely on connection-local variables.\n\n`with-shell-interpreter` comes by default with its own custom implementation of connection-local variables. It can be configured with var `with-shell-interpreter-connection-local-vars`.\n\nIt comes with a fallback entry for default configuration of remote interpreters:\n\n```el\n'((\".*\" . ((explicit-shell-file-name . \"/bin/bash\")\n           (explicit-bash-args . (\"-c\" \"export EMACS=; export TERM=dumb; stty echo; bash\"))\n           (shell-command-switch . \"-c\"))))\n```\n\nTo add an entry, just:\n\n```el\n(add-to-list with-shell-interpreter-connection-local-vars '(\".*@openwrt\") . ((explicit-shell-file-name . \"/bin/ash\")\n                                                                             (explicit-bash-args . (\"-i\"))\n                                                                             (shell-command-switch . \"-c\")))\n```\n\nAlternatively, you can instead choose to use Emacs' native implementation (more restrictive and cumbersome to configure):\n\n```el\n(setq with-shell-interpreter-connection-local-vars-implem 'native)\n```\n\nThe native implementation is only available since Emacs 26.1. Read docstrings of `connection-local-set-profiles` and `connection-local-set-profile-variables` for more details about it.\n\n\n### Default remote user\n\nYou might want to change the value of `tramp-default-user` if you usually connect to remote host with a user different than your local one.\n\n\n## Legibility\n\nThis code uses form feeds (`^L` character) as separators.\n\nEither package [form-feed](https://github.com/wasamasa/form-feed) or [page-break-lines](https://github.com/purcell/page-break-lines) makes them appear as intended.\n\nPackage [lisp-extra-font-lock](https://github.com/Lindydancer/lisp-extra-font-lock) is also recommended to distinguish between local and global vars in _let_ expressions.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fp3r7%2Fwith-shell-interpreter","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fp3r7%2Fwith-shell-interpreter","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fp3r7%2Fwith-shell-interpreter/lists"}