1
0
Fork 0
mirror of synced 2024-11-29 20:25:34 -05:00

added vim-elixir plugin

This commit is contained in:
jortiz 2016-05-26 11:26:32 -04:00
parent cc0e8a9907
commit 6e162000a8
36 changed files with 1751 additions and 0 deletions

View file

@ -99,6 +99,7 @@ Remove all clutter and focus only on the essential. Similar to iA Writer or Writ
* [vim-markdown](https://github.com/tpope/vim-markdown) * [vim-markdown](https://github.com/tpope/vim-markdown)
* [nginx.vim](https://github.com/vim-scripts/nginx.vim): Highlights configuration files for nginx * [nginx.vim](https://github.com/vim-scripts/nginx.vim): Highlights configuration files for nginx
* [vim-go](https://github.com/fatih/vim-go) * [vim-go](https://github.com/fatih/vim-go)
* [vim-elixir]("https://github.com/elixir-lang/vim-elixir")
## How to include your own stuff? ## How to include your own stuff?

View file

@ -0,0 +1,110 @@
!_TAG_FILE_ENCODING utf-8 //
'ctrl-p' ctrlp.cnx /*'ctrl-p'*
'ctrlp' ctrlp.cnx /*'ctrlp'*
'ctrlp-<c-p>' ctrlp.cnx /*'ctrlp-<c-p>'*
'ctrlp-autocompletion' ctrlp.cnx /*'ctrlp-autocompletion'*
'ctrlp-fullregexp' ctrlp.cnx /*'ctrlp-fullregexp'*
'ctrlp-pasting' ctrlp.cnx /*'ctrlp-pasting'*
'ctrlp-wildignore' ctrlp.cnx /*'ctrlp-wildignore'*
'g:ctrlp_abbrev' ctrlp.cnx /*'g:ctrlp_abbrev'*
'g:ctrlp_arg_map' ctrlp.cnx /*'g:ctrlp_arg_map'*
'g:ctrlp_brief_prompt' ctrlp.cnx /*'g:ctrlp_brief_prompt'*
'g:ctrlp_buffer_func' ctrlp.cnx /*'g:ctrlp_buffer_func'*
'g:ctrlp_bufname_mod' ctrlp.cnx /*'g:ctrlp_bufname_mod'*
'g:ctrlp_bufpath_mod' ctrlp.cnx /*'g:ctrlp_bufpath_mod'*
'g:ctrlp_buftag_ctags_bin' ctrlp.cnx /*'g:ctrlp_buftag_ctags_bin'*
'g:ctrlp_buftag_systemenc' ctrlp.cnx /*'g:ctrlp_buftag_systemenc'*
'g:ctrlp_buftag_types' ctrlp.cnx /*'g:ctrlp_buftag_types'*
'g:ctrlp_by_filename' ctrlp.cnx /*'g:ctrlp_by_filename'*
'g:ctrlp_cache_dir' ctrlp.cnx /*'g:ctrlp_cache_dir'*
'g:ctrlp_clear_cache_on_exit' ctrlp.cnx /*'g:ctrlp_clear_cache_on_exit'*
'g:ctrlp_cmd' ctrlp.cnx /*'g:ctrlp_cmd'*
'g:ctrlp_custom_ignore' ctrlp.cnx /*'g:ctrlp_custom_ignore'*
'g:ctrlp_default_input' ctrlp.cnx /*'g:ctrlp_default_input'*
'g:ctrlp_follow_symlinks' ctrlp.cnx /*'g:ctrlp_follow_symlinks'*
'g:ctrlp_key_loop' ctrlp.cnx /*'g:ctrlp_key_loop'*
'g:ctrlp_lazy_update' ctrlp.cnx /*'g:ctrlp_lazy_update'*
'g:ctrlp_line_prefix' ctrlp.cnx /*'g:ctrlp_line_prefix'*
'g:ctrlp_map' ctrlp.cnx /*'g:ctrlp_map'*
'g:ctrlp_match_current_file' ctrlp.cnx /*'g:ctrlp_match_current_file'*
'g:ctrlp_match_func' ctrlp.cnx /*'g:ctrlp_match_func'*
'g:ctrlp_match_window' ctrlp.cnx /*'g:ctrlp_match_window'*
'g:ctrlp_max_depth' ctrlp.cnx /*'g:ctrlp_max_depth'*
'g:ctrlp_max_files' ctrlp.cnx /*'g:ctrlp_max_files'*
'g:ctrlp_max_history' ctrlp.cnx /*'g:ctrlp_max_history'*
'g:ctrlp_mruf_case_sensitive' ctrlp.cnx /*'g:ctrlp_mruf_case_sensitive'*
'g:ctrlp_mruf_default_order' ctrlp.cnx /*'g:ctrlp_mruf_default_order'*
'g:ctrlp_mruf_exclude' ctrlp.cnx /*'g:ctrlp_mruf_exclude'*
'g:ctrlp_mruf_include' ctrlp.cnx /*'g:ctrlp_mruf_include'*
'g:ctrlp_mruf_max' ctrlp.cnx /*'g:ctrlp_mruf_max'*
'g:ctrlp_mruf_relative' ctrlp.cnx /*'g:ctrlp_mruf_relative'*
'g:ctrlp_mruf_save_on_update' ctrlp.cnx /*'g:ctrlp_mruf_save_on_update'*
'g:ctrlp_open_func' ctrlp.cnx /*'g:ctrlp_open_func'*
'g:ctrlp_open_multiple_files' ctrlp.cnx /*'g:ctrlp_open_multiple_files'*
'g:ctrlp_open_new_file' ctrlp.cnx /*'g:ctrlp_open_new_file'*
'g:ctrlp_open_single_match' ctrlp.cnx /*'g:ctrlp_open_single_match'*
'g:ctrlp_prompt_mappings' ctrlp.cnx /*'g:ctrlp_prompt_mappings'*
'g:ctrlp_regexp' ctrlp.cnx /*'g:ctrlp_regexp'*
'g:ctrlp_reuse_window' ctrlp.cnx /*'g:ctrlp_reuse_window'*
'g:ctrlp_root_markers' ctrlp.cnx /*'g:ctrlp_root_markers'*
'g:ctrlp_show_hidden' ctrlp.cnx /*'g:ctrlp_show_hidden'*
'g:ctrlp_status_func' ctrlp.cnx /*'g:ctrlp_status_func'*
'g:ctrlp_switch_buffer' ctrlp.cnx /*'g:ctrlp_switch_buffer'*
'g:ctrlp_tabpage_position' ctrlp.cnx /*'g:ctrlp_tabpage_position'*
'g:ctrlp_tilde_homedir' ctrlp.cnx /*'g:ctrlp_tilde_homedir'*
'g:ctrlp_use_caching' ctrlp.cnx /*'g:ctrlp_use_caching'*
'g:ctrlp_user_command' ctrlp.cnx /*'g:ctrlp_user_command'*
'g:ctrlp_working_path_mode' ctrlp.cnx /*'g:ctrlp_working_path_mode'*
'g:loaded_ctrlp' ctrlp.cnx /*'g:loaded_ctrlp'*
:CtrlP ctrlp.cnx /*:CtrlP*
:CtrlPBookmarkDir ctrlp.cnx /*:CtrlPBookmarkDir*
:CtrlPBookmarkDirAdd ctrlp.cnx /*:CtrlPBookmarkDirAdd*
:CtrlPBufTag ctrlp.cnx /*:CtrlPBufTag*
:CtrlPBufTagAll ctrlp.cnx /*:CtrlPBufTagAll*
:CtrlPBuffer ctrlp.cnx /*:CtrlPBuffer*
:CtrlPChange ctrlp.cnx /*:CtrlPChange*
:CtrlPChangeAll ctrlp.cnx /*:CtrlPChangeAll*
:CtrlPClearAllCaches ctrlp.cnx /*:CtrlPClearAllCaches*
:CtrlPClearCache ctrlp.cnx /*:CtrlPClearCache*
:CtrlPDir ctrlp.cnx /*:CtrlPDir*
:CtrlPLastMode ctrlp.cnx /*:CtrlPLastMode*
:CtrlPLine ctrlp.cnx /*:CtrlPLine*
:CtrlPMRU ctrlp.cnx /*:CtrlPMRU*
:CtrlPMixed ctrlp.cnx /*:CtrlPMixed*
:CtrlPQuickfix ctrlp.cnx /*:CtrlPQuickfix*
:CtrlPRTS ctrlp.cnx /*:CtrlPRTS*
:CtrlPRoot ctrlp.cnx /*:CtrlPRoot*
:CtrlPTag ctrlp.cnx /*:CtrlPTag*
:CtrlPUndo ctrlp.cnx /*:CtrlPUndo*
ClearAllCtrlPCaches ctrlp.cnx /*ClearAllCtrlPCaches*
ClearCtrlPCache ctrlp.cnx /*ClearCtrlPCache*
ControlP ctrlp.cnx /*ControlP*
CtrlP ctrlp.cnx /*CtrlP*
ResetCtrlP ctrlp.cnx /*ResetCtrlP*
ctrlp-autoignore-extension ctrlp.cnx /*ctrlp-autoignore-extension*
ctrlp-changelog ctrlp.cnx /*ctrlp-changelog*
ctrlp-commands ctrlp.cnx /*ctrlp-commands*
ctrlp-content ctrlp.cnx /*ctrlp-content*
ctrlp-credits ctrlp.cnx /*ctrlp-credits*
ctrlp-customization ctrlp.cnx /*ctrlp-customization*
ctrlp-default-value ctrlp.cnx /*ctrlp-default-value*
ctrlp-extensions ctrlp.cnx /*ctrlp-extensions*
ctrlp-input-formats ctrlp.cnx /*ctrlp-input-formats*
ctrlp-intro ctrlp.cnx /*ctrlp-intro*
ctrlp-mappings ctrlp.cnx /*ctrlp-mappings*
ctrlp-miscellaneous-configs ctrlp.cnx /*ctrlp-miscellaneous-configs*
ctrlp-options ctrlp.cnx /*ctrlp-options*
ctrlp.txt ctrlp.cnx /*ctrlp.txt*
g:ctrlp_dont_split ctrlp.cnx /*g:ctrlp_dont_split*
g:ctrlp_dotfiles ctrlp.cnx /*g:ctrlp_dotfiles*
g:ctrlp_highlight_match ctrlp.cnx /*g:ctrlp_highlight_match*
g:ctrlp_jump_to_buffer ctrlp.cnx /*g:ctrlp_jump_to_buffer*
g:ctrlp_live_update ctrlp.cnx /*g:ctrlp_live_update*
g:ctrlp_match_window_bottom ctrlp.cnx /*g:ctrlp_match_window_bottom*
g:ctrlp_match_window_reversed ctrlp.cnx /*g:ctrlp_match_window_reversed*
g:ctrlp_max_height ctrlp.cnx /*g:ctrlp_max_height*
g:ctrlp_mru_files ctrlp.cnx /*g:ctrlp_mru_files*
g:ctrlp_open_multi ctrlp.cnx /*g:ctrlp_open_multi*
g:ctrlp_persistent_input ctrlp.cnx /*g:ctrlp_persistent_input*
g:ctrlp_regexp_search ctrlp.cnx /*g:ctrlp_regexp_search*
string-match ctrlp.cnx /*string-match*

View file

@ -0,0 +1,8 @@
language: ruby
rvm:
- 1.9.3
before_install: sudo apt-get install vim-gtk
before_script:
- "export DISPLAY=:99.0"
- "sh -e /etc/init.d/xvfb start"
script: "bundle exec rspec --color -f d"

View file

@ -0,0 +1,4 @@
source 'https://rubygems.org'
gem 'rspec'
gem 'vimrunner'

View file

@ -0,0 +1,20 @@
GEM
remote: https://rubygems.org/
specs:
diff-lcs (1.2.4)
rspec (2.13.0)
rspec-core (~> 2.13.0)
rspec-expectations (~> 2.13.0)
rspec-mocks (~> 2.13.0)
rspec-core (2.13.1)
rspec-expectations (2.13.0)
diff-lcs (>= 1.1.3, < 2.0)
rspec-mocks (2.13.1)
vimrunner (0.3.1)
PLATFORMS
ruby
DEPENDENCIES
rspec
vimrunner

View file

@ -0,0 +1,13 @@
Copyright 2012 Plataformatec
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.

View file

@ -0,0 +1,62 @@
# vim-elixir
[![Build Status](https://travis-ci.org/elixir-lang/vim-elixir.svg?branch=master)](https://travis-ci.org/elixir-lang/vim-elixir)
[Elixir](http://elixir-lang.org) support for vim. This plugin also adds support
for Elixir's templating language, EEx.
Features included so far:
* Syntax highlighting for Elixir and EEx
* Filetype detection for `.ex`, `.exs` and `.eex` files
* Automatic indentation
## Installation
### Plugin managers
The most common plugin managers include [vim-plug][vim-plug],
[NeoBundle][neobundle], [Vundle][vundle] and [pathogen.vim][pathogen].
With pathogen.vim, just clone this repository inside `~/.vim/bundle`:
```bash
git clone https://github.com/elixir-lang/vim-elixir.git ~/.vim/bundle/vim-elixir
```
With the other plugin managers, just follow the instructions on the homepage of
each plugin. In general, you have to add a line to your `~/.vimrc`:
```viml
" vim-plug
Plug 'elixir-lang/vim-elixir'
" NeoBundle
NeoBundle 'elixir-lang/vim-elixir'
" Vundle
Plugin 'elixir-lang/vim-elixir'
```
### Manual installation
Copy the contents of each directory in the respective directories inside
`~/.vim`.
## Syntastic integration
> :warning: **Warning:** older versions (`<= 3.4.0-106`) of
> [Syntastic][syntastic] check Elixir scripts *by executing them*. In addition
> to being unsafe, this can cause Vim to hang while saving Elixir scripts. This
> is not an error in `vim-elixir`. This issue [can be fixed in
> Syntastic][syntastic-issue-fix] by disabling Elixir checking by default.
>
> **If your version of Syntastic is below `3.4.0-107` (16 July 2014), you should
> update to a newer version.**
[vim-plug]: https://github.com/junegunn/vim-plug
[vundle]: https://github.com/gmarik/Vundle.vim
[neobundle]: https://github.com/Shougo/neobundle.vim
[pathogen]: https://github.com/tpope/vim-pathogen
[syntastic]: https://github.com/scrooloose/syntastic
[syntastic-issue-fix]: https://github.com/scrooloose/syntastic/commit/1d19dff701524ebed90a4fbd7c7cd75ab954b79d

View file

@ -0,0 +1,25 @@
if exists("current_compiler")
finish
endif
let current_compiler = "exunit"
if exists(":CompilerSet") != 2 " older Vim always used :setlocal
command -nargs=* CompilerSet setlocal <args>
endif
let s:cpo_save = &cpo
set cpo-=C
CompilerSet makeprg=mix\ test
CompilerSet errorformat=
\%E\ \ %n)\ %m,
\%+G\ \ \ \ \ **\ %m,
\%+G\ \ \ \ \ stacktrace:,
\%C\ \ \ \ \ %f:%l,
\%+G\ \ \ \ \ \ \ (%\\w%\\+)\ %f:%l:\ %m,
\%+G\ \ \ \ \ \ \ %f:%l:\ %.%#,
\**\ (%\\w%\\+)\ %f:%l:\ %m
let &cpo = s:cpo_save
unlet s:cpo_save
" vim: nowrap sw=2 sts=2 ts=8:

View file

@ -0,0 +1,15 @@
au BufRead,BufNewFile *.ex,*.exs call s:setf('elixir')
au BufRead,BufNewFile *.eex call s:setf('eelixir')
au BufRead,BufNewFile * call s:DetectElixir()
au FileType elixir,eelixir setl sw=2 sts=2 et iskeyword+=!,?
function! s:setf(filetype) abort
let &filetype = a:filetype
endfunction
function! s:DetectElixir()
if getline(1) =~ '^#!.*\<elixir\>'
call s:setf('elixir')
endif
endfunction

View file

@ -0,0 +1,87 @@
if exists("b:did_ftplugin")
finish
endif
let s:save_cpo = &cpo
set cpo-=C
let s:undo_ftplugin = ""
let s:browsefilter = "All Files (*.*)\t*.*\n"
let s:match_words = ""
if !exists("g:eelixir_default_subtype")
let g:eelixir_default_subtype = "html"
endif
if !exists("b:eelixir_subtype")
let s:lines = getline(1)."\n".getline(2)."\n".getline(3)."\n".getline(4)."\n".getline(5)."\n".getline("$")
let b:eelixir_subtype = matchstr(s:lines,'eelixir_subtype=\zs\w\+')
if b:eelixir_subtype == ''
let b:eelixir_subtype = matchstr(&filetype,'^eex\.\zs\w\+')
endif
if b:eelixir_subtype == ''
let b:eelixir_subtype = matchstr(substitute(expand("%:t"),'\c\%(\.eex\|\.eelixir\)\+$','',''),'\.\zs\w\+$')
endif
if b:eelixir_subtype == 'ex'
let b:eelixir_subtype = 'elixir'
elseif b:eelixir_subtype == 'exs'
let b:eelixir_subtype = 'elixir'
elseif b:eelixir_subtype == 'yml'
let b:eelixir_subtype = 'yaml'
elseif b:eelixir_subtype == 'js'
let b:eelixir_subtype = 'javascript'
elseif b:eelixir_subtype == 'txt'
" Conventional; not a real file type
let b:eelixir_subtype = 'text'
elseif b:eelixir_subtype == ''
let b:eelixir_subtype = g:eelixir_default_subtype
endif
endif
if exists("b:eelixir_subtype") && b:eelixir_subtype != ''
exe "runtime! ftplugin/".b:eelixir_subtype.".vim ftplugin/".b:eelixir_subtype."_*.vim ftplugin/".b:eelixir_subtype."/*.vim"
else
runtime! ftplugin/html.vim ftplugin/html_*.vim ftplugin/html/*.vim
endif
unlet! b:did_ftplugin
" Override our defaults if these were set by an included ftplugin.
if exists("b:undo_ftplugin")
let s:undo_ftplugin = b:undo_ftplugin
unlet b:undo_ftplugin
endif
if exists("b:browsefilter")
let s:browsefilter = b:browsefilter
unlet b:browsefilter
endif
if exists("b:match_words")
let s:match_words = b:match_words
unlet b:match_words
endif
runtime! ftplugin/elixir.vim ftplugin/elixir_*.vim ftplugin/elixir/*.vim
let b:did_ftplugin = 1
" Combine the new set of values with those previously included.
if exists("b:undo_ftplugin")
let s:undo_ftplugin = b:undo_ftplugin . " | " . s:undo_ftplugin
endif
if exists ("b:browsefilter")
let s:browsefilter = substitute(b:browsefilter,'\cAll Files (\*\.\*)\t\*\.\*\n','','') . s:browsefilter
endif
if exists("b:match_words")
let s:match_words = b:match_words . ',' . s:match_words
endif
" Load the combined list of match_words for matchit.vim
if exists("loaded_matchit")
let b:match_words = s:match_words
endif
setlocal comments=:<%#
setlocal commentstring=<%#\ %s\ %>
let b:undo_ftplugin = "setl cms< "
\ " | unlet! b:browsefilter b:match_words | " . s:undo_ftplugin
let &cpo = s:save_cpo

View file

@ -0,0 +1,57 @@
if (exists("b:did_ftplugin"))
finish
endif
let b:did_ftplugin = 1
" Matchit support
if exists("loaded_matchit") && !exists("b:match_words")
let b:match_ignorecase = 0
let b:match_words = '\:\@<!\<\%(do\|fn\)\:\@!\>' .
\ ':' .
\ '\<\%(else\|elsif\|catch\|after\|rescue\)\:\@!\>' .
\ ':' .
\ '\:\@<!\<end\>' .
\ ',{:},\[:\],(:)'
endif
setlocal comments=:#
setlocal commentstring=#\ %s
function! GetElixirFilename(word)
let word = a:word
" get first thing that starts uppercase, until the first space or end of line
let word = substitute(word,'^\s*\(\u[^ ]\+\).*$','\1','g')
" remove any trailing characters that don't look like a nested module
let word = substitute(word,'\.\U.*$','','g')
" replace module dots with slash
let word = substitute(word,'\.','/','g')
" remove any special chars
let word = substitute(word,'[^A-z0-9-_/]','','g')
" convert to snake_case
let word = substitute(word,'\(\u\+\)\(\u\l\)','\1_\2','g')
let word = substitute(word,'\(\u\+\)\(\u\l\)','\1_\2','g')
let word = substitute(word,'\(\l\|\d\)\(\u\)','\1_\2','g')
let word = substitute(word,'-','_','g')
let word = tolower(word)
return word
endfunction
let &l:path =
\ join([
\ getcwd().'/lib',
\ getcwd().'/src',
\ getcwd().'/deps/**/lib',
\ getcwd().'/deps/**/src',
\ &g:path
\ ], ',')
setlocal includeexpr=GetElixirFilename(v:fname)
setlocal suffixesadd=.ex,.exs,.eex,.erl,.yrl,.hrl
setlocal formatoptions-=t formatoptions+=croqlj

View file

@ -0,0 +1,67 @@
if exists("b:did_indent")
finish
endif
runtime! indent/elixir.vim
unlet! b:did_indent
setlocal indentexpr=
if exists("b:eelixir_subtype")
exe "runtime! indent/".b:eelixir_subtype.".vim"
else
runtime! indent/html.vim
endif
unlet! b:did_indent
if &l:indentexpr == ''
if &l:cindent
let &l:indentexpr = 'cindent(v:lnum)'
else
let &l:indentexpr = 'indent(prevnonblank(v:lnum-1))'
endif
endif
let b:eelixir_subtype_indentexpr = &l:indentexpr
let b:did_indent = 1
setlocal indentexpr=GetEelixirIndent()
setlocal indentkeys=o,O,*<Return>,<>>,{,},0),0],o,O,!^F,=end,=else,=elsif,=catch,=after,=rescue
" Only define the function once.
if exists("*GetEelixirIndent")
finish
endif
function! GetEelixirIndent(...)
if a:0 && a:1 == '.'
let v:lnum = line('.')
elseif a:0 && a:1 =~ '^\d'
let v:lnum = a:1
endif
let vcol = col('.')
call cursor(v:lnum,1)
let inelixir = searchpair('<%','','%>','W')
call cursor(v:lnum,vcol)
if inelixir && getline(v:lnum) !~ '^<%\|^\s*%>'
let ind = GetElixirIndent()
else
exe "let ind = ".b:eelixir_subtype_indentexpr
endif
let lnum = prevnonblank(v:lnum-1)
let line = getline(lnum)
let cline = getline(v:lnum)
if cline =~# '^\s*<%\s*\%(end\|else\|elsif\|catch\|after\|rescue\)\>.*%>'
let ind = ind - &sw
elseif line =~# '\S\s*<%\s*end\s*%>'
let ind = ind - &sw
endif
if line =~# '<%[=%]\=\s*.*\<do\s*%>'
let ind = ind + &sw
elseif line =~# '<%\s*\%(else\|elsif\|catch\|after\|rescue\)\>.*%>'
let ind = ind + &sw
endif
if cline =~# '^\s*%>\s*$'
let ind = ind - &sw
endif
return ind
endfunction

