nix.py 3.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136
  1. # -*- coding: utf-8 -*-
  2. """
  3. pygments.lexers.nix
  4. ~~~~~~~~~~~~~~~~~~~
  5. Lexers for the NixOS Nix language.
  6. :copyright: Copyright 2006-2019 by the Pygments team, see AUTHORS.
  7. :license: BSD, see LICENSE for details.
  8. """
  9. import re
  10. from pygments.lexer import RegexLexer, include
  11. from pygments.token import Text, Comment, Operator, Keyword, Name, String, \
  12. Number, Punctuation, Literal
  13. __all__ = ['NixLexer']
  14. class NixLexer(RegexLexer):
  15. """
  16. For the `Nix language <http://nixos.org/nix/>`_.
  17. .. versionadded:: 2.0
  18. """
  19. name = 'Nix'
  20. aliases = ['nixos', 'nix']
  21. filenames = ['*.nix']
  22. mimetypes = ['text/x-nix']
  23. flags = re.MULTILINE | re.UNICODE
  24. keywords = ['rec', 'with', 'let', 'in', 'inherit', 'assert', 'if',
  25. 'else', 'then', '...']
  26. builtins = ['import', 'abort', 'baseNameOf', 'dirOf', 'isNull', 'builtins',
  27. 'map', 'removeAttrs', 'throw', 'toString', 'derivation']
  28. operators = ['++', '+', '?', '.', '!', '//', '==',
  29. '!=', '&&', '||', '->', '=']
  30. punctuations = ["(", ")", "[", "]", ";", "{", "}", ":", ",", "@"]
  31. tokens = {
  32. 'root': [
  33. # comments starting with #
  34. (r'#.*$', Comment.Single),
  35. # multiline comments
  36. (r'/\*', Comment.Multiline, 'comment'),
  37. # whitespace
  38. (r'\s+', Text),
  39. # keywords
  40. ('(%s)' % '|'.join(re.escape(entry) + '\\b' for entry in keywords), Keyword),
  41. # highlight the builtins
  42. ('(%s)' % '|'.join(re.escape(entry) + '\\b' for entry in builtins),
  43. Name.Builtin),
  44. (r'\b(true|false|null)\b', Name.Constant),
  45. # operators
  46. ('(%s)' % '|'.join(re.escape(entry) for entry in operators),
  47. Operator),
  48. # word operators
  49. (r'\b(or|and)\b', Operator.Word),
  50. # punctuations
  51. ('(%s)' % '|'.join(re.escape(entry) for entry in punctuations), Punctuation),
  52. # integers
  53. (r'[0-9]+', Number.Integer),
  54. # strings
  55. (r'"', String.Double, 'doublequote'),
  56. (r"''", String.Single, 'singlequote'),
  57. # paths
  58. (r'[\w.+-]*(\/[\w.+-]+)+', Literal),
  59. (r'\<[\w.+-]+(\/[\w.+-]+)*\>', Literal),
  60. # urls
  61. (r'[a-zA-Z][a-zA-Z0-9\+\-\.]*\:[\w%/?:@&=+$,\\.!~*\'-]+', Literal),
  62. # names of variables
  63. (r'[\w-]+\s*=', String.Symbol),
  64. (r'[a-zA-Z_][\w\'-]*', Text),
  65. ],
  66. 'comment': [
  67. (r'[^/*]+', Comment.Multiline),
  68. (r'/\*', Comment.Multiline, '#push'),
  69. (r'\*/', Comment.Multiline, '#pop'),
  70. (r'[*/]', Comment.Multiline),
  71. ],
  72. 'singlequote': [
  73. (r"'''", String.Escape),
  74. (r"''\$\{", String.Escape),
  75. (r"''\n", String.Escape),
  76. (r"''\r", String.Escape),
  77. (r"''\t", String.Escape),
  78. (r"''", String.Single, '#pop'),
  79. (r'\$\{', String.Interpol, 'antiquote'),
  80. (r"[^']", String.Single),
  81. ],
  82. 'doublequote': [
  83. (r'\\', String.Escape),
  84. (r'\\"', String.Escape),
  85. (r'\\$\{', String.Escape),
  86. (r'"', String.Double, '#pop'),
  87. (r'\$\{', String.Interpol, 'antiquote'),
  88. (r'[^"]', String.Double),
  89. ],
  90. 'antiquote': [
  91. (r"\}", String.Interpol, '#pop'),
  92. # TODO: we should probably escape also here ''${ \${
  93. (r"\$\{", String.Interpol, '#push'),
  94. include('root'),
  95. ],
  96. }
  97. def analyse_text(text):
  98. rv = 0.0
  99. # TODO: let/in
  100. if re.search(r'import.+?<[^>]+>', text):
  101. rv += 0.4
  102. if re.search(r'mkDerivation\s+(\(|\{|rec)', text):
  103. rv += 0.4
  104. if re.search(r'=\s+mkIf\s+', text):
  105. rv += 0.4
  106. if re.search(r'\{[a-zA-Z,\s]+\}:', text):
  107. rv += 0.1
  108. return rv