• Stars
    star
    207
  • Rank 189,769 (Top 4 %)
  • Language
    Emacs Lisp
  • License
    GNU General Publi...
  • Created over 2 years ago
  • Updated 3 months ago

Reviews

There are no reviews yet. Be the first to send feedback to the community and the maintainers!

Repository Details

Emacs shell commands with DWIM behaviour

👉 Support this work via GitHub Sponsors

dwim-shell-command

Run M-x dwim-shell-command to execute DWIM shell commands

  • Asynchronously.
  • Using noweb templates.
  • Automatically injecting files (from dired or other buffers) or kill ring.
  • Managing buffer focus with heuristics.
  • Showing progress bar.
  • Quick buffer exit.
  • More reusable history.

Bring command-line utilities to your Emacs workflows

Use dwim-shell-command-on-marked-files to easily integrate command-line utilities into frequent Emacs workflows (ie. operate on current buffer or dired files).

(defun my/dwim-shell-command-convert-to-gif ()
  "Convert all marked videos to optimized gif(s)."
  (interactive)
  (dwim-shell-command-on-marked-files
   "Convert to gif"
   "ffmpeg -loglevel quiet -stats -y -i <<f>> -pix_fmt rgb24 -r 15 <<fne>>.gif"
   :utils "ffmpeg"))

Which files

dwim-shell-command attempts to guess which file(s) you may want the command to operate on.

If visiting a dired buffer, draw the marked file(s).

If visiting any other buffer with an associated file, use that.

noweb templates

Operate on drawn files using either the following:

  • <<f>> (file path)
  • <<fne>> (file path without extension)
  • <<e>> (extension)
  • <<td>> (generate a temporary directory)
  • <<*>> (all files joined)
  • <<cb>> (clipboard)

For example:

With drawn files path/to/image1.png and path/to/image2.png

convert <<f>> <<fne>>.jpg expands to

convert path/to/image1.png path/to/image1.jpg
convert path/to/image2.png path/to/image2.jpg

while ls -lh <<*>> expands to

ls -lh path/to/image1.png path/to/image2.png

Focus

dwim-shell-command creates a process buffer to capture command output, but neither displays nor focuses on it by default. Instead, it tries to guess what’s more convenient to focus on.

While the process is busy, show a spinner in the minibuffer. No focus changes.

After process is finished:

If there were any files created in the default-directory, jump to a dired buffer and move point to the new file (via dired-jump).

images/showme.png

If no new files were created, automatically switch focus to the process buffer and display its output.

Note: You can prevent this automatic focus by prepending your command with whitespace.

” convert <<f>> <<fne>>.jpg”

If the shell command caused any errors, offer to focus the process buffer and display its output.

Easily create utilities

Command-line utilities like ffmpeg can be easily integrated into Emacs flows (without the need to remember any flags or parameters) by wrapping command invocations into functions and invoking via M-x (or your favorite binding). Same DWIM behavior from dwim-shell-command is inherited.

All gifs in this README were created via M-x dwim-shell-command-convert-to-gif, powered by dwim-shell-command-on-marked-files:

(defun my/dwim-shell-command-convert-to-gif ()
  "Convert all marked videos to optimized gif(s)."
  (interactive)
  (dwim-shell-command-on-marked-files
   "Convert to gif"
   "ffmpeg -loglevel quiet -stats -y -i <<f>> -pix_fmt rgb24 -r 15 <<fne>>.gif"
   :utils "ffmpeg"))

This makes wrapping one-liners a breeze, so let’s do some more…

(defun my/dwim-shell-command-convert-audio-to-mp3 ()
  "Convert all marked audio to mp3(s)."
  (interactive)
  (dwim-shell-command-on-marked-files
   "Convert to mp3"
   "ffmpeg -stats -n -i '<<f>>' -acodec libmp3lame '<<fne>>.mp3'"
   :utils "ffmpeg"))

(defun my/dwim-shell-command-convert-image-to-jpg ()
  "Convert all marked images to jpg(s)."
  (interactive)
  (dwim-shell-command-on-marked-files
   "Convert to jpg"
   "convert -verbose '<<f>>' '<<fne>>.jpg'"
   :utils "convert"))

(defun my/dwim-shell-command-drop-video-audio ()
  "Drop audio from all marked videos."
  (interactive)
  (dwim-shell-command-on-marked-files
   "Drop audio" "ffmpeg -i '<<f>>' -c copy -an '<<fne>>_no_audio.<<e>>'"
   :utils "ffmpeg"))

Quick exit

Process buffers are read-only and can be quickly closed by pressing q.

More reusable history

Because of templates, command history becomes automatically reusable in other contexts.

Install

dwim-shell-command is available on MELPA.

https://melpa.org/packages/dwim-shell-command.svg

  1. Install via M-x package-install.
  2. Require, set edit style, and add company backend:
(require 'dwim-shell-command)

Now you’re ready to run

M-x dwim-shell-command

use-package

Alternatively, can also install via use-package, define your own commands and remap to shell-command’s existing binding using something like:

(use-package dwim-shell-command
  :ensure t
  :bind (([remap shell-command] . dwim-shell-command)
         :map dired-mode-map
         ([remap dired-do-async-shell-command] . dwim-shell-command)
         ([remap dired-do-shell-command] . dwim-shell-command)
         ([remap dired-smart-shell-command] . dwim-shell-command))
  :config
  (defun my/dwim-shell-command-convert-to-gif ()
    "Convert all marked videos to optimized gif(s)."
    (interactive)
    (dwim-shell-command-on-marked-files
     "Convert to gif"
     "ffmpeg -loglevel quiet -stats -y -i <<f>> -pix_fmt rgb24 -r 15 <<fne>>.gif"
     :utils "ffmpeg")))

Install command line utilities

I’m including an optional package (dwim-shell-commands.el), with all the command line utilities I’ve brought in via dwim-shell-command-on-marked-files. Feel free to optionally load it via:

(require 'dwim-shell-commands)

To give you an idea, here’s what I got so far:

  • dwim-shell-commands-audio-to-mp3
  • dwim-shell-commands-bin-plist-to-xml
  • dwim-shell-commands-clipboard-to-qr
  • dwim-shell-commands-drop-video-audio
  • dwim-shell-commands-files-combined-size
  • dwim-shell-commands-git-clone-clipboard-url
  • dwim-shell-commands-git-clone-clipboard-url-to-downloads
  • dwim-shell-commands-image-to-grayscale
  • dwim-shell-commands-image-to-icns
  • dwim-shell-commands-image-to-jpg
  • dwim-shell-commands-image-to-png
  • dwim-shell-commands-pdf-password-protect
  • dwim-shell-commands-reorient-image
  • dwim-shell-commands-resize-gif
  • dwim-shell-commands-resize-image
  • dwim-shell-commands-resize-video
  • dwim-shell-commands-speed-up-gif
  • dwim-shell-commands-speed-up-video
  • dwim-shell-commands-unzip
  • dwim-shell-commands-video-to-gif
  • dwim-shell-commands-video-to-optimized-gif
  • dwim-shell-commands-video-to-webp

Support this work

👉 Support my work via GitHub Sponsors