hemmet is a CLI-tool, that expands text snippets to markup blocks in Haskell/Elm/HTML/CSS/Bash. The template language is similar to Emmet/ZenCoding (has a subset of their features) and has an optional BEM flavour :) Also hemmet can generate file trees (useful for project scaffolding).
$ echo "#root>h1.red+p.article" | hemmet dom html <div id="root"> <h1 class="red"></h1> <p class="article"></p> </div>
TUI
In addition to the CLI-tool there is a TUI-app hemmeti which one can use to write templates having a live preview.
That's how the HTML generation looks like:
And this is a file tree scaffolding:
Usage
$ hemmet INPUT OUTPUT -e EXPRESSION
or
$ echo "EXPRESSION" | hemmet INPUT OUTPUT
See hemmet --help for full options list.
hemmeti uses the same options but runs interactively.
Inputs (syntaxes)
domworks with DOM-templates,bemworks with BEM-templates,ftreeworks with file tree templates.
DOM-templates
Hemmet expands Emmet-like templates and produces these formats (outputs)
html, just HTML
echo "#root>h1.red+p.article" | hemmet dom html
<div id="root"> <h1 class="red"></h1> <p class="article"></p> </div>
css, styles for all classes in the template
echo "#root>h1.red+p.article" | hemmet dom css
.article { } .red { }
elm, an Elm.Html markup
echo "#root>h1.red+p.article" | hemmet dom css
div [ id "root" ] [ h1 [ class "red" ] [] , p [ class "article" ] [] ]
lucid, the Lucid HTML eDSL
echo "#root>h1.red+p.article" | hemmet dom css
div_ [id_ "root"] $ do h1_ [class_ "red"] p_ [class_ "article"]
Template syntax
Nesting
p+ul>(li+li+ul>li+li)+p
<p></p> <ul> <li></li> <li></li> <ul> <li></li> <li></li> </ul> </ul> <p></p>
Tags
Tag name prepends the id or classes if any. If no tag was defined the div will be used.
Id
Just #id, one at time.
Classes
Just .class.another, simple that.
BEM-templates
Hemmet expands BEM-templates with structure checking and produce outputs:
react-flux— eDSL for react-flux Haskell library
$ echo ":foo>.bar" | hemmet bem react-flux
divc_ "foo" $ do divc_ "foo__bar" $ pure ()
html
$ echo ":foo>.bar" | hemmet bem html
<div class="foo"> <div class="foo__bar"></div> </div>
css
$ echo ":foo>.bar" | hemmet bem css
.foo { } .foo__bar { }
Template syntax
Tags are the same.
Nesting
form:form>.submit:button>img.icon:icon+.label:label
<form class="form"> <div class="button form__submit"> <img class="icon button__icon"></img> <div class="label button__label"></div> </div> </form>
Modifiers
form:login-form>button.submit-button:button~small~disabled
<form class="login-form"> <button class="button button_small button_disabled login-form__submit-button"></button> </form>
Variables
:foo$bar~baz
divc_ ("foo foo_baz" <> bar) $ pure ()
Note: at the moment variables are available only for the react-flux output!
Root node stripping
<:foo>.bar+.baz (note leading <)
<div class="foo__bar"></div> <div class="foo__baz"></div>
File trees
The ftree templates can be transformed to:
tree, the pseudographical file tree representation.
$ echo "docs/{todo.txt to_read.txt}" | hemmet ftree tree
.
└── docs/
├── to_read.txt
└── todo.txt
bashscript, that constructs a real tree!
$ echo "docs/{todo.txt to_read.txt}" | hemmet ftree bash
#!/bin/bash cat <<PREVIEW_END This file tree will be created: . └── docs/ ├── to_read.txt └── todo.txt PREVIEW_END read -p "Press any key to continue..." -n1 -s set -euf -o pipefail mkdir "docs" && pushd "docs" touch "to_read.txt" touch "todo.txt" popd
You can even make a shell script that will call the TUI and then execute the result of generation automatically.
Generating Haskell source trees
With |hs| prefix you can scaffold Haskell projects:
$ echo "|hs|app/main src/*lib/{data-types utils} !foo-bar" | hemmet ftree tree
.
├── App/
│ └── Main.hs
├── Src/
│ ├── Lib/
│ │ ├── DataTypes.hs
│ │ └── Utils.hs
│ └── Lib.hs
└── foo-bar
Note that
- files get
.hsextension, *beforelibmeans "also create a.hsmodule for this folder",!before any name means "don't touch this item"- "kebab-case" morphs to "CamelCase"
Generating Python source trees
With |py| prefix you can scaffold Python projects:
$ echo "|py|src/*package/{core str-utils} !foo-bar" | hemmet ftree tree
.
├── foo-bar
└── src/
└── package/
├── __init__.py
├── core.py
└── str_utils.py
Note that
- files get
.pyextension, *beforepackagemeans "also create an__init__.pymodule",!before any name means "don't touch this item"- "kebab-case" morphs to "snake_case"
Integration with Emacs
- put a
hemmetbinary somewhere in$PATH - add to your
.emacs
(defun hemmet-expand-region () (interactive) (let ((f (lambda (b e) (shell-command-on-region b e "hemmet dom html" t t "*hemmet error*" t)))) (if (region-active-p) (funcall f (region-beginning) (region-end)) (funcall f (line-beginning-position) (line-end-position))) )) ;; bind using a function from "bind-key" package (bind-key "C-c C-j" 'hemmet-expand-region html-mode-map) ;; or just use built-in function (define-key haskell-mode-map (kbd "C-c C-j") 'hemmet-expand-region)