Coverage for /pythoncovmergedfiles/medio/medio/usr/local/lib/python3.11/site-packages/pygments/lexers/nix.py: 93%
Shortcuts on this page
r m x toggle line displays
j k next/prev highlighted chunk
0 (zero) top of page
1 (one) first highlighted chunk
Shortcuts on this page
r m x toggle line displays
j k next/prev highlighted chunk
0 (zero) top of page
1 (one) first highlighted chunk
1"""
2 pygments.lexers.nix
3 ~~~~~~~~~~~~~~~~~~~
5 Lexers for the NixOS Nix language.
7 :copyright: Copyright 2006-2025 by the Pygments team, see AUTHORS.
8 :license: BSD, see LICENSE for details.
9"""
11import re
13from pygments.lexer import RegexLexer, include
14from pygments.token import Text, Comment, Operator, Keyword, Name, String, \
15 Number, Punctuation, Literal
17__all__ = ['NixLexer']
20class NixLexer(RegexLexer):
21 """
22 For the Nix language.
23 """
25 name = 'Nix'
26 url = 'http://nixos.org/nix/'
27 aliases = ['nixos', 'nix']
28 filenames = ['*.nix']
29 mimetypes = ['text/x-nix']
30 version_added = '2.0'
32 keywords = ['rec', 'with', 'let', 'in', 'inherit', 'assert', 'if',
33 'else', 'then', '...']
34 builtins = ['import', 'abort', 'baseNameOf', 'dirOf', 'isNull', 'builtins',
35 'map', 'removeAttrs', 'throw', 'toString', 'derivation']
36 operators = ['++', '+', '?', '.', '!', '//', '==', '/',
37 '!=', '&&', '||', '->', '=', '<', '>', '*', '-']
39 punctuations = ["(", ")", "[", "]", ";", "{", "}", ":", ",", "@"]
41 tokens = {
42 'root': [
43 # comments starting with #
44 (r'#.*$', Comment.Single),
46 # multiline comments
47 (r'/\*', Comment.Multiline, 'comment'),
49 # whitespace
50 (r'\s+', Text),
52 # keywords
53 ('({})'.format('|'.join(re.escape(entry) + '\\b' for entry in keywords)), Keyword),
55 # highlight the builtins
56 ('({})'.format('|'.join(re.escape(entry) + '\\b' for entry in builtins)),
57 Name.Builtin),
59 (r'\b(true|false|null)\b', Name.Constant),
61 # floats
62 (r'-?(\d+\.\d*|\.\d+)([eE][-+]?\d+)?', Number.Float),
64 # integers
65 (r'-?[0-9]+', Number.Integer),
67 # paths
68 (r'[\w.+-]*(\/[\w.+-]+)+', Literal),
69 (r'~(\/[\w.+-]+)+', Literal),
70 (r'\<[\w.+-]+(\/[\w.+-]+)*\>', Literal),
72 # operators
73 ('({})'.format('|'.join(re.escape(entry) for entry in operators)),
74 Operator),
76 # word operators
77 (r'\b(or|and)\b', Operator.Word),
79 (r'\{', Punctuation, 'block'),
81 # punctuations
82 ('({})'.format('|'.join(re.escape(entry) for entry in punctuations)), Punctuation),
84 # strings
85 (r'"', String.Double, 'doublequote'),
86 (r"''", String.Multiline, 'multiline'),
88 # urls
89 (r'[a-zA-Z][a-zA-Z0-9\+\-\.]*\:[\w%/?:@&=+$,\\.!~*\'-]+', Literal),
91 # names of variables
92 (r'[\w-]+(?=\s*=)', String.Symbol),
93 (r'[a-zA-Z_][\w\'-]*', Text),
95 (r"\$\{", String.Interpol, 'antiquote'),
96 ],
97 'comment': [
98 (r'[^/*]+', Comment.Multiline),
99 (r'/\*', Comment.Multiline, '#push'),
100 (r'\*/', Comment.Multiline, '#pop'),
101 (r'[*/]', Comment.Multiline),
102 ],
103 'multiline': [
104 (r"''(\$|'|\\n|\\r|\\t|\\)", String.Escape),
105 (r"''", String.Multiline, '#pop'),
106 (r'\$\{', String.Interpol, 'antiquote'),
107 (r"[^'\$]+", String.Multiline),
108 (r"\$[^\{']", String.Multiline),
109 (r"'[^']", String.Multiline),
110 (r"\$(?=')", String.Multiline),
111 ],
112 'doublequote': [
113 (r'\\(\\|"|\$|n)', String.Escape),
114 (r'"', String.Double, '#pop'),
115 (r'\$\{', String.Interpol, 'antiquote'),
116 (r'[^"\\\$]+', String.Double),
117 (r'\$[^\{"]', String.Double),
118 (r'\$(?=")', String.Double),
119 (r'\\', String.Double),
120 ],
121 'antiquote': [
122 (r"\}", String.Interpol, '#pop'),
123 # TODO: we should probably escape also here ''${ \${
124 (r"\$\{", String.Interpol, '#push'),
125 include('root'),
126 ],
127 'block': [
128 (r"\}", Punctuation, '#pop'),
129 include('root'),
130 ],
131 }
133 def analyse_text(text):
134 rv = 0.0
135 # TODO: let/in
136 if re.search(r'import.+?<[^>]+>', text):
137 rv += 0.4
138 if re.search(r'mkDerivation\s+(\(|\{|rec)', text):
139 rv += 0.4
140 if re.search(r'=\s+mkIf\s+', text):
141 rv += 0.4
142 if re.search(r'\{[a-zA-Z,\s]+\}:', text):
143 rv += 0.1
144 return rv