All Projects → riscy → Shx For Emacs

riscy / Shx For Emacs

Licence: gpl-3.0
An Emacs shell-mode (and comint-mode) extension that enables displaying small plots and graphics and lets users write shell commands in Emacs Lisp.

Programming Languages

shell
77523 projects

Labels

Projects that are alternatives of or similar to Shx For Emacs

Writingwithemacs
Tips, Examples, and Resources for Writing with Emacs
Stars: ✭ 150 (-7.41%)
Mutual labels:  emacs
Consult
consult.el - Consulting completing-read
Stars: ✭ 153 (-5.56%)
Mutual labels:  emacs
Modern Cpp Font Lock
C++ font-lock for Emacs
Stars: ✭ 159 (-1.85%)
Mutual labels:  emacs
Doom Snippets
The Doom Emacs snippets library
Stars: ✭ 150 (-7.41%)
Mutual labels:  emacs
Discover.el
Discover more of emacs with context menus!
Stars: ✭ 153 (-5.56%)
Mutual labels:  emacs
Ac Php
emacs auto-complete & company-mode for php
Stars: ✭ 157 (-3.09%)
Mutual labels:  emacs
Org Fragtog
Automatically toggle Org mode LaTeX fragment previews as the cursor enters and exits them
Stars: ✭ 149 (-8.02%)
Mutual labels:  emacs
Evil
The extensible vi layer for Emacs.
Stars: ✭ 2,265 (+1298.15%)
Mutual labels:  emacs
Org Msg
OrgMsg is a GNU/Emacs global minor mode mixing up Org mode and Message mode to compose and reply to emails in a Outlook HTML friendly style.
Stars: ✭ 153 (-5.56%)
Mutual labels:  emacs
Evil Goggles
Display visual hint on evil edit operations
Stars: ✭ 159 (-1.85%)
Mutual labels:  emacs
Emacs4cl
A 40 line ~/.emacs to quickly set up vanilla Emacs for Common Lisp programming
Stars: ✭ 151 (-6.79%)
Mutual labels:  emacs
Linum Relative
display relative line number in the left margin in emacs
Stars: ✭ 152 (-6.17%)
Mutual labels:  emacs
String Inflection
underscore -> UPCASE -> CamelCase conversion of names
Stars: ✭ 157 (-3.09%)
Mutual labels:  emacs
Mastodon.el
Emacs client for Mastodon
Stars: ✭ 150 (-7.41%)
Mutual labels:  emacs
Org Mode
This is a MIRROR only, do not send PR.
Stars: ✭ 158 (-2.47%)
Mutual labels:  emacs
Swiper
Ivy - a generic completion frontend for Emacs, Swiper - isearch with an overview, and more. Oh, man!
Stars: ✭ 1,948 (+1102.47%)
Mutual labels:  emacs
Hexo Renderer Org
Hexo renderer plugin for emacs org-mode
Stars: ✭ 157 (-3.09%)
Mutual labels:  emacs
Lpy
Minimal Python IDE for GNU Emacs
Stars: ✭ 161 (-0.62%)
Mutual labels:  emacs
Typescript.el
TypeScript-support for Emacs
Stars: ✭ 160 (-1.23%)
Mutual labels:  emacs
Explain Pause Mode
top, but for Emacs.
Stars: ✭ 158 (-2.47%)
Mutual labels:  emacs

#+TITLE: shx for Emacs #+OPTIONS: toc:3 author:t creator:nil num:nil #+AUTHOR: Chris Rayner #+EMAIL: [email protected]

