Add Handlebars and Mustache templates. (Ember.)

This commit is contained in:
Max Bucknell 2015-01-11 09:44:35 +00:00
parent 24b08086bc
commit 678c8426ad
5 changed files with 409 additions and 0 deletions

View file

@ -0,0 +1,130 @@
mustache and handlebars mode for vim
====================================
A vim plugin for working with [mustache][mustache] and
[handlebars][handlebars] templates. It has:
- syntax highlighting
- matchit support
- mustache abbreviations (optional)
- section movement mappings `[[` and `]]`
- text objects `ie` (inside element) and `ae` (around element)
**Note**: for compatibility reason #7, we've renamed the repo name from
`vim-mode` to `vim-mustache-handlebars`.
### Install for pathogen
cd ~/.vim/
git clone git://github.com/mustache/vim-mustache-handlebars.git bundle/mustache
vim bundle/mustache/example.mustache
Get [pathogen][pathogen].
### Install for vundle
Add `Plugin 'mustache/vim-mustache-handlebars'` to your `.vimrc` and do a
`:PluginInstall`.
### Manually Install
cd ~/.local/src
git clone git://github.com/mustache/vim-mustache-handlebars.git mustache.vim
cp -R mustache.vim/syntax/* ~/.vim/syntax/
cp -R mustache.vim/ftdetect/* ~/.vim/ftdetect/
cp -R mustache.vim/ftplugin/* ~/.vim/ftplugin/
vim mustache.vim/example.mustache
### Mustache Abbreviations
You can activate mustache abbreviations by putting this line in your `.vimrc`:
`let g:mustache_abbreviations = 1`
Now you get a set of convenient abbreviations. Underscore `_` indicates where
your cursor ends up after typing an abbreviation:
- `{{` => `{{_}}`
- `{{{` => `{{{_}}}`
- `{{!` => `{{!_}}`
- `{{>` => `{{>_}}`
- `{{<` => `{{<_}}`
- `{{#` produces
```
{{# _}}
{{/}}
```
- `{{if` produces
```
{{#if _}}
{{/if}}
```
- `{{ife` produces
```
{{#if _}}
{{else}}
{{/if}}
```
### Section movement mappings
Following the vim convention of jumping from section to section, `[[` and `]]`
mappings are implemented for easier movement between mustache tags.
- `]]` jumps to the first following tag
- `[[` jumps to the first previous tag
Count with section movements is supported:
- `2]]` jumps to the second next tag
### Text objects
Vim has a very powerful concept of "text objects". If you aren't using text objects,
you can get familiar with it on [this vim help
link](http://vimdoc.sourceforge.net/htmldoc/motion.html#text-objects). Learning
text objects really speeds up the vim workflow.
In that spirit, this plugin defines 2 text objects:
- `ie` a mnemonic for `inside element`, selects all the text inside the
mustache tag.
For example, when used with `vie` it will visually select the
bold text in the following snippets: {{**some_variable**}},
{{{**different_variable**}}}.
- `ae` a mnemonic for `around element`, selects the whole mustache tag,
including the curly braces.
Example, `vae` visually selects the bold text in the following
snippets: **{{some_variable}}** or **{{{another_variable}}}**.
Here are other usage examples:
- `dae` - deletes the whole mustache tag, including the curly braces
- `die` - deletes **inside** the mustache tag, leaving only curly braces
- `yae` - "yanks" the whole mustache tag - with curly braces
- `cie` - deletes **inside** the mustache tag and goes in insert mode
`ie` and `ae` text objects are enabled by default. To disable them, put the
following in your `.vimrc`:
let g:mustache_operators = 0
## Maintainers
* [Bruno Michel](http://github.com/nono)
* [Bruno Sutic](http://github.com/bruno-)
* [Juvenn Woo](http://github.com/juvenn)
This is combined work from
[juvenn/mustache.vim](http://github.com/juvenn/mustache.vim) and
[nono/vim-handlebars](http://github.com/nono/vim-handlebars).
----
Thanks [@5long](http://github.com/5long) for adding matchit support.
You're encouraged to propose ideas or have discussions via github
issues.
[mustache]: http://mustache.github.io
[handlebars]: http://handlebarsjs.com
[pathogen]: https://github.com/tpope/vim-pathogen

View file

@ -0,0 +1,66 @@
<!DOCTYPE html>
<html>
<head>
<title>
{{title}}
</title>
{{!}}
</head>
<body>
<div id="main">
<h1>Mustache Showdown</h1>
Basic mustache {{hello}}
{{ hello}}, {{hello }} and {{ hello }} are OK
<de>{{d d d}}
{{Everything will be hilighted here}}
Mustaches hilighted in
<span class="color:{{awesome_color}};font-size:1.2em">attribute value</span>
{{#repo}}
This is an mustache [enumerable] section
<li>{{ name }}</li>
{{/repo}}
Inverted sections are supported too
{{^repo}}
No repos :(
{{/repo}}
You can {{{yield}}} here
{{! <> this is a comment TODO:}}
Another {{!-- comment --}}, this one is a block comment.
{{!-- TODO: some remark
<div>
Multililine {{comments}} with
{{variables}}
</div> --}}
This is a partial {{> partial1 }}
Yet another partial {{< partial2 }}, for ctemplate
{{=<% %>=}}Sorry, cusomized delimiter not handled yet<%={{}}=%>
{{#if some_helper}}
And here is an example of handlebars if...
{{else}}
... with optional else added. Try matchit `%` command over if/else/if.
{{/if}}
Thanks goes to {{@defunkt}}
Feedback/blames go to {{@juvenn}}
{{Frustrations}} go to /dev/null
Multililine {{comments}} with
{{variables}}
</div>
</body>
</html>

View file

@ -0,0 +1,4 @@
if has("autocmd")
au BufNewFile,BufRead *.mustache,*.hogan,*.hulk,*.hjs set filetype=html.mustache syntax=mustache | runtime! ftplugin/mustache.vim ftplugin/mustache*.vim ftplugin/mustache/*.vim
au BufNewFile,BufRead *.handlebars,*.hbs set filetype=html.handlebars syntax=mustache | runtime! ftplugin/mustache.vim ftplugin/mustache*.vim ftplugin/mustache/*.vim
endif

View file

@ -0,0 +1,120 @@
if exists('g:loaded_mustache_handlebars') && g:loaded_mustache_handlebars
finish
endif
let g:loaded_mustache_handlebars = 1
let s:cpo_save = &cpo
set cpo&vim
" Matchit support for Mustache & Handlebars
" extending HTML matchit groups
if exists("loaded_matchit") && exists("b:match_words")
let b:match_words = b:match_words
\ . ',{:},[:],(:),'
\ . '\%({{\)\@<=#\s*\%(if\|unless\)\s*.\{-}}}'
\ . ':'
\ . '\%({{\)\@<=\s*else\s*}}'
\ . ':'
\ . '\%({{\)\@<=/\s*\%(if\|unless\)\s*}},'
\ . '\%({{\)\@<=[#^]\s*\([-0-9a-zA-Z_?!/.]\+\).\{-}}}'
\ . ':'
\ . '\%({{\)\@<=/\s*\1\s*}}'
endif
if exists("g:mustache_abbreviations")
inoremap <buffer> {{{ {{{}}}<left><left><left>
inoremap <buffer> {{ {{}}<left><left>
inoremap <buffer> {{! {{!}}<left><left>
inoremap <buffer> {{< {{<}}<left><left>
inoremap <buffer> {{> {{>}}<left><left>
inoremap <buffer> {{# {{#}}<cr>{{/}}<up><left><left>
inoremap <buffer> {{if {{#if }}<cr>{{/if}}<up><left>
inoremap <buffer> {{ife {{#if }}<cr>{{else}}<cr>{{/if}}<up><up><left>
endif
" Section movement
" Adapted from vim-ruby - many thanks to the maintainers of that plugin
function! s:sectionmovement(pattern,flags,mode,count)
norm! m'
if a:mode ==# 'v'
norm! gv
endif
let i = 0
while i < a:count
let i = i + 1
" saving current position
let line = line('.')
let col = col('.')
let pos = search(a:pattern,'W'.a:flags)
" if there's no more matches, return to last position
if pos == 0
call cursor(line,col)
return
endif
endwhile
endfunction
nnoremap <silent> <buffer> [[ :<C-U>call <SID>sectionmovement('{{','b','n',v:count1)<CR>
nnoremap <silent> <buffer> ]] :<C-U>call <SID>sectionmovement('{{','' ,'n',v:count1)<CR>
xnoremap <silent> <buffer> [[ :<C-U>call <SID>sectionmovement('{{','b','v',v:count1)<CR>
xnoremap <silent> <buffer> ]] :<C-U>call <SID>sectionmovement('{{','' ,'v',v:count1)<CR>
" Operator pending mappings
" Operators are available by default. Set `let g:mustache_operators = 0` in
" your .vimrc to disable them.
if ! exists("g:mustache_operators")
let g:mustache_operators = 1
endif
if exists("g:mustache_operators") && g:mustache_operators
onoremap <silent> <buffer> ie :<C-U>call <SID>wrap_inside()<CR>
onoremap <silent> <buffer> ae :<C-U>call <SID>wrap_around()<CR>
xnoremap <silent> <buffer> ie :<C-U>call <SID>wrap_inside()<CR>
xnoremap <silent> <buffer> ae :<C-U>call <SID>wrap_around()<CR>
endif
function! s:wrap_around()
" If the cursor is at the end of the tag element, move back
" so that the end tag can be detected.
while getline('.')[col('.')-1] ==# '}'
execute 'norm h'
endwhile
" Moves to the end of the closing tag
let pos = search('}}','We')
if pos != 0
if getline('.')[col('.')] ==# '}'
" Ending tag contains 3 closing brackets '}}}',
" move to the last bracket.
execute 'norm l'
endif
" select the whole tag
execute 'norm v%'
endif
endfunction
function! s:wrap_inside()
" If the cursor is at the end of the tag element, move back
" so that the end tag can be detected.
while getline('.')[col('.')-1] ==# '}'
execute 'norm h'
endwhile
" Moves to the end of the closing tag
let pos = search('}}','W')
if pos != 0
" select only inside the tag
execute 'norm v%loho'
endif
endfunction
let &cpo = s:cpo_save
unlet s:cpo_save
" vim: nofoldenable

View file

@ -0,0 +1,89 @@
" Mustache & Handlebars syntax
" Language: Mustache, Handlebars
" Maintainer: Juvenn Woo <machese@gmail.com>
" Screenshot: http://imgur.com/6F408
" Version: 2
" Last Change: Oct 26th 2013
" Remark:
" It lexically hilights embedded mustaches (exclusively) in html file.
" While it was written for Ruby-based Mustache template system, it should
" work for Google's C-based *ctemplate* as well as Erlang-based *et*. All
" of them are, AFAIK, based on the idea of ctemplate.
" References:
" [Mustache](http://github.com/defunkt/mustache)
" [Handlebars](https://github.com/wycats/handlebars.js)
" [ctemplate](http://code.google.com/p/google-ctemplate/)
" [ctemplate doc](http://google-ctemplate.googlecode.com/svn/trunk/doc/howto.html)
" [et](http://www.ivan.fomichev.name/2008/05/erlang-template-engine-prototype.html)
" TODO: Feedback is welcomed.
" Read the HTML syntax to start with
if version < 600
so <sfile>:p:h/html.vim
else
runtime! syntax/html.vim
unlet b:current_syntax
endif
if version < 600
syntax clear
elseif exists("b:current_syntax")
finish
endif
" Standard HiLink will not work with included syntax files
if version < 508
command! -nargs=+ HtmlHiLink hi link <args>
else
command! -nargs=+ HtmlHiLink hi def link <args>
endif
syntax match mustacheError '}}}\?'
syntax match mustacheInsideError '{{[{$#<>=!\/]\?'
syntax region mustacheInside start=/{{/ end=/}}}\?/ keepend containedin=TOP,@htmlMustacheContainer
syntax match mustacheOperators '=\|\.\|/' contained containedin=mustacheInside,@htmlMustacheContainer
syntax region mustacheSection start='{{[$#^/]'lc=2 end=/}}/me=e-2 contained containedin=mustacheInside,@htmlMustacheContainer
syntax region mustachePartial start=/{{[<>]/lc=2 end=/}}/me=e-2 contained containedin=mustacheInside,@htmlMustacheContainer
syntax region mustacheMarkerSet start=/{{=/lc=2 end=/=}}/me=e-2 contained containedin=mustacheInside,@htmlMustacheContainer
syntax match mustacheHandlebars '{{\|}}' contained containedin=mustacheInside,@htmlMustacheContainer
syntax match mustacheUnescape '{{{\|}}}' contained containedin=mustacheInside,@htmlMustacheContainer
syntax match mustacheConditionals '\([/#]\(if\|unless\)\|else\)' contained containedin=mustacheInside
syntax match mustacheHelpers '[/#]\(with\|each\)' contained containedin=mustacheSection
syntax region mustacheComment start=/{{!/rs=s+2 skip=/{{.\{-}}}/ end=/}}/re=e-2 contains=Todo contained containedin=mustacheInside,@htmlMustacheContainer
syntax region mustacheBlockComment start=/{{!--/rs=s+2 skip=/{{.\{-}}}/ end=/--}}/re=e-2 contains=Todo contained extend containedin=mustacheInside,@htmlMustacheContainer
syntax region mustacheQString start=/'/ skip=/\\'/ end=/'/ contained containedin=mustacheInside
syntax region mustacheDQString start=/"/ skip=/\\"/ end=/"/ contained containedin=mustacheInside
" Clustering
syntax cluster htmlMustacheContainer add=htmlHead,htmlTitle,htmlString,htmlH1,htmlH2,htmlH3,htmlH4,htmlH5,htmlH6,htmlLink,htmlBold,htmlUnderline,htmlItalic,htmlValue
" Hilighting
" mustacheInside hilighted as Number, which is rarely used in html
" you might like change it to Function or Identifier
HtmlHiLink mustacheVariable Number
HtmlHiLink mustacheVariableUnescape Number
HtmlHiLink mustachePartial Number
HtmlHiLink mustacheSection Number
HtmlHiLink mustacheMarkerSet Number
HtmlHiLink mustacheComment Comment
HtmlHiLink mustacheBlockComment Comment
HtmlHiLink mustacheError Error
HtmlHiLink mustacheInsideError Error
HtmlHiLink mustacheHandlebars Special
HtmlHiLink mustacheUnescape Identifier
HtmlHiLink mustacheOperators Operator
HtmlHiLink mustacheConditionals Conditional
HtmlHiLink mustacheHelpers Repeat
HtmlHiLink mustacheQString String
HtmlHiLink mustacheDQString String
syn region mustacheScriptTemplate start=+<script [^>]*type *=[^>]*text/\(mustache\|x-handlebars-template\)[^>]*>+
\ end=+</script>+me=s-1 keepend
\ contains=mustacheInside,@htmlMustacheContainer,htmlTag,htmlEndTag,htmlTagName,htmlSpecialChar
let b:current_syntax = "mustache"
delcommand HtmlHiLink