From de3110b733880502b23faf9af4d450f22a4b15f7 Mon Sep 17 00:00:00 2001 From: Adam Stankiewicz Date: Thu, 17 Dec 2015 10:48:07 +0100 Subject: [PATCH] Add ansible support, closes #96 --- README.md | 1 + build | 1 + ftdetect/polyglot.vim | 15 ++++ ftplugin/ansible.vim | 8 +++ indent/ansible.vim | 58 +++++++++++++++ syntax/ansible.vim | 90 +++++++++++++++++++++++ syntax/ansible_hosts.vim | 35 +++++++++ syntax/ansible_template.vim | 31 ++++++++ syntax/jinja2.vim | 139 ++++++++++++++++++++++++++++++++++++ 9 files changed, 378 insertions(+) create mode 100644 ftplugin/ansible.vim create mode 100644 indent/ansible.vim create mode 100644 syntax/ansible.vim create mode 100644 syntax/ansible_hosts.vim create mode 100644 syntax/ansible_template.vim create mode 100644 syntax/jinja2.vim diff --git a/README.md b/README.md index 5528f3d5b..5c1eff1d7 100644 --- a/README.md +++ b/README.md @@ -25,6 +25,7 @@ Optionally download one of the [releases](https://github.com/sheerun/vim-polyglo ## Language packs +- [ansible](https://github.com/pearofducks/ansible-vim) (syntax, indent, ftplugin, ftdetect) - [arduino](https://github.com/sudar/vim-arduino-syntax) (syntax, indent, ftdetect) - [blade](https://github.com/jwalton512/vim-blade) (syntax, indent, ftdetect) - [c++11](https://github.com/octol/vim-cpp-enhanced-highlight) (syntax) diff --git a/build b/build index 8f920c710..474a1f088 100755 --- a/build +++ b/build @@ -96,6 +96,7 @@ EOF } PACKS=" + ansible:pearofducks/ansible-vim arduino:sudar/vim-arduino-syntax blade:jwalton512/vim-blade c++11:octol/vim-cpp-enhanced-highlight diff --git a/ftdetect/polyglot.vim b/ftdetect/polyglot.vim index fdb540e2b..ee6cd63a9 100644 --- a/ftdetect/polyglot.vim +++ b/ftdetect/polyglot.vim @@ -1,3 +1,18 @@ +if !exists('g:polyglot_disabled') || index(g:polyglot_disabled, 'ansible') == -1 + +function! DetectAnsible() + let filepath = expand("%:p") + let filename = expand("%:t") + if filepath =~ '\v/(tasks|roles)/.*\.ya?ml$' || filepath =~ '\v/(group|host)_vars/' || filename =~ '\v(playbook|site)\.ya?ml$' + set ft=ansible + endif + unlet filepath + unlet filename +endfunction +:au BufNewFile,BufRead *.yml,*yaml,*/{group,host}_vars/* call DetectAnsible() +:au BufNewFile,BufRead *.j2 set ft=ansible_template +:au BufNewFile,BufRead hosts set ft=ansible_hosts +endif if !exists('g:polyglot_disabled') || index(g:polyglot_disabled, 'arduino') == -1 au BufRead,BufNewFile *.ino,*.pde set filetype=arduino diff --git a/ftplugin/ansible.vim b/ftplugin/ansible.vim new file mode 100644 index 000000000..df766194d --- /dev/null +++ b/ftplugin/ansible.vim @@ -0,0 +1,8 @@ +if !exists('g:polyglot_disabled') || index(g:polyglot_disabled, 'ansible') == -1 + +" Slow yaml highlighting workaround +if exists('+regexpengine') && ('®expengine' == 0) + setlocal regexpengine=1 +endif + +endif diff --git a/indent/ansible.vim b/indent/ansible.vim new file mode 100644 index 000000000..c802186bc --- /dev/null +++ b/indent/ansible.vim @@ -0,0 +1,58 @@ +if !exists('g:polyglot_disabled') || index(g:polyglot_disabled, 'ansible') == -1 + +let s:save_cpo = &cpo +set cpo&vim + +setlocal indentexpr=GetAnsibleIndent(v:lnum) +setlocal indentkeys=!^F,o,O,0#,0},0],<:>,-,* +setlocal nosmartindent +setlocal expandtab +setlocal softtabstop=2 +setlocal shiftwidth=2 +setlocal commentstring=#%s +setlocal formatoptions=cl +" c -> wrap long comments, including # +" l -> do not wrap long lines + +let s:comment = '\v^\s*#' " # comment +let s:array_entry = '\v^\s*-\s' " - foo +let s:named_module_entry = '\v^\s*-\s*(name|hosts):\s*\S' " - name: 'do stuff' +let s:dictionary_entry = '\v^\s*[^:-]+:\s*$' " with_items: +let s:key_value = '\v^\s*[^:-]+:\s*\S' " apt: name=package +let s:scalar_value = '\v:\s*[>|\|]\s*$' " shell: > + +if exists('*GetAnsibleIndent') + finish +endif + +function GetAnsibleIndent(lnum) + if a:lnum == 1 || !prevnonblank(a:lnum-1) + return 0 + endif + let prevlnum = prevnonblank(a:lnum - 1) + let maintain = indent(prevlnum) + let increase = maintain + &sw + + let line = getline(prevlnum) + if line =~ s:array_entry + if line =~ s:named_module_entry + return increase + else + return maintain + endif + elseif line =~ s:dictionary_entry + return increase + elseif line =~ s:key_value + if line =~ s:scalar_value + return increase + else + return maintain + endif + else + return maintain + endif +endfunction + +let &cpo = s:save_cpo + +endif diff --git a/syntax/ansible.vim b/syntax/ansible.vim new file mode 100644 index 000000000..ed0eafbff --- /dev/null +++ b/syntax/ansible.vim @@ -0,0 +1,90 @@ +if !exists('g:polyglot_disabled') || index(g:polyglot_disabled, 'ansible') == -1 + +" Vim syntax file +" Language: Ansible YAML/Jinja templates +" Maintainer: Dave Honneffer +" Last Change: 2015.09.06 + +if exists("b:current_syntax") + finish +endif + +if !exists("main_syntax") + let main_syntax = 'yaml' +endif + +let b:current_syntax = '' +unlet b:current_syntax +runtime! syntax/yaml.vim + +let b:current_syntax = '' +unlet b:current_syntax +syntax include @Yaml syntax/yaml.vim + +let b:current_syntax = '' +unlet b:current_syntax +syntax include @Jinja syntax/jinja2.vim + +" Jinja +" ================================ + +syn cluster jinjaSLSBlocks add=jinjaTagBlock,jinjaVarBlock,jinjaComment +" https://github.com/mitsuhiko/jinja2/blob/6b7c0c23/ext/Vim/jinja.vim +syn region jinjaTagBlock matchgroup=jinjaTagDelim start=/{%-\?/ end=/-\?%}/ containedin=ALLBUT,jinjaTagBlock,jinjaVarBlock,jinjaRaw,jinjaString,jinjaNested,jinjaComment,@jinjaSLSBlocks +syn region jinjaVarBlock matchgroup=jinjaVarDelim start=/{{-\?/ end=/-\?}}/ containedin=ALLBUT,jinjaTagBlock,jinjaVarBlock,jinjaRaw,jinjaString,jinjaNested,jinjaComment,@jinjaSLSBlocks +syn region jinjaComment matchgroup=jinjaCommentDelim start="{#" end="#}" containedin=ALLBUT,jinjaTagBlock,jinjaVarBlock,jinjaString,@jinjaSLSBlocks +highlight link jinjaVariable Constant +highlight link jinjaVarDelim Delimiter + +" YAML +" ================================ + +" Reset some YAML to plain styling +" the number 80 in Ansible isn't any more important than the word root +highlight link yamlInteger NONE +highlight link yamlBool NONE +highlight link yamlFlowString NONE +" but it does make sense we visualize quotes easily +highlight link yamlFlowStringDelimiter Delimiter + +fun! s:attribute_highlight(attributes) + if a:attributes =~ 'a' + syn match ansible_attributes "\v\w+\=" containedin=yamlPlainScalar + else + syn match ansible_attributes "\v^\s*\w+\=" containedin=yamlPlainScalar + endif + if a:attributes =~ 'n' + highlight link ansible_attributes NONE + elseif a:attributes =~ 'd' + highlight link ansible_attributes Comment + else + highlight link ansible_attributes Structure + endif +endfun + +if exists("g:ansible_attribute_highlight") + call s:attribute_highlight(g:ansible_attribute_highlight) +else + call s:attribute_highlight('ad') +endif + +if exists("g:ansible_name_highlight") + syn keyword ansible_name name containedin=yamlBlockMappingKey contained + if g:ansible_name_highlight =~ 'd' + highlight link ansible_name Comment + else + highlight link ansible_name Underlined + endif +endif + +syn keyword ansible_debug_keywords debug containedin=yamlBlockMappingKey contained +highlight link ansible_debug_keywords Debug + +syn match ansible_with_keywords "\vwith_.+" containedin=yamlBlockMappingKey contained +syn keyword ansible_special_keywords include until retries delay when only_if become become_user block rescue always notify containedin=yamlBlockMappingKey contained +highlight link ansible_with_keywords Statement +highlight link ansible_special_keywords Statement + +let b:current_syntax = "ansible" + +endif diff --git a/syntax/ansible_hosts.vim b/syntax/ansible_hosts.vim new file mode 100644 index 000000000..fde5bf6f3 --- /dev/null +++ b/syntax/ansible_hosts.vim @@ -0,0 +1,35 @@ +if !exists('g:polyglot_disabled') || index(g:polyglot_disabled, 'ansible') == -1 + +" Vim syntax file +" Language: Ansible hosts files +" Maintainer: Dave Honneffer +" Last Change: 2015.09.23 + +if exists("b:current_syntax") + finish +endif + +syn case ignore +syn match hostsFirstWord "\v^\S+" +syn match hostsAttributes "\v\S*\=" +syn region hostsHeader start="\v^\s*\[" end="\v\]" +syn keyword hostsHeaderSpecials children vars containedin=hostsHeader contained +syn match hostsComment "\v^[#;].*$" + +highlight link hostsFirstWord Label +highlight link hostsHeader Define +highlight link hostsComment Comment +highlight link hostsHeaderSpecials Identifier +highlight link hostsAttributes Structure + +if exists("g:ansible_attribute_highlight") + if g:ansible_attribute_highlight =~ 'n' + highlight link hostsAttributes NONE + elseif g:ansible_attribute_highlight =~ 'd' + highlight link hostsAttributes Comment + endif +endif + +let b:current_syntax = "ansible_hosts" + +endif diff --git a/syntax/ansible_template.vim b/syntax/ansible_template.vim new file mode 100644 index 000000000..31ca4b240 --- /dev/null +++ b/syntax/ansible_template.vim @@ -0,0 +1,31 @@ +if !exists('g:polyglot_disabled') || index(g:polyglot_disabled, 'ansible') == -1 + +" Vim syntax file +" Language: Ansible YAML/Jinja templates +" Maintainer: Dave Honneffer +" Last Change: 2015.09.06 + +if exists("b:current_syntax") + finish +endif + +if !exists("main_syntax") + let main_syntax = 'jinja2' +endif + +let b:current_syntax = '' +unlet b:current_syntax +runtime! syntax/jinja2.vim + +if exists("g:ansible_extra_syntaxes") + let s:extra_syntax = split(g:ansible_extra_syntaxes) + for syntax_name in s:extra_syntax + let b:current_syntax = '' + unlet b:current_syntax + execute 'runtime!' "syntax/" . syntax_name + endfor +endif + +let b:current_syntax = "ansible_template" + +endif diff --git a/syntax/jinja2.vim b/syntax/jinja2.vim new file mode 100644 index 000000000..3ddea85c2 --- /dev/null +++ b/syntax/jinja2.vim @@ -0,0 +1,139 @@ +if !exists('g:polyglot_disabled') || index(g:polyglot_disabled, 'ansible') == -1 + +" Vim syntax file +" Language: Jinja template +" Maintainer: Armin Ronacher +" Last Change: 2008 May 9 +" Version: 1.1 +" +" Known Bugs: +" because of odd limitations dicts and the modulo operator +" appear wrong in the template. +" +" Changes: +" +" 2008 May 9: Added support for Jinja2 changes (new keyword rules) + +" .vimrc variable to disable html highlighting +if !exists('g:jinja_syntax_html') + let g:jinja_syntax_html=1 +endif + +" For version 5.x: Clear all syntax items +" For version 6.x: Quit when a syntax file was already loaded +if !exists("main_syntax") + if version < 600 + syntax clear + elseif exists("b:current_syntax") + finish +endif + let main_syntax = 'jinja' +endif + +" Pull in the HTML syntax. +if g:jinja_syntax_html + if version < 600 + so :p:h/html.vim + else + runtime! syntax/html.vim + unlet b:current_syntax + endif +endif + +syntax case match + +" Jinja template built-in tags and parameters (without filter, macro, is and raw, they +" have special threatment) +syn keyword jinjaStatement containedin=jinjaVarBlock,jinjaTagBlock,jinjaNested contained and if else in not or recursive as import + +syn keyword jinjaStatement containedin=jinjaVarBlock,jinjaTagBlock,jinjaNested contained is filter skipwhite nextgroup=jinjaFilter +syn keyword jinjaStatement containedin=jinjaTagBlock contained macro skipwhite nextgroup=jinjaFunction +syn keyword jinjaStatement containedin=jinjaTagBlock contained block skipwhite nextgroup=jinjaBlockName + +" Variable Names +syn match jinjaVariable containedin=jinjaVarBlock,jinjaTagBlock,jinjaNested contained /[a-zA-Z_][a-zA-Z0-9_]*/ +syn keyword jinjaSpecial containedin=jinjaVarBlock,jinjaTagBlock,jinjaNested contained false true none False True None loop super caller varargs kwargs + +" Filters +syn match jinjaOperator "|" containedin=jinjaVarBlock,jinjaTagBlock,jinjaNested contained skipwhite nextgroup=jinjaFilter +syn match jinjaFilter contained /[a-zA-Z_][a-zA-Z0-9_]*/ +syn match jinjaFunction contained /[a-zA-Z_][a-zA-Z0-9_]*/ +syn match jinjaBlockName contained /[a-zA-Z_][a-zA-Z0-9_]*/ + +" Jinja template constants +syn region jinjaString containedin=jinjaVarBlock,jinjaTagBlock,jinjaNested contained start=/"/ skip=/\(\\\)\@\)*\\"/ end=/"/ +syn region jinjaString containedin=jinjaVarBlock,jinjaTagBlock,jinjaNested contained start=/'/ skip=/\(\\\)\@\)*\\'/ end=/'/ +syn match jinjaNumber containedin=jinjaVarBlock,jinjaTagBlock,jinjaNested contained /[0-9]\+\(\.[0-9]\+\)\?/ + +" Operators +syn match jinjaOperator containedin=jinjaVarBlock,jinjaTagBlock,jinjaNested contained /[+\-*\/<>=!,:]/ +syn match jinjaPunctuation containedin=jinjaVarBlock,jinjaTagBlock,jinjaNested contained /[()\[\]]/ +syn match jinjaOperator containedin=jinjaVarBlock,jinjaTagBlock,jinjaNested contained /\./ nextgroup=jinjaAttribute +syn match jinjaAttribute contained /[a-zA-Z_][a-zA-Z0-9_]*/ + +" Jinja template tag and variable blocks +syn region jinjaNested matchgroup=jinjaOperator start="(" end=")" transparent display containedin=jinjaVarBlock,jinjaTagBlock,jinjaNested contained +syn region jinjaNested matchgroup=jinjaOperator start="\[" end="\]" transparent display containedin=jinjaVarBlock,jinjaTagBlock,jinjaNested contained +syn region jinjaNested matchgroup=jinjaOperator start="{" end="}" transparent display containedin=jinjaVarBlock,jinjaTagBlock,jinjaNested contained +syn region jinjaTagBlock matchgroup=jinjaTagDelim start=/{%-\?/ end=/-\?%}/ containedin=ALLBUT,jinjaTagBlock,jinjaVarBlock,jinjaRaw,jinjaString,jinjaNested,jinjaComment + +syn region jinjaVarBlock matchgroup=jinjaVarDelim start=/{{-\?/ end=/-\?}}/ containedin=ALLBUT,jinjaTagBlock,jinjaVarBlock,jinjaRaw,jinjaString,jinjaNested,jinjaComment + +" Jinja template 'raw' tag +syn region jinjaRaw matchgroup=jinjaRawDelim start="{%\s*raw\s*%}" end="{%\s*endraw\s*%}" containedin=ALLBUT,jinjaTagBlock,jinjaVarBlock,jinjaString,jinjaComment + +" Jinja comments +syn region jinjaComment matchgroup=jinjaCommentDelim start="{#" end="#}" containedin=ALLBUT,jinjaTagBlock,jinjaVarBlock,jinjaString + +" Block start keywords. A bit tricker. We only highlight at the start of a +" tag block and only if the name is not followed by a comma or equals sign +" which usually means that we have to deal with an assignment. +syn match jinjaStatement containedin=jinjaTagBlock contained /\({%-\?\s*\)\@<=\<[a-zA-Z_][a-zA-Z0-9_]*\>\(\s*[,=]\)\@!/ + +" and context modifiers +syn match jinjaStatement containedin=jinjaTagBlock contained /\/ + + +" Define the default highlighting. +" For version 5.7 and earlier: only when not done already +" For version 5.8 and later: only when an item doesn't have highlighting yet +if version >= 508 || !exists("did_jinja_syn_inits") + if version < 508 + let did_jinja_syn_inits = 1 + command -nargs=+ HiLink hi link + else + command -nargs=+ HiLink hi def link + endif + + HiLink jinjaPunctuation jinjaOperator + HiLink jinjaAttribute jinjaVariable + HiLink jinjaFunction jinjaFilter + + HiLink jinjaTagDelim jinjaTagBlock + HiLink jinjaVarDelim jinjaVarBlock + HiLink jinjaCommentDelim jinjaComment + HiLink jinjaRawDelim jinja + + HiLink jinjaSpecial Special + HiLink jinjaOperator Normal + HiLink jinjaRaw Normal + HiLink jinjaTagBlock PreProc + HiLink jinjaVarBlock PreProc + HiLink jinjaStatement Statement + HiLink jinjaFilter Function + HiLink jinjaBlockName Function + HiLink jinjaVariable Identifier + HiLink jinjaString Constant + HiLink jinjaNumber Constant + HiLink jinjaComment Comment + + delcommand HiLink +endif + +let b:current_syntax = "jinja" + +if main_syntax == 'jinja' + unlet main_syntax +endif + +endif