diff options
-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 |