blob: ef52cddf46ddb5ddc375e6f09ce7854ecb1c652f [file] [log] [blame]
Bram Moolenaar86b48162022-12-06 18:20:10 +00001" Vim syntax file
2" Language: Nix
James Fleming72904d52023-07-29 12:01:18 +02003" Maintainer: James Fleming <james@electronic-quill.net>
4" (Github username: equill)
Bram Moolenaar86b48162022-12-06 18:20:10 +00005" Original Author: Daiderd Jordan <daiderd@gmail.com>
6" Acknowledgement: Based on vim-nix maintained by Daiderd Jordan <daiderd@gmail.com>
7" https://github.com/LnL7/vim-nix
8" License: MIT
James Fleming72904d52023-07-29 12:01:18 +02009" Last Change: 2023 Aug 19
Bram Moolenaar86b48162022-12-06 18:20:10 +000010
11if exists("b:current_syntax")
12 finish
13endif
14
15let s:cpo_save = &cpo
16set cpo&vim
17
18syn keyword nixBoolean true false
19syn keyword nixNull null
20syn keyword nixRecKeyword rec
21
22syn keyword nixOperator or
23syn match nixOperator '!=\|!'
24syn match nixOperator '<=\?'
25syn match nixOperator '>=\?'
26syn match nixOperator '&&'
27syn match nixOperator '//\='
28syn match nixOperator '=='
29syn match nixOperator '?'
30syn match nixOperator '||'
31syn match nixOperator '++\='
32syn match nixOperator '-'
33syn match nixOperator '\*'
34syn match nixOperator '->'
35
36syn match nixParen '[()]'
37syn match nixInteger '\d\+'
38
39syn keyword nixTodo FIXME NOTE TODO OPTIMIZE XXX HACK contained
40syn match nixComment '#.*' contains=nixTodo,@Spell
41syn region nixComment start=+/\*+ end=+\*/+ contains=nixTodo,@Spell
42
43syn region nixInterpolation matchgroup=nixInterpolationDelimiter start="\${" end="}" contained contains=@nixExpr,nixInterpolationParam
44
45syn match nixSimpleStringSpecial /\\\%([nrt"\\$]\|$\)/ contained
46syn match nixStringSpecial /''['$]/ contained
47syn match nixStringSpecial /\$\$/ contained
48syn match nixStringSpecial /''\\[nrt]/ contained
49
50syn match nixSimpleStringSpecial /\$\$/ contained
51
52syn match nixInvalidSimpleStringEscape /\\[^nrt"\\$]/ contained
53syn match nixInvalidStringEscape /''\\[^nrt]/ contained
54
55syn region nixSimpleString matchgroup=nixStringDelimiter start=+"+ skip=+\\"+ end=+"+ contains=nixInterpolation,nixSimpleStringSpecial,nixInvalidSimpleStringEscape
56syn region nixString matchgroup=nixStringDelimiter start=+''+ skip=+''['$\\]+ end=+''+ contains=nixInterpolation,nixStringSpecial,nixInvalidStringEscape
57
58syn match nixFunctionCall "[a-zA-Z_][a-zA-Z0-9_'-]*"
59
60syn match nixPath "[a-zA-Z0-9._+-]*\%(/[a-zA-Z0-9._+-]\+\)\+"
61syn match nixHomePath "\~\%(/[a-zA-Z0-9._+-]\+\)\+"
62syn match nixSearchPath "[a-zA-Z0-9._+-]\+\%(\/[a-zA-Z0-9._+-]\+\)*" contained
63syn match nixPathDelimiter "[<>]" contained
64syn match nixSearchPathRef "<[a-zA-Z0-9._+-]\+\%(\/[a-zA-Z0-9._+-]\+\)*>" contains=nixSearchPath,nixPathDelimiter
65syn match nixURI "[a-zA-Z][a-zA-Z0-9.+-]*:[a-zA-Z0-9%/?:@&=$,_.!~*'+-]\+"
66
67syn match nixAttributeDot "\." contained
68syn match nixAttribute "[a-zA-Z_][a-zA-Z0-9_'-]*\ze\%([^a-zA-Z0-9_'.-]\|$\)" contained
69syn region nixAttributeAssignment start="=" end="\ze;" contained contains=@nixExpr
70syn region nixAttributeDefinition start=/\ze[a-zA-Z_"$]/ end=";" contained contains=nixComment,nixAttribute,nixInterpolation,nixSimpleString,nixAttributeDot,nixAttributeAssignment
71
James Fleming72904d52023-07-29 12:01:18 +020072syn region nixInheritAttributeSubExpr start="("ms=e+1 end="\ze)" contained contains=nixAttributeDot,@nixExpr
73syn region nixInheritAttributeScope start="\ze(" end=")" contained contains=nixInheritAttributeSubExpr
Bram Moolenaar86b48162022-12-06 18:20:10 +000074syn region nixAttributeDefinition matchgroup=nixInherit start="\<inherit\>" end=";" contained contains=nixComment,nixInheritAttributeScope,nixAttribute
75
76syn region nixAttributeSet start="{" end="}" contains=nixComment,nixAttributeDefinition
77
78" vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv
79syn region nixArgumentDefinitionWithDefault matchgroup=nixArgumentDefinition start="[a-zA-Z_][a-zA-Z0-9_'-]*\ze\%(\s\|#.\{-\}\n\|\n\|/\*\_.\{-\}\*/\)*?\@=" matchgroup=NONE end="[,}]\@=" transparent contained contains=@nixExpr
80" vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv
81syn match nixArgumentDefinition "[a-zA-Z_][a-zA-Z0-9_'-]*\ze\%(\s\|#.\{-\}\n\|\n\|/\*\_.\{-\}\*/\)*[,}]\@=" contained
82syn match nixArgumentEllipsis "\.\.\." contained
83syn match nixArgumentSeparator "," contained
84
85" vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv
86syn match nixArgOperator '@\%(\s\|#.\{-\}\n\|\n\|/\*\_.\{-\}\*/\)*[a-zA-Z_][a-zA-Z0-9_'-]*\%(\s\|#.\{-\}\n\|\n\|/\*\_.\{-\}\*/\)*:'he=s+1 contained contains=nixAttribute
87
88" vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv
89syn match nixArgOperator '[a-zA-Z_][a-zA-Z0-9_'-]*\%(\s\|#.\{-\}\n\|\n\|/\*\_.\{-\}\*/\)*@'hs=e-1 contains=nixAttribute nextgroup=nixFunctionArgument
90
91" This is a bit more complicated, because function arguments can be passed in a
92" very similar form on how attribute sets are defined and two regions with the
93" same start patterns will shadow each other. Instead of a region we could use a
94" match on {\_.\{-\}}, which unfortunately doesn't take nesting into account.
95"
96" So what we do instead is that we look forward until we are sure that it's a
97" function argument. Unfortunately, we need to catch comments and both vertical
98" and horizontal white space, which the following regex should hopefully do:
99"
100" "\%(\s\|#.\{-\}\n\|\n\|/\*\_.\{-\}\*/\)*"
101"
Viktor Szépedbf749b2023-10-16 09:53:37 +0200102" It is also used throughout the whole file and is marked with 'v's as well.
Bram Moolenaar86b48162022-12-06 18:20:10 +0000103"
104" Fortunately the matching rules for function arguments are much simpler than
105" for real attribute sets, because we can stop when we hit the first ellipsis or
106" default value operator, but we also need to paste the "whitespace & comments
107" eating" regex all over the place (marked with 'v's):
108"
109" Region match 1: { foo ? ... } or { foo, ... } or { ... } (ellipsis)
110" vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv {----- identifier -----}vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv
111syn 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
112
113" Now it gets more tricky, because we need to look forward for the colon, but
114" there could be something like "{}@foo:", even though it's highly unlikely.
115"
116" Region match 2: {}
117" vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv@vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv{----- identifier -----} vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv
118syn 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
119
120" vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv
121syn match nixSimpleFunctionArgument "[a-zA-Z_][a-zA-Z0-9_'-]*\ze\%(\s\|#.\{-\}\n\|\n\|/\*\_.\{-\}\*/\)*:\([\n ]\)\@="
122
123syn region nixList matchgroup=nixListBracket start="\[" end="\]" contains=@nixExpr
124
125syn region nixLetExpr matchgroup=nixLetExprKeyword start="\<let\>" end="\<in\>" contains=nixComment,nixAttributeDefinition
126
127syn keyword nixIfExprKeyword then contained
128syn region nixIfExpr matchgroup=nixIfExprKeyword start="\<if\>" end="\<else\>" contains=@nixExpr,nixIfExprKeyword
129
130syn region nixWithExpr matchgroup=nixWithExprKeyword start="\<with\>" matchgroup=NONE end=";" contains=@nixExpr
131
132syn region nixAssertExpr matchgroup=nixAssertKeyword start="\<assert\>" matchgroup=NONE end=";" contains=@nixExpr
133
134syn cluster nixExpr contains=nixBoolean,nixNull,nixOperator,nixParen,nixInteger,nixRecKeyword,nixConditional,nixBuiltin,nixSimpleBuiltin,nixComment,nixFunctionCall,nixFunctionArgument,nixArgOperator,nixSimpleFunctionArgument,nixPath,nixHomePath,nixSearchPathRef,nixURI,nixAttributeSet,nixList,nixSimpleString,nixString,nixLetExpr,nixIfExpr,nixWithExpr,nixAssertExpr,nixInterpolation
135
136" These definitions override @nixExpr and have to come afterwards:
137
138syn match nixInterpolationParam "[a-zA-Z_][a-zA-Z0-9_'-]*\%(\.[a-zA-Z_][a-zA-Z0-9_'-]*\)*" contained
139
140" Non-namespaced Nix builtins as of version 2.0:
141syn keyword nixSimpleBuiltin
142 \ abort baseNameOf derivation derivationStrict dirOf fetchGit
143 \ fetchMercurial fetchTarball import isNull map mapAttrs placeholder removeAttrs
144 \ scopedImport throw toString
145
146
147" Namespaced and non-namespaced Nix builtins as of version 2.0:
148syn keyword nixNamespacedBuiltin contained
149 \ abort add addErrorContext all any attrNames attrValues baseNameOf
150 \ catAttrs compareVersions concatLists concatStringsSep currentSystem
151 \ currentTime deepSeq derivation derivationStrict dirOf div elem elemAt
152 \ fetchGit fetchMercurial fetchTarball fetchurl filter \ filterSource
153 \ findFile foldl' fromJSON functionArgs genList \ genericClosure getAttr
154 \ getEnv hasAttr hasContext hashString head import intersectAttrs isAttrs
155 \ isBool isFloat isFunction isInt isList isNull isString langVersion
156 \ length lessThan listToAttrs map mapAttrs match mul nixPath nixVersion
157 \ parseDrvName partition path pathExists placeholder readDir readFile
158 \ removeAttrs replaceStrings scopedImport seq sort split splitVersion
159 \ storeDir storePath stringLength sub substring tail throw toFile toJSON
160 \ toPath toString toXML trace tryEval typeOf unsafeDiscardOutputDependency
161 \ unsafeDiscardStringContext unsafeGetAttrPos valueSize fromTOML bitAnd
162 \ bitOr bitXor floor ceil
163
164syn match nixBuiltin "builtins\.[a-zA-Z']\+"he=s+9 contains=nixComment,nixNamespacedBuiltin
165
166hi def link nixArgOperator Operator
167hi def link nixArgumentDefinition Identifier
168hi def link nixArgumentEllipsis Operator
169hi def link nixAssertKeyword Keyword
170hi def link nixAttribute Identifier
171hi def link nixAttributeDot Operator
172hi def link nixBoolean Boolean
173hi def link nixBuiltin Special
174hi def link nixComment Comment
175hi def link nixConditional Conditional
176hi def link nixHomePath Include
177hi def link nixIfExprKeyword Keyword
178hi def link nixInherit Keyword
179hi def link nixInteger Integer
180hi def link nixInterpolation Macro
181hi def link nixInterpolationDelimiter Delimiter
182hi def link nixInterpolationParam Macro
183hi def link nixInvalidSimpleStringEscape Error
184hi def link nixInvalidStringEscape Error
185hi def link nixLetExprKeyword Keyword
186hi def link nixNamespacedBuiltin Special
187hi def link nixNull Constant
188hi def link nixOperator Operator
189hi def link nixPath Include
190hi def link nixPathDelimiter Delimiter
191hi def link nixRecKeyword Keyword
192hi def link nixSearchPath Include
193hi def link nixSimpleBuiltin Keyword
194hi def link nixSimpleFunctionArgument Identifier
195hi def link nixSimpleString String
196hi def link nixSimpleStringSpecial SpecialChar
197hi def link nixString String
198hi def link nixStringDelimiter Delimiter
199hi def link nixStringSpecial Special
200hi def link nixTodo Todo
201hi def link nixURI Include
202hi def link nixWithExprKeyword Keyword
203
204" This could lead up to slow syntax highlighting for large files, but usually
205" large files such as all-packages.nix are one large attribute set, so if we'd
206" use sync patterns we'd have to go back to the start of the file anyway
207syn sync fromstart
208
209let b:current_syntax = "nix"
210
211let &cpo = s:cpo_save
212unlet s:cpo_save