File: TEMPLATES.md

package info (click to toggle)
leiningen-clojure 2.9.0-1
  • links: PTS, VCS
  • area: main
  • in suites: buster
  • size: 2,312 kB
  • sloc: xml: 881; sh: 771; lisp: 46; makefile: 34; java: 16
file content (164 lines) | stat: -rw-r--r-- 6,103 bytes parent folder | download | duplicates (2)
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
157
158
159
160
161
162
163
164
<!-- START doctoc generated TOC please keep comment here to allow auto update -->
<!-- DON'T EDIT THIS SECTION, INSTEAD RE-RUN doctoc TO UPDATE -->
**Table of Contents**  *generated with [DocToc](https://github.com/thlorenz/doctoc)*

- [Writing Templates](#writing-templates)
  - [Structure](#structure)
  - [Templating System](#templating-system)
      - [A warning about Mustache tag delimiters](#a-warning-about-mustache-tag-delimiters)
  - [Distributing your Template](#distributing-your-template)

<!-- END doctoc generated TOC please keep comment here to allow auto update -->

# Writing Templates

Suppose you've written a fabulously popular library, used the world
over by adoring fans. For the purposes of this document, let's say
this library is called "liquid-cool". If using liquid-cool takes a bit
of setup, or if you'd just like to give your users a little guidance
on how one might best create a new project which uses liquid-cool, you
might want to provide a template for it (just like how `lein` already
provides built-in templates for "app", "plugin", and so on).

Let's assume your library's project dir is `~/dev/liquid-cool`. Create
a template for it like so:

    cd ~/dev
    lein new template liquid-cool --to-dir liquid-cool-template

Your new template would look like:

    liquid-cool-template
    ├── LICENSE
    ├── project.clj
    ├── README.md
    ├── resources
    |   └── leiningen
    |       └── new
    |           └── liquid_cool
    |               └── foo.clj
    └── src
        └── leiningen
            └── new
                └── liquid_cool.clj

Note that you'll now have a new and separate project named
"liquid-cool-template". It will have a group-id of "liquid-cool", and
an artifact-id of "lein-template".

> All lein templates have an artifact-id of "lein-template", and are
> differentiated by their group-id, which always should match the
> project for which they provide a template.

## Structure

The files that your template will provide to users are in
`resources/leiningen/new/liquid_cool`. The template generator starts you off
with just one, named "foo.clj". You can see it referenced in
`src/leiningen/new/liquid_cool.clj`, right underneath the
`->files data` line.

You can delete `foo.clj` if you like (and its corresponding line in
`liquid_cool.clj`), and start populating that
`resources/leiningen/new/liquid_cool` directory with the files you wish to be
part of your template. For everything you add, make sure the
`liquid_cool.clj` file receives corresponding entries in that `->files`
call. For examples to follow, have a look inside [the \*.clj files for
the built-in
templates](https://github.com/technomancy/leiningen/tree/stable/resources/leiningen/new).

## Testing Your Template

While developing a template, if you're in the template project directory, 
leiningen will pick it up and you'll be able to test it.  e.g. from the
`liquid-cool-template` dir:

    $ lein new liquid-cool myproject

will create a directory called `myproject`, built from your template.
Alternately, if you want to test your template from another directory on
your system (without publishing your template to clojars yet), just run:

    $ lein install

You should then be able to run `lein new liquid-cool myproject` from any
directory on your system.

## Templating System

The default generated template uses [stencil][] for templating, which implements the
language-agnostic templating system [Mustache][]. All the available tag types
can be found in the [Mustache manual][mustache-manual]; we will only go through
the most common tag type here.

Suppose we want to add in a standard markdown readme file where the input name
is the main header of the file. To be able to do so, we must do two things:
Ensure that the input name is contained within the `data` mapped to the key X,
and that we have a template file which looks up the key X by wrapping it in
double mustaches like so: `{{X}}`. As for our input name, `data` already
contains the line `:name name`, which means we can lookup the input name by
writing `{{name}}` in the template file. To try it out, save the following
contents in the file `resources/leiningen/new/liquid_cool/README.md`:

```markdown
# {{name}}

This is our readme!
```

And add the following line right underneath the `->files data` line:

```clj
["README.md" (render "README.md" data)]
```

Now, if we for instance say `lein new liquid-cool liquid-cool-app`, the newly
generated project will contain a file named `README.md` where the header is
`liquid-cool-app`.

[stencil]: https://github.com/davidsantiago/stencil
[Mustache]: https://mustache.github.io/
[mustache-manual]: https://mustache.github.io/mustache.5.html

#### A warning about Mustache tag delimiters
Clojure syntax can conflict with the default mustache tag delimiter. For 
example, when destructuring a nested map:

```clj
(let [{{:keys [a b]} :ab} some-map]
  (do-something a b))
```

Stencil will interpret the `{{` as the start of a mustache tag, but since the
contents are not valid mustache, the render fails. To get around this, we can 
change the mustache delimiter temporarily, like so:

```clj
{{! Change mustache delimiter to <% and %> }}
{{=<% %>=}}

(let [{{:keys [a b]} :ab} some-map]
  (do-something a b))

<%! Reset mustache delimiter %>
<%={{ }}=%>
```

## Distributing your Template

Templates are just maven artifacts. Particularly, they need only be on
the classpath when `lein new` is called. So, as a side-effect, you
can just put your templates in a jar and toss them on clojars and have
people install them like normal Leiningen plugins.

In Leiningen 2.x, templates get dynamically fetched if they're not
found. So for instance `lein new heroku myproject` will find the
latest version of the `heroku/lein-template` project from Clojars and
use that.

Users of Leiningen 1.x (1.6.2 or later) can also use the template if
they install the `lein-newnew` plugin:

    $ lein plugin install lein-newnew 0.3.6
    $ lein new foo
    $ lein new plugin lein-foo