├── .gitignore ├── LICENSE ├── README.md ├── addon-info.json ├── autoload ├── elm.vim └── elm │ └── util.vim ├── doc └── elm-vim.txt ├── ftdetect └── elm.vim ├── ftplugin ├── elm.vim └── elm │ └── tagbar.vim ├── indent └── elm.vim ├── plugin └── elm.vim ├── rplugin └── python3 │ └── deoplete │ └── sources │ └── deoplete_elm.py ├── screenshots ├── logo.png └── syntax_highlighting.png ├── syntax └── elm.vim └── syntax_checkers └── elm └── elm_make.vim /.gitignore: -------------------------------------------------------------------------------- 1 | .DS_Store 2 | doc/tags 3 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Copyright (c) 2015, Joseph Hager 2 | All rights reserved. 3 | 4 | Redistribution and use in source and binary forms, with or without 5 | modification, are permitted provided that the following conditions are met: 6 | 7 | * Redistributions of source code must retain the above copyright notice, this 8 | list of conditions and the following disclaimer. 9 | 10 | * Redistributions in binary form must reproduce the above copyright notice, 11 | this list of conditions and the following disclaimer in the documentation 12 | and/or other materials provided with the distribution. 13 | 14 | * Neither the name of elm-vim nor the names of its 15 | contributors may be used to endorse or promote products derived from 16 | this software without specific prior written permission. 17 | 18 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 19 | AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 20 | IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 21 | DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE 22 | FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 23 | DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 24 | SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 25 | CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 26 | OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 27 | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 28 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # elm-vim 2 | 3 | ![logo](https://raw.github.com/elmcast/elm-vim/master/screenshots/logo.png) 4 | 5 | ## Features 6 | 7 | 1. Syntax highlighting 8 | 1. Automatic indentation 9 | 1. Function completion 10 | 1. Build and package commands 11 | 1. Code formatting and linting 12 | 1. Documentation lookup 13 | 1. REPL integration 14 | 15 | Check out this [ElmCast video](https://vimeo.com/132107269) for more detail. 16 | 17 | ## Installation 18 | 19 | If you don't have a preferred installation method, I recommend installing [vim-plug](https://github.com/junegunn/vim-plug), and then simply add `Plug 'elmcast/elm-vim'` to your plugin section: 20 | 21 | *NOTE:* If you are using [vim-polyglot](https://github.com/sheerun/vim-polyglot), you need to disable its default elm plugin by adding `let g:polyglot_disabled = ['elm']` to your config file. 22 | 23 | ### Requirements 24 | 25 | First, make sure you have the [Elm Platform](http://elm-lang.org/install) installed. The simplest method to get started is to use the official [npm](https://www.npmjs.com/package/elm) package. 26 | 27 | ``` 28 | npm install -g elm 29 | ``` 30 | 31 | In order to run unit tests from within vim, install [elm-test](https://github.com/rtfeldman/node-elm-test) 32 | 33 | ``` 34 | npm install -g elm-test 35 | ``` 36 | 37 | For code completion and doc lookups, install [elm-oracle](https://github.com/elmcast/elm-oracle). 38 | 39 | ``` 40 | npm install -g elm-oracle 41 | ``` 42 | 43 | To automatically format your code, install [elm-format](https://github.com/avh4/elm-format). 44 | 45 | ``` 46 | npm install -g elm-format 47 | ``` 48 | 49 | ## Mappings 50 | 51 | The plugin provides several `` mappings which can be used to create custom 52 | mappings. The following keybindings are provided by default: 53 | 54 | | Keybinding | Description | 55 | | ---------------------- | ------------------------------------------------------------------- | 56 | | \m | Compile the current buffer. | 57 | | \b | Compile the Main.elm file in the project. | 58 | | \t | Runs the tests of the current buffer or 'tests/TestRunner'. | 59 | | \r | Opens an elm repl in a subprocess. | 60 | | \e | Shows the detail of the current error or warning. | 61 | | \d | Shows the type and docs for the word under the cursor. | 62 | | \w | Opens the docs web page for the word under the cursor. | 63 | 64 | You can disable these mappings if you want to use your own. 65 | 66 | ```vim 67 | let g:elm_setup_keybindings = 0 68 | ``` 69 | 70 | ## Integration 71 | 72 | ### [Ale](https://github.com/w0rp/ale) 73 | 74 | The preferred linter to use with elm-vim is Ale. It should work out of the box. 75 | 76 | ### [Syntastic](https://github.com/scrooloose/syntastic) 77 | 78 | Syntastic support should work out of the box, but we recommend the following settings: 79 | 80 | ```vim 81 | let g:syntastic_always_populate_loc_list = 1 82 | let g:syntastic_auto_loc_list = 1 83 | 84 | let g:elm_syntastic_show_warnings = 1 85 | ``` 86 | 87 | ### [YouCompleteMe](https://github.com/Valloric/YouCompleteMe) 88 | 89 | ```vim 90 | let g:ycm_semantic_triggers = { 91 | \ 'elm' : ['.'], 92 | \} 93 | ``` 94 | 95 | ### [Neocomplete](https://github.com/Shougo/neocomplete.vim) 96 | 97 | ```vim 98 | call neocomplete#util#set_default_dictionary( 99 | \ 'g:neocomplete#sources#omni#input_patterns', 100 | \ 'elm', 101 | \ '\.') 102 | ``` 103 | 104 | ## Usage 105 | 106 | ```vim 107 | :help elm-vim 108 | ``` 109 | 110 | ```vim 111 | let g:elm_jump_to_error = 0 112 | let g:elm_make_output_file = "elm.js" 113 | let g:elm_make_show_warnings = 0 114 | let g:elm_syntastic_show_warnings = 0 115 | let g:elm_browser_command = "" 116 | let g:elm_detailed_complete = 0 117 | let g:elm_format_autosave = 1 118 | let g:elm_format_fail_silently = 0 119 | let g:elm_setup_keybindings = 1 120 | ``` 121 | 122 | * `:ElmMake [filename]` calls `elm-make` with the given file. If no file is given it uses the current file being edited. 123 | 124 | * `:ElmMakeMain` attempts to call `elm-make` with "Main.elm". 125 | 126 | * `:ElmTest` calls `elm-test` with the given file. If no file is given it runs it in the root of your project. 127 | 128 | * `:ElmRepl` runs `elm-repl`, which will return to vim on exiting. 129 | 130 | * `:ElmErrorDetail` shows the detail of the current error in the quickfix window. 131 | 132 | * `:ElmShowDocs` queries elm-oracle, then echoes the type and docs for the word under the cursor. 133 | 134 | * `:ElmBrowseDocs` queries elm-oracle, then opens docs web page for the word under the cursor. 135 | 136 | * `:ElmFormat` formats the current buffer with elm-format. 137 | 138 | ## Screenshots 139 | 140 | ![errors and completion](https://raw.github.com/elmcast/elm-vim/master/screenshots/syntax_highlighting.png) 141 | 142 | ## Credits 143 | 144 | * Other vim-plugins, thanks for inspiration (elm.vim, ocaml.vim, haskell-vim) 145 | * [Contributors](https://github.com/elmcast/elm-vim/graphs/contributors) of elm-vim 146 | 147 | ## License 148 | 149 | Copyright © Joseph Hager. See `LICENSE` for more details. 150 | -------------------------------------------------------------------------------- /addon-info.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "elm-vim", 3 | "description": "Full featured Elm (elm-lang) support for Vim.", 4 | "author": "Joseph Hager ", 5 | "repository" : {"type": "git", "url": "https://github.com/ajhager/elm-vim.git"} 6 | } 7 | -------------------------------------------------------------------------------- /autoload/elm.vim: -------------------------------------------------------------------------------- 1 | let s:errors = [] 2 | 3 | function! s:elmOracle(...) abort 4 | let l:project = finddir('elm-stuff/..', '.;') 5 | if len(l:project) == 0 6 | echoerr '`elm-stuff` not found! run `elm-package install` for autocomplete.' 7 | return [] 8 | endif 9 | 10 | let l:filename = expand('%:p') 11 | 12 | if a:0 == 0 13 | let l:oldiskeyword = &iskeyword 14 | " Some non obvious values used in 'iskeyword': 15 | " @ = all alpha 16 | " 48-57 = numbers 0 to 9 17 | " @-@ = character @ 18 | " 124 = | 19 | setlocal iskeyword=@,48-57,@-@,_,-,~,!,#,$,%,&,*,+,=,<,>,/,?,.,\\,124,^ 20 | let l:word = expand('') 21 | let &iskeyword = l:oldiskeyword 22 | else 23 | let l:word = a:1 24 | endif 25 | 26 | let l:infos = elm#Oracle(l:filename, l:word) 27 | if v:shell_error != 0 28 | call elm#util#EchoError("elm-oracle failed:\n\n", l:infos) 29 | return [] 30 | endif 31 | 32 | let l:d = split(l:infos, '\n') 33 | if len(l:d) > 0 34 | return elm#util#DecodeJSON(l:d[0]) 35 | endif 36 | 37 | return [] 38 | endf 39 | 40 | " Vim command to format Elm files with elm-format 41 | function! elm#Format() abort 42 | " check for elm-format 43 | if elm#util#CheckBin('elm-format', 'https://github.com/avh4/elm-format') ==# '' 44 | return 45 | endif 46 | 47 | " save cursor position, folds and many other things 48 | let l:curw = {} 49 | try 50 | mkview! 51 | catch 52 | let l:curw = winsaveview() 53 | endtry 54 | 55 | " save our undo file to be restored after we are done. 56 | let l:tmpundofile = tempname() 57 | exe 'wundo! ' . l:tmpundofile 58 | 59 | " write current unsaved buffer to a temporary file 60 | let l:tmpname = tempname() . '.elm' 61 | call writefile(getline(1, '$'), l:tmpname) 62 | 63 | " call elm-format on the temporary file 64 | let l:out = system('elm-format ' . l:tmpname . ' --output ' . l:tmpname) 65 | 66 | " if there is no error 67 | if v:shell_error == 0 68 | try | silent undojoin | catch | endtry 69 | 70 | " replace current file with temp file, then reload buffer 71 | let l:old_fileformat = &fileformat 72 | call rename(l:tmpname, expand('%')) 73 | silent edit! 74 | let &fileformat = l:old_fileformat 75 | let &syntax = &syntax 76 | elseif g:elm_format_fail_silently == 0 77 | call elm#util#EchoLater('EchoError', 'elm-format:', l:out) 78 | endif 79 | 80 | " save our undo history 81 | silent! exe 'rundo ' . l:tmpundofile 82 | call delete(l:tmpundofile) 83 | 84 | " restore our cursor/windows positions, folds, etc.. 85 | if empty(l:curw) 86 | silent! loadview 87 | else 88 | call winrestview(l:curw) 89 | endif 90 | endf 91 | 92 | " Query elm-oracle and echo the type and docs for the word under the cursor. 93 | function! elm#ShowDocs() abort 94 | " check for the elm-oracle binary 95 | if elm#util#CheckBin('elm-oracle', 'https://github.com/elmcast/elm-oracle') ==# '' 96 | return 97 | endif 98 | 99 | let l:response = s:elmOracle() 100 | 101 | if len(l:response) > 0 102 | let l:info = l:response[0] 103 | redraws! | echohl Identifier | echon l:info.fullName | echohl None | echon ' : ' | echohl Function | echon l:info.signature | echohl None | echon "\n\n" . l:info.comment 104 | else 105 | call elm#util#Echo('elm-oracle:', '...no match found') 106 | endif 107 | endf 108 | 109 | " Query elm-oracle and open the docs for the word under the cursor. 110 | function! elm#BrowseDocs() abort 111 | " check for the elm-oracle binary 112 | if elm#util#CheckBin('elm-oracle', 'https://github.com/elmcast/elm-oracle') ==# '' 113 | return 114 | endif 115 | 116 | let l:response = s:elmOracle() 117 | 118 | if len(l:response) > 0 119 | let l:info = l:response[0] 120 | call elm#util#OpenBrowser(l:info.href) 121 | else 122 | call elm#util#Echo('elm-oracle:', '...no match found') 123 | endif 124 | endf 125 | 126 | 127 | function! elm#Syntastic(input) abort 128 | let l:fixes = [] 129 | 130 | let l:bin = 'elm' 131 | let l:subcommand = 'make' 132 | let l:format = '--report=json' 133 | let l:input = shellescape(a:input) 134 | let l:output = '--output=' . shellescape(syntastic#util#DevNull()) 135 | let l:command = l:bin . ' ' . l:subcommand . ' ' . l:format . ' ' . l:input . ' ' . l:output 136 | let l:reports = s:ExecuteInRoot(l:command) 137 | 138 | for l:report in split(l:reports, '\n') 139 | if l:report[0] ==# '[' 140 | for l:error in elm#util#DecodeJSON(l:report) 141 | if g:elm_syntastic_show_warnings == 0 && l:error.type ==? 'warning' 142 | else 143 | if a:input == l:error.file 144 | call add(s:errors, l:error) 145 | call add(l:fixes, {'filename': l:error.file, 146 | \'valid': 1, 147 | \'bufnr': bufnr('%'), 148 | \'type': (l:error.type ==? 'error') ? 'E' : 'W', 149 | \'lnum': l:error.region.start.line, 150 | \'col': l:error.region.start.column, 151 | \'text': l:error.overview}) 152 | endif 153 | endif 154 | endfor 155 | endif 156 | endfor 157 | 158 | return l:fixes 159 | endf 160 | 161 | function! elm#Build(input, output, show_warnings) abort 162 | let s:errors = [] 163 | let l:fixes = [] 164 | let l:rawlines = [] 165 | 166 | let l:bin = 'elm' 167 | let l:subcommand = 'make' 168 | let l:format = '--report=json' 169 | let l:input = shellescape(a:input) 170 | let l:output = '--output=' . shellescape(a:output) 171 | let l:command = l:bin . ' ' . l:subcommand . ' ' . l:format . ' ' . l:input . ' ' . l:output 172 | let l:reports = s:ExecuteInRoot(l:command) 173 | 174 | for l:report in split(l:reports, '\n') 175 | if l:report[0] ==# '[' 176 | for l:error in elm#util#DecodeJSON(l:report) 177 | if a:show_warnings == 0 && l:error.type ==? 'warning' 178 | else 179 | call add(s:errors, l:error) 180 | call add(l:fixes, {'filename': l:error.file, 181 | \'valid': 1, 182 | \'type': (l:error.type ==? 'error') ? 'E' : 'W', 183 | \'lnum': l:error.region.start.line, 184 | \'col': l:error.region.start.column, 185 | \'text': l:error.overview}) 186 | endif 187 | endfor 188 | else 189 | call add(l:rawlines, l:report) 190 | endif 191 | endfor 192 | 193 | let l:details = join(l:rawlines, "\n") 194 | let l:lines = split(l:details, "\n") 195 | if !empty(l:lines) 196 | let l:overview = l:lines[0] 197 | else 198 | let l:overview = '' 199 | endif 200 | 201 | if l:details ==# '' || l:details =~? '^Successfully.*' 202 | else 203 | call add(s:errors, {'overview': l:details, 'details': l:details}) 204 | call add(l:fixes, {'filename': expand('%', 1), 205 | \'valid': 1, 206 | \'type': 'E', 207 | \'lnum': 0, 208 | \'col': 0, 209 | \'text': l:overview}) 210 | endif 211 | 212 | return l:fixes 213 | endf 214 | 215 | " Make the given file, or the current file if none is given. 216 | function! elm#Make(...) abort 217 | if elm#util#CheckBin('elm', 'http://elm-lang.org/install') ==# '' 218 | return 219 | endif 220 | 221 | call elm#util#Echo('elm make:', 'building...') 222 | 223 | let l:input = (a:0 == 0) ? expand('%:p') : a:1 224 | let l:fixes = elm#Build(l:input, g:elm_make_output_file, g:elm_make_show_warnings) 225 | 226 | if len(l:fixes) > 0 227 | call elm#util#EchoWarning('', 'found ' . len(l:fixes) . ' errors') 228 | 229 | call setqflist(l:fixes, 'r') 230 | cwindow 231 | 232 | if get(g:, 'elm_jump_to_error', 1) 233 | ll 1 234 | endif 235 | else 236 | call elm#util#EchoSuccess('', 'Sucessfully compiled') 237 | 238 | call setqflist([]) 239 | cwindow 240 | endif 241 | endf 242 | 243 | " Show the detail of the current error in the quickfix window. 244 | function! elm#ErrorDetail() abort 245 | if !empty(filter(tabpagebuflist(), 'getbufvar(v:val, "&buftype") ==? "quickfix"')) 246 | exec ':copen' 247 | let l:linenr = line('.') 248 | exec ':wincmd p' 249 | if len(s:errors) > 0 250 | let l:detail = s:errors[l:linenr-1].details 251 | if l:detail ==# '' 252 | let l:detail = s:errors[l:linenr-1].overview 253 | endif 254 | echo l:detail 255 | endif 256 | endif 257 | endf 258 | 259 | " Open the elm repl in a subprocess. 260 | function! elm#Repl() abort 261 | " check for the elm-repl binary 262 | if elm#util#CheckBin('elm-repl', 'http://elm-lang.org/install') ==# '' 263 | return 264 | endif 265 | 266 | if has('nvim') 267 | term('elm-repl') 268 | else 269 | !elm-repl 270 | endif 271 | endf 272 | 273 | function! elm#Oracle(filepath, word) abort 274 | let l:bin = 'elm-oracle' 275 | let l:filepath = shellescape(a:filepath) 276 | let l:word = shellescape(a:word) 277 | let l:command = l:bin . ' ' . l:filepath . ' ' . l:word 278 | return s:ExecuteInRoot(l:command) 279 | endfunction 280 | 281 | let s:fullComplete = '' 282 | 283 | " Complete the current token using elm-oracle 284 | function! elm#Complete(findstart, base) abort 285 | " a:base is unused, but the callback function for completion expects 2 arguments 286 | if a:findstart 287 | let l:line = getline('.') 288 | 289 | let l:idx = col('.') - 1 290 | let l:start = 0 291 | while l:idx > 0 && l:line[l:idx - 1] =~# '[a-zA-Z0-9_\.]' 292 | if l:line[l:idx - 1] ==# '.' && l:start == 0 293 | let l:start = l:idx 294 | endif 295 | let l:idx -= 1 296 | endwhile 297 | 298 | if l:start == 0 299 | let l:start = l:idx 300 | endif 301 | 302 | let s:fullComplete = l:line[l:idx : col('.')-2] 303 | 304 | return l:start 305 | else 306 | " check for the elm-oracle binary 307 | if elm#util#CheckBin('elm-oracle', 'https://github.com/elmcast/elm-oracle') ==# '' 308 | return [] 309 | endif 310 | 311 | let l:res = [] 312 | let l:response = s:elmOracle(s:fullComplete) 313 | 314 | let l:detailed = get(g:, 'elm_detailed_complete', 0) 315 | 316 | for l:r in l:response 317 | let l:menu = '' 318 | if l:detailed 319 | let l:menu = ': ' . l:r.signature 320 | endif 321 | call add(l:res, {'word': l:r.name, 'menu': l:menu}) 322 | endfor 323 | 324 | return l:res 325 | endif 326 | endf 327 | 328 | " If the current buffer contains a consoleRunner, run elm-test with it. 329 | " Otherwise run elm-test in the root of your project which deafults to 330 | " running 'elm-test tests/TestRunner'. 331 | function! elm#Test() abort 332 | if elm#util#CheckBin('elm-test', 'https://github.com/rtfeldman/node-elm-test') ==# '' 333 | return 334 | endif 335 | 336 | if match(getline(1, '$'), 'consoleRunner') < 0 337 | let l:out = s:ExecuteInRoot('elm-test') 338 | call elm#util#EchoSuccess('elm-test', l:out) 339 | else 340 | let l:filepath = shellescape(expand('%:p')) 341 | let l:out = s:ExecuteInRoot('elm-test ' . l:filepath) 342 | call elm#util#EchoSuccess('elm-test', l:out) 343 | endif 344 | endf 345 | 346 | " Returns the closest parent with an elm-package.json or elm.json file. 347 | function! elm#FindRootDirectory() abort 348 | let l:elm_root = getbufvar('%', 'elmRoot') 349 | if empty(l:elm_root) 350 | let l:current_file = expand('%:p') 351 | let l:dir_current_file = fnameescape(fnamemodify(l:current_file, ':h')) 352 | let l:old_match = findfile('elm-package.json', l:dir_current_file . ';') 353 | let l:new_match = findfile('elm.json', l:dir_current_file . ';') 354 | if !empty(l:new_match) 355 | let l:elm_root = fnamemodify(l:new_match, ':p:h') 356 | elseif !empty(l:old_match) 357 | let l:elm_root = fnamemodify(l:old_match, ':p:h') 358 | else 359 | let l:elm_root = '' 360 | endif 361 | 362 | if !empty(l:elm_root) 363 | call setbufvar('%', 'elmRoot', l:elm_root) 364 | endif 365 | endif 366 | return l:elm_root 367 | endfunction 368 | 369 | " Executes a command in the project directory. 370 | function! s:ExecuteInRoot(cmd) abort 371 | let l:cd = exists('*haslocaldir') && haslocaldir() ? 'lcd ' : 'cd ' 372 | let l:current_dir = getcwd() 373 | let l:root_dir = elm#FindRootDirectory() 374 | 375 | try 376 | execute l:cd . fnameescape(l:root_dir) 377 | let l:out = system(a:cmd) 378 | finally 379 | execute l:cd . fnameescape(l:current_dir) 380 | endtry 381 | 382 | return l:out 383 | endfunction 384 | -------------------------------------------------------------------------------- /autoload/elm/util.vim: -------------------------------------------------------------------------------- 1 | " IsWin returns 1 if current OS is Windows or 0 otherwise 2 | fun! elm#util#IsWin() abort 3 | let l:win = ['win16', 'win32', 'win32unix', 'win64', 'win95'] 4 | for l:w in l:win 5 | if (has(l:w)) 6 | return 1 7 | endif 8 | endfor 9 | 10 | return 0 11 | endf 12 | 13 | fun! elm#util#CheckBin(bin, url) abort 14 | let l:binpath = substitute(a:bin, '^\s*\(.\{-}\)\s*$', '\1', '') 15 | 16 | if executable(l:binpath) 17 | return l:binpath 18 | endif 19 | 20 | call elm#util#EchoWarning('elm-vim:', 'could not find ' . l:binpath . ' [' . a:url . ']') 21 | 22 | return '' 23 | endf 24 | 25 | " Determines the browser command to use 26 | fun! s:get_browser_command() abort 27 | let l:elm_browser_command = get(g:, 'elm_browser_command', '') 28 | if l:elm_browser_command ==? '' 29 | if elm#util#IsWin() 30 | let l:elm_browser_command = '!start rundll32 url.dll,FileProtocolHandler %URL%' 31 | elseif has('mac') || has('macunix') || has('gui_macvim') || system('uname') =~? '^darwin' 32 | let l:elm_browser_command = 'open %URL%' 33 | elseif executable('xdg-open') 34 | let l:elm_browser_command = 'xdg-open %URL%' 35 | elseif executable('firefox') 36 | let l:elm_browser_command = 'firefox %URL% &' 37 | else 38 | let l:elm_browser_command = '' 39 | endif 40 | endif 41 | return l:elm_browser_command 42 | endf 43 | 44 | " OpenBrowser opens a url in the default browser 45 | fun! elm#util#OpenBrowser(url) abort 46 | let l:cmd = s:get_browser_command() 47 | if len(l:cmd) == 0 48 | redraw 49 | echohl WarningMsg 50 | echo "It seems that you don't have general web browser. Open URL below." 51 | echohl None 52 | echo a:url 53 | return 54 | endif 55 | if l:cmd =~? '^!' 56 | let l:cmd = substitute(l:cmd, '%URL%', '\=shellescape(a:url)', 'g') 57 | silent! exec l:cmd 58 | elseif l:cmd =~# '^:[A-Z]' 59 | let l:cmd = substitute(l:cmd, '%URL%', '\=a:url', 'g') 60 | exec l:cmd 61 | else 62 | let l:cmd = substitute(l:cmd, '%URL%', '\=shellescape(a:url)', 'g') 63 | call system(l:cmd) 64 | endif 65 | endf 66 | 67 | " DecodeJSON decodes a string of json into a viml object 68 | fun! elm#util#DecodeJSON(s) abort 69 | let l:true = 1 70 | let l:false = 0 71 | let l:null = 0 72 | return eval(a:s) 73 | endf 74 | 75 | " Remove ANSI escape characters used for highlighting purposes 76 | fun! s:strip_color(msg) abort 77 | return substitute(a:msg, '\e\[[0-9;]\+[mK]', '', 'g') 78 | endf 79 | 80 | " Print functions 81 | fun! elm#util#Echo(title, msg) abort 82 | redraws! | echon a:title . ' ' | echohl Identifier | echon s:strip_color(a:msg) | echohl None 83 | endf 84 | 85 | fun! elm#util#EchoSuccess(title, msg) abort 86 | redraws! | echon a:title . ' ' | echohl Function | echon s:strip_color(a:msg) | echohl None 87 | endf 88 | 89 | fun! elm#util#EchoWarning(title, msg) abort 90 | redraws! | echon a:title . ' ' | echohl WarningMsg | echon s:strip_color(a:msg) | echohl None 91 | endf 92 | 93 | fun! elm#util#EchoError(title, msg) abort 94 | redraws! | echon a:title . ' ' | echohl ErrorMsg | echon s:strip_color(a:msg) | echohl None 95 | endf 96 | 97 | fun! elm#util#EchoLater(func_name, title, msg) abort 98 | let s:echo_func_name = a:func_name 99 | let s:echo_title = a:title 100 | let s:echo_msg = a:msg 101 | endf 102 | 103 | fun! elm#util#EchoStored() abort 104 | if exists('s:echo_func_name') && exists('s:echo_title') && exists('s:echo_msg') 105 | call elm#util#{s:echo_func_name}(s:echo_title, s:echo_msg) 106 | unlet s:echo_func_name 107 | unlet s:echo_title 108 | unlet s:echo_msg 109 | endif 110 | endf 111 | 112 | function! elm#util#GoToModule(name) 113 | if empty(a:name) | return | endif 114 | if empty(matchstr(a:name, '^Native\.')) 115 | let l:extension = '.elm' 116 | else 117 | let l:extension = '.js' 118 | endif 119 | let l:rel_path = substitute(a:name, '\.', '/', 'g') . l:extension 120 | let l:root = elm#FindRootDirectory() 121 | 122 | let l:module_file = s:findLocalModule(l:rel_path, l:root) 123 | if !filereadable(l:module_file) 124 | let l:module_file = s:findDependencyModule(l:rel_path, l:root) 125 | endif 126 | 127 | if filereadable(l:module_file) 128 | exec 'edit ' . fnameescape(l:module_file) 129 | else 130 | return s:error("Can't find module \"" . a:name . "\"") 131 | endif 132 | endfunction 133 | 134 | function! s:findLocalModule(rel_path, root) 135 | let l:old_match = findfile('elm-package.json', a:root . ';') 136 | let l:new_match = findfile('elm.json', a:root . ';') 137 | if !empty(l:new_match) 138 | let l:package_json = l:new_match 139 | elseif !empty(l:old_match) 140 | let l:package_json = l:old_match 141 | endif 142 | if exists('*json_decode') 143 | let l:package = json_decode(readfile(l:package_json)) 144 | let l:source_roots = l:package['source-directories'] 145 | else 146 | " This is a fallback for vim's which do not support json_decode. 147 | " It simply only looks in the 'src' subdirectory and fails otherwise. 148 | let l:source_roots = ['src'] 149 | end 150 | for l:source_root in l:source_roots 151 | let l:file_path = a:root . '/' . l:source_root . '/' . a:rel_path 152 | if !filereadable(l:file_path) 153 | continue 154 | endif 155 | return l:file_path 156 | endfor 157 | endfunction 158 | 159 | function! s:findDependencyModule(rel_path, root) 160 | " If we are a dependency ourselves, we need to check our siblings. 161 | " This is because elm package doesn't install dependencies recursively. 162 | let l:root = substitute(a:root, '\/elm-stuff/packages.\+$', '', '') 163 | 164 | " We naively craws the dependencies dir for any fitting module name. 165 | " If it exists, we'll find it. If multiple filenames match, 166 | " there's a chance we return the wrong one. 167 | let l:module_paths = glob(l:root . '/elm-stuff/packages/**/' . a:rel_path, 0, 1) 168 | if len(l:module_paths) > 0 169 | return l:module_paths[0] 170 | endif 171 | endfunction 172 | 173 | " Using the built-in :echoerr prints a stacktrace, which isn't that nice. 174 | " From: https://github.com/moll/vim-node/blob/master/autoload/node.vim 175 | function! s:error(msg) 176 | echohl ErrorMsg 177 | echomsg a:msg 178 | echohl NONE 179 | let v:errmsg = a:msg 180 | endfunction 181 | -------------------------------------------------------------------------------- /doc/elm-vim.txt: -------------------------------------------------------------------------------- 1 | *elm-vim.txt* Elm development plugin 2 | *elm-vim* 3 | 4 | =============================================================================== 5 | oooo o8o 6 | `888 `"' 7 | .ooooo. 888 ooo. .oo. .oo. oooo ooo oooo ooo. .oo. .oo. 8 | d88' `88b 888 `888P"Y88bP"Y88b `88. .8' `888 `888P"Y88bP"Y88b 9 | 888ooo888 888 888 888 888 `88..8' 888 888 888 888 10 | 888 .o 888 888 888 888 .o. `888' 888 888 888 888 11 | `Y8bod8P' o888o o888o o888o o888o Y8P `8' o888o o888o o888o o888o 12 | =============================================================================== 13 | CONTENTS *elm-contents* 14 | 15 | 1. Intro............................................|elm-intro| 16 | 2. Install..........................................|elm-install| 17 | 3. Commands.........................................|elm-commands| 18 | 4. Mappings.........................................|elm-mappings| 19 | 5. Settings.........................................|elm-settings| 20 | 6. Troubleshooting..................................|elm-troubleshooting| 21 | 7. Credits..........................................|elm-credits| 22 | 23 | =============================================================================== 24 | INTRO *elm-intro* 25 | 26 | Homepage: https://github.com/elmcast/elm-vim 27 | 28 | Elm (http://elm-lang.org) support for Vim. 29 | 30 | * Improved Syntax highlighting, including backtick operators, booleans, 31 | chars, triple quotes, string escapes, and tuple functions 32 | * Improved Indentation 33 | * Commands and mappings for interfacing with the elm platform 34 | * Auto-complete 35 | 36 | =============================================================================== 37 | INSTALL *elm-install* 38 | 39 | Elm-vim follows the standard runtime path structure, so you should use a common 40 | and well known plugin manager to install it. Do not use elm-vim with other Elm 41 | plugins. 42 | 43 | 44 | * https://github.com/tpope/vim-pathogen > 45 | 46 | git clone https://github.com/elmcast/elm-vim.git ~/.vim/bundle/elm-vim 47 | < 48 | 49 | * https://github.com/junegunn/vim-plug > 50 | 51 | Plug 'elmcast/elm-vim' 52 | 53 | < 54 | * https://github.com/Shougo/neobundle.vim > 55 | 56 | NeoBundle 'elmcast/elm-vim' 57 | < 58 | 59 | * https://github.com/gmarik/vundle > 60 | 61 | Plugin 'elmcast/elm-vim' 62 | 63 | < 64 | * Manually > 65 | 66 | Copy all of the files into your `~/.vim` directory 67 | < 68 | 69 | Please be sure all necessary binaries are installed (such as `elm`, 70 | `elm-doc`, `elm-reactor`, etc..) from http://elm-lang.org/. You may also want 71 | to install `elm-test` with 'npm install -g elm-test' if you want to run unit 72 | tests from within vim. 73 | 74 | 75 | =============================================================================== 76 | COMMANDS *elm-commands* 77 | 78 | :ElmMake [file] 79 | 80 | ElmMake calls `elm make` with the given {file}. If no {file} is given 81 | it uses the current file being edited. 82 | 83 | :ElmMakeMain 84 | 85 | ElmMakeMain attempts to call `elm make` with "Main.elm". 86 | 87 | :ElmTest [file] 88 | 89 | ElmTest calls `elm-test` with the given {file}. If no {file} is given 90 | it runs it in the root of your project. 91 | 92 | :ElmRepl 93 | 94 | ElmRepl opens an elm repl in a subprocess. 95 | 96 | :ElmErrorDetail 97 | 98 | ElmErrorDetail shows the detail of the current error in the quickfix 99 | window. 100 | 101 | :ElmShowDocs 102 | 103 | ElmShowDocs queries elm-oracle, then echos the type and docs for the 104 | word under the cursor. 105 | 106 | :ElmBrowseDocs 107 | 108 | ElmBrowseDocs queries elm-oracle, then opens docs web page for the 109 | word under the cursor. 110 | 111 | :ElmFormat 112 | 113 | ElmFormat formats the current buffer with elm-format. 114 | 115 | =============================================================================== 116 | MAPPINGS *elm-mappings* 117 | 118 | elm-vim has several keys which can be used to create custom mappings 119 | For example, to create a mapping that `elm make` the current file, create a 120 | mapping for the `(elm make)` plug: > 121 | 122 | au FileType elm nmap m (elm make) 123 | 124 | As always, you can create more advanced mappings with |elm-commands|. 125 | Available keys are: 126 | 127 | *(elm make)* 128 | 129 | Calls `elm make` for the current file 130 | 131 | *(elm make-main)* 132 | 133 | Calls `elm make` with "Main.elm" 134 | 135 | *(elm-test)* 136 | 137 | Calls `elm test` with "Test[filename].elm" 138 | 139 | *(elm-repl)* 140 | 141 | Calls `elm repl` in a subprocess 142 | 143 | *(elm-error-detail)* 144 | 145 | Shows the detail of the current error. 146 | 147 | *(elm-show-docs)* 148 | 149 | Queries `elm oracle` and shows the docs for the word under the cursor. 150 | 151 | *(elm-browse-docs)* 152 | 153 | Queries `elm oracle` and browses the docs for the word under the cursor. 154 | 155 | =============================================================================== 156 | SETTINGS *elm-settings* 157 | 158 | *'g:elm_jump_to_error'* 159 | 160 | This setting configures whether to have vim jump the cursor to the first error 161 | found when running commands. By default it's enabled. 162 | > 163 | let g:elm_jump_to_error = 0 164 | < 165 | *'g:elm_make_output_file'* 166 | 167 | This setting configures which file elm make will compile to. 168 | > 169 | let g:elm_make_output_file = "elm.js" 170 | < 171 | *'g:elm_make_show_warnings'* 172 | 173 | This setting configures if warnings should be shown in the quickfix window. 174 | > 175 | let g:elm_make_show_warnings = 0 176 | < 177 | 178 | *'g:elm_syntastic_show_warnings'* 179 | 180 | This setting configures if warnings should be sent to syntastic. 181 | > 182 | let g:elm_syntastic_show_warnings = 0 183 | < 184 | 185 | *'g:elm_browser_command'* 186 | 187 | This setting configures the browser command used to browse docs. 188 | > 189 | let g:elm_browser_command = '' 190 | < 191 | *'g:elm_setup_keybindings'* 192 | 193 | This setting toggles adding some default command keybindings. 194 | > 195 | let g:elm_setup_keybindings = 1 196 | < 197 | 198 | *'g:elm_detailed_complete'* 199 | 200 | This setting toggles showing type signatures in the complete menu. 201 | > 202 | let g:elm_detailed_complete = 0 203 | < 204 | 205 | *'g:elm_format_autosave'* 206 | 207 | This setting toggles whether the current buffer should be formatted on save. 208 | > 209 | let g:elm_format_autosave = 0 210 | < 211 | 212 | *'g:elm_format_fail_silently'* 213 | 214 | This setting toggles whether format errors show be display. 215 | > 216 | let g:elm_format_fail_silently = 0 217 | < 218 | 219 | 220 | =============================================================================== 221 | TROUBLESHOOTING *elm-troubleshooting* 222 | 223 | For issues, please see https://github.com/elmcast/elm-vim/issues. 224 | 225 | =============================================================================== 226 | CREDITS *elm-credits* 227 | 228 | * Other vim-plugins, thanks for inspiration (elm.vim, ocaml.vim, haskell-vim) 229 | * elm-vim contributors: https://github.com/elmcast/elm-vim/graphs/contributors 230 | 231 | vim:ft=help:et:ts=2:sw=2:sts=2:norl 232 | -------------------------------------------------------------------------------- /ftdetect/elm.vim: -------------------------------------------------------------------------------- 1 | " detection for Elm (http://elm-lang.org/) 2 | 3 | au BufRead,BufNewFile *.elm set filetype=elm 4 | -------------------------------------------------------------------------------- /ftplugin/elm.vim: -------------------------------------------------------------------------------- 1 | " plugin for Elm (http://elm-lang.org/) 2 | 3 | if exists('b:did_ftplugin') 4 | finish 5 | endif 6 | 7 | let b:did_ftplugin = 1 8 | 9 | " Settings 10 | if !exists('g:elm_jump_to_error') 11 | let g:elm_jump_to_error = 0 12 | endif 13 | 14 | if !exists('g:elm_make_output_file') 15 | let g:elm_make_output_file = 'elm.js' 16 | endif 17 | 18 | if !exists('g:elm_make_show_warnings') 19 | let g:elm_make_show_warnings = 0 20 | endif 21 | 22 | if !exists('g:elm_syntastic_show_warnings') 23 | let g:elm_syntastic_show_warnings = 0 24 | endif 25 | 26 | if !exists('g:elm_format_autosave') 27 | let g:elm_format_autosave = 1 28 | endif 29 | 30 | if !exists('g:elm_format_fail_silently') 31 | let g:elm_format_fail_silently = 0 32 | endif 33 | 34 | if !exists('g:elm_setup_keybindings') 35 | let g:elm_setup_keybindings = 1 36 | endif 37 | 38 | setlocal omnifunc=elm#Complete 39 | 40 | setlocal comments=:-- 41 | setlocal commentstring=--\ %s 42 | 43 | " Commands 44 | command -buffer -nargs=? -complete=file ElmMake call elm#Make() 45 | command -buffer ElmMakeMain call elm#Make("Main.elm") 46 | command -buffer -nargs=? -complete=file ElmTest call elm#Test() 47 | command -buffer ElmRepl call elm#Repl() 48 | command -buffer ElmErrorDetail call elm#ErrorDetail() 49 | command -buffer ElmShowDocs call elm#ShowDocs() 50 | command -buffer ElmBrowseDocs call elm#BrowseDocs() 51 | command -buffer ElmFormat call elm#Format() 52 | 53 | " Commands cleanup 54 | let b:undo_ftplugin = " 55 | \ delcommand ElmMake 56 | \|delcommand ElmMakeMain 57 | \|delcommand ElmTest 58 | \|delcommand ElmRepl 59 | \|delcommand ElmErrorDetail 60 | \|delcommand ElmShowDocs 61 | \|delcommand ElmBrowseDocs 62 | \|delcommand ElmFormat 63 | \" 64 | 65 | if get(g:, 'elm_setup_keybindings', 1) 66 | nmap m (elm-make) 67 | nmap b (elm-make-main) 68 | nmap t (elm-test) 69 | nmap r (elm-repl) 70 | nmap e (elm-error-detail) 71 | nmap d (elm-show-docs) 72 | nmap w (elm-browse-docs) 73 | endif 74 | 75 | " Better gf command 76 | nmap gf :call elm#util#GoToModule(expand('')) 77 | 78 | " Elm code formatting on save 79 | if get(g:, 'elm_format_autosave', 1) 80 | augroup elmFormat 81 | autocmd! 82 | autocmd BufWritePre *.elm call elm#Format() 83 | autocmd BufWritePost *.elm call elm#util#EchoStored() 84 | augroup END 85 | endif 86 | if has('win32') 87 | set viewdir=$HOME/vimfiles/views/ 88 | endif 89 | 90 | " Enable go to file under cursor from module name 91 | " Based on: https://github.com/elixir-lang/vim-elixir/blob/bd66ed134319d1e390f3331e8c4d525109f762e8/ftplugin/elixir.vim#L22-L56 92 | function! GetElmFilename(word) 93 | let l:word = a:word 94 | 95 | " replace module dots with slash 96 | let l:word = substitute(l:word,'\.','/','g') 97 | 98 | return l:word 99 | endfunction 100 | 101 | let &l:path = 102 | \ join([ 103 | \ elm#FindRootDirectory().'/src', 104 | \ elm#FindRootDirectory().'/elm-stuff/packages/**/src', 105 | \ &g:path 106 | \ ], ',') 107 | setlocal includeexpr=GetElmFilename(v:fname) 108 | setlocal include=^\\s*import\\s\\+ 109 | setlocal suffixesadd=.elm 110 | -------------------------------------------------------------------------------- /ftplugin/elm/tagbar.vim: -------------------------------------------------------------------------------- 1 | if !executable('ctags') 2 | finish 3 | elseif globpath(&runtimepath, 'plugin/tagbar.vim') ==? '' 4 | finish 5 | endif 6 | 7 | function! s:SetTagbar() 8 | if !exists('g:tagbar_type_elm') 9 | let g:tagbar_type_elm = { 10 | \ 'ctagstype' : 'elm', 11 | \ 'kinds' : [ 12 | \ 'c:constants', 13 | \ 'f:functions', 14 | \ 'p:ports' 15 | \ ] 16 | \ } 17 | endif 18 | endfunction 19 | 20 | call s:SetTagbar() 21 | -------------------------------------------------------------------------------- /indent/elm.vim: -------------------------------------------------------------------------------- 1 | " indentation for Elm (http://elm-lang.org/) 2 | 3 | " Only load this indent file when no other was loaded. 4 | if exists('b:did_indent') 5 | finish 6 | endif 7 | let b:did_indent = 1 8 | 9 | " Local defaults 10 | setlocal expandtab 11 | setlocal indentexpr=GetElmIndent() 12 | setlocal indentkeys+=0=else,0=if,0=of,0=import,0=then,0=type,0\|,0},0\],0),=-},0=in 13 | setlocal nolisp 14 | setlocal nosmartindent 15 | 16 | " Comment formatting 17 | setlocal comments=s1fl:{-,mb:\ ,ex:-},:-- 18 | 19 | " Only define the function once. 20 | if exists('*GetElmIndent') 21 | finish 22 | endif 23 | 24 | " Indent pairs 25 | function! s:FindPair(pstart, pmid, pend) 26 | "call search(a:pend, 'bW') 27 | return indent(searchpair(a:pstart, a:pmid, a:pend, 'bWn', 'synIDattr(synID(line("."), col("."), 0), "name") =~? "string\\|comment"')) 28 | endfunction 29 | 30 | function! GetElmIndent() 31 | let l:lnum = v:lnum - 1 32 | 33 | " Ident 0 if the first line of the file: 34 | if l:lnum == 0 35 | return 0 36 | endif 37 | 38 | let l:ind = indent(l:lnum) 39 | let l:lline = getline(l:lnum) 40 | let l:line = getline(v:lnum) 41 | 42 | " Indent if current line begins with '}': 43 | if l:line =~? '^\s*}' 44 | return s:FindPair('{', '', '}') 45 | 46 | " Indent if current line begins with 'else': 47 | elseif l:line =~# '^\s*else\>' 48 | if l:lline !~# '^\s*\(if\|then\)\>' 49 | return s:FindPair('\', '', '\') 50 | endif 51 | 52 | " Indent if current line begins with 'then': 53 | elseif l:line =~# '^\s*then\>' 54 | if l:lline !~# '^\s*\(if\|else\)\>' 55 | return s:FindPair('\', '', '\') 56 | endif 57 | 58 | " HACK: Indent lines in case with nearest case clause: 59 | elseif l:line =~# '->' && l:line !~# ':' && l:line !~# '\\' 60 | return indent(search('^\s*case', 'bWn')) + &shiftwidth 61 | 62 | " HACK: Don't change the indentation if the last line is a comment. 63 | elseif l:lline =~# '^\s*--' 64 | return l:ind 65 | 66 | " Align the end of block comments with the start 67 | elseif l:line =~# '^\s*-}' 68 | return indent(search('{-', 'bWn')) 69 | 70 | " Indent double shift after let with an empty rhs 71 | elseif l:lline =~# '\.*\s=$' 72 | return l:ind + 4 + &shiftwidth 73 | 74 | " Align 'in' with the parent let. 75 | elseif l:line =~# '^\s*in\>' 76 | return indent(search('^\s*let', 'bWn')) 77 | 78 | " Align bindings with the parent let. 79 | elseif l:lline =~# '\' 80 | return l:ind + 4 81 | 82 | " Align bindings with the parent in. 83 | elseif l:lline =~# '^\s*in\>' 84 | return l:ind + 4 85 | 86 | endif 87 | 88 | " Add a 'shiftwidth' after lines ending with: 89 | if l:lline =~# '\(|\|=\|->\|<-\|(\|\[\|{\|\<\(of\|else\|if\|then\)\)\s*$' 90 | let l:ind = l:ind + &shiftwidth 91 | 92 | " Add a 'shiftwidth' after lines starting with type ending with '=': 93 | elseif l:lline =~# '^\s*type' && l:line =~# '^\s*=' 94 | let l:ind = l:ind + &shiftwidth 95 | 96 | " Back to normal indent after comments: 97 | elseif l:lline =~# '-}\s*$' 98 | call search('-}', 'bW') 99 | let l:ind = indent(searchpair('{-', '', '-}', 'bWn', 'synIDattr(synID(line("."), col("."), 0), "name") =~? "string"')) 100 | 101 | " Ident some operators if there aren't any starting the last line. 102 | elseif l:line =~# '^\s*\(!\|&\|(\|`\|+\||\|{\|[\|,\)=' && l:lline !~# '^\s*\(!\|&\|(\|`\|+\||\|{\|[\|,\)=' && l:lline !~# '^\s*$' 103 | let l:ind = l:ind + &shiftwidth 104 | 105 | elseif l:lline ==# '' && getline(l:lnum - 1) !=# '' 106 | let l:ind = indent(search('^\s*\S+', 'bWn')) 107 | 108 | endif 109 | 110 | return l:ind 111 | endfunc 112 | -------------------------------------------------------------------------------- /plugin/elm.vim: -------------------------------------------------------------------------------- 1 | if exists('g:loaded_elm') 2 | finish 3 | endif 4 | 5 | let g:loaded_elm = 1 6 | 7 | " Mappings 8 | nnoremap (elm-make) :call elm#Make() 9 | nnoremap (elm-make-main) :call elm#Make("Main.elm") 10 | nnoremap (elm-test) :call elm#Test() 11 | nnoremap (elm-repl) :call elm#Repl() 12 | nnoremap (elm-error-detail) :call elm#ErrorDetail() 13 | nnoremap (elm-show-docs) :call elm#ShowDocs() 14 | nnoremap (elm-browse-docs) :call elm#BrowseDocs() 15 | -------------------------------------------------------------------------------- /rplugin/python3/deoplete/sources/deoplete_elm.py: -------------------------------------------------------------------------------- 1 | # ============================================================================= 2 | # FILE: deoplete_elm.py 3 | # AUTHOR: Pawel Bogut 4 | # ============================================================================= 5 | 6 | from .base import Base 7 | from os import path 8 | import re 9 | import subprocess 10 | import json 11 | 12 | 13 | class Source(Base): 14 | 15 | def __init__(self, vim): 16 | Base.__init__(self, vim) 17 | 18 | self.name = 'elm' 19 | self.mark = '[elm]' 20 | self.filetypes = ['elm'] 21 | self.rank = 1000 22 | self.input_pattern = r'[^\s\'"]*' 23 | self.current = vim.current 24 | self.vim = vim 25 | 26 | def on_init(self, context): 27 | self.oracle_cmd = 'elm-oracle' 28 | 29 | def get_complete_position(self, context): 30 | m = re.search(r'[^\s\'"]*$', context['input']) 31 | if m: 32 | return m.start() 33 | 34 | def get_complete_query(self, context): 35 | m = re.search(r'[^\s\'"]*$', context['input']) 36 | if m: 37 | return m.group() 38 | return None 39 | 40 | def gather_candidates(self, context): 41 | file_path = self.current.buffer.name 42 | current_path = self.get_project_root(file_path) 43 | query = self.get_complete_query(context) 44 | cmd = 'cd {} && {} {} "{}"'.format(current_path, self.oracle_cmd, 45 | file_path, query) 46 | if not query or query == '': 47 | return [] 48 | 49 | proc = subprocess.Popen(cmd, stdout=subprocess.PIPE, shell=True) 50 | output = proc.stdout.read() 51 | 52 | jsonData = str(output.decode('utf-8')) 53 | 54 | if not jsonData or jsonData == '': 55 | return [] 56 | 57 | result = json.loads(jsonData) 58 | 59 | if not result: 60 | return [] 61 | 62 | candidates = [] 63 | 64 | for item in result: 65 | word = self.get_word(item, query) 66 | candidate = {'word': word, 67 | 'abbr': word, 68 | 'kind': item['signature'], 69 | 'info': item['comment'], 70 | 'dup': 0} 71 | candidates.append(candidate) 72 | 73 | return candidates 74 | 75 | def get_word(self, item, query): 76 | if item['name'].find(query) == 0: 77 | return item['name'] 78 | else: 79 | return item['fullName'] 80 | 81 | def get_project_root(self, file_path): 82 | current_path = path.dirname(file_path) 83 | while current_path != '/' and not path.exists( 84 | path.join(current_path, 'elm-package.json') 85 | ): 86 | current_path = path.dirname(current_path) 87 | 88 | if current_path == '/': 89 | current_path = path.dirname(file_path) 90 | 91 | return current_path 92 | -------------------------------------------------------------------------------- /screenshots/logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ElmCast/elm-vim/4b71facd77297cb33bbb3b14894676cff0a9bd1d/screenshots/logo.png -------------------------------------------------------------------------------- /screenshots/syntax_highlighting.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ElmCast/elm-vim/4b71facd77297cb33bbb3b14894676cff0a9bd1d/screenshots/syntax_highlighting.png -------------------------------------------------------------------------------- /syntax/elm.vim: -------------------------------------------------------------------------------- 1 | " syntax highlighting for Elm (http://elm-lang.org/) 2 | 3 | if exists('b:current_syntax') 4 | finish 5 | endif 6 | 7 | " Keywords 8 | syn keyword elmConditional else if of then 9 | syn keyword elmAlias alias 10 | syn keyword elmTypedef contained type port 11 | syn keyword elmImport exposing as import module where 12 | 13 | " Operators 14 | syn match elmOperator contained "\([-!#$%`&\*\+./<=>\?@\\^|~:]\|\<_\>\)" 15 | 16 | " Types 17 | syn match elmType "\<[A-Z][0-9A-Za-z_'-]*" 18 | syn keyword elmNumberType number 19 | 20 | " Delimiters 21 | syn match elmDelimiter "[,;]" 22 | syn match elmBraces "[()[\]{}]" 23 | 24 | " Functions 25 | syn match elmTupleFunction "\((,\+)\)" 26 | 27 | " Comments 28 | syn keyword elmTodo TODO FIXME XXX contained 29 | syn match elmLineComment "--.*" contains=elmTodo,@spell 30 | syn region elmComment matchgroup=elmComment start="{-|\=" end="-}" contains=elmTodo,elmComment,@spell fold 31 | 32 | " Strings 33 | syn match elmStringEscape "\\u[0-9a-fA-F]\{4}" contained 34 | syn match elmStringEscape "\\[nrfvbt\\\"]" contained 35 | syn region elmString start="\"" skip="\\\"" end="\"" contains=elmStringEscape,@spell 36 | syn region elmTripleString start="\"\"\"" skip="\\\"" end="\"\"\"" contains=elmStringEscape,@spell 37 | syn match elmChar "'[^'\\]'\|'\\.'\|'\\u[0-9a-fA-F]\{4}'" 38 | 39 | " Numbers 40 | syn match elmInt "-\?\<\d\+\>\|0[xX][0-9a-fA-F]\+\>" 41 | syn match elmFloat "\(\<\d\+\.\d\+\>\)" 42 | 43 | " Identifiers 44 | syn match elmTopLevelDecl "^\s*[a-zA-Z][a-zA-z0-9_]*\('\)*\s\+:\(\r\n\|\r\|\n\|\s\)\+" contains=elmOperator 45 | syn match elmFuncName /^\l\w*/ 46 | 47 | " Folding 48 | syn region elmTopLevelTypedef start="type" end="\n\(\n\n\)\@=" contains=ALL fold 49 | syn region elmTopLevelFunction start="^[a-zA-Z].\+\n[a-zA-Z].\+=" end="^\(\n\+\)\@=" contains=ALL fold 50 | syn region elmCaseBlock matchgroup=elmCaseBlockDefinition start="^\z\(\s\+\)\" end="^\z1\@!\W\@=" end="\(\n\n\z1\@!\)\@=" end="\n\z1\@!\(\n\n\)\@=" contains=ALL fold 51 | syn region elmCaseItemBlock start="^\z\(\s\+\).\+->$" end="^\z1\@!\W\@=" end="\(\n\n\z1\@!\)\@=" end="\(\n\z1\S\)\@=" contains=ALL fold 52 | syn region elmLetBlock matchgroup=elmLetBlockDefinition start="\" end="\" contains=ALL fold 53 | 54 | hi def link elmFuncName Function 55 | hi def link elmCaseBlockDefinition Conditional 56 | hi def link elmCaseBlockItemDefinition Conditional 57 | hi def link elmLetBlockDefinition TypeDef 58 | hi def link elmTopLevelDecl Function 59 | hi def link elmTupleFunction Normal 60 | hi def link elmTodo Todo 61 | hi def link elmComment Comment 62 | hi def link elmLineComment Comment 63 | hi def link elmString String 64 | hi def link elmTripleString String 65 | hi def link elmChar String 66 | hi def link elmStringEscape Special 67 | hi def link elmInt Number 68 | hi def link elmFloat Float 69 | hi def link elmDelimiter Delimiter 70 | hi def link elmBraces Delimiter 71 | hi def link elmTypedef TypeDef 72 | hi def link elmImport Include 73 | hi def link elmConditional Conditional 74 | hi def link elmAlias Delimiter 75 | hi def link elmOperator Operator 76 | hi def link elmType Identifier 77 | hi def link elmNumberType Identifier 78 | 79 | syn sync minlines=500 80 | 81 | let b:current_syntax = 'elm' 82 | -------------------------------------------------------------------------------- /syntax_checkers/elm/elm_make.vim: -------------------------------------------------------------------------------- 1 | " syntastic syntax checker 2 | 3 | if exists('g:loaded_syntastic_elm_elm_make_checker') 4 | finish 5 | endif 6 | let g:loaded_syntastic_elm_elm_make_checker = 1 7 | 8 | let s:save_cpo = &cpoptions 9 | set cpoptions&vim 10 | 11 | function! SyntaxCheckers_elm_elm_IsAvailable() dict 12 | return executable(substitute('elm', '^\s*\(.\{-}\)\s*$', '\1', '')) 13 | endfunction 14 | 15 | function! SyntaxCheckers_elm_elm_make_GetLocList() dict 16 | return elm#Syntastic(expand('%:p')) 17 | endfunction 18 | 19 | call g:SyntasticRegistry.CreateAndRegisterChecker({ 20 | \ 'filetype': 'elm', 21 | \ 'name': 'elm_make', 22 | \ 'exec': 'elm make'}) 23 | 24 | let &cpoptions = s:save_cpo 25 | unlet s:save_cpo 26 | --------------------------------------------------------------------------------