kaarvok/kaarvok.el

140 lines
5 KiB
EmacsLisp
Raw Normal View History

;;; kaarvok --- Generate directory structures from templates
2013-05-20 01:20:26 +02:00
;; Copyright (C) 2013 Tom Willemse
;; Author: Tom Willemse <tom@ryuslash.org>
;; Keywords: convenience
;; Package-Version: 0.1.0
;; This file is part of kaarvok.
2013-05-20 01:20:26 +02:00
;; kaarvok 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.
2013-05-20 01:20:26 +02:00
;; kaarvok is distributed in the hope that it will be useful, but
;; WITHOUT ANY WARRANTY; without even the implied warranty of
2013-05-20 01:20:26 +02:00
;; 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 kaarvok. If not, see <http://www.gnu.org/licenses/>.
2013-05-20 01:20:26 +02:00
;;; Commentary:
;; This project helps you recreate directory structures from template
;; directory structures. The files, file names and directory names of
;; these templates contain variable placeholders, which will be
;; replaced by whatever value you wish to use when copied.
;;; Code:
(defvar kaarvok-templates-directory "~/.emacs.d/templates"
2012-05-17 18:41:04 +02:00
"Where templates are stored.")
(defvar kaarvok-template-var-delimiter "$!"
"Strings used to delimit variable names.")
(defun kaarvok-template-var-regexp ()
"Create the regexp which identifies a variable in a template."
(concat kaarvok-template-var-delimiter
"\\([^" kaarvok-template-var-delimiter " \t\n]+\\)"
kaarvok-template-var-delimiter))
2012-05-17 18:41:04 +02:00
(defvar kaarvok-value-alist nil
"A placeholder where replacement values will be kept.
2012-05-17 18:41:04 +02:00
This is let-bound when `kaarvok-create-project-from-template' is
called and should not be edited directly.")
(defun kaarvok-replace-all (from to str)
2012-05-27 15:56:10 +02:00
"Simply replace all occurrences of FROM with TO in STR."
2012-05-17 18:41:04 +02:00
(while (string-match from str)
(set 'str (replace-match to t t str)))
str)
(defun kaarvok-get-replacement (key)
2012-05-27 15:56:10 +02:00
"Find, or ask for and save, the replacement value for KEY."
(let ((replacement (assoc key kaarvok-value-alist)))
2012-05-17 18:41:04 +02:00
(when (eq replacement nil)
(set 'replacement
`(,key . ,(read-from-minibuffer (concat key ": "))))
(add-to-list 'kaarvok-value-alist replacement))
2012-05-17 18:41:04 +02:00
replacement))
(defun kaarvok-parse-file-name (filename)
"Parse FILENAME and replace all variables.
Use values provided by the user."
(while (string-match (kaarvok-template-var-regexp) filename)
2012-05-17 18:41:04 +02:00
(let* ((tpl-var (match-string 1 filename))
(replacement-value (kaarvok-get-replacement tpl-var)))
2012-05-17 18:41:04 +02:00
(set 'filename (replace-match (cdr replacement-value) t t
filename))))
(let ((noext (file-name-sans-extension filename))
(ext (file-name-extension filename t)))
(set 'noext (kaarvok-replace-all "\\." "/" noext))
2012-05-17 18:41:04 +02:00
(concat noext ext)))
(defun kaarvok-parse-file (file)
"Parse FILE and replace all variables."
2012-05-17 18:41:04 +02:00
(insert-file-contents file)
(while (re-search-forward (kaarvok-template-var-regexp) nil t)
2012-05-17 18:41:04 +02:00
(let* ((tpl-var (match-string 1))
(replacement-value (kaarvok-get-replacement tpl-var)))
2012-05-17 18:41:04 +02:00
(replace-match (cdr replacement-value) t t))))
(defun kaarvok-parse-and-copy-file (src dst)
"Copy SRC to DST.
If necessary, parse the file and filename first."
(let* ((parsed-dst (kaarvok-parse-file-name dst))
2012-05-17 18:41:04 +02:00
(parsed-dst-dir (file-name-directory parsed-dst)))
(when (not (file-exists-p parsed-dst-dir))
(make-directory parsed-dst-dir t))
(with-temp-file parsed-dst
(kaarvok-parse-file src))))
2012-05-17 18:41:04 +02:00
(defun kaarvok-copy-directory (directory to)
"Copy template DIRECTORY to TO.
Parse both paths and files in the process."
2012-05-17 18:41:04 +02:00
(let ((files (directory-files directory t "[^.]\\{1,2\\}$" t)))
(while files
(let* ((src-filename (car files))
(dst-filename
(concat to "/" (file-name-nondirectory src-filename))))
(if (file-directory-p src-filename)
(kaarvok-copy-directory src-filename dst-filename)
2012-05-17 18:41:04 +02:00
(if (string-equal (file-name-extension src-filename) "etpl")
(kaarvok-parse-and-copy-file
2012-05-17 18:41:04 +02:00
src-filename (file-name-sans-extension dst-filename))
(let ((to (kaarvok-parse-file-name to)))
(if (not (file-exists-p to))
(make-directory to t)
(unless (file-directory-p to)
(error
(concat "Cannot create project at %s, file "
"already exists and is not a directory.") to))))
(copy-file src-filename
(kaarvok-parse-file-name dst-filename)))))
2012-05-17 18:41:04 +02:00
(set 'files (cdr files)))))
;;;###autoload
(defun kaarvok-create-project-from-template (template destination)
"Take TEMPLATE, copy it to DESTINATION.
Replace any occurrences of variables with user-povided values."
2012-05-17 18:41:04 +02:00
(interactive "MTemplate: \nGDestination: ")
(let ((kaarvok-value-alist))
(kaarvok-copy-directory
(concat kaarvok-templates-directory "/" template) destination)))
2012-05-27 15:56:52 +02:00
(provide 'kaarvok)
;;; kaarvok.el ends here