diff options
| author | Adam Stankiewicz <sheerun@sher.pl> | 2019-06-08 13:34:40 +0200 | 
|---|---|---|
| committer | Adam Stankiewicz <sheerun@sher.pl> | 2019-06-08 13:34:40 +0200 | 
| commit | ebf9ec9d62302ad95e677572562f5010eebd4e21 (patch) | |
| tree | a94841c36a39f63f6a1535a7a4117e101b79752c | |
| parent | 9caa678708a97022ba44f0bf86de22b07e9bde86 (diff) | |
| download | vim-polyglot-ebf9ec9d62302ad95e677572562f5010eebd4e21.tar.gz vim-polyglot-ebf9ec9d62302ad95e677572562f5010eebd4e21.zip | |
Add zig support, closes #405
Diffstat (limited to '')
| -rw-r--r-- | README.md | 3 | ||||
| -rw-r--r-- | autoload/zig/config.vim | 43 | ||||
| -rw-r--r-- | autoload/zig/fmt.vim | 170 | ||||
| -rw-r--r-- | autoload/zig/list.vim | 162 | ||||
| -rw-r--r-- | autoload/zig/util.vim | 394 | ||||
| -rwxr-xr-x | build | 1 | ||||
| -rw-r--r-- | ftdetect/polyglot.vim | 7 | ||||
| -rw-r--r-- | ftplugin/zig.vim | 18 | ||||
| -rw-r--r-- | syntax/zig.vim | 106 | 
9 files changed, 903 insertions, 1 deletions
| @@ -10,7 +10,7 @@ A collection of language packs for Vim.  > One to rule them all, one to find them, one to bring them all and in the darkness bind them.  - It **won't affect your startup time**, as scripts are loaded only on demand\*. -- It **installs and updates 120+ times faster** than the <!--Package Count-->140<!--/Package Count--> packages it consists of. +- It **installs and updates 120+ times faster** than the <!--Package Count-->141<!--/Package Count--> packages it consists of.  - Solid syntax and indentation support (other features skipped). Only the best language packs.  - All unnecessary files are ignored (like enormous documentation from php support).  - No support for esoteric languages, only most popular ones (modern too, like `slim`). @@ -185,6 +185,7 @@ If you need full functionality of any plugin, please use it directly with your p  - [xml](https://github.com/amadeus/vim-xml) (syntax)  - [yaml](https://github.com/stephpy/vim-yaml) (syntax, ftplugin)  - [yard](https://github.com/sheerun/vim-yardoc) (syntax) +- [zig](https://github.com/ziglang/zig.vim) (syntax, autoload, ftplugin)  <!--/Language Packs-->  ## Updating diff --git a/autoload/zig/config.vim b/autoload/zig/config.vim new file mode 100644 index 00000000..9a87fa1c --- /dev/null +++ b/autoload/zig/config.vim @@ -0,0 +1,43 @@ +if exists('g:polyglot_disabled') && index(g:polyglot_disabled, 'zig') != -1 +  finish +endif + +function! zig#config#ListTypeCommands() abort +  return get(g:, 'zig_list_type_commands', {}) +endfunction + +function! zig#config#ListType() abort +  return get(g:, 'zig_list_type', '') +endfunction + +function! zig#config#ListAutoclose() abort +  return get(g:, 'zig_list_autoclose', 1) +endfunction + +function! zig#config#ListHeight() abort +  return get(g:, "zig_list_height", 0) +endfunction + +function! zig#config#FmtAutosave() abort +  return get(g:, "zig_fmt_autosave", 0) +endfunction + +function! zig#config#SetFmtAutosave(value) abort +  let g:zig_fmt_autosave = a:value +endfunction + +function! zig#config#FmtCommand() abort +  return get(g:, "zig_fmt_command", ['zig', 'fmt', '--color', 'off']) +endfunction + +function! zig#config#FmtFailSilently() abort +  return get(g:, "zig_fmt_fail_silently", 0) +endfunction + +function! zig#config#FmtExperimental() abort +  return get(g:, "zig_fmt_experimental", 0) +endfunction + +function! zig#config#Debug() abort +  return get(g:, 'zig_debug', []) +endfunction diff --git a/autoload/zig/fmt.vim b/autoload/zig/fmt.vim new file mode 100644 index 00000000..cc7862c7 --- /dev/null +++ b/autoload/zig/fmt.vim @@ -0,0 +1,170 @@ +if exists('g:polyglot_disabled') && index(g:polyglot_disabled, 'zig') != -1 +  finish +endif + +" Adapted from fatih/vim-go: autoload/go/fmt.vim +" +" Copyright 2011 The Go Authors. All rights reserved. +" Use of this source code is governed by a BSD-style +" license that can be found in the LICENSE file. +" +function! zig#fmt#Format() abort +  if zig#config#FmtExperimental() +    " Using winsaveview to save/restore cursor state has the problem of +    " closing folds on save: +    "   https://github.com/fatih/vim-go/issues/502 +    " One fix is to use mkview instead. Unfortunately, this sometimes causes +    " other bad side effects: +    "   https://github.com/fatih/vim-go/issues/728 +    " and still closes all folds if foldlevel>0: +    "   https://github.com/fatih/vim-go/issues/732 +    let l:curw = {} +    try +      mkview! +    catch +      let l:curw = winsaveview() +    endtry + +    " save our undo file to be restored after we are done. This is needed to +    " prevent an additional undo jump due to BufWritePre auto command and also +    " restore 'redo' history because it's getting being destroyed every +    " BufWritePre +    let tmpundofile = tempname() +    exe 'wundo! ' . tmpundofile +  else +    " Save cursor position and many other things. +    let l:curw = winsaveview() +  endif + +  " Save cursor position and many other things. +  let l:curw = winsaveview() + +  let bin_name = zig#config#FmtCommand() + +  " Get current position in file +  let current_col = col('.') +  let orig_line_count = line('$') + +  " Save current buffer first, else fmt will run on the original file and we +  " will lose our changes. +  silent! execute 'write' expand('%') + +  let [l:out, l:err] = zig#fmt#run(bin_name, expand('%')) + +  if l:err == 0 +    call zig#fmt#update_file(expand('%')) +  elseif !zig#config#FmtFailSilently() +    let errors = s:parse_errors(expand('%'), out) +    call s:show_errors(errors) +  endif + +  let diff_offset = line('$') - orig_line_count + +  if zig#config#FmtExperimental() +    " restore our undo history +    silent! exe 'rundo ' . tmpundofile +    call delete(tmpundofile) + +    " Restore our cursor/windows positions, folds, etc. +    if empty(l:curw) +      silent! loadview +    else +      call winrestview(l:curw) +    endif +  else +    " Restore our cursor/windows positions. +    call winrestview(l:curw) +  endif + +  " be smart and jump to the line the new statement was added/removed +  call cursor(line('.') + diff_offset, current_col) + +  " Syntax highlighting breaks less often. +  syntax sync fromstart +endfunction + +" update_file updates the target file with the given formatted source +function! zig#fmt#update_file(target) +  " remove undo point caused via BufWritePre +  try | silent undojoin | catch | endtry + +  " reload buffer to reflect latest changes +  silent edit! + +  let l:listtype = zig#list#Type("ZigFmt") + +  " the title information was introduced with 7.4-2200 +  " https://github.com/vim/vim/commit/d823fa910cca43fec3c31c030ee908a14c272640 +  if has('patch-7.4.2200') +    " clean up previous list +    if l:listtype == "quickfix" +      let l:list_title = getqflist({'title': 1}) +    else +      let l:list_title = getloclist(0, {'title': 1}) +    endif +  else +    " can't check the title, so assume that the list was for go fmt. +    let l:list_title = {'title': 'Format'} +  endif + +  if has_key(l:list_title, "title") && l:list_title['title'] == "Format" +    call zig#list#Clean(l:listtype) +  endif +endfunction + +" run runs the gofmt/goimport command for the given source file and returns +" the output of the executed command. Target is the real file to be formatted. +function! zig#fmt#run(bin_name, target) +  let l:cmd = [] +  call extend(cmd, a:bin_name) +  call extend(cmd, [a:target]) +  return zig#util#Exec(l:cmd) +endfunction + +" parse_errors parses the given errors and returns a list of parsed errors +function! s:parse_errors(filename, content) abort +  let splitted = split(a:content, '\n') + +  " list of errors to be put into location list +  let errors = [] +  for line in splitted +    let tokens = matchlist(line, '^\(.\{-}\):\(\d\+\):\(\d\+\)\s*\(.*\)') +    if !empty(tokens) +      call add(errors,{ +            \"filename": a:filename, +            \"lnum":     tokens[2], +            \"col":      tokens[3], +            \"text":     tokens[4], +            \ }) +    endif +  endfor + +  return errors +endfunction + +" show_errors opens a location list and shows the given errors. If the given +" errors is empty, it closes the the location list +function! s:show_errors(errors) abort +  let l:listtype = zig#list#Type("ZigFmt") +  if !empty(a:errors) +    call zig#list#Populate(l:listtype, a:errors, 'Format') +    echohl Error | echomsg "zig fmt returned error" | echohl None +  endif + +  " this closes the window if there are no errors or it opens +  " it if there is any +  call zig#list#Window(l:listtype, len(a:errors)) +endfunction + +function! zig#fmt#ToggleFmtAutoSave() abort +  if zig#config#FmtAutosave() +    call zig#config#SetFmtAutosave(0) +    call zig#util#EchoProgress("auto fmt disabled") +    return +  end + +  call zig#config#SetFmtAutosave(1) +  call zig#util#EchoProgress("auto fmt enabled") +endfunction + +" vim: sw=2 ts=2 et diff --git a/autoload/zig/list.vim b/autoload/zig/list.vim new file mode 100644 index 00000000..97ebf47f --- /dev/null +++ b/autoload/zig/list.vim @@ -0,0 +1,162 @@ +if exists('g:polyglot_disabled') && index(g:polyglot_disabled, 'zig') != -1 +  finish +endif + +" Adapted from fatih/vim-go: autoload/go/list.vim +" +" Copyright 2011 The Go Authors. All rights reserved. +" Use of this source code is governed by a BSD-style +" license that can be found in the LICENSE file. +" + +" Window opens the list with the given height up to 10 lines maximum. +" Otherwise g:zig_loclist_height is used. +" +" If no or zero height is given it closes the window by default. +" To prevent this, set g:zig_list_autoclose = 0 +function! zig#list#Window(listtype, ...) abort +  " we don't use lwindow to close the location list as we need also the +  " ability to resize the window. So, we are going to use lopen and lclose +  " for a better user experience. If the number of errors in a current +  " location list increases/decreases, cwindow will not resize when a new +  " updated height is passed. lopen in the other hand resizes the screen. +  if !a:0 || a:1 == 0 +    call zig#list#Close(a:listtype) +    return +  endif + +  let height = zig#config#ListHeight() +  if height == 0 +    " prevent creating a large location height for a large set of numbers +    if a:1 > 10 +      let height = 10 +    else +      let height = a:1 +    endif +  endif + +  if a:listtype == "locationlist" +    exe 'lopen ' . height +  else +    exe 'copen ' . height +  endif +endfunction + + +" Get returns the current items from the list +function! zig#list#Get(listtype) abort +  if a:listtype == "locationlist" +    return getloclist(0) +  else +    return getqflist() +  endif +endfunction + +" Populate populate the list with the given items +function! zig#list#Populate(listtype, items, title) abort +  if a:listtype == "locationlist" +    call setloclist(0, a:items, 'r') + +    " The last argument ({what}) is introduced with 7.4.2200: +    " https://github.com/vim/vim/commit/d823fa910cca43fec3c31c030ee908a14c272640 +    if has("patch-7.4.2200") | call setloclist(0, [], 'a', {'title': a:title}) | endif +  else +    call setqflist(a:items, 'r') +    if has("patch-7.4.2200") | call setqflist([], 'a', {'title': a:title}) | endif +  endif +endfunction + +" Parse parses the given items based on the specified errorformat and +" populates the list. +function! zig#list#ParseFormat(listtype, errformat, items, title) abort +  " backup users errorformat, will be restored once we are finished +  let old_errorformat = &errorformat + +  " parse and populate the location list +  let &errorformat = a:errformat +  try +    call zig#list#Parse(a:listtype, a:items, a:title) +  finally +    "restore back +    let &errorformat = old_errorformat +  endtry +endfunction + +" Parse parses the given items based on the global errorformat and +" populates the list. +function! zig#list#Parse(listtype, items, title) abort +  if a:listtype == "locationlist" +    lgetexpr a:items +    if has("patch-7.4.2200") | call setloclist(0, [], 'a', {'title': a:title}) | endif +  else +    cgetexpr a:items +    if has("patch-7.4.2200") | call setqflist([], 'a', {'title': a:title}) | endif +  endif +endfunction + +" JumpToFirst jumps to the first item in the location list +function! zig#list#JumpToFirst(listtype) abort +  if a:listtype == "locationlist" +    ll 1 +  else +    cc 1 +  endif +endfunction + +" Clean cleans and closes the location list +function! zig#list#Clean(listtype) abort +  if a:listtype == "locationlist" +    lex [] +  else +    cex [] +  endif + +  call zig#list#Close(a:listtype) +endfunction + +" Close closes the location list +function! zig#list#Close(listtype) abort +  let autoclose_window = zig#config#ListAutoclose() +  if !autoclose_window +    return +  endif + +  if a:listtype == "locationlist" +    lclose +  else +    cclose +  endif +endfunction + +function! s:listtype(listtype) abort +  let listtype = zig#config#ListType() +  if empty(listtype) +    return a:listtype +  endif + +  return listtype +endfunction + +" s:default_list_type_commands is the defaults that will be used for each of +" the supported commands (see documentation for g:zig_list_type_commands). When +" defining a default, quickfix should be used if the command operates on +" multiple files, while locationlist should be used if the command operates on a +" single file or buffer. Keys that begin with an underscore are not supported +" in g:zig_list_type_commands. +let s:default_list_type_commands = { +      \ "ZigFmt":                "locationlist", +  \ } + +function! zig#list#Type(for) abort +  let l:listtype = s:listtype(get(s:default_list_type_commands, a:for)) +  if l:listtype == "0" +    call zig#util#EchoError(printf( +          \ "unknown list type command value found ('%s'). Please open a bug report in the zig.vim repo.", +          \ a:for)) +    let l:listtype = "quickfix" +  endif + +  return get(zig#config#ListTypeCommands(), a:for, l:listtype) +endfunction + +" vim: sw=2 ts=2 et diff --git a/autoload/zig/util.vim b/autoload/zig/util.vim new file mode 100644 index 00000000..bb2df40c --- /dev/null +++ b/autoload/zig/util.vim @@ -0,0 +1,394 @@ +if exists('g:polyglot_disabled') && index(g:polyglot_disabled, 'zig') != -1 +  finish +endif + +" Adapted from vim-go: autoload/go/util.vim +" +" Copyright 2011 The Go Authors. All rights reserved. +" Use of this source code is governed by a BSD-style +" license that can be found in the LICENSE file. +" + +" PathSep returns the appropriate OS specific path separator. +function! zig#util#PathSep() abort +  if zig#util#IsWin() +    return '\' +  endif +  return '/' +endfunction + +" PathListSep returns the appropriate OS specific path list separator. +function! zig#util#PathListSep() abort +  if zig#util#IsWin() +    return ";" +  endif +  return ":" +endfunction + +" LineEnding returns the correct line ending, based on the current fileformat +function! zig#util#LineEnding() abort +  if &fileformat == 'dos' +    return "\r\n" +  elseif &fileformat == 'mac' +    return "\r" +  endif + +  return "\n" +endfunction + +" Join joins any number of path elements into a single path, adding a +" Separator if necessary and returns the result +function! zig#util#Join(...) abort +  return join(a:000, zig#util#PathSep()) +endfunction + +" IsWin returns 1 if current OS is Windows or 0 otherwise +function! zig#util#IsWin() abort +  let win = ['win16', 'win32', 'win64', 'win95'] +  for w in win +    if (has(w)) +      return 1 +    endif +  endfor + +  return 0 +endfunction + +" IsMac returns 1 if current OS is macOS or 0 otherwise. +function! zig#util#IsMac() abort +  return has('mac') || +        \ has('macunix') || +        \ has('gui_macvim') || +        \ zig#util#Exec(['uname'])[0] =~? '^darwin' +endfunction + + " Checks if using: + " 1) Windows system, + " 2) And has cygpath executable, + " 3) And uses *sh* as 'shell' +function! zig#util#IsUsingCygwinShell() +  return zig#util#IsWin() && executable('cygpath') && &shell =~ '.*sh.*' +endfunction + +" Check if Vim jobs API is supported. +" +" The (optional) first paramter can be added to indicate the 'cwd' or 'env' +" parameters will be used, which wasn't added until a later version. +function! zig#util#has_job(...) abort +  " cwd and env parameters to job_start was added in this version. +  if a:0 > 0 && a:1 is 1 +    return has('job') && has("patch-8.0.0902") +  endif + +  " job was introduced in 7.4.xxx however there are multiple bug fixes and one +  " of the latest is 8.0.0087 which is required for a stable async API. +  return has('job') && has("patch-8.0.0087") +endfunction + +let s:env_cache = {} + +" env returns the go environment variable for the given key. Where key can be +" GOARCH, GOOS, GOROOT, etc... It caches the result and returns the cached +" version. +function! zig#util#env(key) abort +  let l:key = tolower(a:key) +  if has_key(s:env_cache, l:key) +    return s:env_cache[l:key] +  endif + +  if executable('go') +    let l:var = call('zig#util#'.l:key, []) +    if zig#util#ShellError() != 0 +      call zig#util#EchoError(printf("'go env %s' failed", toupper(l:key))) +      return '' +    endif +  else +    let l:var = eval("$".toupper(a:key)) +  endif + +  let s:env_cache[l:key] = l:var +  return l:var +endfunction + +" Run a shell command. +" +" It will temporary set the shell to /bin/sh for Unix-like systems if possible, +" so that we always use a standard POSIX-compatible Bourne shell (and not e.g. +" csh, fish, etc.) See #988 and #1276. +function! s:system(cmd, ...) abort +  " Preserve original shell and shellredir values +  let l:shell = &shell +  let l:shellredir = &shellredir + +  if !zig#util#IsWin() && executable('/bin/sh') +      set shell=/bin/sh shellredir=>%s\ 2>&1 +  endif + +  try +    return call('system', [a:cmd] + a:000) +  finally +    " Restore original values +    let &shell = l:shell +    let &shellredir = l:shellredir +  endtry +endfunction + +" System runs a shell command "str". Every arguments after "str" is passed to +" stdin. +function! zig#util#System(str, ...) abort +  return call('s:system', [a:str] + a:000) +endfunction + +" Exec runs a shell command "cmd", which must be a list, one argument per item. +" Every list entry will be automatically shell-escaped +" Every other argument is passed to stdin. +function! zig#util#Exec(cmd, ...) abort +  if len(a:cmd) == 0 +    call zig#util#EchoError("zig#util#Exec() called with empty a:cmd") +    return ['', 1] +  endif + +  let l:bin = a:cmd[0] + +  if !executable(l:bin) +    call zig#util#EchoError(printf("could not find binary '%s'", a:cmd[0])) +    return ['', 1] +  endif + +  return call('s:exec', [a:cmd] + a:000) +endfunction + +function! s:exec(cmd, ...) abort +  let l:bin = a:cmd[0] +  let l:cmd = zig#util#Shelljoin([l:bin] + a:cmd[1:]) +  if zig#util#HasDebug('shell-commands') +    call zig#util#EchoInfo('shell command: ' . l:cmd) +  endif + +  let l:out = call('s:system', [l:cmd] + a:000) +  return [l:out, zig#util#ShellError()] +endfunction + +function! zig#util#ShellError() abort +  return v:shell_error +endfunction + +" StripPath strips the path's last character if it's a path separator. +" example: '/foo/bar/'  -> '/foo/bar' +function! zig#util#StripPathSep(path) abort +  let last_char = strlen(a:path) - 1 +  if a:path[last_char] == zig#util#PathSep() +    return strpart(a:path, 0, last_char) +  endif + +  return a:path +endfunction + +" StripTrailingSlash strips the trailing slash from the given path list. +" example: ['/foo/bar/']  -> ['/foo/bar'] +function! zig#util#StripTrailingSlash(paths) abort +  return map(copy(a:paths), 'zig#util#StripPathSep(v:val)') +endfunction + +" Shelljoin returns a shell-safe string representation of arglist. The +" {special} argument of shellescape() may optionally be passed. +function! zig#util#Shelljoin(arglist, ...) abort +  try +    let ssl_save = &shellslash +    set noshellslash +    if a:0 +      return join(map(copy(a:arglist), 'shellescape(v:val, ' . a:1 . ')'), ' ') +    endif + +    return join(map(copy(a:arglist), 'shellescape(v:val)'), ' ') +  finally +    let &shellslash = ssl_save +  endtry +endfunction + +fu! zig#util#Shellescape(arg) +  try +    let ssl_save = &shellslash +    set noshellslash +    return shellescape(a:arg) +  finally +    let &shellslash = ssl_save +  endtry +endf + +" Shelllist returns a shell-safe representation of the items in the given +" arglist. The {special} argument of shellescape() may optionally be passed. +function! zig#util#Shelllist(arglist, ...) abort +  try +    let ssl_save = &shellslash +    set noshellslash +    if a:0 +      return map(copy(a:arglist), 'shellescape(v:val, ' . a:1 . ')') +    endif +    return map(copy(a:arglist), 'shellescape(v:val)') +  finally +    let &shellslash = ssl_save +  endtry +endfunction + +" Returns the byte offset for line and column +function! zig#util#Offset(line, col) abort +  if &encoding != 'utf-8' +    let sep = zig#util#LineEnding() +    let buf = a:line == 1 ? '' : (join(getline(1, a:line-1), sep) . sep) +    let buf .= a:col == 1 ? '' : getline('.')[:a:col-2] +    return len(iconv(buf, &encoding, 'utf-8')) +  endif +  return line2byte(a:line) + (a:col-2) +endfunction +" +" Returns the byte offset for the cursor +function! zig#util#OffsetCursor() abort +  return zig#util#Offset(line('.'), col('.')) +endfunction + +" Windo is like the built-in :windo, only it returns to the window the command +" was issued from +function! zig#util#Windo(command) abort +  let s:currentWindow = winnr() +  try +    execute "windo " . a:command +  finally +    execute s:currentWindow. "wincmd w" +    unlet s:currentWindow +  endtry +endfunction + +" snippetcase converts the given word to given preferred snippet setting type +" case. +function! zig#util#snippetcase(word) abort +  let l:snippet_case = zig#config#AddtagsTransform() +  if l:snippet_case == "snakecase" +    return zig#util#snakecase(a:word) +  elseif l:snippet_case == "camelcase" +    return zig#util#camelcase(a:word) +  else +    return a:word " do nothing +  endif +endfunction + +" snakecase converts a string to snake case. i.e: FooBar -> foo_bar +" Copied from tpope/vim-abolish +function! zig#util#snakecase(word) abort +  let word = substitute(a:word, '::', '/', '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 + +" camelcase converts a string to camel case. e.g. FooBar or foo_bar will become +" fooBar. +" Copied from tpope/vim-abolish. +function! zig#util#camelcase(word) abort +  let word = substitute(a:word, '-', '_', 'g') +  if word !~# '_' && word =~# '\l' +    return substitute(word, '^.', '\l&', '') +  else +    return substitute(word, '\C\(_\)\=\(.\)', '\=submatch(1)==""?tolower(submatch(2)) : toupper(submatch(2))','g') +  endif +endfunction + +" pascalcase converts a string to 'PascalCase'. e.g. fooBar or foo_bar will +" become FooBar. +function! zig#util#pascalcase(word) abort +  let word = zig#util#camelcase(a:word) +  return toupper(word[0]) . word[1:] +endfunction + +" Echo a message to the screen and highlight it with the group in a:hi. +" +" The message can be a list or string; every line with be :echomsg'd separately. +function! s:echo(msg, hi) +  let l:msg = [] +  if type(a:msg) != type([]) +    let l:msg = split(a:msg, "\n") +  else +    let l:msg = a:msg +  endif + +  " Tabs display as ^I or <09>, so manually expand them. +  let l:msg = map(l:msg, 'substitute(v:val, "\t", "        ", "")') + +  exe 'echohl ' . a:hi +  for line in l:msg +    echom "zig.vim: " . line +  endfor +  echohl None +endfunction + +function! zig#util#EchoSuccess(msg) +  call s:echo(a:msg, 'Function') +endfunction +function! zig#util#EchoError(msg) +  call s:echo(a:msg, 'ErrorMsg') +endfunction +function! zig#util#EchoWarning(msg) +  call s:echo(a:msg, 'WarningMsg') +endfunction +function! zig#util#EchoProgress(msg) +  redraw +  call s:echo(a:msg, 'Identifier') +endfunction +function! zig#util#EchoInfo(msg) +  call s:echo(a:msg, 'Debug') +endfunction + +" Get all lines in the buffer as a a list. +function! zig#util#GetLines() +  let buf = getline(1, '$') +  if &encoding != 'utf-8' +    let buf = map(buf, 'iconv(v:val, &encoding, "utf-8")') +  endif +  if &l:fileformat == 'dos' +    " XXX: line2byte() depend on 'fileformat' option. +    " so if fileformat is 'dos', 'buf' must include '\r'. +    let buf = map(buf, 'v:val."\r"') +  endif +  return buf +endfunction + +" Make a named temporary directory which starts with "prefix". +" +" Unfortunately Vim's tempname() is not portable enough across various systems; +" see: https://github.com/mattn/vim-go/pull/3#discussion_r138084911 +function! zig#util#tempdir(prefix) abort +  " See :help tempfile +  if zig#util#IsWin() +    let l:dirs = [$TMP, $TEMP, 'c:\tmp', 'c:\temp'] +  else +    let l:dirs = [$TMPDIR, '/tmp', './', $HOME] +  endif + +  let l:dir = '' +  for l:d in dirs +    if !empty(l:d) && filewritable(l:d) == 2 +      let l:dir = l:d +      break +    endif +  endfor + +  if l:dir == '' +    call zig#util#EchoError('Unable to find directory to store temporary directory in') +    return +  endif + +  " Not great randomness, but "good enough" for our purpose here. +  let l:rnd = sha256(printf('%s%s', localtime(), fnamemodify(bufname(''), ":p"))) +  let l:tmp = printf("%s/%s%s", l:dir, a:prefix, l:rnd) +  call mkdir(l:tmp, 'p', 0700) +  return l:tmp +endfunction + +" Report if the user enabled a debug flag in g:zig_debug. +function! zig#util#HasDebug(flag) +  return index(zig#config#Debug(), a:flag) >= 0 +endfunction + +" vim: sw=2 ts=2 et @@ -293,6 +293,7 @@ PACKS="    xls:vim-scripts/XSLT-syntax    yaml:stephpy/vim-yaml    yard:sheerun/vim-yardoc +  zig:ziglang/zig.vim  "  rm -rf tmp diff --git a/ftdetect/polyglot.vim b/ftdetect/polyglot.vim index 48c6e61e..f66f72c5 100644 --- a/ftdetect/polyglot.vim +++ b/ftdetect/polyglot.vim @@ -1449,3 +1449,10 @@ autocmd BufNewFile,BufRead *.xdc setfiletype xdc    augroup end  endif +if !exists('g:polyglot_disabled') || index(g:polyglot_disabled, 'zig') == -1 +  augroup filetypedetect +  " zig, from zig.vim in ziglang/zig.vim +au BufRead,BufNewFile *.zig set filetype=zig +  augroup end +endif + diff --git a/ftplugin/zig.vim b/ftplugin/zig.vim new file mode 100644 index 00000000..38008957 --- /dev/null +++ b/ftplugin/zig.vim @@ -0,0 +1,18 @@ +if exists('g:polyglot_disabled') && index(g:polyglot_disabled, 'zig') != -1 +  finish +endif + +" Only do this when not done yet for this buffer +if (exists("b:did_ftplugin")) +  finish +endif + +let b:did_ftplugin = 1 + +set expandtab +set tabstop=4 +set shiftwidth=4 + +setlocal suffixesadd=.zig +setlocal commentstring=//\ %s +setlocal makeprg=zig\ build diff --git a/syntax/zig.vim b/syntax/zig.vim new file mode 100644 index 00000000..05e29d5f --- /dev/null +++ b/syntax/zig.vim @@ -0,0 +1,106 @@ +if exists('g:polyglot_disabled') && index(g:polyglot_disabled, 'zig') != -1 +  finish +endif + +" Vim syntax file +" Language: Zig +" Maintainer: Andrew Kelley +" Latest Revision: 03 August 2016 + +if exists("b:current_syntax") +  finish +endif +let b:current_syntax = "zig" + +syn keyword zigStorage const var extern packed export pub noalias inline comptime nakedcc stdcallcc volatile allowzero align linksection threadlocal +syn keyword zigStructure struct enum union error +syn keyword zigStatement break return continue asm defer errdefer unreachable try catch async await suspend resume cancel +syn keyword zigConditional if else switch and or orelse +syn keyword zigRepeat while for + +syn keyword zigConstant null undefined +syn keyword zigKeyword fn usingnamespace test +syn keyword zigType bool f16 f32 f64 f128 void noreturn type anyerror promise +syn keyword zigType i0 u0 isize  usize comptime_int comptime_float +syn keyword zigType c_short c_ushort c_int c_uint c_long c_ulong c_longlong c_ulonglong c_longdouble c_void + +syn keyword zigBoolean true false + +syn match zigType "\v<[iu][1-9]\d*>" + +syn match zigOperator display "\%(+%\?\|-%\?\|/\|*%\?\|=\|\^\|&\|?\||\|!\|>\|<\|%\|<<%\?\|>>\)=\?" +syn match zigArrowCharacter display "->" + +syn match zigBuiltinFn "\v\@(addWithOverflow|ArgType|atomicLoad|bitCast|breakpoint)>" +syn match zigBuiltinFn "\v\@(alignCast|alignOf|cDefine|cImport|cInclude)>" +syn match zigBuiltinFn "\v\@(cUndef|canImplicitCast|clz|cmpxchgWeak|cmpxchgStrong|compileError)>" +syn match zigBuiltinFn "\v\@(compileLog|ctz|popCount|divExact|divFloor|divTrunc)>" +syn match zigBuiltinFn "\v\@(embedFile|export|tagName|TagType|errorName)>" +syn match zigBuiltinFn "\v\@(errorReturnTrace|fence|fieldParentPtr|field)>" +syn match zigBuiltinFn "\v\@(frameAddress|import|inlineCall|newStackCall|intToPtr|IntType)>" +syn match zigBuiltinFn "\v\@(maxValue|memberCount|memberName|memberType)>" +syn match zigBuiltinFn "\v\@(memcpy|memset|minValue|mod|mulWithOverflow)>" +syn match zigBuiltinFn "\v\@(noInlineCall|bitOffsetOf|byteOffsetOf|OpaqueType|panic|ptrCast)>" +syn match zigBuiltinFn "\v\@(ptrToInt|rem|returnAddress|setCold)>" +syn match zigBuiltinFn "\v\@(setRuntimeSafety|setEvalBranchQuota|setFloatMode)>" +syn match zigBuiltinFn "\v\@(setGlobalLinkage|setGlobalSection|shlExact|This|hasDecl)>" +syn match zigBuiltinFn "\v\@(shlWithOverflow|shrExact|sizeOf|sqrt|bswap|subWithOverflow|intCast|floatCast|intToFloat|floatToInt|boolToInt|errSetCast)>" +syn match zigBuiltinFn "\v\@(truncate|typeId|typeInfo|typeName|typeOf|atomicRmw|bytesToSlice|sliceToBytes)>" +syn match zigBuiltinFn "\v\@(intToError|errorToInt|intToEnum|enumToInt|setAlignStack|handle|bitreverse|Vector)>" + +syn match zigDecNumber display "\<[0-9]\+\%(.[0-9]\+\)\=\%([eE][+-]\?[0-9]\+\)\=" +syn match zigHexNumber display "\<0x[a-fA-F0-9]\+\%([a-fA-F0-9]\+\%([pP][+-]\?[0-9]\+\)\?\)\=" +syn match zigOctNumber display "\<0o[0-7]\+" +syn match zigBinNumber display "\<0b[01]\+\%(.[01]\+\%([eE][+-]\?[0-9]\+\)\?\)\=" + + +syn match zigCharacterInvalid display contained /b\?'\zs[\n\r\t']\ze'/ +syn match zigCharacterInvalidUnicode display contained /b'\zs[^[:cntrl:][:graph:][:alnum:][:space:]]\ze'/ +syn match zigCharacter /b'\([^\\]\|\\\(.\|x\x\{2}\)\)'/ contains=zigEscape,zigEscapeError,zigCharacterInvalid,zigCharacterInvalidUnicode +syn match zigCharacter /'\([^\\]\|\\\(.\|x\x\{2}\|u\x\{4}\|U\x\{6}\)\)'/ contains=zigEscape,zigEscapeUnicode,zigEscapeError,zigCharacterInvalid + +syn region zigCommentLine start="//" end="$" contains=zigTodo,@Spell +syn region zigCommentLineDoc start="////\@!" end="$" contains=zigTodo,@Spell + +" TODO: match only the first '\\' within the zigMultilineString as zigMultilineStringPrefix +syn match zigMultilineStringPrefix display contained /c\?\\\\/ +syn region zigMultilineString start="c\?\\\\" end="$" contains=zigMultilineStringPrefix + +syn keyword zigTodo contained TODO + +syn match     zigEscapeError   display contained /\\./ +syn match     zigEscape        display contained /\\\([nrt\\'"]\|x\x\{2}\)/ +syn match     zigEscapeUnicode display contained /\\\(u\x\{4}\|U\x\{6}\)/ +syn region    zigString      start=+c\?"+ skip=+\\\\\|\\"+ end=+"+ oneline contains=zigEscape,zigEscapeUnicode,zigEscapeError,@Spell + +hi def link zigDecNumber zigNumber +hi def link zigHexNumber zigNumber +hi def link zigOctNumber zigNumber +hi def link zigBinNumber zigNumber + +hi def link zigBuiltinFn Function +hi def link zigKeyword Keyword +hi def link zigType Type +hi def link zigCommentLine Comment +hi def link zigCommentLineDoc SpecialComment +hi def link zigTodo Todo +hi def link zigString String +hi def link zigMultilineString String +hi def link zigMultilineStringContent String +hi def link zigMultilineStringPrefix Comment +hi def link zigCharacterInvalid Error +hi def link zigCharacterInvalidUnicode zigCharacterInvalid +hi def link zigCharacter Character +hi def link zigEscape Special +hi def link zigEscapeUnicode zigEscape +hi def link zigEscapeError Error +hi def link zigBoolean Boolean +hi def link zigConstant Constant +hi def link zigNumber Number +hi def link zigArrowCharacter zigOperator +hi def link zigOperator Operator +hi def link zigStorage StorageClass +hi def link zigStructure Structure +hi def link zigStatement Statement +hi def link zigConditional Conditional +hi def link zigRepeat Repeat | 
