GNU Emacs package for transforming files with Makefile recipes
What and why
Curry command line tools with Makefiles and select a Makefile to call
dired dispatching on selected files' extension.
I'm sure you've encountered your share of "How do I transform X to
Y?"-type questions on the web. I know I have. A lot of answers involve
using kitchen-sink tools like
convert. These tools are
great: they can transform almost anything into anything else. But
they come with a price of a gazillion switches that are hard to
remember (and to type in, for that matter).
This package solves this problem by moving the complex command to a Makefile with customizable literate parameters at the top. Additionally it catalogs all available Makefiles by the file extension that they work on. It also creates a Makefile template for you when a selected action doesn't exist.
You write the command only once. All the other times, you just customize the literate switches.
It's possible to not have to write the command at all if it's available in the repository.
Since the command is meant to be written just once, you can have a more complex and optimized command, compared to the one that you would normally enter in the terminal.
In case of multiple files,
makeallows to use multiple cores without the actual command knowing about it. This means that people with different processors can use the same Makefile to the most efficiency, calling
make -j2where appropriate.
The Elisp layer of this package solves the problem of Makefiles and file names with spaces.
Clone this repository:
$ cd ~/git/ $ git clone https://github.com/abo-abo/make-it-so
(add-to-list 'load-path "~/git/make-it-so") (require 'make-it-so) (setq mis-recipes-directory "~/git/make-it-so/recipes/") (mis-config-default)
This method means that any Makefile that you create will be under version control.
If you install from MELPA, you only need this:
However beware that your recipes will be in your
and will be wiped when you update the package. Which is fine if
you just want to give it a quick go or don't plan on creating your own
recipes. But if you do, move your recipes directory to a different place
The workflow for using existing recipes
As a sample scenario, assume you want to trim (change running time) one or more *.ogv files.
So you navigate to their location with
dired and mark
them in case there's more than one.
Next, you call
make-it-so (bound to ,). It recognizes the "ogv"
extension and offers
trim actions. You can
navigate with C-n/C-p, select with RET and cancel with C-g.
After you've selected
trim, the selected files and the corresponding
Makefile will be moved to a staging directory within
your current directory. The staging directory will be named after the
action and the first selected file.
The Makefile will be opened for you to customize switches which start out as:
from = 00:00:01 to = 00:00:23
The actual command called will be:
ffmpeg -i $< -ss $(from) -t $(to) -c copy $@
but this complexity is distanced from you, and you can just select
to if you want.
Next you call
mis-save-and-compile (bound to f5 for
and test your result.
After this you can:
mis-abort(bound to C-M-,): the staging directory will be deleted and all files restored to their places. Basically, this is just an undo with respect to
mis-finalize(bound to C-,): in addition to
mis-abortthe generated files will be moved to the original directory.
mis-replace(bound to C-M-.): in addition to
mis-finalizethe source files will be moved to trash.
Note that in all three cases any modifications to the Makefile
template will be lost, along with all files in the staging directory
except those that were copied when you first called
those registered by the Makefile in "provide" file.
There's also mis-dispatch (bound to C-.) that allows to call the above three commands by name and remind you their shortcuts.
Screencast for transforming *.svg to *.png
The workflow for adding new recipes
As a sample scenario, assume you want to convert *.svg to *.png.
An internet search lead to Stack Overflow and this command:
inkscape -z -e test.png -w 1024 -h 1024 test.svg
Navigate to the file(s) in
make-it-sowith ,. No default actions are available, so just type "to-png" and hit RET. The "to-" prefix signifies that this is a conversion, adapting the Makefile to this form:
# This is a template for the Makefile. # Parameters should go in the upper half as: # width = 200 # and be referenced in the command as $(width) # ______________________________________________________________________________ DIRSVG = $(shell dir *.svg) DIRPNG = $(DIRSVG:.svg=.png) all: clean Makefile $(DIRPNG) %.png: %.svg echo "add command here" echo $@ >> provide clean: rm -f *.png provide # Insert the install command here. # e.g. sudo apt-get install ffmpeg install-tools: echo "No tools required" # Use this target when one file requires another. # See "../../cue/split/Makefile" for an example. require: @echo .PHONY: all install-tools require clean
If the action name doesn't have a "to-" prefix, the transformation is assumed to be e.g. "svg" -> "out.svg". You can change this of course by editing the Makefile.
In case the command name and package name don't coincide, or the command needs additional packages in order to work you might want to change
echo "No tools required"to
sudo apt-get install inkscape. This should serve as a reminder of what you should install when you're on a new system in order for the Makefile to work. And you can call
make install-toolsto install them of course.
echo "add command here"with
inkscape -z -e $@ -w $(width) -h $(height) $^. The parameters
heightwill go to the top of the Makefile, where they can be customized.
$@refers to the output file,
test.pngin this case.
$^refers to the input file,
test.svgin this case.
That's it. You can see the final Makefile here. Test if the command works with f5 from the Makefile. If you're happy with it, call
mis-finalizewith C-, from
dired. The Makefile will be saved for all future calls to
- Remember to use
dired-jumpcommand to jump from any file (or even the compilation buffer) to the associated directory.
dired-mark-files-regexp(bound to Shift 85) that will mark all files of specific type in directory. This is much faster than m when you want to convert a bunch of files.
- Until you're sure that the command and the Makefile work properly make backups. In fact, make backups period.
As you can see, the list of Makefile recipes is quite scarce at the moment. So new Makefile contributions are most welcome.