├── Makefile ├── README.md ├── make-it-so.el └── recipes ├── ape └── to-flac │ └── Makefile ├── chm └── to-pdf │ └── Makefile ├── cue └── split │ └── Makefile ├── dot └── to-png │ └── Makefile ├── epub └── to-pdf │ └── Makefile ├── flac └── to-mp3 │ └── Makefile ├── gif └── gifsicle │ └── Makefile ├── ipynb └── to-md │ └── Makefile ├── m4a └── to-mp3 │ └── Makefile ├── md ├── to-html │ └── Makefile └── to-org │ └── Makefile ├── mix └── enca │ └── Makefile ├── mp3 └── trim │ └── Makefile ├── mp4 ├── replace-audio │ └── Makefile ├── to-mp3 │ └── Makefile └── trim │ └── Makefile ├── ogv ├── crop │ └── Makefile ├── to-gif │ └── Makefile ├── to-mp4 │ └── Makefile └── trim │ └── Makefile ├── pdf └── to-txt │ └── Makefile ├── png └── to-gif │ └── Makefile ├── svg └── to-png │ └── Makefile ├── tiff └── to-jpg │ └── Makefile └── txt └── encode-utf8 └── Makefile /Makefile: -------------------------------------------------------------------------------- 1 | EMACS = emacs 2 | 3 | .PHONY: compile clean 4 | 5 | compile: 6 | $(EMACS) -batch --eval "(byte-compile-file \"make-it-so.el\")" 7 | 8 | clean: 9 | rm -f *.elc 10 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # make-it-so 2 | 3 | **GNU Emacs package for transforming files with Makefile recipes** 4 | 5 | ## What and why 6 | 7 | ### Terse description 8 | 9 | Curry command line tools with Makefiles and select a Makefile to call 10 | from `dired` dispatching on selected files' extension. 11 | 12 | ### Long story 13 | 14 | I'm sure you've encountered your share of "How do I transform X to 15 | Y?"-type questions on the web. I know I have. A lot of answers involve 16 | using kitchen-sink tools like `ffmpeg` or `convert`. These tools are 17 | great: they can transform almost anything into anything else. But 18 | they come with a price of a gazillion switches that are hard to 19 | remember (and to type in, for that matter). 20 | 21 | This package solves this problem by moving the complex command to a 22 | Makefile with customizable literate parameters at the top. 23 | Additionally it catalogs all available Makefiles by the file extension 24 | that they work on. 25 | It also creates a Makefile template for you when a selected action 26 | doesn't exist. 27 | 28 | ### Advantages 29 | 30 | 1. You write the command only once. All the other times, you just 31 | customize the literate switches. 32 | 33 | 2. It's possible to not have to write the command at all if it's 34 | available in the repository. 35 | 36 | 3. Since the command is meant to be written just once, you can have a 37 | more complex and optimized command, compared to the one that you 38 | would normally enter in the terminal. 39 | 40 | 4. In case of multiple files, `make` allows to use multiple cores 41 | without the actual command knowing about it. This means that people 42 | with different processors can use the same Makefile to the most 43 | efficiency, calling `make -j8` or `make -j2` where appropriate. 44 | 45 | 5. The Elisp layer of this package solves the problem of Makefiles 46 | and file names with spaces. 47 | 48 | ## Installation 49 | 50 | ### From here: 51 | 52 | Clone this repository: 53 | 54 | $ cd ~/git/ 55 | $ git clone https://github.com/abo-abo/make-it-so 56 | 57 | Add to `.emacs`: 58 | 59 | (add-to-list 'load-path "~/git/make-it-so") 60 | (require 'make-it-so) 61 | (mis-config-default) 62 | 63 | This method means that any Makefile that you create will be under 64 | version control. 65 | 66 | ### From MELPA: 67 | 68 | If you install from MELPA, you only need this: 69 | 70 | (mis-config-default) 71 | 72 | However beware that your recipes will be in your `package-user-dir` 73 | and will be **wiped** when you update the package. Which is fine if 74 | you just want to give it a quick go or don't plan on creating your own 75 | recipes. But if you do, move your recipes directory to a different place 76 | and configure `mis-recipes-directory` properly. 77 | 78 | ## The workflow for using existing recipes 79 | 80 | As a sample scenario, assume you want to trim (change running time) 81 | one or more *.ogv files. 82 | 83 | So you navigate to their location with `dired` and [mark][dired-mark] 84 | them in case there's more than one. 85 | 86 | Next, you call `make-it-so` (bound to **,**). It recognizes the "ogv" 87 | extension and offers `crop`, `to-gif` and `trim` actions. You can 88 | navigate with **C-n**/**C-p**, select with **RET** and cancel with **C-g**. 89 | 90 | After you've selected `trim`, the selected files and the corresponding 91 | [Makefile][trim-makefile] will be moved to a *staging* directory within 92 | your current directory. The staging directory will be named after the 93 | action and the first selected file. 94 | 95 | The Makefile will be opened for you to customize switches which start out as: 96 | 97 | from = 00:00:01 98 | to = 00:00:23 99 | 100 | The actual command called will be: 101 | 102 | ffmpeg -i $< -ss $(from) -t $(to) -c copy $@ 103 | 104 | but this complexity is distanced from you, and you can just select 105 | `from` and `to` if you want. 106 | 107 | Next you call `mis-save-and-compile` (bound to **f5** for `make-mode`) 108 | and test your result. 109 | 110 | After this you can: 111 | 112 | 1. Call `mis-abort` (bound to **C-M-,**): the staging directory will be deleted and all 113 | files restored to their places. Basically, this is just an undo 114 | with respect to `make-it-so`. 115 | 2. Call `mis-finalize` (bound to **C-,**): in addition to `mis-abort` the generated files will be 116 | moved to the original directory. 117 | 3. Call `mis-replace` (bound to **C-M-.**): in addition to `mis-finalize` the source files will be 118 | moved to trash. 119 | 120 | Note that in all three cases any modifications to the Makefile 121 | template *will be lost*, along with all files in the staging directory 122 | except those that were copied when you first called `make-it-so` and 123 | those registered by the Makefile in "provide" file. 124 | 125 | There's also *mis-dispatch* (bound to **C-.**) that allows to call the 126 | above three commands by name and remind you their shortcuts. 127 | 128 | ### Screencast for transforming *.svg to *.png 129 | 130 | ![gif][svg-png] 131 | 132 | ## Available recipes 133 | 134 | 1. cue-spit 135 | 2. flac-to-mp3 136 | 3. ogv-trim 137 | 4. ogv-crop 138 | 5. ogv-to-gif 139 | 6. svg-to-png 140 | 7. md-to-html 141 | 8. mp4-to-mp3 142 | 9. m4a-to-mp3 143 | 9. chm-to-pdf 144 | 10. pdf-to-txt 145 | 146 | ## The workflow for adding new recipes 147 | 148 | As a sample scenario, assume you want to convert *.svg to *.png. 149 | 150 | 1. An internet search lead to [Stack Overflow][stack] and this command: 151 | 152 | inkscape -z -e test.png -w 1024 -h 1024 test.svg 153 | 154 | 2. Navigate to the file(s) in `dired` and call `make-it-so` with **,**. 155 | No default actions are available, so just type "to-png" and hit **RET**. 156 | The "to-" prefix signifies that this is a conversion, adapting the Makefile to this form: 157 | 158 | # This is a template for the Makefile. 159 | # Parameters should go in the upper half as: 160 | # width = 200 161 | # and be referenced in the command as $(width) 162 | 163 | # ______________________________________________________________________________ 164 | 165 | DIRSVG = $(shell dir *.svg) 166 | 167 | DIRPNG = $(DIRSVG:.svg=.png) 168 | 169 | all: clean Makefile $(DIRPNG) 170 | 171 | %.png: %.svg 172 | echo "add command here" 173 | echo $@ >> provide 174 | 175 | clean: 176 | rm -f *.png provide 177 | 178 | # Insert the install command here. 179 | # e.g. sudo apt-get install ffmpeg 180 | install-tools: 181 | echo "No tools required" 182 | 183 | .PHONY: all install-tools clean 184 | 185 | If the action name doesn't have a "to-" prefix, the transformation is assumed to be 186 | e.g. "svg" -> "out.svg". You can change this of course by editing the Makefile. 187 | 188 | 3. In case the command name and package name don't coincide, or the 189 | command needs additional packages in order to work you might want to 190 | change `echo "No tools required"` to `sudo apt-get install inkscape`. 191 | This should serve as a reminder of what you should install when you're 192 | on a new system in order for the Makefile to work. And you can call `make install-tools` 193 | to install them of course. 194 | 195 | 4. Replace `echo "add command here"` with `inkscape -z -e $@ -w $(width) -h $(height) $^`. 196 | The parameters `width` and `height` will go to the top of the Makefile, where they 197 | can be customized. `$@` refers to the output file, `test.png` in this case. 198 | `$^` refers to the input file, `test.svg` in this case. 199 | 200 | 5. That's it. You can see the final Makefile [here][to-png-makefile]. 201 | Test if the command works with **f5** from the Makefile. If you're 202 | happy with it, call `mis-finalize` with **C-,** from `dired`. The 203 | Makefile will be saved for all future calls to `make-it-so`. 204 | 205 | ## Usage Tips 206 | 207 | - Remember to use `dired-jump` command to jump from any file (or even 208 | the compilation buffer) to the associated directory. 209 | - Remember `dired-mark-files-regexp` (bound to Shift 85) that will mark all files 210 | of specific type in directory. This is much faster than **m** when you want 211 | to convert a bunch of files. 212 | - Until you're sure that the command and the Makefile work properly 213 | make backups. In fact, make backups period. 214 | 215 | ## Contributing 216 | 217 | As you can see, the list of Makefile recipes is quite scarce at the 218 | moment. So new Makefile contributions are most welcome. 219 | 220 | [dired-mark]: https://www.gnu.org/software/emacs/manual/html_node/emacs/Marks-vs-Flags.html#Marks-vs-Flags 221 | [trim-makefile]: https://raw.githubusercontent.com/abo-abo/make-it-so/master/recipes/ogv/trim/Makefile 222 | [to-png-makefile]: https://raw.githubusercontent.com/abo-abo/make-it-so/master/recipes/svg/to-png/Makefile 223 | [stack]: http://stackoverflow.com/questions/9853325/how-to-convert-a-svg-to-a-png-with-image-magick 224 | [svg-png]: https://raw.githubusercontent.com/abo-abo/make-it-so/gh-pages/svg-png.gif 225 | -------------------------------------------------------------------------------- /make-it-so.el: -------------------------------------------------------------------------------- 1 | ;;; make-it-so.el --- Transform files with Makefile recipes. -*- lexical-binding: t -*- 2 | 3 | ;; Copyright (C) 2014 Oleh Krehel 4 | 5 | ;; Author: Oleh Krehel 6 | ;; URL: https://github.com/abo-abo/make-it-so 7 | ;; Version: 0.1.0 8 | ;; Package-Requires: ((swiper "0.8.0") (emacs "24")) 9 | ;; Keywords: make, dired 10 | 11 | ;; This file is not part of GNU Emacs 12 | 13 | ;; This file is free software; you can redistribute it and/or modify 14 | ;; it under the terms of the GNU General Public License as published by 15 | ;; the Free Software Foundation; either version 3, or (at your option) 16 | ;; any later version. 17 | 18 | ;; This program is distributed in the hope that it will be useful, 19 | ;; but WITHOUT ANY WARRANTY; without even the implied warranty of 20 | ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 21 | ;; GNU General Public License for more details. 22 | 23 | ;; For a full copy of the GNU General Public License 24 | ;; see . 25 | 26 | ;;; Commentary: 27 | ;; 28 | ;; This package is aimed on minimizing the effort of interacting with 29 | ;; the command tools involved in transforming files. 30 | ;; 31 | ;; For instance, once in a blue moon you might need to transform a 32 | ;; large flac file based on a cue file into smaller flac files, or mp3 33 | ;; files for that matter. 34 | ;; 35 | ;; Case 1: if you're doing it for the first time, you'll search the 36 | ;; internet for a command tool that does this job, and for particular 37 | ;; switches. 38 | ;; 39 | ;; Case 2: you've done it before. The problem is that when you want to 40 | ;; do the transform for the second time, you have likely forgotten all 41 | ;; the command switches and maybe even the command itself. 42 | ;; 43 | ;; The solution is to write the command to a Makefile when you find it 44 | ;; the first time around. This particular Makefile you should save to 45 | ;; ./recipes/cue/split/Makefile. 46 | ;; 47 | ;; Case 3: you have a Makefile recipe. Just navigate to the dispatch 48 | ;; file (*.cue in this case) with `dired' and press "," which is bound 49 | ;; to `make-it-so'. You'll be prompted to select a transformation 50 | ;; recipe that applies to *.cue files. Select "split". The following 51 | ;; steps are: 52 | ;; 53 | ;; 1. A staging directory will be created in place of the input 54 | ;; files and they will be moved there. 55 | ;; 56 | ;; 2. Your selected Makefile template will be copied to the staging 57 | ;; directory and opened for you to tweak the parameters. 58 | ;; 59 | ;; 3. When you're done, call `compile' to make the transformation. 60 | ;; It's bound to [f5] in `make-mode' by this package. 61 | ;; 62 | ;; 4. If you want to cancel at this point, discarding the results of 63 | ;; the transformation (which is completely safe, since they can be 64 | ;; regenerated), call `mis-abort', bound to "C-M-,". 65 | ;; 66 | ;; 5. If you want to keep both the input and output files, call 67 | ;; `mis-finalize', bound to "C-,". 68 | ;; 69 | ;; 6. If you want to keep only the output files, call `mis-replace', 70 | ;; bound to "C-M-.". The original files will be moved to trash. 71 | ;; 72 | ;; 7. Finally, consider contributing Makefile recipes to allow 73 | ;; other users to skip Case 1 and Case 2. 74 | ;; 75 | 76 | ;;; Code: 77 | 78 | ;;* Requires 79 | (require 'dired) 80 | (require 'make-mode) 81 | (require 'cl-lib) 82 | (require 'package) 83 | 84 | ;;* Customization 85 | (defgroup make-it-so nil 86 | "Transfrom files in `dired' with Makefile recipes." 87 | :group 'dired 88 | :prefix "mis-") 89 | 90 | (defcustom mis-completion-method 'ivy 91 | "Method to select a candidate from a list of strings." 92 | :type '(choice 93 | (const :tag "Ivy" ivy) 94 | (const :tag "Helm" helm))) 95 | 96 | (defvar mis-load-file-name (or load-file-name 97 | (buffer-file-name))) 98 | 99 | (defcustom mis-recipes-directory (expand-file-name 100 | "recipes" 101 | (file-name-directory mis-load-file-name)) 102 | "Directory with available recipes." 103 | :type 'directory) 104 | 105 | (defcustom mis-bindings-alist 106 | '((make-it-so . ",") 107 | (mis-finalize . "C-,") 108 | (mis-abort . "C-M-,") 109 | (mis-dispatch . "C-.") 110 | (mis-replace . "C-M-.")) 111 | "List of bindings for the minor mode.") 112 | 113 | (defcustom mis-make-command "make -j8" 114 | "Customize the make command. 115 | Option -j8 will allow up to 8 asynchronous processes to make the targets.") 116 | 117 | (defcustom mis-makefile-preamble " 118 | # This is a template for the Makefile. 119 | # Parameters should go in the upper half as: 120 | # width = 200 121 | # and be referenced in the command as $(width)" 122 | "Preamble to be inserted at the top of makefile templates." 123 | :type 'string) 124 | 125 | (defcustom mis-makefile-key-descriptions " 126 | # Press (mis-save-and-compile) to run this makefile (i.e. apply the transformation). 127 | 128 | # Then press one of: 129 | # C-, (mis-finalize) : finalize the transformation (delete makefile and other auxiliary files). 130 | # C-M-, (mis-abort) : revert back to state before `mis-action' was called. 131 | # C-M-. (mis-replace) : additionally to finalizing, delete the original file." 132 | "Key descriptions inserted into Makefiles." 133 | :type 'string) 134 | 135 | ;;* Setup 136 | (defvar mis-mode-map 137 | (let ((map (make-sparse-keymap))) 138 | (mapc (lambda (x) (define-key map (kbd (cdr x)) (car x))) 139 | mis-bindings-alist) 140 | map)) 141 | 142 | (defvar mis-makefile-mode-map 143 | (let ((map (make-sparse-keymap))) 144 | (define-key map (kbd "") 'mis-save-and-compile) 145 | (define-key map (kbd "C-,") 'mis-finalize) 146 | (define-key map (kbd "C-M-,") 'mis-abort) 147 | map)) 148 | 149 | (defvar mis-current-files nil 150 | "Current set of files to transform.") 151 | 152 | ;;;###autoload 153 | (define-minor-mode mis-mode 154 | "Add make-it-so key bindings to `dired-mode'. 155 | 156 | \\{mis-mode-map}" 157 | :keymap mis-mode-map) 158 | 159 | ;;;###autoload 160 | (define-minor-mode mis-makefile-mode 161 | "Add make-it-so key bindings to `makefile-mode' 162 | 163 | \\{mis-makefile-mode-map}" 164 | :keymap mis-makefile-mode-map) 165 | 166 | ;;;###autoload 167 | (defun mis-config-default () 168 | "Easy config." 169 | (add-hook 'dired-mode-hook 'mis-mode)) 170 | 171 | (declare-function helm "helm") 172 | (declare-function ivy-read "ivy") 173 | 174 | (defun mis-competing-read (prompt collection action) 175 | (if (eq mis-completion-method 'helm) 176 | (progn 177 | (require 'helm) 178 | (require 'helm-help) 179 | (helm :sources 180 | `((name . ,prompt) 181 | (candidates . ,collection) 182 | (action . ,action)))) 183 | (require 'ivy) 184 | (ivy-read prompt collection 185 | :action action))) 186 | 187 | ;;* Interactive 188 | ;;;###autoload 189 | (defun mis-browse () 190 | "List all available recipes. 191 | Jump to the Makefile of the selected recipe." 192 | (interactive) 193 | (mis-competing-read 194 | "Recipes" 195 | (mis-recipes) 196 | (lambda (x) 197 | (if (string-match "^\\([^-]+\\)-\\(.*\\)$" x) 198 | (find-file 199 | (mis-build-path 200 | (mis-directory) 201 | (match-string 1 x) 202 | (match-string 2 x) 203 | "Makefile")) 204 | (error "Failed to split %s" x))))) 205 | 206 | (defun mis-create-makefile (action) 207 | "Create a new Makefile for ACTION." 208 | (let* ((olde (file-name-extension (car mis-current-files))) 209 | (newe (if (string-match "^to-\\(.*\\)" action) 210 | (match-string 1 action) 211 | (concat "out." olde))) 212 | (preamble (concat (substring mis-makefile-preamble 1) 213 | "\n\n#" (make-string 78 ?_) "\n")) 214 | (olds (format "DIR%s = $(shell dir *.%s)" (upcase olde) olde)) 215 | (news (format "DIR%s = $(DIR%s:.%s=.%s)" 216 | (upcase newe) (upcase olde) olde newe)) 217 | (t-all (format "all: clean Makefile $(DIR%s)" (upcase newe))) 218 | (t-new (concat 219 | (format "%%.%s: %%.%s\n\techo \"add command here\"" newe olde) 220 | "\n\techo $@ >> provide")) 221 | (t-clean (format "clean:\n\trm -f *.%s provide" newe)) 222 | (t-tools (concat 223 | "# Insert the install command here.\n" 224 | "# e.g. sudo apt-get install ffmpeg\n" 225 | "install-tools:\n\t" 226 | "echo \"No tools required\"")) 227 | (t-phony ".PHONY: all install-tools clean")) 228 | (mapconcat 'identity 229 | (list preamble olds news t-all t-new 230 | t-clean t-tools t-phony) 231 | "\n\n"))) 232 | 233 | ;;;###autoload 234 | (defun make-it-so (arg) 235 | "When called from `dired', offer a list of transformations. 236 | Available trasformations are dispatched on currently selected 237 | file(s)' extension. Therefore it's an error when files with 238 | multiple extensions are marked. After an action is selected, 239 | proceed to call `mis-action' for that action." 240 | (interactive "p") 241 | (cl-case major-mode 242 | (wdired-mode 243 | (call-interactively 'self-insert-command)) 244 | (dired-mode 245 | (let ((dispatch-file (car (dired-get-marked-files nil t))) 246 | (files (dired-get-marked-files))) 247 | (setq mis-current-files 248 | (if (member dispatch-file files) 249 | (cons dispatch-file 250 | (delete dispatch-file files)) 251 | files)) 252 | (if (or (mis-all-equal 253 | (mapcar #'file-name-extension mis-current-files)) 254 | (= arg 2) 255 | (y-or-n-p "Mixed extensions in selection, continue?")) 256 | (let* ((ext (file-name-extension (car mis-current-files))) 257 | (candidates (if (= arg 2) 258 | (mis-recipes-by-ext "mix") 259 | (mis-recipes-by-ext ext)))) 260 | (mis-competing-read 261 | "Makefile: " candidates 'mis-action)) 262 | (error "Mixed extensions in selection")))) 263 | (t 264 | (error "Must be called from dired")))) 265 | 266 | ;;;###autoload 267 | (defun mis-abort () 268 | "Abort tranformation. 269 | This function should revert to the state before `mis-action' was called." 270 | (interactive) 271 | (unless (file-exists-p "Makefile") 272 | (error "No Makefile in current directory")) 273 | (let* ((makefile-buffer (find-buffer-visiting (expand-file-name "Makefile"))) 274 | (dir (expand-file-name default-directory)) 275 | (dired-buffer 276 | (cl-find-if 277 | (lambda (b) 278 | (with-current-buffer b 279 | (and (eq major-mode 'dired-mode) 280 | (equal (expand-file-name default-directory) dir)))) 281 | (buffer-list))) 282 | (targets (read (mis-slurp "targets"))) 283 | (first-target (car targets)) 284 | (sources (read (mis-slurp "sources")))) 285 | (when makefile-buffer 286 | (kill-buffer makefile-buffer)) 287 | (when dired-buffer 288 | (kill-buffer dired-buffer)) 289 | (let (from to) 290 | (while (setq from (pop targets)) 291 | (setq to (pop sources)) 292 | (make-directory (file-name-directory to) t) 293 | (rename-file from to))) 294 | (let ((inhibit-message t)) 295 | (dired (file-name-directory (directory-file-name dir)))) 296 | (delete-directory dir t) 297 | (revert-buffer) 298 | (let ((pt (point))) 299 | (goto-char (point-min)) 300 | (when (string-match "\\.mix\\'" first-target) 301 | (setq first-target (substring first-target 0 (match-beginning 0)))) 302 | (if (search-forward (file-name-nondirectory first-target)) 303 | (goto-char (match-beginning 0)) 304 | (goto-char pt))))) 305 | 306 | ;;;###autoload 307 | (defun mis-finalize () 308 | "Finalize transformation. 309 | In addition to `mis-abort' copy over the files listed in 310 | \"provide\". Each Makefile should append all essential files 311 | that it creates to a \"provide\" file. All generated files not in \"provide\", 312 | i.e. intermediates and logs and such, will be deleted." 313 | (interactive) 314 | (unless (file-exists-p "Makefile") 315 | (error "No Makefile in current directory")) 316 | (unless (file-exists-p "provide") 317 | (error "No provide in current directory")) 318 | (let ((provides (split-string (mis-slurp "provide") "\n" t)) 319 | (compilation (get-buffer "*compilation*"))) 320 | (when provides 321 | (mapc (lambda (f) (mis-rename-unquote f (expand-file-name ".."))) provides) 322 | (when compilation 323 | (kill-buffer compilation))) 324 | (mis-abort))) 325 | 326 | ;;;###autoload 327 | (defun mis-replace () 328 | "Finalize transformation. 329 | In addition to `mis-finalize' move source files to trash." 330 | (interactive) 331 | (let ((sources (read (mis-slurp "sources")))) 332 | (mis-finalize) 333 | (mapc 'mis-delete-file sources)) 334 | (revert-buffer)) 335 | 336 | ;;;###autoload 337 | (defun mis-dispatch () 338 | "Choose \"mis-\" via completion." 339 | (interactive) 340 | (mis-competing-read 341 | "Action: " 342 | (mapcar 343 | (lambda (x) 344 | (list 345 | (format "% -30s%s" x 346 | (or (cdr (assoc x mis-bindings-alist)) 347 | "not bound")) 348 | x)) 349 | '(mis-finalize mis-abort mis-replace)) 350 | (lambda (x) (call-interactively (car x))))) 351 | 352 | ;;;###autoload 353 | (defun mis-save-and-compile () 354 | "Save current buffer and call `compile' with `mis-make-command'. 355 | Switch to other window afterwards." 356 | (interactive) 357 | (save-buffer) 358 | (compile mis-make-command) 359 | (with-current-buffer (compilation-find-buffer) 360 | (mis-makefile-mode))) 361 | 362 | ;;* Utilities 363 | (defun mis-directory-files (directory) 364 | "Return results of (`directory-files' DIRECTORY) without \".\" and \"..\"." 365 | (and (file-exists-p directory) 366 | (delete "." (delete ".." (directory-files directory))))) 367 | 368 | (defun mis-recipes-by-ext (ext) 369 | "Return a list of recipes available for EXT." 370 | (setq ext (or ext "nil")) 371 | (mis-directory-files 372 | (expand-file-name ext (mis-directory)))) 373 | 374 | (defun mis-recipes () 375 | "Return a list of current recipes." 376 | (let ((formats (mis-directory-files (mis-directory)))) 377 | (apply #'append 378 | (cl-loop for f in formats 379 | collect 380 | (mapcar (lambda (x) (format "%s-%s" f x)) 381 | (mis-recipes-by-ext f)))))) 382 | 383 | (defun mis-build-path (&rest lst) 384 | "Build a path from LST." 385 | (cl-reduce (lambda (a b) (expand-file-name b a)) lst)) 386 | 387 | (defun mis-build-path-create (&rest lst) 388 | "Build a path from LST. Create intermediate directories." 389 | (expand-file-name 390 | (car (last lst)) 391 | (cl-reduce 392 | (lambda (a b) 393 | (let ((dir (expand-file-name b a))) 394 | (unless (file-exists-p dir) 395 | (make-directory dir)) 396 | dir)) 397 | (butlast lst 1)))) 398 | 399 | (defun mis-slurp (file) 400 | "Return contents of FILE." 401 | (if (file-exists-p file) 402 | (with-temp-buffer 403 | (insert-file-contents file) 404 | (buffer-substring-no-properties 405 | (point-min) 406 | (point-max))) 407 | (error "No file \"%s\" in current directory" file))) 408 | 409 | (defun mis-spit (str file) 410 | "Write STR to FILE." 411 | (with-temp-buffer 412 | (insert str) 413 | (write-region nil nil file nil 1))) 414 | 415 | (defun mis-all-equal (lst) 416 | "Return t if all elements of LST are equal." 417 | (cl-every (lambda (x) (equal x (car lst))) 418 | (cdr lst))) 419 | 420 | (defun mis-action (x) 421 | "Make it so for recipe X." 422 | (let* ((mix-p (eq current-prefix-arg 2)) 423 | (sources mis-current-files) 424 | (source (file-name-nondirectory (car sources))) 425 | (ext (if mix-p "mix" (file-name-extension source))) 426 | (basedir (or (file-name-directory source) 427 | default-directory)) 428 | (dir (expand-file-name 429 | (format "%s_%s" x (file-name-nondirectory source)) 430 | basedir)) 431 | (makefile-template 432 | (mis-build-path (mis-directory) ext x "Makefile")) 433 | (makefile-name (expand-file-name "Makefile" dir))) 434 | (mkdir dir) 435 | (let ((targets (mapcar 436 | (lambda (x) 437 | (mis-rename-quote x dir mix-p)) 438 | sources))) 439 | ;; If a recipe exists, copy it. 440 | ;; Otherwise create a new one, move it here and mark it to be 441 | ;; restored to the proper location. 442 | (if (file-exists-p makefile-template) 443 | (with-temp-buffer 444 | (insert (substring mis-makefile-key-descriptions 1) "\n\n") 445 | (insert-file-contents makefile-template) 446 | (write-file makefile-name)) 447 | (let ((package-location (expand-file-name ".." mis-recipes-directory))) 448 | (unless (file-exists-p (expand-file-name ".git" package-location)) 449 | (warn "%s is not version controlled, recipes may be lost on package update" 450 | package-location))) 451 | (mis-spit (mis-create-makefile x) makefile-name) 452 | (push makefile-name targets) 453 | (push makefile-template sources)) 454 | (mis-spit (prin1-to-string targets) 455 | (expand-file-name "targets" dir)) 456 | (mis-spit (prin1-to-string sources) 457 | (expand-file-name "sources" dir)) 458 | (find-file makefile-name) 459 | (mis-makefile-mode)))) 460 | 461 | (defun mis-delete-file (file) 462 | "Delete FILE." 463 | (move-file-to-trash file)) 464 | 465 | (defun mis-rename-quote (file dir &optional mix) 466 | "Move FILE to DIR, changing spaces to underscores." 467 | (let ((dest (expand-file-name 468 | (replace-regexp-in-string 469 | ":" "β" 470 | (replace-regexp-in-string 471 | " " "α" (file-name-nondirectory file))) dir))) 472 | (when mix 473 | (setq dest (concat dest ".mix"))) 474 | (rename-file file dest) 475 | dest)) 476 | 477 | (defun mis-rename-unquote (file dir) 478 | "Move FILE to DIR, changing spaces to underscores." 479 | (let ((dest (expand-file-name 480 | (replace-regexp-in-string 481 | "β" ":" 482 | (replace-regexp-in-string 483 | "α" " " (file-name-nondirectory file))) 484 | dir))) 485 | (rename-file file dest) 486 | dest)) 487 | 488 | (defun mis-directory () 489 | "A getter for `mis-recipes-directory'." 490 | (if (file-exists-p mis-recipes-directory) 491 | mis-recipes-directory 492 | ;; look for recipes in package directory 493 | (let* ((default-directory package-user-dir) 494 | (dirs (file-expand-wildcards "*make-it-so*"))) 495 | (if (= 1 (length dirs)) 496 | (setq mis-recipes-directory 497 | (mis-build-path (car dirs) "recipes")) 498 | (error "Not one make-it-so in package dir"))))) 499 | 500 | (provide 'make-it-so) 501 | 502 | ;;; make-it-so.el ends here 503 | -------------------------------------------------------------------------------- /recipes/ape/to-flac/Makefile: -------------------------------------------------------------------------------- 1 | DIRAPE = $(shell dir *.ape) 2 | DIRFLAC = $(DIRAPE:.ape=.flac) 3 | 4 | all: clean Makefile $(DIRFLAC) 5 | 6 | %.flac: %.ape 7 | avconv -i '$^' '$@' 8 | echo '$@' >> provide 9 | 10 | clean: 11 | rm -f *.flac provide 12 | 13 | install-tools: 14 | sudo apt-get install avconv 15 | 16 | .PHONY: all install-tools clean 17 | -------------------------------------------------------------------------------- /recipes/chm/to-pdf/Makefile: -------------------------------------------------------------------------------- 1 | DIRCHM = $(shell dir *.chm) 2 | 3 | DIRPDF = $(DIRCHM:.chm=.pdf) 4 | 5 | all: clean Makefile $(DIRPDF) 6 | 7 | %.pdf: %.chm 8 | chm2pdf --continuous $^ 9 | echo $@ >> provide 10 | 11 | clean: 12 | rm -f *.pdf provide 13 | 14 | install-tools: 15 | sudo apt-get install chm2pdf 16 | 17 | .PHONY: all install-tools clean 18 | -------------------------------------------------------------------------------- /recipes/cue/split/Makefile: -------------------------------------------------------------------------------- 1 | # ——— parameters ——————————————————————————————————————————————————————————————— 2 | FILEFORMAT = "`printf %02g $$TRACKNUMBER` - $$ARTIST - $$TITLE.flac" 3 | 4 | # ——— implementation ——————————————————————————————————————————————————————————— 5 | remcontents = if [ -f $(1) ]; then cat $(1) | while read f; do rm -f "$$f";done;fi 6 | 7 | CUEFILE = $(shell dir *.cue) 8 | 9 | all: split provide 10 | 11 | split: $(CUEFILE) 12 | make clean 13 | cuebreakpoints "$(CUEFILE)" | shnsplit -o flac *.flac 14 | cuetag "$(CUEFILE)" split-track*.flac 15 | ls split-track*.flac > "$@" 16 | 17 | provide: split Makefile 18 | rm -f "$@" 19 | cat split | while read a; do \ 20 | ARTIST=`metaflac "$$a" --show-tag=ARTIST | sed s/.*=//g`; \ 21 | TITLE=`metaflac "$$a" --show-tag=TITLE | sed s/.*=//g`; \ 22 | TRACKNUMBER=`metaflac "$$a" --show-tag=TRACKNUMBER | sed s/.*=//g`; \ 23 | mv "$$a" $(FILEFORMAT); \ 24 | echo $(FILEFORMAT) >> "$@"; \ 25 | done 26 | cp "$@" split 27 | 28 | clean: 29 | if [ -f output ]; then $(call remcontents,output);rm -f output split;fi 30 | if [ -f split ]; then $(call remcontents,split);rm -f split;fi 31 | rm -f provide 32 | 33 | install-tools: 34 | sudo apt-get install cuetools shntool flac wavpack 35 | 36 | .PHONY: all install-tools clean 37 | -------------------------------------------------------------------------------- /recipes/dot/to-png/Makefile: -------------------------------------------------------------------------------- 1 | DIRDOT = $(shell dir *.dot) 2 | 3 | DIRPNG = $(DIRDOT:.dot=.png) 4 | 5 | all: clean Makefile $(DIRPNG) 6 | 7 | %.png: %.dot 8 | dot -Tpng "$^" > "$@" 9 | echo $@ >> provide 10 | 11 | clean: 12 | rm -f *.png provide 13 | 14 | install-tools: 15 | sudo apt-get install graphviz 16 | 17 | .PHONY: all install-tools clean 18 | -------------------------------------------------------------------------------- /recipes/epub/to-pdf/Makefile: -------------------------------------------------------------------------------- 1 | DIREPUB = $(shell dir *.epub) 2 | 3 | DIRPDF = $(DIREPUB:.epub=.pdf) 4 | 5 | all: clean Makefile $(DIRPDF) 6 | 7 | %.pdf: %.epub 8 | ebook-convert $^ $@ 9 | echo $@ >> provide 10 | 11 | clean: 12 | rm -f *.pdf provide 13 | 14 | install-tools: 15 | sudo apt-get install calibre 16 | 17 | .PHONY: all install-tools clean 18 | -------------------------------------------------------------------------------- /recipes/flac/to-mp3/Makefile: -------------------------------------------------------------------------------- 1 | # ——— parameters ——————————————————————————————————————————————————————————————— 2 | bitrate = 320k 3 | frequency = 48000 4 | channels = 2 5 | 6 | # ——— implementation ——————————————————————————————————————————————————————————— 7 | DIRFLAC = $(shell dir *.flac) 8 | DIRMP3 = $(DIRFLAC:.flac=.mp3) 9 | 10 | all: clean Makefile $(DIRMP3) 11 | 12 | %.mp3: %.flac 13 | avconv -i "$<" -ab $(bitrate) -ac $(channels) -ar $(frequency) "$@" 14 | echo "$@" >> provide 15 | 16 | clean: 17 | rm -f *.mp3 provide 18 | 19 | install-tools: 20 | sudo apt-get install libav-tools 21 | 22 | .PHONY: all install-tools clean 23 | -------------------------------------------------------------------------------- /recipes/gif/gifsicle/Makefile: -------------------------------------------------------------------------------- 1 | # ——— parameters ——————————————————————————————————————————————————————————————— 2 | 3 | # delay between frames in hundredths of a second 4 | delay = 60 5 | 6 | # ——— implementation ——————————————————————————————————————————————————————————— 7 | DIRGIF = $(shell ls *.gif | grep -v anime.gif) 8 | 9 | all: anime.gif 10 | 11 | anime.gif: Makefile $(DIRGIF) 12 | rm -f anime.gif 13 | gifsicle --delay=$(delay) --colors=256 --loop $(DIRGIF) -o $@ 14 | echo $@ >> provide 15 | 16 | clean: 17 | rm -f anime.gif provide 18 | 19 | install-tools: 20 | sudo apt-get install gifsicle 21 | 22 | .PHONY: all install-tools clean 23 | -------------------------------------------------------------------------------- /recipes/ipynb/to-md/Makefile: -------------------------------------------------------------------------------- 1 | DIRIPYNB = $(shell dir *.ipynb) 2 | 3 | DIRMD = $(DIRIPYNB:.ipynb=.md) 4 | 5 | all: clean Makefile $(DIRMD) 6 | 7 | %.md: %.ipynb 8 | jupyter nbconvert --to markdown $^ 9 | echo $@ >> provide 10 | 11 | clean: 12 | rm -f *.md provide 13 | 14 | install-tools: 15 | sudo pip install jupyter 16 | 17 | .PHONY: all install-tools clean 18 | -------------------------------------------------------------------------------- /recipes/m4a/to-mp3/Makefile: -------------------------------------------------------------------------------- 1 | DIRM4A = $(shell dir *.m4a) 2 | 3 | DIRMP3 = $(DIRM4A:.m4a=.mp3) 4 | 5 | all: clean Makefile $(DIRMP3) 6 | 7 | %.mp3: %.m4a 8 | ffmpeg -v 5 -y -i "$^" -acodec libmp3lame -ac 2 -ab 192k "$@" 9 | echo "$@" >> provide 10 | 11 | clean: 12 | rm -f *.mp3 provide 13 | 14 | install-tools: 15 | sudo apt-get install ffmpeg 16 | 17 | .PHONY: all install-tools clean 18 | -------------------------------------------------------------------------------- /recipes/md/to-html/Makefile: -------------------------------------------------------------------------------- 1 | DIRMD = $(shell dir *.md) 2 | DIRHTML = $(DIRMD:.md=.html) 3 | 4 | all: clean Makefile $(DIRHTML) 5 | 6 | %.html: %.md 7 | pandoc -o "$@" "$^" 8 | echo "$@" >> provide 9 | 10 | clean: 11 | rm -f *.html provide 12 | 13 | install-tools: 14 | sudo apt-get install pandoc 15 | 16 | .PHONY: all install-tools clean 17 | -------------------------------------------------------------------------------- /recipes/md/to-org/Makefile: -------------------------------------------------------------------------------- 1 | DIRMD = $(shell dir *.md) 2 | 3 | DIRORG = $(DIRMD:.md=.org) 4 | 5 | all: clean Makefile $(DIRORG) 6 | 7 | %.org: %.md 8 | pandoc $^ -o $@ 9 | echo $@ >> provide 10 | 11 | clean: 12 | rm -f *.org provide 13 | 14 | install-tools: 15 | sudo apt-get install pandoc 16 | 17 | .PHONY: all install-tools clean 18 | -------------------------------------------------------------------------------- /recipes/mix/enca/Makefile: -------------------------------------------------------------------------------- 1 | # ——— parameters ——————————————————————————————————————————————————————————————— 2 | LANGUAGE = zh_CN 3 | ENCODE_TO = utf-8 4 | 5 | # ——— implementation ——————————————————————————————————————————————————————————— 6 | DIRMIX = $(shell dir *.mix) 7 | DIROUT = $(DIRMIX:.mix=.out) 8 | 9 | all: $(DIROUT) 10 | 11 | %.out: %.mix 12 | cp "$^" "$@" 13 | enca -L $(LANGUAGE) -x $(ENCODE_TO) "$@" 14 | echo "$@" >> provide 15 | 16 | install-tools: 17 | sudo apt-get install enca 18 | 19 | .PHONY: all install-tools 20 | -------------------------------------------------------------------------------- /recipes/mp3/trim/Makefile: -------------------------------------------------------------------------------- 1 | # ——— parameters ——————————————————————————————————————————————————————————————— 2 | from_to = -ss 00:00:10 -t 00:00:25 3 | from_to = -ss 00:00:10 4 | # ——— implementation ——————————————————————————————————————————————————————————— 5 | DIRMP3 = $(shell dir *.mp3) 6 | 7 | DIROUT.MP3 = $(DIRMP3:.mp3=.out.mp3) 8 | 9 | all: clean Makefile $(DIROUT.MP3) 10 | 11 | %.out.mp3: %.mp3 12 | ffmpeg -i "$<" -acodec copy $(from_to) "$@" 13 | echo "$@" >> provide 14 | 15 | clean: 16 | rm -f *.out.mp3 provide 17 | 18 | install-tools: 19 | sudo apt-get install ffmpeg 20 | 21 | .PHONY: all install-tools clean 22 | -------------------------------------------------------------------------------- /recipes/mp4/replace-audio/Makefile: -------------------------------------------------------------------------------- 1 | DIRMP4 = $(shell dir *.mp4) 2 | DIRMP3 = $(shell dir *.mp3) 3 | 4 | DIROUT.MP4 = $(DIRMP4:.mp4=.out.mp4) 5 | 6 | all: clean Makefile $(DIROUT.MP4) 7 | 8 | %.out.mp4: %.mp4 9 | avconv -i "$^" -i $(DIRMP3) \ 10 | -c:v copy -map 0:0 -map 1:0 \ 11 | -c:a libvo_aacenc -b:a 320k -ar 48000 -async 48000 \ 12 | "$@" 13 | 14 | clean: 15 | rm -f *.out.mp4 provide 16 | 17 | install-tools: 18 | sudo apt-get install libavcodec-extra 19 | 20 | .PHONY: all install-tools clean 21 | -------------------------------------------------------------------------------- /recipes/mp4/to-mp3/Makefile: -------------------------------------------------------------------------------- 1 | # ——— parameters ——————————————————————————————————————————————————————————————— 2 | bitrate = 320k 3 | 4 | # ——— implementation ——————————————————————————————————————————————————————————— 5 | DIRMP4 = $(shell dir *.mp4) 6 | DIRMP3 = $(DIRMP4:.mp4=.mp3) 7 | 8 | all: clean Makefile $(DIRMP3) 9 | 10 | %.mp3: %.mp4 11 | AV_LOG_FORCE_NOCOLOR=TRUE avconv -loglevel info -i "$<" -vn -ab $(bitrate) "$@" 12 | echo "$@" >> provide 13 | 14 | clean: 15 | rm -f *.mp3 provide 16 | 17 | install-tools: 18 | sudo apt-get install libav-tools libavcodec-extra 19 | 20 | .PHONY: all install-tools clean 21 | -------------------------------------------------------------------------------- /recipes/mp4/trim/Makefile: -------------------------------------------------------------------------------- 1 | # ——— parameters ——————————————————————————————————————————————————————————————— 2 | from = 00:00:00 3 | to = 00:00:23 4 | 5 | # ——— implementation ——————————————————————————————————————————————————————————— 6 | DIRMP4 = $(shell find . -maxdepth 1 -name '*.mp4' -type f ! -name '*.out.mp4' | tr '\n' ' ') 7 | DIROUT.MP4 = $(DIRMP4:.mp4=.out.mp4) 8 | 9 | all: Makefile $(DIROUT.MP4) 10 | 11 | %.out.mp4: %.mp4 12 | avconv -i "$^" -vcodec copy -acodec copy -ss $(from) -t $(to) "$@" 13 | echo "$@" >> provide 14 | 15 | clean: 16 | rm -f *.out.mp4 provide 17 | 18 | install-tools: 19 | sudo apt-get install libav-tools 20 | 21 | .PHONY: all install-tools clean 22 | -------------------------------------------------------------------------------- /recipes/ogv/crop/Makefile: -------------------------------------------------------------------------------- 1 | # ——— parameters ——————————————————————————————————————————————————————————————— 2 | left = 1 3 | top = 10 4 | width = 220 5 | height = 220 6 | 7 | # ——— implementation ——————————————————————————————————————————————————————————— 8 | INOGV = $(shell find . -maxdepth 1 -type f -name '*.ogv' ! -name '*.out.ogv' | tr '\n' ' ') 9 | OUTOGV = $(INOGV:.ogv=.out.ogv) 10 | 11 | all: clean $(OUTOGV) 12 | 13 | %.out.ogv: %.ogv 14 | rm -f *.out.ogv 15 | ffmpeg -i "$<" -r 24 -mbd rd -flags +mv4+aic -trellis 2 -cmp 2 -subcmp 2 -g 300 -pass 1 \ 16 | -y -f ogg -vf "crop=$(width):$(height):$(left):$(top)" /dev/null 17 | ffmpeg -i "$<" -r 24 -mbd rd -flags +mv4+aic -trellis 2 -cmp 2 -subcmp 2 -g 300 -pass 2 \ 18 | -vf "crop=$(width):$(height):$(left):$(top)" "$@" 19 | echo "$@" >> provide 20 | 21 | clean: 22 | rm -f *.out.ogv *.log provide 23 | 24 | install-tools: 25 | sudo apt-get install ffmpeg 26 | 27 | .PHONY: all install-tools clean 28 | -------------------------------------------------------------------------------- /recipes/ogv/to-gif/Makefile: -------------------------------------------------------------------------------- 1 | # ——— comments ————————————————————————————————————————————————————————————————— 2 | # The frames are stored in output/. You can 3 | # - delete frames with e.g. dired 4 | # - edit frames with e.g. GIMP 5 | # Afterwards, call make again to compose the frames in output/ into a gif. 6 | 7 | # ——— implementation ——————————————————————————————————————————————————————————— 8 | OGV = $(shell find . -maxdepth 1 -type f -name '*.ogv' ! -name '*.out.ogv' | tr '\n' ' ') 9 | GIF = $(OGV:.ogv=.gif) 10 | 11 | all: $(GIF) 12 | 13 | %.output: %.ogv 14 | mplayer -ao null $< -vo jpeg:outdir="$@" 15 | 16 | %.unoptimized.gif: %.output 17 | convert "$> provide 22 | 23 | clean: 24 | rm -f *.gif 25 | rm -rf ./*.output 26 | 27 | install-tools: 28 | sudo apt-get install ffmpeg imagemagick 29 | 30 | .PHONY: all install-tools provide clean 31 | -------------------------------------------------------------------------------- /recipes/ogv/to-mp4/Makefile: -------------------------------------------------------------------------------- 1 | DIROGV = $(shell dir *.ogv) 2 | DIRMP4 = $(DIROGV:.ogv=.mp4) 3 | 4 | all: clean Makefile $(DIRMP4) 5 | 6 | %.mp4: %.ogv 7 | avconv -i $^ $@ 8 | echo $@ >> provide 9 | 10 | clean: 11 | rm -f *.mp4 provide 12 | 13 | install-tools: 14 | sudo apt-get install avconv 15 | 16 | .PHONY: all install-tools clean 17 | -------------------------------------------------------------------------------- /recipes/ogv/trim/Makefile: -------------------------------------------------------------------------------- 1 | # ——— parameters ——————————————————————————————————————————————————————————————— 2 | from = 00:00:01 3 | to = 00:00:23 4 | 5 | # ——— implementation ——————————————————————————————————————————————————————————— 6 | INOGV = $(shell find . -maxdepth 1 -name '*.ogv' -type f ! -name '*.out.ogv' | tr '\n' ' ') 7 | OUTOGV = $(INOGV:.ogv=.out.ogv) 8 | 9 | all: $(OUTOGV) 10 | 11 | %.out.ogv: %.ogv Makefile 12 | rm -f "$@" 13 | ffmpeg -i $< -ss $(from) -t $(to) -vcodec copy -acodec copy "$@" 14 | echo "$@" >> provide 15 | 16 | clean: 17 | rm -f *.out.ogv provide 18 | 19 | install-tools: 20 | sudo apt-get install ffmpeg 21 | 22 | .PHONY: all install-tools clean 23 | -------------------------------------------------------------------------------- /recipes/pdf/to-txt/Makefile: -------------------------------------------------------------------------------- 1 | DIRPDF = $(shell dir *.pdf 2>/dev/null) 2 | 3 | DIRTXT = $(DIRPDF:.pdf=.txt) 4 | 5 | all: clean Makefile $(DIRTXT) 6 | 7 | %.txt: %.pdf 8 | pdftotext $^ 9 | echo $@ >> provide 10 | 11 | clean: 12 | rm -f *.txt provide 13 | 14 | install-tools: 15 | sudo apt-get install poppler-utils 16 | 17 | .PHONY: all install-tools clean 18 | -------------------------------------------------------------------------------- /recipes/png/to-gif/Makefile: -------------------------------------------------------------------------------- 1 | DIRPNG = $(shell dir *.png) 2 | 3 | DIRGIF = $(DIRPNG:.png=.gif) 4 | 5 | all: clean Makefile $(DIRGIF) 6 | 7 | %.gif: %.png 8 | convert $^ -channel Alpha -threshold 80% $@ 9 | echo $@ >> provide 10 | 11 | clean: 12 | rm -f *.gif provide 13 | 14 | install-tools: 15 | echo "No tools required" 16 | 17 | .PHONY: all install-tools clean 18 | -------------------------------------------------------------------------------- /recipes/svg/to-png/Makefile: -------------------------------------------------------------------------------- 1 | # ——— parameters ——————————————————————————————————————————————————————————————— 2 | width = 320 3 | height = 320 4 | 5 | # ——— implementation ——————————————————————————————————————————————————————————— 6 | DIRSVG = $(shell dir *.svg) 7 | 8 | DIRPNG = $(DIRSVG:.svg=.png) 9 | 10 | all: clean Makefile $(DIRPNG) 11 | 12 | %.png: %.svg 13 | inkscape -z -e "$@" -w $(width) -h $(height) "$^" 14 | echo "$@" >> provide 15 | 16 | clean: 17 | rm -f *.png provide 18 | 19 | install-tools: 20 | sudo apt-get install inkscape 21 | 22 | .PHONY: all install-tools clean 23 | -------------------------------------------------------------------------------- /recipes/tiff/to-jpg/Makefile: -------------------------------------------------------------------------------- 1 | DIRTIFF = $(shell dir *.tiff) 2 | 3 | DIRJPG = $(DIRTIFF:.tiff=.jpg) 4 | 5 | all: clean Makefile $(DIRJPG) 6 | 7 | %.jpg: %.tiff 8 | convert $^ $@ 9 | echo $@ >> provide 10 | 11 | clean: 12 | rm -f *.jpg provide 13 | 14 | install-tools: 15 | echo "No tools required" 16 | 17 | .PHONY: all install-tools clean 18 | -------------------------------------------------------------------------------- /recipes/txt/encode-utf8/Makefile: -------------------------------------------------------------------------------- 1 | DIRTXT = $(shell dir *.txt) 2 | 3 | DIROUT.TXT = $(DIRTXT:.txt=.out.txt) 4 | 5 | all: clean Makefile $(DIROUT.TXT) 6 | 7 | %.out.txt: %.txt 8 | iconv -t UTF-8 $^ > $@ 9 | echo $@ >> provide 10 | 11 | clean: 12 | rm -f *.out.txt provide 13 | 14 | install-tools: 15 | echo "No tools required" 16 | 17 | .PHONY: all install-tools clean 18 | --------------------------------------------------------------------------------