substitute: Improve functional decomposition.
[guix.git] / guix / build / emacs-utils.scm
blobfd06aad7ac7bd4af797325288a313dbce038f5d5
1 ;;; GNU Guix --- Functional package management for GNU
2 ;;; Copyright © 2014 Mark H Weaver <mhw@netris.org>
3 ;;; Copyright © 2014 Alex Kost <alezost@gmail.com>
4 ;;;
5 ;;; This file is part of GNU Guix.
6 ;;;
7 ;;; GNU Guix is free software; you can redistribute it and/or modify it
8 ;;; under the terms of the GNU General Public License as published by
9 ;;; the Free Software Foundation; either version 3 of the License, or (at
10 ;;; your option) any later version.
11 ;;;
12 ;;; GNU Guix is distributed in the hope that it will be useful, but
13 ;;; WITHOUT ANY WARRANTY; without even the implied warranty of
14 ;;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15 ;;; GNU General Public License for more details.
16 ;;;
17 ;;; You should have received a copy of the GNU General Public License
18 ;;; along with GNU Guix.  If not, see <http://www.gnu.org/licenses/>.
20 (define-module (guix build emacs-utils)
21   #:export (%emacs
22             emacs-batch-eval
23             emacs-batch-edit-file
24             emacs-generate-autoloads
25             emacs-byte-compile-directory
26             emacs-substitute-sexps
27             emacs-substitute-variables))
29 ;;; Commentary:
30 ;;;
31 ;;; Tools to programmatically edit files using Emacs,
32 ;;; e.g. to replace entire s-expressions in elisp files.
33 ;;;
34 ;;; Code:
36 (define %emacs
37   ;; The `emacs' command.
38   (make-parameter "emacs"))
40 (define (emacs-batch-eval expr)
41   "Run Emacs in batch mode, and execute the elisp code EXPR."
42   (unless (zero? (system* (%emacs) "--quick" "--batch"
43                           (format #f "--eval=~S" expr)))
44     (error "emacs-batch-eval failed!" expr)))
46 (define (emacs-batch-edit-file file expr)
47   "Load FILE in Emacs using batch mode, and execute the elisp code EXPR."
48   (unless (zero? (system* (%emacs) "--quick" "--batch"
49                           (string-append "--visit=" file)
50                           (format #f "--eval=~S" expr)))
51     (error "emacs-batch-edit-file failed!" file expr)))
53 (define (emacs-generate-autoloads name directory)
54   "Generate autoloads for Emacs package NAME placed in DIRECTORY."
55   (let* ((file (string-append directory "/" name "-autoloads.el"))
56          (expr `(let ((backup-inhibited t)
57                       (generated-autoload-file ,file))
58                   (update-directory-autoloads ,directory))))
59     (emacs-batch-eval expr)))
61 (define* (emacs-byte-compile-directory dir #:optional (dependency-dirs '()))
62   "Byte compile all files in DIR and its sub-directories.  Before compiling
63 the files, add DIR and all directories in DEPENDENCY-DIRS to 'load-path'."
64   (let ((expr `(progn
65                 (add-to-list 'load-path ,dir)
66                 (when ',dependency-dirs
67                   (setq load-path (append ',dependency-dirs load-path)))
68                 (byte-recompile-directory (file-name-as-directory ,dir) 0))))
69     (emacs-batch-eval expr)))
71 (define-syntax emacs-substitute-sexps
72   (syntax-rules ()
73     "Substitute the S-expression immediately following the first occurrence of
74 LEADING-REGEXP by the string returned by REPLACEMENT in FILE.  For example:
76   (emacs-substitute-sexps \"w3m.el\"
77     (\"defcustom w3m-command\"
78      (string-append w3m \"/bin/w3m\"))
79     (\"defvar w3m-image-viewer\"
80      (string-append imagemagick \"/bin/display\")))
82 This replaces the default values of the `w3m-command' and `w3m-image-viewer'
83 variables declared in `w3m.el' with the results of the `string-append' calls
84 above.  Note that LEADING-REGEXP uses Emacs regexp syntax."
85     ((emacs-substitute-sexps file (leading-regexp replacement) ...)
86      (emacs-batch-edit-file file
87        `(progn (progn (goto-char (point-min))
88                       (re-search-forward ,leading-regexp)
89                       (kill-sexp)
90                       (insert " ")
91                       (insert ,(format #f "~S" replacement)))
92                ...
93                (basic-save-buffer))))))
95 (define-syntax emacs-substitute-variables
96   (syntax-rules ()
97     "Substitute the default value of VARIABLE by the string returned by
98 REPLACEMENT in FILE.  For example:
100   (emacs-substitute-variables \"w3m.el\"
101     (\"w3m-command\" (string-append w3m \"/bin/w3m\"))
102     (\"w3m-image-viewer\" (string-append imagemagick \"/bin/display\")))
104 This replaces the default values of the `w3m-command' and `w3m-image-viewer'
105 variables declared in `w3m.el' with the results of the `string-append' calls
106 above."
107     ((emacs-substitute-variables file (variable replacement) ...)
108      (emacs-substitute-sexps file
109        ((string-append "(def[a-z]+[[:space:]\n]+" variable "\\>")
110         replacement)
111        ...))))
113 ;;; emacs-utils.scm ends here