Coverage for /pythoncovmergedfiles/medio/medio/usr/local/lib/python3.11/site-packages/pygments/lexers/make.py: 72%

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

53 statements  

1""" 

2 pygments.lexers.make 

3 ~~~~~~~~~~~~~~~~~~~~ 

4 

5 Lexers for Makefiles and similar. 

6 

7 :copyright: Copyright 2006-2025 by the Pygments team, see AUTHORS. 

8 :license: BSD, see LICENSE for details. 

9""" 

10 

11import re 

12 

13from pygments.lexer import Lexer, RegexLexer, include, bygroups, \ 

14 do_insertions, using 

15from pygments.token import Text, Comment, Operator, Keyword, Name, String, \ 

16 Punctuation, Whitespace 

17from pygments.lexers.shell import BashLexer 

18 

19__all__ = ['MakefileLexer', 'BaseMakefileLexer', 'CMakeLexer'] 

20 

21 

22class MakefileLexer(Lexer): 

23 """ 

24 Lexer for BSD and GNU make extensions (lenient enough to handle both in 

25 the same file even). 

26 

27 *Rewritten in Pygments 0.10.* 

28 """ 

29 

30 name = 'Makefile' 

31 aliases = ['make', 'makefile', 'mf', 'bsdmake'] 

32 filenames = ['*.mak', '*.mk', 'Makefile', 'makefile', 'Makefile.*', 'GNUmakefile'] 

33 mimetypes = ['text/x-makefile'] 

34 url = 'https://en.wikipedia.org/wiki/Make_(software)' 

35 version_added = '' 

36 

37 r_special = re.compile( 

38 r'^(?:' 

39 # BSD Make 

40 r'\.\s*(include|undef|error|warning|if|else|elif|endif|for|endfor)|' 

41 # GNU Make 

42 r'\s*(ifeq|ifneq|ifdef|ifndef|else|endif|-?include|define|endef|:|vpath)|' 

43 # GNU Automake 

44 r'\s*(if|else|endif))(?=\s)') 

45 r_comment = re.compile(r'^\s*@?#') 

46 

47 def get_tokens_unprocessed(self, text): 

48 ins = [] 

49 lines = text.splitlines(keepends=True) 

50 done = '' 

51 lex = BaseMakefileLexer(**self.options) 

52 backslashflag = False 

53 for line in lines: 

54 if self.r_special.match(line) or backslashflag: 

55 ins.append((len(done), [(0, Comment.Preproc, line)])) 

56 backslashflag = line.strip().endswith('\\') 

57 elif self.r_comment.match(line): 

58 ins.append((len(done), [(0, Comment, line)])) 

59 else: 

60 done += line 

61 yield from do_insertions(ins, lex.get_tokens_unprocessed(done)) 

62 

63 def analyse_text(text): 

64 # Many makefiles have $(BIG_CAPS) style variables 

65 if re.search(r'\$\([A-Z_]+\)', text): 

66 return 0.1 

67 

68 

69class BaseMakefileLexer(RegexLexer): 

70 """ 

71 Lexer for simple Makefiles (no preprocessing). 

72 """ 

73 

74 name = 'Base Makefile' 

75 aliases = ['basemake'] 

76 filenames = [] 

77 mimetypes = [] 

78 url = 'https://en.wikipedia.org/wiki/Make_(software)' 

79 version_added = '0.10' 

80 

81 tokens = { 

82 'root': [ 

83 # recipes (need to allow spaces because of expandtabs) 

84 (r'^(?:[\t ]+.*\n|\n)+', using(BashLexer)), 

85 # special variables 

86 (r'\$[<@$+%?|*]', Keyword), 

87 (r'\s+', Whitespace), 

88 (r'#.*?\n', Comment), 

89 (r'((?:un)?export)(\s+)(?=[\w${}\t -]+\n)', 

90 bygroups(Keyword, Whitespace), 'export'), 

91 (r'(?:un)?export\s+', Keyword), 

92 # assignment 

93 (r'([\w${}().-]+)(\s*)([!?:+]?=)([ \t]*)((?:.*\\\n)+|.*\n)', 

94 bygroups( 

95 Name.Variable, Whitespace, Operator, Whitespace, 

96 using(BashLexer))), 

97 # strings 

98 (r'"(\\\\|\\[^\\]|[^"\\])*"', String.Double), 

99 (r"'(\\\\|\\[^\\]|[^'\\])*'", String.Single), 

100 # targets 

101 (r'([^\n:]+)(:+)([ \t]*)', bygroups( 

102 Name.Function, Operator, Whitespace), 

103 'block-header'), 

104 # expansions 

105 (r'\$\(', Keyword, 'expansion'), 

106 ], 

107 'expansion': [ 

108 (r'[^\w$().-]+', Text), 

109 (r'[\w.-]+', Name.Variable), 

110 (r'\$', Keyword), 

111 (r'\(', Keyword, '#push'), 

112 (r'\)', Keyword, '#pop'), 

113 ], 

114 'export': [ 

115 (r'[\w${}-]+', Name.Variable), 

116 (r'\n', Text, '#pop'), 

117 (r'\s+', Whitespace), 

118 ], 

119 'block-header': [ 

120 (r'[,|]', Punctuation), 

121 (r'#.*?\n', Comment, '#pop'), 

122 (r'\\\n', Text), # line continuation 

123 (r'\$\(', Keyword, 'expansion'), 

124 (r'[a-zA-Z_]+', Name), 

125 (r'\n', Whitespace, '#pop'), 

126 (r'.', Text), 

127 ], 

128 } 

129 

130 

131class CMakeLexer(RegexLexer): 

132 """ 

133 Lexer for CMake files. 

134 """ 

135 name = 'CMake' 

