diff options
-rw-r--r-- | README.md | 2 | ||||
-rwxr-xr-x | build | 2 | ||||
-rw-r--r-- | ftdetect/polyglot.vim | 10 | ||||
-rw-r--r-- | ftplugin/nix.vim | 20 | ||||
-rw-r--r-- | indent/nix.vim | 86 | ||||
-rw-r--r-- | syntax/nix.vim | 302 |
6 files changed, 285 insertions, 137 deletions
@@ -92,7 +92,7 @@ If you need full functionality of any plugin, please use it directly with your p - [mathematica](https://github.com/rsmenon/vim-mathematica) (syntax, ftplugin) - [nginx](https://github.com/chr4/nginx.vim) (syntax, indent, ftplugin) - [nim](https://github.com/zah/nim.vim) (syntax, compiler, indent) -- [nix](https://github.com/spwhitt/vim-nix) (syntax, ftplugin) +- [nix](https://github.com/LnL7/vim-nix) (syntax, indent, ftplugin) - [objc](https://github.com/b4winckler/vim-objc) (ftplugin, syntax, indent) - [ocaml](https://github.com/jrk/vim-ocaml) (syntax, indent, ftplugin) - [octave](https://github.com/vim-scripts/octave.vim--) (syntax) @@ -165,7 +165,7 @@ PACKS=" mathematica:rsmenon/vim-mathematica nginx:chr4/nginx.vim nim:zah/nim.vim:_BASIC - nix:spwhitt/vim-nix + nix:LnL7/vim-nix objc:b4winckler/vim-objc ocaml:jrk/vim-ocaml octave:vim-scripts/octave.vim-- diff --git a/ftdetect/polyglot.vim b/ftdetect/polyglot.vim index e42ae508..77024a16 100644 --- a/ftdetect/polyglot.vim +++ b/ftdetect/polyglot.vim @@ -591,8 +591,14 @@ au BufNewFile,BufRead *.nim,*.nims set filetype=nim augroup END augroup filetypedetect -" nix:spwhitt/vim-nix -autocmd BufNewFile,BufRead *.nix setfiletype nix +" nix:LnL7/vim-nix +" Vim filetype detect +" Language: Nix +" Maintainer: Daiderd Jordan <daiderd@gmail.com> +" URL: https://github.com/LnL7/vim-nix + +au BufRead,BufNewFile *.nix set filetype=nix +au FileType nix setl sw=2 sts=2 et iskeyword+=- augroup END augroup filetypedetect diff --git a/ftplugin/nix.vim b/ftplugin/nix.vim index 19d20977..8f3cf812 100644 --- a/ftplugin/nix.vim +++ b/ftplugin/nix.vim @@ -1,17 +1,17 @@ if !exists('g:polyglot_disabled') || index(g:polyglot_disabled, 'nix') == -1 -if exists("b:did_ftplugin") - finish +" Vim filetype plugin +" Language: Nix +" Maintainer: Daiderd Jordan <daiderd@gmail.com> +" URL: https://github.com/LnL7/vim-nix + +if (exists("b:did_ftplugin")) + finish endif -let b:did_ftplugin=1 +let b:did_ftplugin = 1 -setlocal comments= -setlocal commentstring=#\ %s -" Nixpkgs indent settings -setlocal tabstop=2 -setlocal softtabstop=2 -setlocal shiftwidth=2 -setlocal expandtab +setlocal comments=:# +setlocal commentstring=#\ %s endif diff --git a/indent/nix.vim b/indent/nix.vim new file mode 100644 index 00000000..679b224f --- /dev/null +++ b/indent/nix.vim @@ -0,0 +1,86 @@ +if !exists('g:polyglot_disabled') || index(g:polyglot_disabled, 'nix') == -1 + +" Vim indent file +" Language: Nix +" Maintainer: Daiderd Jordan <daiderd@gmail.com> +" URL: https://github.com/LnL7/vim-nix + +if exists("b:did_indent") + finish +endif +let b:did_indent = 1 + +setlocal indentexpr=GetNixIndent() +setlocal indentkeys+=0=then,0=else,0=inherit,*<Return> + +if exists("*GetNixIndent") + finish +endif + +let s:cpo_save = &cpo +set cpo&vim + +let s:skip_syntax = '\%(Comment\|String\)$' +let s:block_open = '\%({\|[\)' +let s:block_close = '\%(}\|]\)' + +function! GetNixIndent() + let lnum = prevnonblank(v:lnum - 1) + let ind = indent(lnum) + + " At the start of the file use zero indent. + if lnum == 0 + return 0 + endif + + if synIDattr(synID(v:lnum, 1, 1), "name") !~ s:skip_syntax + let current_line = getline(v:lnum) + let last_line = getline(lnum) + + if last_line =~ s:block_open . '\s*$' + let ind += &sw + endif + + if current_line =~ '^\s*' . s:block_close + let ind -= &sw + endif + + if last_line =~ '\<let\s*$' + let ind += &sw + endif + + if getline(v:lnum - 1) =~ '^\<in\s*$' + let ind += &sw + endif + + if current_line =~ '^\s*in\>' + let ind -= &sw + endif + endif + + if synIDattr(synID(v:lnum, 1, 1), "name") =~ '^nixString' + let current_line = getline(v:lnum) + + let ind = indent(v:lnum) + let bslnum = searchpair('''''', '', '''''', 'bnW', + \ 'synIDattr(synID(line("."), col("."), 0), "name") =~? "InterpolationSpecial$"') + + if ind <= indent(bslnum) + let ind = indent(bslnum) + &sw + endif + + if current_line =~ '^\s*''''[^''\$]' + let ind = indent(bslnum) + endif + if current_line =~ '^\s*''''$' + let ind = indent(bslnum) + endif + endif + + return ind +endfunction + +let &cpo = s:cpo_save +unlet s:cpo_save + +endif diff --git a/syntax/nix.vim b/syntax/nix.vim index 9a275ea7..ee0f4173 100644 --- a/syntax/nix.vim +++ b/syntax/nix.vim @@ -1,131 +1,187 @@ if !exists('g:polyglot_disabled') || index(g:polyglot_disabled, 'nix') == -1 -" -" Syntax file for Nix -" -" TODO: -" Emphasize : -" Deemphasize ; -" Consistent () -" rec (red?) +" Vim syntax file +" Language: Nix +" Maintainer: Daiderd Jordan <daiderd@gmail.com> +" URL: https://github.com/LnL7/vim-nix if exists("b:current_syntax") - finish + finish endif -" Operators -syn match nixOperator "\V++" -syn match nixOperator "\V+" -syn match nixOperator "\V!" -syn match nixOperator "\V==" -syn match nixOperator "\V!=" -syn match nixOperator "\V&&" -syn match nixOperator "\V||" -syn match nixOperator "\V->" - -syn match nixOperator "\V-" -syn match nixOperator "\V*" -syn match nixOperator "\V/" -syn match nixOperator "\V>" -syn match nixOperator "\V<" - -" Keywords -syn keyword nixKeyword let in or assert inherit null with rec -syn keyword nixConditional if else then -syn keyword nixBoolean true false - -" Builtins -syn keyword nixBuiltin builtins abort add attrNames attrValues - \ baseNameOf compareVersions concatLists currentSystem deepSeq - \ derivation dirOf div elem elemAt filter filterSource fromJSON - \ getAttr getEnv hasAttr hashString head import intersectAttrs - \ isAttrs isList isFunction isString isInt isBool isNull length - \ lessThan listToAttrs map mul parseDrvNames pathExists readDir - \ readFile removeAttrs seq stringLength sub substring tail throw - \ toFile toJSON toPath toString toXML trace typeOf tryEval - -syn match nixpkgs "<nixpkgs>" -syn match nixSpecialOper "\V@\|;\|,\|?\|..." - -" Attribute Lists -"syn match nixBrace "\v[(){}\[\]]|rec\s*\{" -syn region nixSet matchgroup=nixBraces start="{" end="}" contains=ALL -syn region nixRecSet matchgroup=nixBraces start="rec\s*{" end="}" contains=ALL -syn region nixList matchgroup=nixBraces start="\[" end="\]" contains=ALLBUT,nixAttr -syn match nixAttr "\v[0-9A-Za-z\-\_]+\ze\s*\=" contained - -syn match nixInteger "\v<\d+>" - -" Functions -syn match nixFuncArg "\v\zs\w+\ze\s*:" - -" TODO: Exclude ; and other illegal characters -syn match nixPath "\v\S*/\S+|\S+/\S*" - -" This operator is placed after nixPath to override nixPath's highlighting -syn match nixOperator "\V//" - -" Strings -syn match nixStringIndentedEscapes +'''\|''\${\|''\\n\|''\\r\|''\\t+ -syn match nixStringEscapes +\\"\|\\\${\|\\n\|\\r\|\\t\|\\\\+ -syn region nixStringIndented - \ start=+''+ - \ skip=+'''+ - \ end=+''+ - \ contains=nixAntiquotation,nixStringIndentedEscapes -syn region nixString - \ start=+"+ - \ skip=+\\"+ - \ end=+"+ - \ contains=nixAntiquotation,nixStringEscapes - -" If this contains nixBrace, it ignores its own closing brace and syntax gets -" thrown way off contains=ALLBUT,nixBrace -syn region nixAntiquotation start=+\${+ end=+}+ contains=nixAntiQuotation - -" Comments -syn region nixMultiLineComment start=+/\*+ skip=+\\"+ end=+\*/+ contains=nixTodos -syn match nixEndOfLineComment "#.*$" contains=nixTodos -syntax keyword nixTodos TODO XXX FIXME NOTE TODOS contained - -" Special (Delimiter -hi def link nixBraces Delimiter -hi def link nixpkgs Special -hi def link nixSpecialOper Special -hi def link nixStringIndentedEscapes SpecialChar -hi def link nixStringEscapes SpecialChar -hi def link nixBuiltin Special -hi def link nixOperator Operator - -" Constants -hi def link nixBoolean Boolean -hi def link nixInteger Number -hi def link nixString String -hi def link nixStringIndented String - -" Comments -hi def link nixMultiLineComment Comment -hi def link nixEndOfLineComment Comment - -" Identifiers -hi def link nixConditional Conditional -hi def link nixKeyword Keyword -hi def link nixOperator Operator -hi def link nixException Exception -hi def link nixAttr Identifier -hi def link nixFuncArg Identifier - -" PreProc -hi def link nixAntiquotation Macro - -" Underlined (html links) -hi def link nixPath Underlined - -" Error - -syn sync maxlines=20000 -syn sync minlines=50000 - -let b:current_syntax = 'nix' +syn keyword nixBoolean true false +syn keyword nixNull null +syn keyword nixRecKeyword rec + +syn keyword nixOperator or +syn match nixOperator '!=\|!' +syn match nixOperator '<=\?' +syn match nixOperator '>=\?' +syn match nixOperator '&&' +syn match nixOperator '//\=' +syn match nixOperator '==' +syn match nixOperator '?' +syn match nixOperator '||' +syn match nixOperator '++\=' +syn match nixOperator '-' +syn match nixOperator '\*' +syn match nixOperator '->' + +syn match nixParen '[()]' +syn match nixInteger '\d\+' + +syn keyword nixTodo FIXME NOTE TODO OPTIMIZE XXX HACK contained +syn match nixComment '#.*' contains=nixTodo,@Spell +syn region nixComment start=+/\*+ end=+\*/+ contains=nixTodo,@Spell + +syn region nixInterpolation matchgroup=nixInterpolationDelimiter start="\${" end="}" contained contains=@nixExpr,nixInterpolationParam + +syn match nixSimpleStringSpecial /\\["nrt\\$]/ contained +syn match nixInterpolationSpecial /''['$]/ contained + +syn region nixSimpleString matchgroup=nixStringDelimiter start=+"+ skip=+\\"+ end=+"+ contains=nixInterpolation,nixSimpleStringSpecial +syn region nixString matchgroup=nixStringDelimiter start=+''+ skip=+''['$]+ end=+''+ contains=nixInterpolation,nixInterpolationSpecial + +syn match nixFunctionCall "[a-zA-Z_][a-zA-Z0-9_'-]*" + +syn match nixPath "[a-zA-Z0-9._+-]*\%(/[a-zA-Z0-9._+-]\+\)\+" +syn match nixHomePath "\~\%(/[a-zA-Z0-9._+-]\+\)\+" +syn match nixSearchPath "[a-zA-Z0-9._+-]\+\%(\/[a-zA-Z0-9._+-]\+\)*" contained +syn match nixPathDelimiter "[<>]" contained +syn match nixSearchPathRef "<[a-zA-Z0-9._+-]\+\%(\/[a-zA-Z0-9._+-]\+\)*>" contains=nixSearchPath,nixPathDelimiter +syn match nixURI "[a-zA-Z][a-zA-Z0-9.+-]*:[a-zA-Z0-9%/?:@&=$,_.!~*'+-]\+" + +syn match nixAttributeDot "\." contained +syn match nixAttribute "[a-zA-Z_][a-zA-Z0-9_'-]*\ze\%([^a-zA-Z0-9_'-.]\|$\)" contained +syn region nixAttributeAssignment start="=" end="\ze;" contained contains=@nixExpr +syn region nixAttributeDefinition start=/\ze[a-zA-Z_"$]/ end=";" contained contains=nixComment,nixAttribute,nixInterpolation,nixSimpleString,nixAttributeDot,nixAttributeAssignment + +syn region nixInheritAttributeScope start="(" end=")" contained contains=nixComment,nixAttributeDot +syn region nixAttributeDefinition matchgroup=nixInherit start="\<inherit\>" end=";" contained contains=nixComment,nixInheritAttributeScope,nixAttribute + +syn region nixAttributeSet start="{" end="}" contains=nixComment,nixAttributeDefinition + +" vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv +syn region nixArgumentDefinitionWithDefault matchgroup=nixArgumentDefinition start="[a-zA-Z_][a-zA-Z0-9_'-]*\ze\%(\s\|#.\{-\}\n\|\n\|/\*\_.\{-\}\*/\)*?\@=" matchgroup=NONE end="[,}]\@=" transparent contained contains=@nixExpr +" vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv +syn match nixArgumentDefinition "[a-zA-Z_][a-zA-Z0-9_'-]*\ze\%(\s\|#.\{-\}\n\|\n\|/\*\_.\{-\}\*/\)*[,}]\@=" contained +syn match nixArgumentEllipsis "\.\.\." contained +syn match nixArgumentSeparator "," contained + +" vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv +syn match nixArgOperator '@\%(\s\|#.\{-\}\n\|\n\|/\*\_.\{-\}\*/\)*[a-zA-Z_][a-zA-Z0-9_'-]*\%(\s\|#.\{-\}\n\|\n\|/\*\_.\{-\}\*/\)*:'he=s+1 contained contains=nixAttribute + +" vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv +syn match nixArgOperator '[a-zA-Z_][a-zA-Z0-9_'-]*\%(\s\|#.\{-\}\n\|\n\|/\*\_.\{-\}\*/\)*@'hs=e-1 contains=nixAttribute nextgroup=nixFunctionArgument + +" This is a bit more complicated, because function arguments can be passed in a +" very similar form on how attribute sets are defined and two regions with the +" same start patterns will shadow each other. Instead of a region we could use a +" match on {\_.\{-\}}, which unfortunately doesn't take nesting into account. +" +" So what we do instead is that we look forward until we are sure that it's a +" function argument. Unfortunately, we need to catch comments and both vertical +" and horizontal white space, which the following regex should hopefully do: +" +" "\%(\s\|#.\{-\}\n\|\n\|/\*\_.\{-\}\*/\)*" +" +" It is also used throught the whole file and is marked with 'v's as well. +" +" Fortunately the matching rules for function arguments are much simpler than +" for real attribute sets, because we can stop when we hit the first ellipsis or +" default value operator, but we also need to paste the "whitespace & comments +" eating" regex all over the place (marked with 'v's): +" +" Region match 1: { foo ? ... } or { foo, ... } or { ... } (ellipsis) +" vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv {----- identifier -----}vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv +syn region nixFunctionArgument start="{\ze\%(\s\|#.\{-\}\n\|\n\|/\*\_.\{-\}\*/\)*\%([a-zA-Z_][a-zA-Z0-9_'-]*\%(\s\|#.\{-\}\n\|\n\|/\*\_.\{-\}\*/\)*[,?}]\|\.\.\.\)" end="}" contains=nixComment,nixArgumentDefinitionWithDefault,nixArgumentDefinition,nixArgumentEllipsis,nixArgumentSeparator nextgroup=nixArgOperator + +" Now it gets more tricky, because we need to look forward for the colon, but +" there could be something like "{}@foo:", even though it's highly unlikely. +" +" Region match 2: {} +" vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv@vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv{----- identifier -----} vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv +syn region nixFunctionArgument start="{\ze\%(\s\|#.\{-\}\n\|\n\|/\*\_.\{-\}\*/\)*}\%(\%(\s\|#.\{-\}\n\|\n\|/\*\_.\{-\}\*/\)*@\%(\s\|#.\{-\}\n\|\n\|/\*\_.\{-\}\*/\)*[a-zA-Z_][a-zA-Z0-9_'-]*\)\%(\s\|#.\{-\}\n\|\n\|/\*\_.\{-\}\*/\)*:" end="}" contains=nixComment nextgroup=nixArgOperator + +" vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv +syn match nixSimpleFunctionArgument "[a-zA-Z_][a-zA-Z0-9_'-]*\ze\%(\s\|#.\{-\}\n\|\n\|/\*\_.\{-\}\*/\)*:/\@!" + +syn region nixList matchgroup=nixListBracket start="\[" end="\]" contains=@nixExpr + +syn region nixLetExpr matchgroup=nixLetExprKeyword start="\<let\>" end="\<in\>" contains=nixComment,nixAttributeDefinition + +syn keyword nixIfExprKeyword then contained +syn region nixIfExpr matchgroup=nixIfExprKeyword start="\<if\>" end="\<else\>" contains=@nixExpr,nixIfExprKeyword + +syn region nixWithExpr matchgroup=nixWithExprKeyword start="\<with\>" matchgroup=NONE end=";" contains=@nixExpr + +syn region nixAssertExpr matchgroup=nixAssertKeyword start="\<assert\>" matchgroup=NONE end=";" contains=@nixExpr + +syn cluster nixExpr contains=nixBoolean,nixNull,nixOperator,nixParen,nixInteger,nixRecKeyword,nixConditional,nixBuiltin,nixSimpleBuiltin,nixComment,nixFunctionCall,nixFunctionArgument,nixSimpleFunctionArgument,nixPath,nixHomePath,nixSearchPathRef,nixURI,nixAttributeSet,nixList,nixSimpleString,nixString,nixLetExpr,nixIfExpr,nixWithExpr,nixAssertExpr + +" These definitions override @nixExpr and have to come afterwards: + +syn match nixInterpolationParam "[a-zA-Z_][a-zA-Z0-9_'-]*\%(\.[a-zA-Z_][a-zA-Z0-9_'-]*\)*" contained + +" Non-namespaced Nix builtins as of version 1.10: +syn keyword nixSimpleBuiltin + \ abort baseNameOf derivation dirOf fetchTarball import map removeAttrs + \ throw toString + +" Namespaced and non-namespaced Nix builtins as of version 1.10: +syn keyword nixNamespacedBuiltin contained + \ abort add all any attrNames attrValues baseNameOf compareVersions + \ concatLists currentSystem deepSeq derivation dirOf div elem elemAt + \ fetchTarball fetchurl filter filterSource foldl' fromJSON genList + \ getAttr getEnv hasAttr hashString head import intersectAttrs isAttrs + \ isBool isFunction isInt isList isString length lessThan listToAttrs map + \ mul parseDrvName pathExists readDir readFile removeAttrs replaceStrings + \ seq sort stringLength sub substring tail throw toFile toJSON toPath + \ toString toXML trace typeOf + +syn match nixBuiltin "builtins\.[a-zA-Z']\+"he=s+9 contains=nixComment,nixNamespacedBuiltin + +hi def link nixArgOperator Operator +hi def link nixArgumentDefinition Identifier +hi def link nixArgumentEllipsis Operator +hi def link nixAssertKeyword Keyword +hi def link nixAttribute Identifier +hi def link nixAttributeDot Operator +hi def link nixBoolean Boolean +hi def link nixBuiltin Special +hi def link nixComment Comment +hi def link nixConditional Conditional +hi def link nixHomePath Include +hi def link nixIfExprKeyword Keyword +hi def link nixInherit Keyword +hi def link nixInteger Integer +hi def link nixInterpolation Macro +hi def link nixInterpolationDelimiter Delimiter +hi def link nixInterpolationParam Macro +hi def link nixInterpolationSpecial Special +hi def link nixLetExprKeyword Keyword +hi def link nixNamespacedBuiltin Special +hi def link nixNull Constant +hi def link nixOperator Operator +hi def link nixPath Include +hi def link nixPathDelimiter Delimiter +hi def link nixRecKeyword Keyword +hi def link nixSearchPath Include +hi def link nixSimpleBuiltin Keyword +hi def link nixSimpleFunctionArgument Identifier +hi def link nixSimpleString String +hi def link nixSimpleStringSpecial SpecialChar +hi def link nixString String +hi def link nixStringDelimiter Delimiter +hi def link nixTodo Todo +hi def link nixURI Include +hi def link nixWithExprKeyword Keyword + +" This could lead up to slow syntax highlighting for large files, but usually +" large files such as all-packages.nix are one large attribute set, so if we'd +" use sync patterns we'd have to go back to the start of the file anyway +syn sync fromstart + +let b:current_syntax = "nix" endif |