https://github.com/chrisbarrett/skeletor.el.git
git clone 'git://github.com/chrisbarrett/skeletor.el.git'
Skeletor provides project templates for Emacs. It also automates the mundane parts of setting up a new project like version control, licenses and tooling.
Skeletor comes with a number of predefined templates and allows you to easily create your own.
Table of Contents
Skeletor comes with predefined project types so it is useful out-of-the-box:
Skeletor is designed to be extensible so you can create your own templates.
Skeletor is available on MELPA. This is the easiest way to install.
Add the following to your init.el:
(require 'package)
(add-to-list 'package-archives
'("melpa" . "http://melpa.milkbox.net/packages/") t)
(when (< emacs-major-version 24)
;; For important compatibility libraries like cl-lib
(add-to-list 'package-archives '("gnu" . "http://elpa.gnu.org/packages/")))
(package-initialize)
Run the following in Emacs to install Skeletor:
M-x package-install skeletor
You will need Emacs 24+, make and Cask to build the project. You will also need to configure MELPA to install dependencies.
Add the following to your init.el:
(require 'package)
(add-to-list 'package-archives
'("melpa" . "http://melpa.milkbox.net/packages/") t)
(when (< emacs-major-version 24)
;; For important compatibility libraries like cl-lib
(add-to-list 'package-archives '("gnu" . "http://elpa.gnu.org/packages/")))
(package-initialize)
Then run the following in the shell to clone Skeletor and install it.
cd
git clone git@github.com:chrisbarrett/skeletor.el.git
cd skeletor
make && make install
Use M-x skeletor-create-project
to create a new project based on an existing template.
You will be guided through any configuration needed.
By default, new projects are created in ~/Projects
. Customise
skeletor-project-directory
to change this.
An additional command, skeletor-create-project-at
, allows you to choose the
directory where the project will be created.
Skeletor allows you to define new types of projects. You can either create a project template, called a skeleton, or you can use an external tool to create the project and use Skeletor to perform additional configuration.
Project skeletons are templates for constructing new projects. The following discussion will use the terms skeleton and template interchangeably.
There are two parts to defining a new project skeleton, discussed in the following sections.
Skeletor uses physical files and directories to represent project templates. When you create a project, Skeletor will copy the template directory and apply certain transformations.
To create a template, make a new directory in skeletor-user-directory
. It can
contain any files and directories you'd like.
It is a good idea to add any files needed for distributing the project source.
Most of the templates that ship with Skeletor include a Makefile, .gitignore
,
README and contributing guidelines.
Below is an example project skeleton structure for Emacs Lisp:
my-elisp-package/
|-- .gitignore
|-- CONTRIBUTING.md
|-- Cask
|-- Makefile
|-- README.md
|-- __PROJECT-NAME__.el
`-- doc
`-- __PROJECT-NAME__.org
Note that Skeletor will handle the creation of a license file itself, so you should not add one to your skeleton.
Once you have created a project skeleton, use the skeletor-define-template
macro to configure how the project template will be created.
Basic Configuration
In the simplest case, you just need to tell Skeletor the name of the template:
(skeletor-define-template "my-elisp-package")
This will add my-elisp-package
to the list of available projects. You can now
create an instance by calling M-x skeletor-create-project my-elisp-package
. Skeletor
will manage the creation of the project, prompt you to choose a license, and
initialise a git repository at the root of the project.
Titles
You can set a custom title for your project type using the :title
keyword
parameter.
(skeletor-define-template "my-elisp-package"
:title "My Elisp Package")
The title is the string that represents the project in the skeletor-create-project
prompt.
Default Licenses
Skeletor will prompt you to select a license when you create a project. Some communities favour a particular license, so Skeletor allows you to pre-populate the license prompt.
For example, Elisp projects are generally licensed under GPL:
(skeletor-define-template "my-elisp-package"
; ...
:default-license (rx bol "gpl"))
Note that the argument to :default-license
is a regular expression so you
don't have to specify the license name precisely.
Custom Actions
You can use the :after-creation
keyword parameter to perform additional
actions after a project has been created. It takes a single-parameter function
taking the path to the newly-created project.
For example, the Elisp project runs a Makefile task in the background to configure the development environment:
(skeletor-define-template "elisp-package"
; ...
:after-creation
(lambda (dir)
(skeletor-async-shell-command "make env")))
You can do anything you want in the after-creation
command, but it is a good
idea to automate as much of the environment setup as possible using a makefile
or shell script. This will help other developers who want to contribute to your
project.
External Tools
Sometimes you need to use an external tool to perform part of the project
configuration. Skeletor provides the skeletor-shell-command
and
skeletor-async-shell-command
functions for this purpose. These functions output to
special buffers and assert that their shell commands were successful.
(skeletor-define-template "elisp-package"
; ...
:after-creation
(lambda (dir)
(skeletor-async-shell-command "make env")))
Because such external tools may not be installed on every system, Skeletor
provides a way to declare these requirements up-front using the
:requires-executables
keyword parameter. It takes an alist of (PROGRAM .
URL)
, where URL
is a link to a project page or download instructions.
For example, the elisp-package
template uses make
and Cask
to bootstrap
the development environment and declares its dependency on these programs:
(skeletor-define-template "elisp-package"
; ...
:requires-executables '(("make" . "http://www.gnu.org/software/make/")
("cask" . "https://github.com/cask/cask")))
Skeletor will search for these two programs when creating an instance of the template. It will display a help window with download links if either of them cannot be found.
Skeletor can perform text substitutions when it creates new projects. This makes it possible to refer to the name of the project, add time-stamps and customise the contents of files according to user input when a project is created.
The __PROJECT-NAME__
substitution is a useful example. Given the following
skeleton,
my-elisp-package/
|-- __PROJECT-NAME__.el
`-- doc
`-- __PROJECT-NAME__.org
the project name entered by the user will be used to name the files. Given a project named foo, Skeletor would instantiate this skeleton as:
foo/
|-- foo.el
`-- doc
`-- foo.org
Substitutions are also applied to the text inside files. A file with the contents,
Name: __USER-NAME__
Project: __PROJECT-NAME__
might be expanded as:
Name: Jane Coder
Project: foo
The skeletor-global-substitutions
variable defines the substitutions available to
all skeletons. It is an alist, where each element is a cons of (STRING .
REPLACEMENT)
. REPLACEMENT
should be a string literal, a variable name, a
function name, or a lambda expression.
You can add your own items to skel-globl-substitutions
. For example:
(add-to-list 'skeletor-global-substitutions
'("__ORGANISATION__" . "Masters of the Universe"))
(add-to-list 'skeletor-global-substitutions
(cons "__HOME__" (getenv "HOME")))
(add-to-list 'skeletor-global-substitutions
(cons "__TIME__" (lambda () (format-time-string "%c"))))
You can also define substitutions available to individual skeletons:
(skeletor-define-template "my-package"
:substitutions
'(("__DESCRIPTION__" . (lambda () (read-string "Description: ")))))
This will prompt you to enter a description when creating an instance of this project.
Template files may contain embedded Elisp expressions that will be evaluated
when the project is created. The expression will be replaced by its result. The
syntax is __(expression)__
.
For example, a template file with the contents:
Current Time: __(format-time-string "%c")__
Current OS: __(shell-command-to-string "uname")__
could be expanded to:
Current Time: Thu Dec 19 16:14:35 2013
Current OS: Darwin
Some communities have well-established tools for creating projects from templates. Skeletor may still be used to orchestrate these tools and perform additional setup steps.
Skeletor provides the skeletor-define-constructor
macro for this purpose. It
is similar to skeletor-define-template
, but it requires you supply a function
that creates the project structure itself.
For example, Bundler is a popular tool in the Ruby community that can create new Ruby projects. Skeletor provides the following binding:
(skeletor-define-constructor "Ruby Gem"
:requires-executables '(("bundle" . "http://bundler.io"))
:no-license? t
:initialise
(lambda (name project-dir)
(skeletor-shell-command (format "bundle gem %s" (shell-quote-argument name))))
:after-creation
(lambda (dir)
(when (and (executable-find "rspec")
(y-or-n-p "Create RSpec test suite? "))
(skeletor-shell-command "rspec --init"))))
Skeletor will use bundle
to create the project structure, offer to create an
RSpec test suite, then add everything to version control.
Yes, please do! More project types are especially welcome. Read over CONTRIBUTING for guidelines.
Skeletor is based on @magnars' Project Archetypes–one of many cool features of his .emacs.d. This, and other goodies, are covered in this emacs chat session with Sacha Chua.
Muchas gracias to @magnars and @rejeep for their excellent libraries and tooling. You guys are stars!
See COPYING. Copyright (c) 2014 Chris Barrett.