View file

@ -0,0 +1,141 @@
if exists("b:did_indent")
finish
endif
let b:did_indent = 1
setlocal nosmartindent
setlocal indentexpr=GetElixirIndent()
setlocal indentkeys+=0),0],0=end,0=else,0=match,0=elsif,0=catch,0=after,0=rescue
if exists("*GetElixirIndent")
finish
endif
let s:cpo_save = &cpo
set cpo&vim
let s:no_colon_before = ':\@<!'
let s:no_colon_after = ':\@!'
let s:symbols_end = '\]\|}\|)'
let s:symbols_start = '\[\|{\|('
let s:arrow = '^.*->$'
let s:skip_syntax = '\%(Comment\|String\)$'
let s:block_skip = "synIDattr(synID(line('.'),col('.'),1),'name') =~? '".s:skip_syntax."'"
let s:block_start = '\<\%(do\|fn\)\>'
let s:block_middle = 'else\|match\|elsif\|catch\|after\|rescue'
let s:block_end = 'end'
let s:starts_with_pipeline = '^\s*|>.*$'
let s:ending_with_assignment = '=\s*$'
let s:indent_keywords = '\<'.s:no_colon_before.'\%('.s:block_start.'\|'.s:block_middle.'\)$'.'\|'.s:arrow
let s:deindent_keywords = '^\s*\<\%('.s:block_end.'\|'.s:block_middle.'\)\>'.'\|'.s:arrow
let s:pair_start = '\<\%('.s:no_colon_before.s:block_start.'\)\>'.s:no_colon_after
let s:pair_middle = '\<\%('.s:block_middle.'\)\>'.s:no_colon_after.'\zs'
let s:pair_end = '\<\%('.s:no_colon_before.s:block_end.'\)\>\zs'
let s:inside_block = 0
function! GetElixirIndent()
let lnum = prevnonblank(v:lnum - 1)
" At the start of the file use zero indent.
if lnum == 0
return 0
endif
let opened_symbol = 0
let current_line = getline(v:lnum)
let last_line = getline(lnum)
let ind = indent(lnum)
" TODO: Remove these 2 lines
" I don't know why, but for the test on spec/indent/lists_spec.rb:24.
" Vim is making some mess on parsing the syntax of 'end', it is being
" recognized as 'elixirString' when should be recognized as 'elixirBlock'.
" This forces vim to sync the syntax.
call synID(v:lnum, 1, 1)
syntax sync fromstart
if synIDattr(synID(v:lnum, 1, 1), "name") !~ s:skip_syntax
if last_line !~ s:arrow
let split_line = split(last_line, '\zs')
let opened_symbol += count(split_line, '(') - count(split_line, ')')
let opened_symbol += count(split_line, '[') - count(split_line, ']')
let opened_symbol += count(split_line, '{') - count(split_line, '}')
end
" if start symbol is followed by a character, indent based on the
" whitespace after the symbol, otherwise use the default shiftwidth
if last_line =~ '\('.s:symbols_start.'\).'
let opened_prefix = matchlist(last_line, '\('.s:symbols_start.'\)\s*')[0]
let ind += (opened_symbol * strlen(opened_prefix))
else
let ind += (opened_symbol * &sw)
endif
if last_line =~ '^\s*\('.s:symbols_end.'\)' || last_line =~ s:indent_keywords
let ind += &sw
endif
if current_line =~ '^\s*\('.s:symbols_end.'\)'
let ind -= &sw
endif
if last_line =~ s:ending_with_assignment && opened_symbol == 0
let b:old_ind = indent(lnum)
let ind += &sw
end
" if line starts with pipeline
" and last line ends with a pipeline,
" align them
if last_line =~ '|>.*$' &&
\ current_line =~ s:starts_with_pipeline
let ind = float2nr(match(last_line, '|>') / &sw) * &sw
" if line starts with pipeline
" and last line is an attribution
" indents pipeline in same level as attribution
elseif current_line =~ s:starts_with_pipeline &&
\ last_line =~ '^[^=]\+=.\+$'
if !exists('b:old_ind') || b:old_ind == 0
let b:old_ind = indent(lnum)
end
let ind = float2nr(matchend(last_line, '=\s*[^ ]') / &sw) * &sw
endif
" if last line starts with pipeline
" and current line doesn't start with pipeline
" returns the indentation before the pipeline
if last_line =~ s:starts_with_pipeline &&
\ current_line !~ s:starts_with_pipeline
let ind = b:old_ind
endif
if current_line =~ s:deindent_keywords
let bslnum = searchpair(
\ s:pair_start,
\ s:pair_middle,
\ s:pair_end,
\ 'nbW',
\ s:block_skip
\ )
let ind = indent(bslnum)
endif
" indent case statements '->'
if current_line =~ s:arrow
let ind += &sw
endif
endif
return ind
endfunction
let &cpo = s:cpo_save
unlet s:cpo_save

