1"""
2 pygments.lexers.teraterm
3 ~~~~~~~~~~~~~~~~~~~~~~~~
4
5 Lexer for Tera Term macro files.
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 RegexLexer, include, bygroups
14from pygments.token import Text, Comment, Operator, Name, String, \
15 Number, Keyword, Error
16
17__all__ = ['TeraTermLexer']
18
19
20class TeraTermLexer(RegexLexer):
21 """
22 For Tera Term macro source code.
23 """
24 name = 'Tera Term macro'
25 url = 'https://ttssh2.osdn.jp/'
26 aliases = ['teratermmacro', 'teraterm', 'ttl']
27 filenames = ['*.ttl']
28 mimetypes = ['text/x-teratermmacro']
29 version_added = '2.4'
30
31 tokens = {
32 'root': [
33 include('comments'),
34 include('labels'),
35 include('commands'),
36 include('builtin-variables'),
37 include('user-variables'),
38 include('operators'),
39 include('numeric-literals'),
40 include('string-literals'),
41 include('all-whitespace'),
42 (r'\S', Text),
43 ],
44 'comments': [
45 (r';[^\r\n]*', Comment.Single),
46 (r'/\*', Comment.Multiline, 'in-comment'),
47 ],
48 'in-comment': [
49 (r'\*/', Comment.Multiline, '#pop'),
50 (r'[^*/]+', Comment.Multiline),
51 (r'[*/]', Comment.Multiline)
52 ],
53 'labels': [
54 (r'(?i)^(\s*)(:[a-z0-9_]+)', bygroups(Text.Whitespace, Name.Label)),
55 ],
56 'commands': [
57 (
58 r'(?i)\b('
59 r'basename|'
60 r'beep|'
61 r'bplusrecv|'
62 r'bplussend|'
63 r'break|'
64 r'bringupbox|'
65 # 'call' is handled separately.
66 r'callmenu|'
67 r'changedir|'
68 r'checksum16|'
69 r'checksum16file|'
70 r'checksum32|'
71 r'checksum32file|'
72 r'checksum8|'
73 r'checksum8file|'
74 r'clearscreen|'
75 r'clipb2var|'
76 r'closesbox|'
77 r'closett|'
78 r'code2str|'
79 r'connect|'
80 r'continue|'
81 r'crc16|'
82 r'crc16file|'
83 r'crc32|'
84 r'crc32file|'
85 r'cygconnect|'
86 r'delpassword|'
87 r'dirname|'
88 r'dirnamebox|'
89 r'disconnect|'
90 r'dispstr|'
91 r'do|'
92 r'else|'
93 r'elseif|'
94 r'enablekeyb|'
95 r'end|'
96 r'endif|'
97 r'enduntil|'
98 r'endwhile|'
99 r'exec|'
100 r'execcmnd|'
101 r'exit|'
102 r'expandenv|'
103 r'fileclose|'
104 r'fileconcat|'
105 r'filecopy|'
106 r'filecreate|'
107 r'filedelete|'
108 r'filelock|'
109 r'filemarkptr|'
110 r'filenamebox|'
111 r'fileopen|'
112 r'fileread|'
113 r'filereadln|'
114 r'filerename|'
115 r'filesearch|'
116 r'fileseek|'
117 r'fileseekback|'
118 r'filestat|'
119 r'filestrseek|'
120 r'filestrseek2|'
121 r'filetruncate|'
122 r'fileunlock|'
123 r'filewrite|'
124 r'filewriteln|'
125 r'findclose|'
126 r'findfirst|'
127 r'findnext|'
128 r'flushrecv|'
129 r'foldercreate|'
130 r'folderdelete|'
131 r'foldersearch|'
132 r'for|'
133 r'getdate|'
134 r'getdir|'
135 r'getenv|'
136 r'getfileattr|'
137 r'gethostname|'
138 r'getipv4addr|'
139 r'getipv6addr|'
140 r'getmodemstatus|'
141 r'getpassword|'
142 r'getspecialfolder|'
143 r'gettime|'
144 r'gettitle|'
145 r'getttdir|'
146 r'getver|'
147 # 'goto' is handled separately.
148 r'if|'
149 r'ifdefined|'
150 r'include|'
151 r'inputbox|'
152 r'int2str|'
153 r'intdim|'
154 r'ispassword|'
155 r'kmtfinish|'
156 r'kmtget|'
157 r'kmtrecv|'
158 r'kmtsend|'
159 r'listbox|'
160 r'loadkeymap|'
161 r'logautoclosemode|'
162 r'logclose|'
163 r'loginfo|'
164 r'logopen|'
165 r'logpause|'
166 r'logrotate|'
167 r'logstart|'
168 r'logwrite|'
169 r'loop|'
170 r'makepath|'
171 r'messagebox|'
172 r'mpause|'
173 r'next|'
174 r'passwordbox|'
175 r'pause|'
176 r'quickvanrecv|'
177 r'quickvansend|'
178 r'random|'
179 r'recvln|'
180 r'regexoption|'
181 r'restoresetup|'
182 r'return|'
183 r'rotateleft|'
184 r'rotateright|'
185 r'scprecv|'
186 r'scpsend|'
187 r'send|'
188 r'sendbreak|'
189 r'sendbroadcast|'
190 r'sendfile|'
191 r'sendkcode|'
192 r'sendln|'
193 r'sendlnbroadcast|'
194 r'sendlnmulticast|'
195 r'sendmulticast|'
196 r'setbaud|'
197 r'setdate|'
198 r'setdebug|'
199 r'setdir|'
200 r'setdlgpos|'
201 r'setdtr|'
202 r'setecho|'
203 r'setenv|'
204 r'setexitcode|'
205 r'setfileattr|'
206 r'setflowctrl|'
207 r'setmulticastname|'
208 r'setpassword|'
209 r'setrts|'
210 r'setspeed|'
211 r'setsync|'
212 r'settime|'
213 r'settitle|'
214 r'show|'
215 r'showtt|'
216 r'sprintf|'
217 r'sprintf2|'
218 r'statusbox|'
219 r'str2code|'
220 r'str2int|'
221 r'strcompare|'
222 r'strconcat|'
223 r'strcopy|'
224 r'strdim|'
225 r'strinsert|'
226 r'strjoin|'
227 r'strlen|'
228 r'strmatch|'
229 r'strremove|'
230 r'strreplace|'
231 r'strscan|'
232 r'strspecial|'
233 r'strsplit|'
234 r'strtrim|'
235 r'testlink|'
236 r'then|'
237 r'tolower|'
238 r'toupper|'
239 r'unlink|'
240 r'until|'
241 r'uptime|'
242 r'var2clipb|'
243 r'wait|'
244 r'wait4all|'
245 r'waitevent|'
246 r'waitln|'
247 r'waitn|'
248 r'waitrecv|'
249 r'waitregex|'
250 r'while|'
251 r'xmodemrecv|'
252 r'xmodemsend|'
253 r'yesnobox|'
254 r'ymodemrecv|'
255 r'ymodemsend|'
256 r'zmodemrecv|'
257 r'zmodemsend'
258 r')\b',
259 Keyword,
260 ),
261 (r'(?i)(call|goto)([ \t]+)([a-z0-9_]+)',
262 bygroups(Keyword, Text.Whitespace, Name.Label)),
263 ],
264 'builtin-variables': [
265 (
266 r'(?i)('
267 r'groupmatchstr1|'
268 r'groupmatchstr2|'
269 r'groupmatchstr3|'
270 r'groupmatchstr4|'
271 r'groupmatchstr5|'
272 r'groupmatchstr6|'
273 r'groupmatchstr7|'
274 r'groupmatchstr8|'
275 r'groupmatchstr9|'
276 r'inputstr|'
277 r'matchstr|'
278 r'mtimeout|'
279 r'param1|'
280 r'param2|'
281 r'param3|'
282 r'param4|'
283 r'param5|'
284 r'param6|'
285 r'param7|'
286 r'param8|'
287 r'param9|'
288 r'paramcnt|'
289 r'params|'
290 r'result|'
291 r'timeout'
292 r')\b',
293 Name.Builtin
294 ),
295 ],
296 'user-variables': [
297 (r'(?i)[a-z_][a-z0-9_]*', Name.Variable),
298 ],
299 'numeric-literals': [
300 (r'(-?)([0-9]+)', bygroups(Operator, Number.Integer)),
301 (r'(?i)\$[0-9a-f]+', Number.Hex),
302 ],
303 'string-literals': [
304 (r'(?i)#(?:[0-9]+|\$[0-9a-f]+)', String.Char),
305 (r"'[^'\n]*'", String.Single),
306 (r'"[^"\n]*"', String.Double),
307 # Opening quotes without a closing quote on the same line are errors.
308 (r"('[^']*)(\n)", bygroups(Error, Text.Whitespace)),
309 (r'("[^"]*)(\n)', bygroups(Error, Text.Whitespace)),
310 ],
311 'operators': [
312 (r'and|not|or|xor', Operator.Word),
313 (r'[!%&*+<=>^~\|\/-]+', Operator),
314 (r'[()]', String.Symbol),
315 ],
316 'all-whitespace': [
317 (r'\s+', Text.Whitespace),
318 ],
319 }
320
321 # Turtle and Tera Term macro files share the same file extension
322 # but each has a recognizable and distinct syntax.
323 def analyse_text(text):
324 if re.search(TeraTermLexer.tokens['commands'][0][0], text):
325 return 0.01