[[https://melpa.org/#/shx][https://melpa.org/packages/shx-badge.svg]] [[https://stable.melpa.org/#/shx][https://stable.melpa.org/packages/shx-badge.svg]] [[https://github.com/riscy/shx-for-emacs/actions][https://github.com/riscy/shx-for-emacs/workflows/test/badge.svg]]

[[file:img/screenshot.png]]

  • Table of Contents :TOC_3_gh:noexport:
  • [[#description][Description]]
  • [[#install][Install]]
    • [[#from-melpa][From MELPA]]
    • [[#from-gnu-guix][From GNU Guix]]
    • [[#manually][Manually]]
  • [[#setup][Setup]]
    • [[#quick-start][Quick-start]]
    • [[#enable-automatically][Enable automatically]]
    • [[#customize][Customize]]
  • [[#key-bindings][Key bindings]]
  • [[#markup-in-the-shell][Markup in the shell]]
  • [[#extra-shell-commands][Extra shell commands]]
    • [[#general-commands][General commands]]
    • [[#graphical-commands][Graphical commands]]
    • [[#asynchronous-commands][Asynchronous commands]]
    • [[#adding-new-commands][Adding new commands]]
  • [[#related][Related]]
  • Description /shx/ or "shell-extras" extends comint-mode in Emacs (e.g. =M-x shell=).

    It's compatible with any underlying REPL (zsh, bash, psql, ipython, etc.).

    It parses the output stream in a few useful ways:

    • Display graphics and plots in the shell with a simple markup language (e.g. ==)
    • Add event-driven and timed behaviors to any shell session
    • Open any filename or URL by arrowing up to it and pressing =RET= (shx will even try to guess the correct directory)
    • Yank any line to the prompt by arrowing up to it and pressing =C-RET=
    • Check the time a command was run by mousing over its prompt

    shx makes it easy to add new shell commands written in elisp. Some are already built in:

    • =:clear= clears the buffer (like =clear= or =Command-K= on macOS)
    • =:e filename.txt= opens a file for editing
    • =:ssh [email protected]:port= starts a remote shell session using tramp
    • =:view image_file.png= embeds an image in the shell
    • =:plotline data_file.txt= embeds a line plot
    • etc.

    It also extends =shell-mode='s syntax highlighting, recenters and highlights content for better viewing when you run commands like comint-previous-prompt and comint-kill-input, and improves compatibility with =evil-mode= by anticipating when to switch to insert mode.

    Use =M-x shx RET= to start a new =shell= session with =shx-mode= enabled.

    /This version is tested with Emacs 26.1/. Check out the [[https://github.com/riscy/shx-for-emacs/releases][release log]].

  • Install *** From MELPA =M-x package-install RET shx RET= to install =shx= from [[https://melpa.org/][MELPA]]. *** From GNU Guix =guix install emacs-shx= to install =shx= from [[https://guix.gnu.org/][GNU Guix]]. *** Manually Add the following to your =.emacs=: #+begin_src elisp (add-to-list 'load-path "~/path/to/shx/") ; add shx.el's directory to the load-path (require 'shx) ; load shell-extras #+end_src

  • Setup *** Quick-start Type =M-x shx RET=. Try out the following commands:

    1. =:e ~/.bashrc= to edit your =.bashrc= (for example)
    2. =:man ls= to display the man page for =ls=
    3. =:help= to a start a completing read for other =shx= commands

*** Enable automatically If you like shx-mode, you can enable it everywhere:

#+begin_src elisp
(shx-global-mode 1)  ; toggle shx-mode on globally
#+end_src

Now shx will run automatically in any =comint-mode= buffer.  If you don't want
shx to run in every comint-mode buffer, you can use =M-x shx-mode= on a
case-by-case basis, or just add hooks to the mode in question, for example:

#+begin_src elisp
(add-hook 'inferior-python-mode-hook #'shx-mode)
#+end_src

*** Customize Use =M-x customize-group RET shx RET= to see shx's many customization options. Here's an example customization using setq: #+begin_src elisp (setq ;; resync the shell's default-directory with Emacs on "z" commands: shx-directory-tracker-regexp "^z " ;; vastly improve display performance by breaking up long output lines shx-max-output 1024 ;; prevent input longer than macOS's typeahead buffer from going through shx-max-input 1024 ;; prefer inlined images and plots to have a height of 250 pixels shx-img-height 250 ;; don't show any incidental hint messages about how to use shx shx-show-hints nil ;; flash the previous comint prompt for a full second when using C-c C-p shx-flash-prompt-time 1.0 ;; use #' to prefix shx commands instead of the default:' shx-leader "#") #+end_src

  • Key bindings | Key binding | Description | |-------------+--------------------------------------------------------------------------| | =C-RET= | If the cursor is not on the prompt, paste the current line to the input | | =RET= | If the cursor is on a filename or a URL, try to open it | | =SPC= | If the prompt is =:=, send =SPC= straight through to the process | | =q= | If the prompt is =:=, send =q= straight through to the process |

    Note the prompt will be =:= when reading through the output of =less= or a =man= page if you run the following: #+begin_src elisp (setenv "LESS" "--dumb --prompt=s") #+end_src

  • Markup in the shell shx's markup can enhance basic command-line applications and drive other events.

    If the output ever contains == on a line by itself, then a scaled rendering of =mountains.png= will be inlined within the text in the shell. This works because =view= is a shx command. shx will execute any (safe) shx command that appears with the following syntax: #+begin_src xml <command arg1 arg2 ...> #+end_src where =command= is a shx command and =arg1 ... argn= is a space-separated list of arguments. Arguments don't need to be surrounded by quotes -- the command will figure out how to parse them.

    You can use this markup to create a barplot (=:plotbar=) after collecting some stats, or generate an =:alert= when a task is finished, and so forth.

  • Extra shell commands shx's 'extra' commands are invoked by typing a =:= followed by the command's name. (You can change the =:= prefix by customizing the shx-leader variable.) These commands are written in elisp and so can access all of Emacs' facilities. Type =:help= to see a complete listing of shx commands.

    One command I use frequently is the =:edit= (shorthand =:e=) command: #+begin_src bash

    edit the .emacs file:

    :edit ~/.emacs

    use tramp to edit .emacs on a remote host through ssh:

    :e /ssh:remote-host.com:~/.emacs

    use tramp to edit .bashrc on a running docker container:

    :e /docker:02fbc948e009:~/.bashrc

    edit a local file as root

    :sedit /etc/passwd #+end_src

    Thanks to [[https://github.com/CeleritasCelery][CeleritasCelery]] it's also possible to use environment variables in the argument list: #+begin_src bash :e $HOME/.emacs.d #+end_src (To see an environment variable's value, use (getenv "").)

    The =:ssh= and =:docker= commands are popular for opening "remote" shells: #+begin_src bash

    open a shell on a remote host:

    :ssh [email protected]

    connect to a running docker container

    :docker 8a8335d63ff3

    reopen the shell on the localhost:

    :ssh #+end_src [[https://github.com/p3r7][Jordan Besly]] points out that you can customize the default interpreter for each "remote" [[https://www.gnu.org/software/emacs/manual/html_node/tramp/Remote-processes.html][using connection-profile-set-local-variables]].

    I also use the =:kept= and =:keep= commands frequently: #+begin_src bash

    write a complicated command:

    wget https://bootstrap.pypa.io/get-pip.py && python get-pip.py

    save the last command:

    :keep

    search for commands having to do with pip:

    :kept pip #+end_src

    Because these commands are written in elisp, shx gives =M-x shell= a lot of the same advantages as =eshell=. You can even evaluate elisp code directly in the buffer (see =:help eval=).

*** General commands | Command | Description | |----------------------+-------------------------------------------------------| | =:alert= | Reveal the buffer with an alert. Useful for markup | | =:clear= | Clear the buffer | | =:date= | Show the date (even when the process is blocked) | | =:diff file1 file2= | Launch an Emacs diff between two files | | =:edit file= | Edit a file. Shortcut: =:e = | | =:eval (elisp-sexp)= | Evaluate some elisp code. Example: =:eval (pwd)= | | =:find = | Run a fuzzy-find for | | =:goto-url = | Completing-read for a URL | | =:header New header= | Change the current header-line-format | | =:kept regexp= | Show a list of your 'kept' commands matching regexp | | =:keep= | Add the previous command to the list of kept commands | | =:man topic= | Invoke the Emacs man page browser on a topic | | =:ssh = | Restart the shell on the specified host |

There are more than this -- type =:help= for a listing of all user commands.

*** Graphical commands | Command | Description | |------------------------------+------------------------| | =:view image_file.jpg= | Display an image | | =:plotbar data_file.txt= | Display a bar plot | | =:plotline data_file.txt= | Display a line plot | | =:plotmatrix data_file.txt= | Display a heatmap | | =:plotscatter data_file.txt= | Display a scatter plot | | =:plot3d data_file.txt= | Display a 3D plot |

These are for displaying inline graphics and plots in the shell buffer.  You
can control how much vertical space an inline image occupies by customizing
the ~shx-img-height~ variable.

Note =convert= (i.e. ImageMagick) and =gnuplot= need to be installed.  If
the binaries are installed but these commands aren't working, customize the
~shx-path-to-convert~ and ~shx-path-to-gnuplot~ variables to point to the
binaries.  Also note these graphical commands aren't yet compatible with
shells launched on remote hosts (e.g. over ssh or in a Docker container).

*** Asynchronous commands | Command | Description | |-----------------------------------+---------------------------------------------------| | =:delay = | Run a shell command after a specific delay | | =:pulse = | Repeat a shell command forever with a given delay | | =:repeat = | Repeat a shell command == times | | =:stop = | Cancel a repeating or delayed command |

Use these to delay, pulse, or repeat a command a specific number of times.
Unfortunately these only support your typical shell commands, and not shx's
extra (colon-prefixed) commands.  So this possible:
#+begin_src bash
# Run the 'pwd' command 10 seconds from now:
:delay 10 pwd
#+end_src
But this is not possible:
#+begin_src bash
# Run the 'pwd' shx command 10 seconds from now (DOES NOT WORK)
:delay 10 :pwd
#+end_src

*** Adding new commands New shx commands are written by defining single-argument elisp functions named shx-cmd-COMMAND-NAME, where =COMMAND-NAME= is what the user would type to invoke it. ***** Example: a command to rename the buffer If you evaluate the following (or add it to your =.emacs=), #+begin_src elisp (defun shx-cmd-rename (name) "(SAFE) Rename the current buffer to NAME." (if (not (ignore-errors (rename-buffer name))) (shx-insert 'error "Can't rename buffer.") (shx-insert "Renaming buffer to " name "\n") (shx--hint "Emacs won't save buffers starting with *"))) #+end_src then each shx buffer will immediately have access to the =:rename= command. When it's invoked, shx will also display a hint about buffer names.

Note the importance of defining a docstring.  This documents the
command so that typing =:help rename= will give the user information on what
the command does.  Further, since the docstring begins with =(SAFE)=,
it becomes part of shx's markup language.  So in this case if:
#+begin_src xml
<rename A new name for the buffer>
#+end_src
appears on a line by itself in the output, the buffer will try to
automatically rename itself.

***** Example: invoking ediff from the shell A command similar to this one is built into shx: #+begin_src elisp (defun shx-cmd-diff (files) "(SAFE) Launch an Emacs ediff' between FILES." (setq files (shx-tokenize files)) (if (not (eq (length files) 2)) (shx-insert 'error "diff <file1> <file2>\n") (shx-insert "invoking ediff...\n") (shx--asynch-funcall #'ediff (mapcar #'expand-file-name files)))) #+end_src Note that =files= is supplied as a string, but it's immediately parsed into a list of strings using ~shx-tokenize~. Helpfully, this function is able to parse various styles of quoting and escaping, for example(shx-tokenize "'file one' file\ two")evaluates to("file one" "file two")`. ***** Example: a command to browse URLs If you execute the following, #+begin_src elisp (defun shx-cmd-browse (url) "Browse the supplied URL." (shx-insert "Browsing " 'font-lock-keyword-face url) (browse-url url)) #+end_src then each shx buffer will have access to the =:browse= command.

  Note the docstring does not specify that this command is =SAFE=.
  This means =<browse url>= will not become part of shx's markup.  That
  makes sense in this case, since you wouldn't want to give a process the
  power to open arbitrary URLs without prompting.
  • Related If you're here, these might be interesting:

    • [[https://www.masteringemacs.org/article/shell-comint-secrets-history-commands][Shell & Comint Secrets: History commands]]
    • [[https://www.masteringemacs.org/article/pcomplete-context-sensitive-completion-emacs][PComplete: Context-Sensitive Completion in Emacs]]
    • [[https://dev.to/_darrenburns/10-tools-to-power-up-your-command-line-4id4][10 tools to power up your command line]]
    • [[https://www.booleanworld.com/customizing-coloring-bash-prompt/][Creating dynamic bash prompts]]
    • [[https://github.com/Orkohunter/keep][The Keep Utility]] inspired the =kept= and =keep= commands
    • [[https://terminalsare.sexy/]["Terminals Are Sexy"]] (portal)
    • [[https://github.com/riscy/command_line_lint][Command-Line Lint]], another project I maintain
    • [[http://ohmyz.sh/][oh my zsh]], a community-driven zsh configuration
    • [[https://github.com/Bash-it/bash-it][bash-it]], a community driven bash configuration

    And if running a =dumb= terminal in Emacs isn't for you, here are some alternatives:

    • [[https://leanpub.com/the-tao-of-tmux/read][The Tao of tmux]], re: working in the terminal with tmux
    • [[https://github.com/zsh-users/zsh-syntax-highlighting][zsh-syntax-highlighting]]
    • [[https://hackernoon.com/macbook-my-command-line-utilities-f8a121c3b019#.clz934ly3][Shell configuration tips]] from Vitaly Belman
    • [[http://www.iterm2.com/documentation-shell-integration.html][Shell integration]] for iTerm2 on macOS
    • [[https://getbitbar.com/][BitBar]] adds program output to menus on macOS
Note that the project description data, including the texts, logos, images, and/or trademarks, for each open source project belongs to its rightful owner. If you wish to add or remove any projects, please contact us at [email protected].