136 url = 'https://cmake.org/documentation/' 

137 aliases = ['cmake'] 

138 filenames = ['*.cmake', 'CMakeLists.txt'] 

139 mimetypes = ['text/x-cmake'] 

140 version_added = '1.2' 

141 

142 tokens = { 

143 'root': [ 

144 # (r'(ADD_CUSTOM_COMMAND|ADD_CUSTOM_TARGET|ADD_DEFINITIONS|' 

145 # r'ADD_DEPENDENCIES|ADD_EXECUTABLE|ADD_LIBRARY|ADD_SUBDIRECTORY|' 

146 # r'ADD_TEST|AUX_SOURCE_DIRECTORY|BUILD_COMMAND|BUILD_NAME|' 

147 # r'CMAKE_MINIMUM_REQUIRED|CONFIGURE_FILE|CREATE_TEST_SOURCELIST|' 

148 # r'ELSE|ELSEIF|ENABLE_LANGUAGE|ENABLE_TESTING|ENDFOREACH|' 

149 # r'ENDFUNCTION|ENDIF|ENDMACRO|ENDWHILE|EXEC_PROGRAM|' 

150 # r'EXECUTE_PROCESS|EXPORT_LIBRARY_DEPENDENCIES|FILE|FIND_FILE|' 

151 # r'FIND_LIBRARY|FIND_PACKAGE|FIND_PATH|FIND_PROGRAM|FLTK_WRAP_UI|' 

152 # r'FOREACH|FUNCTION|GET_CMAKE_PROPERTY|GET_DIRECTORY_PROPERTY|' 

153 # r'GET_FILENAME_COMPONENT|GET_SOURCE_FILE_PROPERTY|' 

154 # r'GET_TARGET_PROPERTY|GET_TEST_PROPERTY|IF|INCLUDE|' 

155 # r'INCLUDE_DIRECTORIES|INCLUDE_EXTERNAL_MSPROJECT|' 

156 # r'INCLUDE_REGULAR_EXPRESSION|INSTALL|INSTALL_FILES|' 

157 # r'INSTALL_PROGRAMS|INSTALL_TARGETS|LINK_DIRECTORIES|' 

158 # r'LINK_LIBRARIES|LIST|LOAD_CACHE|LOAD_COMMAND|MACRO|' 

159 # r'MAKE_DIRECTORY|MARK_AS_ADVANCED|MATH|MESSAGE|OPTION|' 

160 # r'OUTPUT_REQUIRED_FILES|PROJECT|QT_WRAP_CPP|QT_WRAP_UI|REMOVE|' 

161 # r'REMOVE_DEFINITIONS|SEPARATE_ARGUMENTS|SET|' 

162 # r'SET_DIRECTORY_PROPERTIES|SET_SOURCE_FILES_PROPERTIES|' 

163 # r'SET_TARGET_PROPERTIES|SET_TESTS_PROPERTIES|SITE_NAME|' 

164 # r'SOURCE_GROUP|STRING|SUBDIR_DEPENDS|SUBDIRS|' 

165 # r'TARGET_LINK_LIBRARIES|TRY_COMPILE|TRY_RUN|UNSET|' 

166 # r'USE_MANGLED_MESA|UTILITY_SOURCE|VARIABLE_REQUIRES|' 

167 # r'VTK_MAKE_INSTANTIATOR|VTK_WRAP_JAVA|VTK_WRAP_PYTHON|' 

168 # r'VTK_WRAP_TCL|WHILE|WRITE_FILE|' 

169 # r'COUNTARGS)\b', Name.Builtin, 'args'), 

170 (r'\b(\w+)([ \t]*)(\()', bygroups(Name.Builtin, Whitespace, 

171 Punctuation), 'args'), 

172 include('keywords'), 

173 include('ws') 

174 ], 

175 'args': [ 

176 (r'\(', Punctuation, '#push'), 

177 (r'\)', Punctuation, '#pop'), 

178 (r'(\$\{)(.+?)(\})', bygroups(Operator, Name.Variable, Operator)), 

179 (r'(\$ENV\{)(.+?)(\})', bygroups(Operator, Name.Variable, Operator)), 

180 (r'(\$<)(.+?)(>)', bygroups(Operator, Name.Variable, Operator)), 

181 (r'(?s)".*?"', String.Double), 

182 (r'\\\S+', String), 

183 (r'\[(?P<level>=*)\[[\w\W]*?\](?P=level)\]', String.Multiline), 

184 (r'[^)$"# \t\n]+', String), 

185 (r'\n', Whitespace), # explicitly legal 

186 include('keywords'), 

187 include('ws') 

188 ], 

189 'string': [ 

190 

191 ], 

192 'keywords': [ 

193 (r'\b(WIN32|UNIX|APPLE|CYGWIN|BORLAND|MINGW|MSVC|MSVC_IDE|MSVC60|' 

194 r'MSVC70|MSVC71|MSVC80|MSVC90)\b', Keyword), 

195 ], 

196 'ws': [ 

197 (r'[ \t]+', Whitespace), 

198 (r'#\[(?P<level>=*)\[[\w\W]*?\](?P=level)\]', Comment), 

199 (r'#.*\n', Comment), 

200 ] 

201 } 

202 

203 def analyse_text(text): 

204 exp = ( 

205 r'^[ \t]*CMAKE_MINIMUM_REQUIRED[ \t]*' 

206 r'\([ \t]*VERSION[ \t]*\d+(\.\d+)*[ \t]*' 

207 r'([ \t]FATAL_ERROR)?[ \t]*\)[ \t]*' 

208 r'(#[^\n]*)?$' 

209 ) 

210 if re.search(exp, text, flags=re.MULTILINE | re.IGNORECASE): 

211 return 0.8 

212 return 0.0