View file

@ -0,0 +1,73 @@
require 'spec_helper'
describe "Indenting" do
context "single body functions inside do block" do
it "is declared with fn syntax" do
<<-EOF
def do
some_func = fn x -> x end
end
EOF
.should be_elixir_indentation
end
it "is declared with function syntax" do
<<-EOF
def do
some_func = function do x -> x end
end
EOF
.should be_elixir_indentation
end
it "spans in multiple lines" do
<<-EOF
def test do
assert_raise Queue.Empty, fn ->
Q.new |> Q.deq!
end
end
EOF
.should be_elixir_indentation
end
it "spans in multiple lines inside parentheses" do
<<-EOF
defmodule Test do
def lol do
Enum.map([1,2,3], fn x ->
x * 3
end)
end
end
EOF
.should be_elixir_indentation
end
end
context "multiple body functions declaring" do
it "it with fn syntax" do
<<-EOF
fizzbuzz = fn
0, 0, _ -> "FizzBuzz"
0, _, _ -> "Fizz"
_, 0, _ -> "Buzz"
_, _, x -> x
end
EOF
.should be_elixir_indentation
end
it "it with function syntax" do
<<-EOF
fizzbuzz = function do
0, 0, _ -> "FizzBuzz"
0, _, _ -> "Fizz"
_, 0, _ -> "Buzz"
_, _, x -> x
end
EOF
.should be_elixir_indentation
end
end
end

