The scrollbar is updated everytime it's needed, not only on keyups (performance may...
[mp-5.x.git] / mp_syntax.mpsl
blob599ccea773dddcf2344fea588a2400ee4385e9cc
1 /*
3     Minimum Profit 5.x
4     A Programmer's Text Editor
6     Syntax highlight definitions.
8     Copyright (C) 1991-2007 Angel Ortega <angel@triptico.com>
10     This program is free software; you can redistribute it and/or
11     modify it under the terms of the GNU General Public License
12     as published by the Free Software Foundation; either version 2
13     of the License, or (at your option) any later version.
15     This program is distributed in the hope that it will be useful,
16     but WITHOUT ANY WARRANTY; without even the implied warranty of
17     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18     GNU General Public License for more details.
20     You should have received a copy of the GNU General Public License
21     along with this program; if not, write to the Free Software
22     Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
24     http://www.triptico.com
28 /* editor actions */
30 mp.actions['help']      =       sub (d) {
31         local w, h, r;
33         /* get the special word regex separator for help (if any) */
34         r = d.syntax.help_word_regex;
36         /* if there is a word at the cursor position,
37            try searching for help */
38         if ((w = mp.get_word(d, r)) != NULL)
39                 h = mp.help(d, w);
41         if (h == NULL)
42                 mp.alert(sprintf(L("No help for '%s'."), w));
43         else {
44                 local d;
46                 d = mp.new(sprintf(L("<help on '%s'>"), w), h);
47                 d.read_only = 1;
48         }
51 /* default key bindings */
53 mp.keycodes['f1']       =       "help";
55 /* action descriptions */
57 mp.actdesc['help'] = LL("Help on word over cursor");
59 /* data */
61 mp.syntax = {};
63 /* code */
65 sub mp.syn_token_list(l) { '/\b(' ~ join("|", l) ~ ')\b/'; }
67 mp.syntax.c = {
68         'id'            =>      'c',
69         'name'          =>      'C / C++',
70         'filenames'     =>      [ '/\.c$/', '/\.h$/', '/\.l$/', '/\.y$/', '/\.d$/',
71                                 '/\.cpp$/', '/\.hpp$/', '/\.c++$/', '/\.xpm$/' ],
72         'help'          =>      [ "man 2 %s", "man 3 %s" ],
73         'defs'          =>      [
74                 'word1',        [
75                                 mp.syn_token_list( [
76                                 "for", "while", "if", "switch", "case", "do",
77                                 "else", "break", "continue", "return",
78                                 "default", "goto", "main", "fopen", "fclose",
79                                 "fgets", "fgetc", "fputs", "fputc", "fprintf",
80                                 "putc", "printf", "sprintf", "strcpy", "strcat",
81                                 "strcmp", "strncmp", "strtok", "stricmp", "strchr",
82                                 "strrchr", "strlen", "memcmp", "memcpy", "malloc",
83                                 "free", "strncpy", "strncat", "snprintf", "strstr",
84                                 "memset", "memcpy", "va_start", "va_end", "vsprintf",
85                                 "vsnprintf", "atoi", "qsort", "bsearch", "getenv",
86                                 "fscanf", "popen", "pclose", "realloc", "fread",
87                                 "fwrite", "fseek", '\{', '\}', "putchar", "fflush",
88                                 "wcscmp", "swprintf", "wmemcpy", "swscanf", "sscanf",
89                                 "wcslen", "wmemset", "wcscpy", "wcsncpy", "wcscoll",
90                                 "mbstowcs", "wcstombs", "wprintf", "wcschr",
91                                 "wcsrchr", "wcsstr", "strdup", "wctomb", "mbtowc",
92                                 "mbrtowc", "wcrtomb", "open", "close", "read",
93                                 "write", "pipe", "fork", "dup", "dup2", "wait",
94                                 "execl", "execlp", "execle", "execv", "execvp"
95                                 ])
96                 ],
97                 'word2',        [
98                                 mp.syn_token_list( [
99                                 "char", "int", "long", "struct", "union", "const",
100                                 "void", "unsigned", "signed", "auto", "volatile",
101                                 "enum", "typedef", "float", "double", "extern",
102                                 "register", "short", "sizeof", "static", "far",
103                                 "near", "defined", "va_list", "size_t", "wchar_t",
104                                 "iconv_t" ]),
105                                 '/[-=<>:\?\+\*\/\!\%&\|]+/'
106                 ],
107                 'quotes',       [
108                         /* from http://ad.hominem.org/log/2005/05/quoted_strings.php */
109                         "/\"([^\"\\\\\n]*(\\\\.[^\"\\\\\n]*)*)\"/",     /* double-quoted strings */
110                         "/'([^'\\\\\n]*(\\\\.[^'\\\\\n]*)*)'/",         /* single-quoted strings */
111                         "/\b-?[0-9]+\b/",                       /* numbers */
112                         "/\b0x[0-9a-f]+\b/i",                   /* hex numbers */
113                         "/\b[0-9[:upper:]_]+\b/"                /* all-caps words */
114                 ],
115                 'comments',     [
116                         [ '|/\*|', '|\*/|' ],                   /* C-like */
117                         '|//.*$|m',                             /* C++ */
118                         '/^\s*#[a-z]+/m'                        /* CPP directives */
119                 ]
120         ]
123 mp.syntax.rc = {
124         'id'            =>      'rc',
125         'name'          =>      'Resource file',
126         'filenames'     =>      [ '/\.rc$/' ],
127         'defs'          =>      [
128                 'word1',        [ ],
129                 'word2',        [ ],
130                 'quotes',       [
131                         /* from http://ad.hominem.org/log/2005/05/quoted_strings.php */
132                         "/\"([^\"\\\\\n]*(\\\\.[^\"\\\\\n]*)*)\"/",     /* double-quoted strings */
133                         "/'([^'\\\\\n]*(\\\\.[^'\\\\\n]*)*)'/",         /* single-quoted strings */
134                         "/\b-?[0-9]+\b/",                       /* numbers */
135                         "/\b0x[0-9a-f]+\b/i",                   /* hex numbers */
136                         "/\b[0-9[:upper:]_]+\b/"                /* all-caps words */
137                 ],
138                 'comments',     [
139                         [ '|/\*|', '|\*/|' ],                   /* C-like */
140                         '|//.*$|m',                             /* C++ */
141                         '/^\s*#[a-z]+/m'                        /* CPP directives */
142                 ]
143         ]
146 mp.syntax.perl = {
147         'id'            =>      'perl',
148         'name'          =>      'Perl',
149         'filenames'     =>      [ '/\.pl$/i', '/\.pm$/' ],
150         'help'          =>      [ 'perldoc -f %s', 'perldoc %s' ],
151         'help_word_regex' =>    '/[A-Z_][A-Z0-9_:]*/i',
152         'defs'  =>      [
153                 'word1',        [
154                                 mp.syn_token_list( [
155                                 "for", "if", "next", "last", "else", "elsif",
156                                 "unless", "while", "shift", "unshift", "push",
157                                 "pop", "delete", "new", "bless", "return",
158                                 "foreach", "keys", "values", "sort", "grep",
159                                 "tr", "length", "system", "exec", "fork", "map",
160                                 "print", "write", "open", "close", "chop",
161                                 "chomp", "exit", "sleep", "split", "join",
162                                 "sub", "printf", "sprintf", "s", "glob",
163                                 "scalar", "my", "local", "undef", "defined",
164                                 "use", "package", "require", "ref", "can", "isa",
165                                 "qw", "qq", "eq", "ne", "or", "exists",
166                                 "and", "not", "import", "our", "caller" ]),
167                                 '/->/'
168                 ],
169                 'word2',        [
170                                 '/[:\?\+\*\/\!\$@\%&\|~\.]+/',
171                                 '/[\$@%]\w+/'
172                 ],
173                 'quotes',       [
174                         /* from http://ad.hominem.org/log/2005/05/quoted_strings.php */
175                         "/\"([^\"\\\\\n]*(\\\\.[^\"\\\\\n]*)*)\"/",     /* double-quoted strings */
176                         "/'([^'\\\\\n]*(\\\\.[^'\\\\\n]*)*)'/",         /* single-quoted strings */
177                         "/\b-?[0-9]+\b/",                       /* numbers */
178                         "/\b0x[0-9a-f]+\b/i",                   /* hex numbers */
179                         "/\b[0-9[:upper:]_]+\b/",               /* all-caps words */
180                         [ "/q\(/", "/\)/" ],                    /* quote */
181                         [ "/qw\(/", "/\)/" ],                   /* quote word */
182                         '/\w+\s*=>/',                           /* barewords as hash keys 1 */
183                         '/\{\s*-?\w+\s*\}/',                    /* barewords as hash keys 2 */
184                         [ "/`/", "/`/" ],                       /* backticks */
185                         [ "/<<[\"']?EOF.*$/m", "/^EOF$/m" ]     /* 'document here' */
186                 ],
187                 /* color all => as word2 */
188                 'word2',        [ '/=>/' ],
189                 /* color curly brackets as word */
190                 'word',         [ '/[{}]/' ],
191                 'comments',     [
192                         "/#.*$/m",                              /* Comments */
193                         "/__END__\n.*$/",                       /* __END__ */
194                         [ "/^=(head[1-4]|over|item|back|pod|begin|end|for)/m",
195                                 "/^=cut$/m" ]                   /* POD */
196                 ]
197         ],
198         'detect'        =>      sub (d) {
199                 /* take the first line */
200                 local f = d.txt.lines[0];
202                 /* is it a 'she-bang' for Perl? */
203                 return regex('/^#!\s*/usr/bin/(env )?perl/', f);
204         }
208 mp.syntax.mpsl = {
209         'id'            =>      'mpsl',
210         'name'          =>      'MPSL',
211         'filenames'     =>      [ '/\.mpsl$/' ],
212         'defs'          =>      [
213                 'word1',        [
214                                 mp.syn_token_list( [
215                                         'if', 'else', 'while', 'foreach',
216                                         'sub', 'break', 'return', 'eq', 'ne' ]),
217                                 mp.syn_token_list( keys(MPSL.CORE) ),
218                                 '/[\{\}]/'
219                 ],
220                 'word2',        [
221                                 "/(NULL|local)/",
222                                 '/[-=<>:\?\+\*\/\!\%&\|]+/'
223                 ],
224                 'quotes',       [
225                         /* from http://ad.hominem.org/log/2005/05/quoted_strings.php */
226                         "/\"([^\"\\\\\n]*(\\\\.[^\"\\\\\n]*)*)\"/",     /* double-quoted strings */
227                         "/'([^'\\\\\n]*(\\\\.[^'\\\\\n]*)*)'/",         /* single-quoted strings */
228                         "/\b-?[0-9]+\b/",                       /* numbers */
229                         "/\b0x[0-9a-f]+\b/i",                   /* hex numbers */
230                         "/\b[0-9[:upper:]_]+\b/"                /* all-caps words */
231                 ],
232                 'comments',     [
233                         [ '|/\*|', '|\*/|' ]                    /* C-like */
234                 ]
235         ]
238 mp.syntax.sh = {
239         'id'            =>      'sh',
240         'name'          =>      'Shell script',
241         'filenames'     =>      [ '/\.sh$/', '/makefile/i' ],
242         'defs'          =>      [
243                 'word1',        [
244                                 mp.syn_token_list( [
245                                 "if", "then", "else", "elif",
246                                 "fi", "case", "do", "done", "esac",
247                                 "for", "until", "while", "break",
248                                 "in", "source", "alias", "cd",
249                                 "continue", "echo", "eval", "exec",
250                                 "exit", "export", "kill", "logout",
251                                 "printf", "pwd", "read", "return",
252                                 "shift", "test", "trap", "ulimit",
253                                 "umask", "unset", "wait", "cp", "rm" ]),
254                                 '/[\{\}]/'
256                 ],
257                 'word2',        [
258                                 '/\b(local|let|set)\b/',
259                                 '/[-=<>:\?\+\*\!\%&\|]+/',
260                                 '/\$\w+/',
261                                 '/\$\{\w+\}/',
262                                 "/\b[0-9[:upper:]_]+\b/"        /* all-caps words */
263                 ],
264                 'quotes',       [
265                         "/\"([^\"\\\\\n]*(\\\\.[^\"\\\\\n]*)*)\"/",     /* double-quoted strings */
266                         "/'([^'\\\\\n]*(\\\\.[^'\\\\\n]*)*)'/",         /* single-quoted strings */
267                         "/\b-?[0-9]+\b/",                       /* numbers */
268                         "/\b0x[0-9a-f]+\b/i",                   /* hex numbers */
269                         "/\([A-Za-z0-9_]+\)/",                  /* parens */
270                         [ "/`/", "/`/" ],                       /* backticks */
271                         [ "/<<[\"']?EOF[\"']?;$/m", "/^EOF$/m" ]        /* 'document here' */
272                 ],
273                 'comments',     [ "/#.*$/m" ]
274         ],
275         'detect'        =>      sub (d) {
276                 /* take the first line */
277                 local f = d.txt.lines[0];
279                 /* is it a 'she-bang' for usual shells? */
280                 return regex('/^#!\s*/bin/(sh|bash|csh|dash|ksh)/', f) ||
281                        regex('/^#!\s*/usr/bin/make -f/', f);
282         }
287 mp.syntax.html = {
288         'id'            =>      'html',
289         'name'          =>      'HTML',
290         'filenames'     =>      [ '/\.html$/', '/\.htm$/' ],
291         'defs'          =>      [
292                 'word1',        [
293                                 "/<[\/]?[ \t]*(" ~
294                                 join("|", [
295                                 "a", "abbr", "acronym", "address",
296                                 "area", "b", "base", "bdo", "big",
297                                 "blockquote", "body", "br", "button",
298                                 "caption", "center", "cite", "code", "col",
299                                 "colgroup", "dd", "del", "dfn", "div",
300                                 "dl", "dt", "em", "fieldset", "form",
301                                 "h1", "h2", "h3", "h4", "h5", "h6",
302                                 "head", "hr", "html", "i", "img",
303                                 "input", "ins", "kbd", "label", "legend",
304                                 "li", "link", "map", "meta", "noscript",
305                                 "object", "ol", "optgroup", "option",
306                                 "p", "param", "pre", "q", "samp",
307                                 "script", "select", "small", "span",
308                                 "strong", "style", "sub", "sup", "table",
309                                 "tbody", "td", "textarea", "tfoot", "th",
310                                 "thead", "title", "tr", "tt", "ul",
311                                 "var" ] ) ~
312                                 ")[^<>]*>/i"
313                 ],
314                 'word2',        [
315                                 mp.syn_token_list( [
316                                  "!DOCTYPE", "class", "type",
317                                 "cellspacing", "cellpadding",
318                                 "href", "align", "valign", "name", "lang",
319                                 "value", "action", "width", "height",
320                                 "content", "http-equiv", "src", "alt",
321                                 "bgcolor", "text", "link", "vlink", "alink",
322                                 "media" ])
323                 ],
324                 'quotes',       [
325                         "/\"([^\"\\\\\n]*(\\\\.[^\"\\\\\n]*)*)\"/",     /* double-quoted strings */
326                         "/'([^'\\\\\n]*(\\\\.[^'\\\\\n]*)*)'/"          /* single-quoted strings */
327                 ],
328                 'comments',     [
329                                 [ '/<!--/', '/-->/' ]
330                 ]
331         ]
335 mp.syntax.conf = {
336         'id'            =>      'conf',
337         'name'          =>      'Config file',
338         'filenames'     =>      [ '/\.conf$/', '/\.cfg$/', '/^.*\/?\.[0-9a-z_-]+rc$/' ],
339         'defs'          =>      [
340                 'word1',        [ '/^\[.+\]$/m' ],
341                 'word2',        [ "/^[^:=\n]+[:=]/m" ],
342                 'quotes',       [
343                         "/\"([^\"\\\\\n]*(\\\\.[^\"\\\\\n]*)*)\"/",     /* double-quoted strings */
344                         "/'([^'\\\\\n]*(\\\\.[^'\\\\\n]*)*)'/",         /* single-quoted strings */
345                         "/\b-?[0-9]+\b/",                       /* numbers */
346                         "/\b0x[0-9a-f]+\b/i"                    /* hex numbers */
347                 ],
348                 'comments',     [ "/#.*$/m" ]
349         ]
353 mp.syntax.php = {
354         'id'            =>      'php',
355         'name'          =>      'PHP',
356         'filenames'     =>      [ '/\.php[345]?$/', '/\.inc$/' ],
357         'defs'          =>      [
358                 'word1',        [
359                                 mp.syn_token_list( [
360                                 "and", "array", "as",
361                                 "bool", "boolean", "break", "case", "class",
362                                 "const", "continue", "declare", "default",
363                                 "die", "do", "double", "echo", "else", "elseif",
364                                 "empty", "enddeclare", "endfor", "endforeach",
365                                 "endif", "endswitch", "endwhile", "eval",
366                                 "exit", "extends", "__FILE__", "float", "for",
367                                 "foreach", "function", "cfunction", "global",
368                                 "if", "include", "include_once", "int",
369                                 "integer", "isset", "__LINE__", "list", "new",
370                                 "object", "old_function", "or", "print", "real",
371                                 "require", "require_once", "return",
372                                 "static", "string", "switch", "unset", "use",
373                                 "var", "while", "xor", 'true', 'false' ]
374                                 )
375                 ],
376                 'word2',        [ '/\$\w+/', '/[-=<>:\?\+\*\!\%&\|]+/' ],
377                 'quotes',       [
378                         "/\"([^\"\\\\\n]*(\\\\.[^\"\\\\\n]*)*)\"/",     /* double-quoted strings */
379                         "/'([^'\\\\\n]*(\\\\.[^'\\\\\n]*)*)'/",         /* single-quoted strings */
380                         "/\b-?[0-9]+\b/",                       /* numbers */
381                         "/\b0x[0-9a-f]+\b/i",                   /* hex numbers */
382                         "/\b[0-9[:upper:]_]+\b/",               /* all-caps words */
383                         [ "/`/", "/`/" ]                        /* backticks */
384                 ],
385                 'comments',     [
386                         [ '|/\*|', '|\*/|' ],                   /* C-like */
387                         '|//.*$|m'                              /* C++ */
388                 ]
389         ]
392 mp.syntax.python = {
393         'id'            =>      'python',
394         'name'          =>      'Python',
395         'filenames'     =>      [ '/\.py$/' ],
396         'defs'          =>      [
397                 'word1',        [
398                         mp.syn_token_list( [
399                                 "and", "assert", "break", "class", "continue",
400                                 "def", "del", "elif", "else", "except", "exec",
401                                 "finally", "for", "from", "if", "import", "in",
402                                 "is", "lambda", "not", "or", "pass", "print",
403                                 "raise", "return", "try", "while", "yield"
404                                 ]
405                         )
406                 ],
407                 'word2',        [ '/global/', '/\$\w+/', '/[-=<>:\?\+\*\!\%&\|{}]+/' ],
408                 'quotes',       [
409                         "/\"([^\"\\\\\n]*(\\\\.[^\"\\\\\n]*)*)\"/",     /* double-quoted strings */
410                         "/'([^'\\\\\n]*(\\\\.[^'\\\\\n]*)*)'/",         /* single-quoted strings */
411                         "/\b-?[0-9]+\b/",                       /* numbers */
412                         "/\b0x[0-9a-f]+\b/i",                   /* hex numbers */
413                         "/\b[0-9[:upper:]_]+\b/",               /* all-caps words */
414                         [ "/`/", "/`/" ]                        /* backticks */
415                 ],
416                 'comments',     [ "/#.*$/m", [ '/""".+[^"]$/m', '/"""$/m' ] ]
417         ],
418         'detect'        =>      sub (d) {
419                 /* take the first line */
420                 local f = d.txt.lines[0];
422                 /* is it a 'she-bang'? */
423                 return regex('/^#!\s*/usr/bin/(env )?python/', f);
424         }
427 mp.syntax.ruby = {
428         'id'            =>      'ruby',
429         'name'          =>      'Ruby',
430         'filenames'     =>      [ '/\.rb$/' ],
431         'defs'          =>      [
432                 'word1',        [
433                         mp.syn_token_list( [
434                                 "BEGIN", "END", "alias", "and", "begin",
435                                 "break", "case", "class", "def", "defined",
436                                 "do", "else", "elsif", "end", "ensure", 
437                                 "false", "for", "if", "in", "module", "next",
438                                 "nil", "not", "or", "redo", "rescue", "retry",
439                                 "return", "self", "super", "then", "true",
440                                 "undef", "unless", "until", "when", "while",
441                                 "yield", "require", "include" ]
442                         )
443                 ],
444                 'word2',        [ '/[-=<>:\?\+\*\!\%&\|{}]+/', '/=(begin|end)/' ],
445                 'quotes',       [
446                         "/\"([^\"\\\\\n]*(\\\\.[^\"\\\\\n]*)*)\"/",     /* double-quoted strings */
447                         "/'([^'\\\\\n]*(\\\\.[^'\\\\\n]*)*)'/",         /* single-quoted strings */
448                         "/\b-?[0-9]+\b/",                       /* numbers */
449                         "/\b0x[0-9a-f]+\b/i",                   /* hex numbers */
450                         "/\b[0-9[:upper:]_]+\b/",               /* all-caps words */
451                         [ "/`/", "/`/" ]                        /* backticks */
452                 ],
453                 'comments',     [ "/#.*$/m" ]
454         ],
455         'detect'        =>      sub (d) {
456                 /* take the first line */
457                 local f = d.txt.lines[0];
459                 /* is it a 'she-bang'? */
460                 return regex('/^#!\s*/usr/bin/(env )?ruby/', f);
461         }
464 mp.syntax.diff = {
465         'id'            =>      'diff',
466         'name'          =>      'diff',
467         'filenames'     =>      [ '/\.diff$/', '/\.patch$/' ],
468         'defs'          =>      [
469                 'word1',        [ '/^\+.+$/m' ],
470                 'word2',        [ '/^\-.+$/m' ],
471                 'quotes',       [ '/^@@.+@@$/m' ]
472         ]
475 mp.syntax.commit_msg = {
476         'id'            =>      'commit_msg',
477         'name'          =>      'VCS commit message',
478         'filenames'     =>      [ '/sv[kn]-commit.*\./' ],
479         'defs'          =>      [
480                 'word1',        [ '/^AM? .+$/m' ],
481                 'word2',        [ '/^D .+$/m' ],
482                 'quotes',       [ '/^M .+$/m' ],
483                 'comments',     [ '/^=== .+$/m', '/^--.+$/m' ]
484         ]
487 mp.syntax.po = {
488         'id'            =>      'po',
489         'name'          =>      'Gettext file',
490         'filenames'     =>      [ '/\.po$/' ],
491         'defs'          =>      [
492                 'word1',        [ '/^msgid/m' ],
493                 'word2',        [ '/^msgstr/m' ],
494                 'comments',     [ "/#.*$/m" ],
495                 'quotes',       [
496                         "/\"([^\"\\\\\n]*(\\\\.[^\"\\\\\n]*)*)\"/"      /* double-quoted strings */
497                 ]
498         ]
501 mp.syntax.xml = {
502         'id'            =>      'xml',
503         'name'          =>      'XML / XGML',
504         'filenames'     =>      [ '/\.xml$/', '/\.sgml$/' ],
505         'defs'          =>      [
506                 'word1',        [ '/<[^>]+>/' ],
507                 'word2',        [ '/<\?[^\?]+\?>/' ],
508                 'quotes',       [
509                         "/\"([^\"\\\\\n]*(\\\\.[^\"\\\\\n]*)*)\"/",     /* double-quoted strings */
510                         "/'([^'\\\\\n]*(\\\\.[^'\\\\\n]*)*)'/"          /* single-quoted strings */
511                 ],
512                 'comments',     [
513                                 [ '/<!--/', '/-->/' ]
514                 ]
515         ],
516         'detect'        =>      sub (d) {
517                 /* take the first line */
518                 local f = d.txt.lines[0];
520                 return regex('/<\?xml/', f);
521         }
524 mp.syntax.make_output = {
525         'id'            =>      'make_output',
526         'name'          =>      'Make output',
527         'defs'          =>      [
528                 'word1',        [ "/^.*warning:.*$/m" ],
529                 'word2',        [ "/^.*error:.*$/m" ]
530         ]
533 mp.syntax.euphoria = {
534         'id'            =>      'euphoria',
535         'name'          =>      'euphoria',
536         'filenames'     =>      [ '/\.e$/', '/\.eu$/', '/\.ew$/', '/\.ed$/',
537                                 '/\.ex$/', '/\.exw$/', '/\.exu$/' ],
538         'defs'          =>      [
539                 'word1',        [
540                         mp.syn_token_list( [
541                                 "as", "and", "break", "by", "case", "constant", "continue", "do", "end",
542                                 "else", "elsif", "elsifdef",
543                                 "exit", "entry", "enum", "export", "for", "function", "global", "include",
544                                 "if", "ifdef", "label",
545                                 "not", "or", "procedure", "return", "retry", "switch", "then", "type",
546                                 "to", "while", "with", "without", "xor"
547                         ] )
548                 ],
549                 'word2',        [
550                         mp.syn_token_list( [
551                                 "atom", "integer", "sequence", "object"
552                         ] )
553                 ],
554                 'quotes',       [
555                         "/\"([^\"\\\\\n]*(\\\\.[^\"\\\\\n]*)*)\"/",    /* double-quoted strings */
556                         "/'([^'\\\\\n]*(\\\\.[^'\\\\\n]*)*)'/",        /* single-quoted strings */
557                         "/\b-?#[0-9A-F]+\b/",                /* hex numbers */
558                         "/\b-?[0-9]+\b/",                /* numbers */
559                         "/\b[0-9[:upper:]_]+\b/"            /* all-caps words */
560                 ],
561                 'comments',             [ "/--.*$/m" ]
562         ]
565 sub mp.detect_syntax(doc)
566 /* tries to detect the syntax of a document */
568         doc.syntax = NULL;
570         /* loops the syntax highlight definitions */
571         foreach (n, keys(mp.syntax)) {
572                 local s = mp.syntax[n];
574                 /* test the extensions */
575                 foreach (ext, s.filenames) {
576                         if (regex(ext, doc.name)) {
577                                 doc.syntax = s;
578                                 return;
579                         }
580                 }
581         }
583         /* not by extension? try the 'detect' subroutine */
584         foreach (n, keys(mp.syntax)) {
585                 local s = mp.syntax[n];
587                 if (is_exec(s.detect) && s.detect(doc)) {
588                         doc.syntax = s;
589                         return;
590                 }
591         }
595 sub mp.help(doc, word)
597         local h;
599         foreach (c, doc.syntax.help) {
600                 local f;
602                 /* format the command */
603                 c = sprintf(c, word);
605                 /* pipe from it */
606                 if ((f = popen(c, "r")) != NULL) {
607                         local l;
608                         h = [];
610                         while ((l = read(f)) != NULL)
611                                 push(h, mp.chomp(l));
613                         /* fails? */
614                         if (pclose(f) != 0)
615                                 h = NULL;
616                 }
618                 /* is there already help? don't look for more */
619                 if (h != NULL)
620                         break;
621         }
623         return h;