-
Notifications
You must be signed in to change notification settings - Fork 2
/
Copy pathemacs-modular-configuration.el
156 lines (140 loc) · 5.58 KB
/
emacs-modular-configuration.el
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
;;; emacs-modular-configuration.el --- making modular your config file
;;
;; Copyright (C) 2014-2017 Emanuele Tomasi <targzeta@gmail.com>
;;
;; Author: Emanuele Tomasi <targzeta@gmail.com>
;; URL: https://github.com/targzeta/emacs-modular-configuration
;; Maintainer: Emanuele Tomasi <targzeta@gmail.com>
;; Keywords: modular, config
;; Version: 2.0
;;
;; This file is NOT part of GNU Emacs.
;;
;; This program is free software: you can redistribute it and/or
;; modify it under the terms of the GNU General Public License as
;; published by the Free Software Foundation, either version 3 of the
;; License, or (at your option) any later version.
;;
;; This program is distributed in the hope that it will be useful,
;; but WITHOUT ANY WARRANTY; without even the implied warranty of
;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
;; General Public License for more details.
;;
;; You should have received a copy of the GNU General Public License
;; along with this program. If not, see <http://www.gnu.org/licenses/>.
;;
;;; Commentary:
;;
;; Emacs Modular Configuration lets you split your Emacs configuration within
;; of a (configurable) "~/.emacs.d/emc/config" directory. When you're ready,
;; simply call `emc-merge-config-files' and all the ".el" files under that
;; directory tree will merge on a (configurable)
;; "~/.emacs.d/emc/emc-config.el". Lastly, this file will be byte compiled, so
;; all you need to write on your Emacs initalization file (e.g. "~/.emacs" or
;; "~/.emacs.d/init.el") is:
;;
;; (load "~/.emacs.d/emc/emc-config")
;;
;; Note: the directory tree ~/.emacs.d/emc/config will be visited recursively
;; using the BFS algorithm and in alphabetical order.
;;
;;; Installation:
;;
;; Copy this file in a directory which is in the Emacs `load-path', so add this
;; to your Emacs initalization file (e.g. "~/.emacs" or "~/.emacs.d/init.el"):
;; (require 'emacs-modular-configuration)
;; (load ~/.emacs.d/emc/emc-config t)
;;
;;; Usage:
;;
;; Write a bit of ".el" files within "~/.emacs.d/emc/config" directory tree and
;; then run M-x emc-merge-config-files.
;;
;; Next time you start Emacs, you'll load the "~/.emacs.d/emc/emc-config.elc"
;; file. That's all.
;;
;; Customization:
;;
;; M-x customize-group and then "modular-configuration"
;;
;;; Code:
(require 'cl-lib)
;; Definitions
(defgroup add-ons nil
"External add-ons."
:group 'emacs)
(defgroup modular-configuration nil
"Making modular your config file."
:group 'add-ons
:version "2.0"
:prefix "emc")
(defvar emc-version "2.0")
;; Customization
(defcustom emc-config-directory "~/.emacs.d/emc/config"
"Directory tree that contains all your configuration files."
:type 'directory
:group 'modular-configuration)
(defcustom emc-config-file "~/.emacs.d/emc/emc-config.el"
"File where all your configuration files will be merged."
:type 'file
:group 'modular-configuration)
;; Functions
(defun emc-recursive-directory (nodes function)
"Executes FUNCTION for every '.el' file under the DIRECTORY tree.
The DIRECTORY will be visited recursively using the Breadth First
algorithm with every level in alphabetical order.
\n(fn DIRECTORY FUNCTION)"
(unless (listp nodes) (setq nodes (list nodes)))
(let ((directory (pop nodes)))
(when directory
(dolist (element (directory-files-and-attributes directory))
(let* ((path (car element))
(fullpath (concat directory path))
(isdir (car (cdr element)))
(ignore-dir (or (string= path ".") (string= path ".."))))
(cond
((and (eq isdir t) (not ignore-dir))
(push (file-name-as-directory fullpath) nodes))
((and (string= (file-name-extension path) "el") (not (eq isdir t)))
(funcall function fullpath)))))
(emc-recursive-directory (reverse nodes) function))))
(defun emc--merge-file (filename)
(message (format "[emc] Merging %s" filename))
(insert (format "\n;;; Config file: %s\n" filename))
(insert-file-contents filename)
(goto-char (point-max))
(insert ";;;***\n"))
(defun emc--merge-files-and-compile (src-dir dest-file header footer)
(with-temp-file dest-file
(insert header)
(emc-recursive-directory (file-name-as-directory src-dir) 'emc--merge-file)
(insert footer))
(byte-compile-file dest-file))
;;;###autoload
(cl-defun emc-merge-config-files ()
"Merges all `.el' files under `emc-config-directory' on `emc-config-file'.
Whereupon, the `emc-config-file' will also byte-compiled"
(interactive)
(unless (file-exists-p emc-config-directory)
(message (format "[emc] %s not found. Nothing to do!"
emc-config-directory))
(cl-return-from emc-merge-config-files))
; Ensuring destination directory
(mkdir (file-name-directory emc-config-file) t)
(message (format "[emc] Config file will merge into %s" emc-config-file))
(let ((header (concat
";; -*- eval: (read-only-mode 1) -*-\n\n"
";;; " emc-config-file " -- Emacs configurations\n\n"
";; Generated by Emacs Modular Configuration version "
emc-version "\n"
";; DO NOT EDIT THIS FILE.\n"
";; Edit the files under '" emc-config-directory
"' directory tree,\n"
";; then run within emacs"
" 'M-x emc-merge-config-files'\n\n"
";;; Code:\n\n"))
(footer (format ";;; %s ends here" emc-config-file)))
(emc--merge-files-and-compile emc-config-directory emc-config-file
header footer)))
(provide 'emacs-modular-configuration)
;;; emacs-modular-configuration.el ends here