View file

@ -0,0 +1,60 @@
require 'spec_helper'
describe "Indenting" do
specify "'do' indenting" do
<<-EOF
do
something
end
EOF
.should be_elixir_indentation
end
it "does not consider :end as end" do
<<-EOF
defmodule Test do
def lol do
IO.inspect :end
end
end
EOF
.should be_elixir_indentation
end
it "does not consider do: as the start of a block" do
<<-EOF
def f do
if true, do: 42
end
EOF
.should be_elixir_indentation
end
it "do not mislead atom ':do'" do
<<-EOF
def f do
x = :do
end
EOF
.should be_elixir_indentation
end
it "multiline assignment" do
<<-EOF
defmodule Test do
def test do
one =
user
|> build_assoc(:videos)
|> Video.changeset()
other =
user2
|> build_assoc(:videos)
|> Video.changeset()
end
end
EOF
.should be_elixir_indentation
end
end

View file

@ -0,0 +1,15 @@
require 'spec_helper'
describe "Indenting" do
specify "case statements" do
<<-EOF
case some_function do
:ok ->
:ok
{ :error, :message } ->
{ :error, :message }
end
EOF
.should be_elixir_indentation
end
end

View file

@ -0,0 +1,13 @@
require 'spec_helper'
describe "Indenting" do
it "conditional" do
<<-EOF
cond do
foo -> 1
bar -> 2
end
EOF
.should be_elixir_indentation
end
end

View file

@ -0,0 +1,16 @@
require 'spec_helper'
describe "Indenting" do
context "documentation" do
it "with end keyword" do
<<-EOF
defmodule Test do
@doc """
end
"""
end
EOF
.should be_elixir_indentation
end
end
end

View file

@ -0,0 +1,29 @@
require 'spec_helper'
describe "Indenting" do
describe "Embedded Elixir" do
it "if-clauses" do
<<-EOF
# An Example
<%= if true do %>
It is obviously true
<% end %>
---
EOF
.should be_eelixir_indentation
end
it "if-else-clauses" do
<<-EOF
# An Example
<%= if true do %>
It is obviously true
<% else %>
This will never appear
<% end %>
---
EOF
.should be_eelixir_indentation
end
end
end

View file

@ -0,0 +1,23 @@
require 'spec_helper'
describe "Indenting" do
it "if-clauses" do
<<-EOF
if foo do
bar
end
EOF
.should be_elixir_indentation
end
it "if-else-clauses" do
<<-EOF
if foo do
bar
else
baz
end
EOF
.should be_elixir_indentation
end
end

View file

@ -0,0 +1,131 @@
require 'spec_helper'
describe "Indenting" do
specify "lists" do
<<-EOF
def example do
[ :foo,
:bar,
:baz ]
end
EOF
.should be_elixir_indentation
end
specify "nested list" do
<<-EOF
[
[
:foo
]
]
EOF
.should be_elixir_indentation
end
specify "keyword list" do
<<-EOF
def project do
[ name: "mix",
version: "0.1.0",
deps: deps ]
end
EOF
.should be_elixir_indentation
end
specify "keyword" do
<<-EOF
def config do
[ name:
"John" ]
end
EOF
.should be_elixir_indentation
end
specify "list of tuples" do
<<-EOF
def test do
[ { :cowboy, github: "extend/cowboy" },
{ :dynamo, "0.1.0-dev", github: "elixir-lang/dynamo" },
{ :ecto, github: "elixir-lang/ecto" },
{ :pgsql, github: "semiocast/pgsql" } ]
end
EOF
.should be_elixir_indentation
end
specify "list of lists" do
<<-EOF
def test do
[ [:a, :b, :c],
[:d, :e, :f] ]
end
EOF
.should be_elixir_indentation
end
specify "complex list" do
<<-EOF
def test do
[ app: :first,
version: "0.0.1",
dynamos: [First.Dynamo],
compilers: [:elixir, :dynamo, :ecto, :app],
env: [prod: [compile_path: "ebin"]],
compile_path: "tmp/first/ebin",
deps: deps ]
end
EOF
.should be_elixir_indentation
end
specify "lists without whitespace" do
<<-EOF
def project do
[{:bar, path: "deps/umbrella/apps/bar"},
{:umbrella, path: "deps/umbrella"}]
end
EOF
.should be_elixir_indentation
end
specify "lists with line break after square brackets" do
<<-EOF
def project do
[
{ :bar, path: "deps/umbrella/apps/bar" },
{ :umbrella, path: "deps/umbrella" }
]
end
EOF
.should be_elixir_indentation
end
specify "multiple lists with multiline elements" do
<<-EOF
def test do
a = [
%{
foo: 1,
bar: 2
}
]
b = %{
[
:foo,
:bar
]
}
[
a,
b
]
end
EOF
.should be_elixir_indentation
end
end

View file

@ -0,0 +1,71 @@
require 'spec_helper'
describe "Indenting" do
it "using multiline pipeline" do
<<-EOF
"a,b,c,d"
|> String.split(",")
|> Enum.reverse
EOF
.should be_elixir_indentation
end
it "attribuition using multline pipeline operator" do
<<-EOF
[ h | t ] = "a,b,c,d"
|> String.split(",")
|> Enum.reverse
EOF
.should be_elixir_indentation
end
it "function with pipeline operator" do
<<-EOF
def test do
[ h | t ] = "a,b,c,d"
|> String.split(",")
|> Enum.reverse
{ :ok, h }
end
EOF
.should be_elixir_indentation
end
it "do not breaks on `==`" do
<<-EOF
def test do
my_post = Post
|> where([p], p.id == 10)
|> where([p], u.user_id == 1)
|> select([p], p)
end
EOF
.should be_elixir_indentation
end
it "pipeline operator with block open" do
<<-EOF
def test do
"a,b,c,d"
|> String.split(",")
|> Enum.first
|> case do
"a" -> "A"
_ -> "Z"
end
end
EOF
.should be_elixir_indentation
end
it "using a record with pipeline" do
<<-EOF
defrecord RECORD, field_a: nil, field_b: nil
rec = RECORD.new
|> IO.inspect
EOF
.should be_elixir_indentation
end
end

View file

@ -0,0 +1,26 @@
require 'spec_helper'
describe "Indenting" do
specify "multiline tuple" do
<<-EOF
def xpto do
{ :a,
:b,
:c }
end
EOF
.should be_elixir_indentation
end
specify "tuples with break line after square brackets" do
<<-EOF
def method do
{
:bar,
path: "deps/umbrella/apps/bar"
}
end
EOF
.should be_elixir_indentation
end
end

View file

@ -0,0 +1,115 @@
require 'rspec/expectations'
require 'tmpdir'
require 'vimrunner'
class Buffer
attr_reader :file, :vim
def initialize(vim, type)
@file = "test.#{type}"
@vim = vim
end
def reindent(code)
open code do
# remove all indentation
vim.normal 'ggVG999<<'
# force vim to indent the file
vim.normal 'gg=G'
end
end
def syntax(code, pattern)
read code
# move cursor the pattern
vim.search pattern
# get a list of the syntax element
vim.echo <<-EOF
map(synstack(line('.'), col('.')), 'synIDattr(v:val, "name")')
EOF
end
private
def open(code)
read code
# run vim commands
yield if block_given?
vim.write
IO.read(file)
end
def read(code)
File.open(file, 'w') { |f| f.write code }
vim.edit file
end
end
def cleanup(string)
whitespace = string.scan(/^\s*/).first
string.gsub(/^#{whitespace}/, '')
end
{ be_elixir_indentation: :ex,
be_eelixir_indentation: :eex
}.each do |matcher, type|
RSpec::Matchers.define matcher do
buffer = Buffer.new(VIM, type)
match do |code|
actual = cleanup(code)
buffer.reindent(actual) == actual
end
failure_message_for_should do |code|
actual = cleanup(code)
"expected:\n\n#{actual}\n got:\n\n#{ buffer.reindent(actual) }\n after elixir indentation"
end
end
end
{ include_elixir_syntax: :ex,
include_eelixir_syntax: :eex
}.each do |matcher, type|
RSpec::Matchers.define matcher do |syntax, pattern|
buffer = Buffer.new(VIM, type)
match do |code|
cleanup(code)
buffer.syntax(code, pattern).include? syntax
end
failure_message_for_should do |code|
actual = cleanup(code)
"expected #{buffer.syntax(code, pattern)} to include syntax #{syntax}\nfor pattern: /#{pattern}/\n in:\n\n#{actual}"
end
failure_message_for_should_not do |code|
actual = cleanup(code)
"expected #{buffer.syntax(code, pattern)} not to include syntax #{syntax}\nfor pattern: /#{pattern}/\n in:\n\n#{actual}"
end
end
end
RSpec.configure do |config|
config.before(:suite) do
VIM = Vimrunner.start_gvim
VIM.prepend_runtimepath(File.expand_path('../..', __FILE__))
VIM.command('runtime ftdetect/elixir.vim')
VIM.command('runtime ftdetect/eelixir.vim')
end
config.after(:suite) do
VIM.kill
end
config.around(:each) do |example|
# cd into a temporary directory for every example.
Dir.mktmpdir do |dir|
Dir.chdir(dir) do
VIM.command("cd #{dir}")
example.call
end
end
end
end

View file

@ -0,0 +1,24 @@
require 'spec_helper'
describe "Alias syntax" do
it "colorize only module alias" do
<<-EOF
Enum.empty?(...)
EOF
.should include_elixir_syntax('elixirAlias', 'Enum')
end
it "colorize the module alias even if it starts with `!`" do
<<-EOF
!Enum.empty?(...)
EOF
.should include_elixir_syntax('elixirAlias', 'aEnum')
end
it "does not colorize words starting with lowercase letters" do
<<-EOF
aEnum.empty?(...)
EOF
.should_not include_elixir_syntax('elixirAlias', 'aEnum')
end
end

View file

@ -0,0 +1,15 @@
require 'spec_helper'
describe "Default argument syntax" do
it "default argument" do
<<-'EOF'
def foo(bar \\ :baz)
EOF
.should include_elixir_syntax('elixirOperator', '\\')
<<-EOF
def foo(bar // :baz)
EOF
.should include_elixir_syntax('elixirOperator', '\/')
end
end

View file

@ -0,0 +1,26 @@
require 'spec_helper'
describe "Embedded Elixir syntax" do
it "elixir" do
'<%= if true do %>'.should include_eelixir_syntax('elixirKeyword', 'if')
'<%= if true do %>'.should include_eelixir_syntax('elixirBoolean', 'true')
end
it "expression" do
'<%= if true do %>'.should include_eelixir_syntax('eelixirExpression', 'if')
'<% end %>'.should include_eelixir_syntax('eelixirExpression', 'end')
end
it "quote" do
'<%% def f %>'.should include_eelixir_syntax('eelixirQuote', 'def')
end
it "comment" do
'<%# foo bar baz %>'.should include_eelixir_syntax('eelixirComment', 'foo')
end
it "delimiters" do
'<% end %>'.should include_eelixir_syntax('eelixirDelimiter', '<%')
'<% end %>'.should include_eelixir_syntax('eelixirDelimiter', '%>')
end
end

View file

@ -0,0 +1,29 @@
require 'spec_helper'
describe "Guard syntax" do
it "guard in function" do
<<-EOF
def fun(a) when is_atom(a) do
end
EOF
.should include_elixir_syntax('elixirKeyword', 'is_atom')
end
it "guard in case" do
<<-EOF
case
a when is_atom(a) -> {:ok, a}
end
EOF
.should include_elixir_syntax('elixirKeyword', 'is_atom')
end
it "does not highlight outside guards" do
<<-EOF
if is_atom(a) do
{:ok, a}
end
EOF
.should_not include_elixir_syntax('elixirKeyword', 'is_atom')
end
end

View file

@ -0,0 +1,70 @@
require 'spec_helper'
describe "Heredoc syntax" do
describe "binary" do
it "with multiline content" do
<<-EOF
@doc """
foo
"""
EOF
.should include_elixir_syntax('elixirDocString', 'foo')
end
it "escapes quotes unless only preceded by whitespace" do
<<-EOF
@doc """
foo """
"""
EOF
.should include_elixir_syntax('elixirDocString', %q(^\s*\zs"""))
end
it "does not include content on initial line", focus: true do
<<-EOF
String.at """, 0
foo
end
EOF
.should include_elixir_syntax('elixirNumber', '0')
end
it "with interpolation" do
<<-EOF
@doc """
foo \#{bar}
"""
EOF
.should include_elixir_syntax('elixirInterpolation', 'bar')
end
end
describe "character list" do
it "with multiline content" do
<<-EOF
@doc """
foo
"""
EOF
.should include_elixir_syntax('elixirDocString', 'foo')
end
it "escapes quotes unless only preceded by whitespace" do
<<-EOF
@doc '''
foo '''
'''
EOF
.should include_elixir_syntax('elixirDocString', %q(^\s*\zs'''))
end
it "with interpolation" do
<<-EOF
@doc '''
foo \#{bar}
'''
EOF
.should include_elixir_syntax('elixirInterpolation', 'bar')
end
end
end

View file

@ -0,0 +1,12 @@
require 'spec_helper'
describe "List syntax" do
it 'should properly handle "\\\\" inside' do
syntax = <<-EOF
'"\\\\'
var = 1
EOF
syntax.should include_elixir_syntax('elixirId', 'var')
syntax.should_not include_elixir_syntax('elixirString', 'var')
end
end

View file

@ -0,0 +1,11 @@
# encoding: utf-8
require 'spec_helper'
describe "Record syntax" do
it "private record symbol" do
<<-EOF
defrecordp :user, name: "José", age: 25
EOF
.should include_elixir_syntax('elixirAtom', ':user')
end
end

View file

@ -0,0 +1,104 @@
require 'spec_helper'
describe "Sigil syntax" do
describe "upper case" do
it "string" do
'~S(string)'.should include_elixir_syntax('elixirSigilDelimiter', 'S')
'~S(string)'.should include_elixir_syntax('elixirSigil', 'foo')
end
it "character list" do
'~C(charlist)'.should include_elixir_syntax('elixirSigilDelimiter', 'C')
'~C(charlist)'.should include_elixir_syntax('elixirSigil', 'charlist')
end
it "regular expression" do
'~R(regex)'.should include_elixir_syntax('elixirSigilDelimiter', 'R')
'~R(regex)'.should include_elixir_syntax('elixirSigil', 'regex')
end
it "list of words" do
'~W(list of words)'.should include_elixir_syntax('elixirSigilDelimiter', 'W')
'~W(list of words)'.should include_elixir_syntax('elixirSigil', 'list')
end
it "delimited with parans" do
'~S(foo bar)'.should include_elixir_syntax('elixirSigilDelimiter', '(')
'~S(foo bar)'.should include_elixir_syntax('elixirSigilDelimiter', ')')
end
it "delimited with braces" do
'~S{foo bar}'.should include_elixir_syntax('elixirSigilDelimiter', '{')
'~S{foo bar}'.should include_elixir_syntax('elixirSigilDelimiter', '}')
end
it "delimited with brackets" do
'~S[foo bar]'.should include_elixir_syntax('elixirSigilDelimiter', '[')
'~S[foo bar]'.should include_elixir_syntax('elixirSigilDelimiter', ']')
end
it "escapes double quotes unless only preceded by whitespace" do
<<-EOF
~r"""
foo """
"""
EOF
.should include_elixir_syntax('elixirSigilDelimiter', %q(^\s*\zs"""))
end
it "escapes single quotes unless only preceded by whitespace" do
<<-EOF
~r'''
foo '''
'''
EOF
.should include_elixir_syntax('elixirSigilDelimiter', %q(^\s*\zs'''))
end
it "without escapes" do
'~S(foo \n bar)'.should_not include_elixir_syntax('elixirRegexEscape', '\\')
end
it "without interpolation" do
'~S(foo #{bar})'.should_not include_elixir_syntax('elixirInterpolation', 'bar')
end
it "without escaped parans" do
'~S(\( )'.should_not include_elixir_syntax('elixirRegexEscapePunctuation', '( ')
end
end
describe "lower case" do
it "string" do
'~s(string)'.should include_elixir_syntax('elixirSigilDelimiter', 's')
'~s(string)'.should include_elixir_syntax('elixirSigil', 'foo')
end
it "character list" do
'~c(charlist)'.should include_elixir_syntax('elixirSigilDelimiter', 'c')
'~c(charlist)'.should include_elixir_syntax('elixirSigil', 'charlist')
end
it "regular expression" do
'~r(regex)'.should include_elixir_syntax('elixirSigilDelimiter', 'r')
'~r(regex)'.should include_elixir_syntax('elixirSigil', 'regex')
end
it "list of words" do
'~w(list of words)'.should include_elixir_syntax('elixirSigilDelimiter', 'w')
'~w(list of words)'.should include_elixir_syntax('elixirSigil', 'list')
end
it "with escapes" do
'~s(foo \n bar)'.should include_elixir_syntax('elixirRegexEscape', '\\')
end
it "with interpolation" do
'~s(foo #{bar})'.should include_elixir_syntax('elixirInterpolation', 'bar')
end
it "with escaped parans" do
'~s(\( )'.should include_elixir_syntax('elixirRegexEscapePunctuation', '( ')
end
end
end

View file

@ -0,0 +1,17 @@
require 'spec_helper'
describe "Struct syntax" do
it "without defaults" do
<<-EOF
defstruct [:name, :age]
EOF
.should include_elixir_syntax('elixirAtom', ':name')
end
it "with defaults" do
<<-EOF
defstruct name: "john", age: 27
EOF
.should include_elixir_syntax('elixirAtom', 'name:')
end
end

View file

@ -0,0 +1,12 @@
require 'spec_helper'
describe "Variable syntax" do
it "unused" do
<<-EOF
def handle_call(:pop, _from, [h|stack]) do
{ :reply, h, stack }
end
EOF
.should include_elixir_syntax('elixirUnusedVariable', '_from')
end
end

View file

@ -0,0 +1,61 @@
if exists("b:current_syntax")
finish
endif
if !exists("main_syntax")
let main_syntax = 'eelixir'
endif
if !exists("g:eelixir_default_subtype")
let g:eelixir_default_subtype = "html"
endif
if !exists("b:eelixir_subtype")
let s:lines = getline(1)."\n".getline(2)."\n".getline(3)."\n".getline(4)."\n".getline(5)."\n".getline("$")
let b:eelixir_subtype = matchstr(s:lines,'eelixir_subtype=\zs\w\+')
if b:eelixir_subtype == ''
let b:eelixir_subtype = matchstr(&filetype,'^eex\.\zs\w\+')
endif
if b:eelixir_subtype == ''
let b:eelixir_subtype = matchstr(substitute(expand("%:t"),'\c\%(\.eex\|\.eelixir\)\+$','',''),'\.\zs\w\+$')
endif
if b:eelixir_subtype == 'ex'
let b:eelixir_subtype = 'elixir'
elseif b:eelixir_subtype == 'exs'
let b:eelixir_subtype = 'elixir'
elseif b:eelixir_subtype == 'yml'
let b:eelixir_subtype = 'yaml'
elseif b:eelixir_subtype == 'js'
let b:eelixir_subtype = 'javascript'
elseif b:eelixir_subtype == 'txt'
" Conventional; not a real file type
let b:eelixir_subtype = 'text'
elseif b:eelixir_subtype == ''
let b:eelixir_subtype = g:eelixir_default_subtype
endif
endif
if exists("b:eelixir_subtype") && b:eelixir_subtype != ''
exe "runtime! syntax/".b:eelixir_subtype.".vim"
unlet! b:current_syntax
endif
syn include @elixirTop syntax/elixir.vim
syn cluster eelixirRegions contains=eelixirBlock,eelixirExpression,eelixirComment
exe 'syn region eelixirExpression matchgroup=eelixirDelimiter start="<%" end="%\@<!%>" contains=@elixirTop containedin=ALLBUT,@eelixirRegions keepend'
exe 'syn region eelixirExpression matchgroup=eelixirDelimiter start="<%=" end="%\@<!%>" contains=@elixirTop containedin=ALLBUT,@eelixirRegions keepend'
exe 'syn region eelixirQuote matchgroup=eelixirDelimiter start="<%%" end="%\@<!%>" contains=@elixirTop containedin=ALLBUT,@eelixirRegions keepend'
exe 'syn region eelixirComment matchgroup=eelixirDelimiter start="<%#" end="%\@<!%>" contains=elixirTodo,@Spell containedin=ALLBUT,@eelixirRegions keepend'
" Define the default highlighting.
hi def link eelixirDelimiter PreProc
hi def link eelixirComment Comment
let b:current_syntax = 'eelixir'
if main_syntax == 'eelixir'
unlet main_syntax
endif

View file

@ -0,0 +1,188 @@
if exists("b:current_syntax")
finish
endif
" syncing starts 2000 lines before top line so docstrings don't screw things up
syn sync minlines=2000
syn cluster elixirNotTop contains=@elixirRegexSpecial,@elixirStringContained,@elixirDeclaration,elixirTodo,elixirArguments,elixirBlockDefinition
syn match elixirComment '#.*' contains=elixirTodo,@Spell
syn keyword elixirTodo FIXME NOTE TODO OPTIMIZE XXX HACK contained
syn keyword elixirKeyword case when with cond for if unless try receive send
syn keyword elixirKeyword exit raise throw after rescue catch else
syn keyword elixirKeyword quote unquote super spawn spawn_link spawn_monitor
" Functions used on guards
syn keyword elixirKeyword contained is_atom is_binary is_bitstring is_boolean
syn keyword elixirKeyword contained is_float is_function is_integer is_list
syn keyword elixirKeyword contained is_map is_nil is_number is_pid is_port
syn keyword elixirKeyword contained is_record is_reference is_tuple is_exception
syn keyword elixirKeyword contained abs bit_size byte_size div elem hd length
syn keyword elixirKeyword contained map_size node rem round tl trunc tuple_size
syn match elixirGuard '.*when.*' contains=ALLBUT,@elixirNotTop
syn keyword elixirInclude import require alias use
syn keyword elixirSelf self
syn match elixirId '\<[_a-zA-Z]\w*[!?]\?\>'
" This unfortunately also matches function names in function calls
syn match elixirUnusedVariable '\(([^)]*\)\@<=\<_\w*\>'
syn keyword elixirOperator and not or when xor in
syn match elixirOperator '!==\|!=\|!'
syn match elixirOperator '=\~\|===\|==\|='
syn match elixirOperator '<<<\|<<\|<=\|<-\|<'
syn match elixirOperator '>>>\|>>\|>=\|>'
syn match elixirOperator '->\|--\|-'
syn match elixirOperator '++\|+'
syn match elixirOperator '&&&\|&&\|&'
syn match elixirOperator '|||\|||\||>\||'
syn match elixirOperator '\.\.\|\.'
syn match elixirOperator "\^\^\^\|\^"
syn match elixirOperator '\\\\\|::\|\*\|/\|\~\~\~\|@'
syn match elixirAtom '\(:\)\@<!:\%([a-zA-Z_]\w*\%([?!]\|=[>=]\@!\)\?\|<>\|===\?\|>=\?\|<=\?\)'
syn match elixirAtom '\(:\)\@<!:\%(<=>\|&&\?\|%\(()\|\[\]\|{}\)\|++\?\|--\?\|||\?\|!\|//\|[%&`/|]\)'
syn match elixirAtom "\%([a-zA-Z_]\w*[?!]\?\):\(:\)\@!"
syn match elixirAlias '\<[!]\?[A-Z]\w*\(\.[A-Z]\w*\)*\>'
syn keyword elixirBoolean true false nil
syn match elixirVariable '@[a-z]\w*'
syn match elixirVariable '&\d\+'
syn keyword elixirPseudoVariable __FILE__ __DIR__ __MODULE__ __ENV__ __CALLER__
syn match elixirNumber '\<\d\(_\?\d\)*\(\.[^[:space:][:digit:]]\@!\(_\?\d\)*\)\?\([eE][-+]\?\d\(_\?\d\)*\)\?\>'
syn match elixirNumber '\<0[xX][0-9A-Fa-f]\+\>'
syn match elixirNumber '\<0[bB][01]\+\>'
syn match elixirRegexEscape "\\\\\|\\[aAbBcdDefGhHnrsStvVwW]\|\\\d\{3}\|\\x[0-9a-fA-F]\{2}" contained
syn match elixirRegexEscapePunctuation "?\|\\.\|*\|\\\[\|\\\]\|+\|\\^\|\\\$\|\\|\|\\(\|\\)\|\\{\|\\}" contained
syn match elixirRegexQuantifier "[*?+][?+]\=" contained display
syn match elixirRegexQuantifier "{\d\+\%(,\d*\)\=}?\=" contained display
syn match elixirRegexCharClass "\[:\(alnum\|alpha\|ascii\|blank\|cntrl\|digit\|graph\|lower\|print\|punct\|space\|upper\|word\|xdigit\):\]" contained display
syn region elixirRegex matchgroup=elixirRegexDelimiter start="%r/" end="/[uiomxfr]*" skip="\\\\" contains=@elixirRegexSpecial
syn cluster elixirRegexSpecial contains=elixirRegexEscape,elixirRegexCharClass,elixirRegexQuantifier,elixirRegexEscapePunctuation
syn cluster elixirStringContained contains=elixirInterpolation,elixirRegexEscape,elixirRegexCharClass
syn region elixirString matchgroup=elixirStringDelimiter start="'" end="'" skip="\\'\|\\\\"
syn region elixirString matchgroup=elixirStringDelimiter start='"' end='"' skip='\\"' contains=@elixirStringContained
syn region elixirInterpolation matchgroup=elixirInterpolationDelimiter start="#{" end="}" contained contains=ALLBUT,elixirComment,@elixirNotTop
syn region elixirDocStringStart matchgroup=elixirDocString start=+"""+ end=+$+ oneline contains=ALLBUT,@elixirNotTop
syn region elixirDocStringStart matchgroup=elixirDocString start=+'''+ end=+$+ oneline contains=ALLBUT,@elixirNotTop
syn region elixirDocString start=+\z("""\)+ end=+^\s*\zs\z1+ contains=elixirDocStringStart,elixirTodo,elixirInterpolation,@Spell keepend fold
syn region elixirDocString start=+\z('''\)+ end=+^\s*\zs\z1+ contains=elixirDocStringStart,elixirTodo,elixirInterpolation,@Spell keepend fold
syn match elixirAtomInterpolated ':\("\)\@=' contains=elixirString
syn match elixirString "\(\w\)\@<!?\%(\\\(x\d{1,2}\|\h{1,2}\h\@!\>\|0[0-7]{0,2}[0-7]\@!\>\|[^x0MC]\)\|(\\[MC]-)+\w\|[^\s\\]\)"
syn region elixirBlock matchgroup=elixirBlockDefinition start="\<do\>:\@!" end="\<end\>" contains=ALLBUT,@elixirNotTop fold
syn region elixirAnonymousFunction matchgroup=elixirBlockDefinition start="\<fn\>" end="\<end\>" contains=ALLBUT,@elixirNotTop fold
syn region elixirArguments start="(" end=")" contained contains=elixirOperator,elixirAtom,elixirPseudoVariable,elixirAlias,elixirBoolean,elixirVariable,elixirUnusedVariable,elixirNumber,elixirDocString,elixirAtomInterpolated,elixirRegex,elixirString,elixirStringDelimiter,elixirRegexDelimiter,elixirInterpolationDelimiter,elixirSigilDelimiter
syn match elixirDelimEscape "\\[(<{\[)>}\]/\"'|]" transparent display contained contains=NONE
syn region elixirSigil matchgroup=elixirSigilDelimiter start="\~\u\z(/\|\"\|'\||\)" end="\z1" skip="\\\\\|\\\z1" contains=elixirDelimEscape fold
syn region elixirSigil matchgroup=elixirSigilDelimiter start="\~\u{" end="}" skip="\\\\\|\\}" contains=elixirDelimEscape fold
syn region elixirSigil matchgroup=elixirSigilDelimiter start="\~\u<" end=">" skip="\\\\\|\\>" contains=elixirDelimEscape fold
syn region elixirSigil matchgroup=elixirSigilDelimiter start="\~\u\[" end="\]" skip="\\\\\|\\\]" contains=elixirDelimEscape fold
syn region elixirSigil matchgroup=elixirSigilDelimiter start="\~\u(" end=")" skip="\\\\\|\\)" contains=elixirDelimEscape fold
syn region elixirSigil matchgroup=elixirSigilDelimiter start="\~\l\z(/\|\"\|'\||\)" end="\z1" skip="\\\\\|\\\z1" fold
syn region elixirSigil matchgroup=elixirSigilDelimiter start="\~\l{" end="}" skip="\\\\\|\\}" contains=@elixirStringContained,elixirRegexEscapePunctuation fold
syn region elixirSigil matchgroup=elixirSigilDelimiter start="\~\l<" end=">" skip="\\\\\|\\>" contains=@elixirStringContained,elixirRegexEscapePunctuation fold
syn region elixirSigil matchgroup=elixirSigilDelimiter start="\~\l\[" end="\]" skip="\\\\\|\\\]" contains=@elixirStringContained,elixirRegexEscapePunctuation fold
syn region elixirSigil matchgroup=elixirSigilDelimiter start="\~\l(" end=")" skip="\\\\\|\\)" contains=@elixirStringContained,elixirRegexEscapePunctuation fold
" Sigils surrounded with docString
syn region elixirSigil matchgroup=elixirSigilDelimiter start=+\~\a\z("""\)+ end=+^\s*\zs\z1+ skip=+\\"+ fold
syn region elixirSigil matchgroup=elixirSigilDelimiter start=+\~\a\z('''\)+ end=+^\s*\zs\z1+ skip=+\\'+ fold
" Defines
syn keyword elixirDefine def nextgroup=elixirFunctionDeclaration skipwhite skipnl
syn keyword elixirPrivateDefine defp nextgroup=elixirFunctionDeclaration skipwhite skipnl
syn keyword elixirModuleDefine defmodule nextgroup=elixirModuleDeclaration skipwhite skipnl
syn keyword elixirProtocolDefine defprotocol nextgroup=elixirProtocolDeclaration skipwhite skipnl
syn keyword elixirImplDefine defimpl nextgroup=elixirImplDeclaration skipwhite skipnl
syn keyword elixirRecordDefine defrecord nextgroup=elixirRecordDeclaration skipwhite skipnl
syn keyword elixirPrivateRecordDefine defrecordp nextgroup=elixirRecordDeclaration skipwhite skipnl
syn keyword elixirMacroDefine defmacro nextgroup=elixirMacroDeclaration skipwhite skipnl
syn keyword elixirPrivateMacroDefine defmacrop nextgroup=elixirMacroDeclaration skipwhite skipnl
syn keyword elixirDelegateDefine defdelegate nextgroup=elixirDelegateDeclaration skipwhite skipnl
syn keyword elixirOverridableDefine defoverridable nextgroup=elixirOverridableDeclaration skipwhite skipnl
syn keyword elixirExceptionDefine defexception nextgroup=elixirExceptionDeclaration skipwhite skipnl
syn keyword elixirCallbackDefine defcallback nextgroup=elixirCallbackDeclaration skipwhite skipnl
syn keyword elixirStructDefine defstruct skipwhite skipnl
" Declarations
syn match elixirModuleDeclaration "[^[:space:];#<]\+" contained contains=elixirAlias nextgroup=elixirBlock skipwhite skipnl
syn match elixirFunctionDeclaration "[^[:space:];#<,()\[\]]\+" contained nextgroup=elixirArguments skipwhite skipnl
syn match elixirProtocolDeclaration "[^[:space:];#<]\+" contained contains=elixirAlias skipwhite skipnl
syn match elixirImplDeclaration "[^[:space:];#<]\+" contained contains=elixirAlias skipwhite skipnl
syn match elixirRecordDeclaration "[^[:space:];#<]\+" contained contains=elixirAlias,elixirAtom skipwhite skipnl
syn match elixirMacroDeclaration "[^[:space:];#<,()\[\]]\+" contained nextgroup=elixirArguments skipwhite skipnl
syn match elixirDelegateDeclaration "[^[:space:];#<,()\[\]]\+" contained contains=elixirFunctionDeclaration skipwhite skipnl
syn region elixirDelegateDeclaration start='\[' end='\]' contained contains=elixirFunctionDeclaration skipwhite skipnl
syn match elixirOverridableDeclaration "[^[:space:];#<]\+" contained contains=elixirAlias skipwhite skipnl
syn match elixirExceptionDeclaration "[^[:space:];#<]\+" contained contains=elixirAlias skipwhite skipnl
syn match elixirCallbackDeclaration "[^[:space:];#<,()\[\]]\+" contained contains=elixirFunctionDeclaration skipwhite skipnl
syn cluster elixirDeclaration contains=elixirFunctionDeclaration,elixirModuleDeclaration,elixirProtocolDeclaration,elixirImplDeclaration,elixirRecordDeclaration,elixirMacroDeclaration,elixirDelegateDeclaration,elixirOverridableDeclaration,elixirExceptionDeclaration,elixirCallbackDeclaration,elixirStructDeclaration
hi def link elixirBlockDefinition Keyword
hi def link elixirDefine Define
hi def link elixirPrivateDefine Define
hi def link elixirModuleDefine Define
hi def link elixirProtocolDefine Define
hi def link elixirImplDefine Define
hi def link elixirRecordDefine Define
hi def link elixirPrivateRecordDefine Define
hi def link elixirMacroDefine Define
hi def link elixirPrivateMacroDefine Define
hi def link elixirDelegateDefine Define
hi def link elixirOverridableDefine Define
hi def link elixirExceptionDefine Define
hi def link elixirCallbackDefine Define
hi def link elixirStructDefine Define
hi def link elixirFunctionDeclaration Function
hi def link elixirMacroDeclaration Macro
hi def link elixirInclude Include
hi def link elixirComment Comment
hi def link elixirTodo Todo
hi def link elixirKeyword Keyword
hi def link elixirOperator Operator
hi def link elixirAtom Constant
hi def link elixirPseudoVariable Constant
hi def link elixirAlias Type
hi def link elixirBoolean Boolean
hi def link elixirVariable Identifier
hi def link elixirSelf Identifier
hi def link elixirUnusedVariable Comment
hi def link elixirNumber Number
hi def link elixirDocString String
hi def link elixirAtomInterpolated elixirAtom
hi def link elixirRegex elixirString
hi def link elixirRegexEscape elixirSpecial
hi def link elixirRegexEscapePunctuation elixirSpecial
hi def link elixirRegexCharClass elixirSpecial
hi def link elixirRegexQuantifier elixirSpecial
hi def link elixirSpecial Special
hi def link elixirString String
hi def link elixirSigil String
hi def link elixirStringDelimiter Delimiter
hi def link elixirRegexDelimiter Delimiter
hi def link elixirInterpolationDelimiter Delimiter
hi def link elixirSigilDelimiter Delimiter
let b:current_syntax = "elixir"