Suppressed error in window initialisation.
[mp-5.x.git] / mp_syntax.mpsl
blobc14075e2eb64f1ce831767576e37fcd34f03055a
1 /*
3     Minimum Profit 5.x
4     A Programmer's Text Editor
6     Syntax highlight definitions.
8     Copyright (C) 1991-2009 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 mp.actions['section_list'] = sub (d) {
52         local l = mp.section_list(d);
54         if (l == NULL)
55                 mp.alert(L("No detection for sections for this mode."));
56         else {
57                 if (size(l) == 0)
58                         mp.alert(L("No sections were found in this document."));
59                 else {
60                         local r = mp.form( [
61                         {
62                                 'label' => L("Section list"),
63                                 'type'  => 'list',
64                                 'list'  => map(sub (e) { e[0]; }, l),
65                                 'value' => 0
66                         }
67                         ]);
69                         if (r != NULL) {
70                                 mp.search_set_y(d, l[r[0]][1]);
71                                 mp.set_x(d, 0);
72                         }
73                 }
74         }
77 /** default key bindings **/
79 mp.keycodes['f1']       =       "help";
80 mp.keycodes['ctrl-d']   =       "section_list";
82 /** action descriptions **/
84 mp.actdesc['help']              = LL("Help on word over cursor");
85 mp.actdesc['section_list']      = LL("Section list...");
87 /* data */
89 mp.syntax = {};
91 /** syntax definitions **/
93 sub mp.syn_token_list(l) { '/\b(' ~ join("|", l) ~ ')\b/'; }
95 mp.syntax.c = {
96         'id'            =>      'c',
97         'name'          =>      'C / C++',
98         'filenames'     =>      [ '/\.c$/i', '/\.h$/i', '/\.l$/i', '/\.y$/i', '/\.d$/i',
99                                 '/\.cpp$/i', '/\.hpp$/i', '/\.c++$/i', '/\.xpm$/i' ],
100         'help'          =>      [ "man 2 %s", "man 3 %s" ],
101         'defs'          =>      [
102                 'word1',        [
103                                 mp.syn_token_list( [
104                                 "for", "while", "if", "switch", "case", "do",
105                                 "else", "break", "continue", "return",
106                                 "default", "goto", "main", "fopen", "fclose",
107                                 "fgets", "fgetc", "fputs", "fputc", "fprintf",
108                                 "putc", "printf", "sprintf", "strcpy", "strcat",
109                                 "strcmp", "strncmp", "strtok", "stricmp", "strchr",
110                                 "strrchr", "strlen", "memcmp", "memcpy", "malloc",
111                                 "free", "strncpy", "strncat", "snprintf", "strstr",
112                                 "memset", "memcpy", "va_start", "va_end", "vsprintf",
113                                 "vsnprintf", "atoi", "qsort", "bsearch", "getenv",
114                                 "fscanf", "popen", "pclose", "realloc", "fread",
115                                 "fwrite", "fseek", '\{', '\}', "putchar", "fflush",
116                                 "wcscmp", "swprintf", "wmemcpy", "swscanf", "sscanf",
117                                 "wcslen", "wmemset", "wcscpy", "wcsncpy", "wcscoll",
118                                 "mbstowcs", "wcstombs", "wprintf", "wcschr",
119                                 "wcsrchr", "wcsstr", "strdup", "wctomb", "mbtowc",
120                                 "mbrtowc", "wcrtomb", "open", "close", "read",
121                                 "write", "pipe", "fork", "dup", "dup2", "wait",
122                                 "execl", "execlp", "execle", "execv", "execvp",
123                                 "class", "template", "new", "delete", "emit",
124                                 "using", "namespace", "try", "catch", "throw"
125                                 ])
126                 ],
127                 'word2',        [
128                                 mp.syn_token_list( [
129                                 "char", "int", "long", "struct", "union", "const",
130                                 "void", "unsigned", "signed", "auto", "volatile",
131                                 "enum", "typedef", "float", "double", "extern",
132                                 "register", "short", "sizeof", "static", "far",
133                                 "near", "defined", "va_list", "size_t", "wchar_t",
134                                 "iconv_t", "virtual", "friend", "operator",
135                                 "public", "protected", "private", "slots", "signals"
136                                  ]),
137                                 '/[-=<>:\?\+\*\/\!\%&\|]+/'
138                 ],
139                 'quotes',       [
140                         /* from http://ad.hominem.org/log/2005/05/quoted_strings.php */
141                         "/\"([^\"\\\\\n]*(\\\\.[^\"\\\\\n]*)*)\"/",     /* double-quoted strings */
142                         "/'([^'\\\\\n]*(\\\\.[^'\\\\\n]*)*)'/",         /* single-quoted strings */
143                         "/\b-?[0-9]+\b/",                       /* numbers */
144                         "/\b[0-9]+e[0-9]+\b/",                  /* numbers in exp format */
145                         "/\b0x[0-9a-f]+\b/i",                   /* hex numbers */
146                         "/\b[0-9[:upper:]_]+\b/"                /* all-caps words */
147                 ],
148                 'comments',     [
149                         [ '|/\*|', '|\*/|' ],                   /* C-like */
150                         '|//.*$|m',                             /* C++ */
151                         '/^\s*#[a-z]+/m'                        /* CPP directives */
152                 ],
153                 'documentation',        [
154                         [ "|/\*\*\n|", '|\*/|' ],               /* mp_doccer */
155                         '/^/\*\*.*\*\*/$/m'                     /* section mark */
156                 ]
157         ],
158         'section'       =>      [ '/(^\/\*\*.*\*\*\/$|^#pragma mark|^\w.*\)$)/' ]
161 mp.syntax.rc = {
162         'id'            =>      'rc',
163         'name'          =>      'Resource file',
164         'filenames'     =>      [ '/\.rc$/i' ],
165         'defs'          =>      [
166                 'word1',        [ ],
167                 'word2',        [ ],
168                 'quotes',       [
169                         /* from http://ad.hominem.org/log/2005/05/quoted_strings.php */
170                         "/\"([^\"\\\\\n]*(\\\\.[^\"\\\\\n]*)*)\"/",     /* double-quoted strings */
171                         "/'([^'\\\\\n]*(\\\\.[^'\\\\\n]*)*)'/",         /* single-quoted strings */
172                         "/\b-?[0-9]+\b/",                       /* numbers */
173                         "/\b0x[0-9a-f]+\b/i",                   /* hex numbers */
174                         "/\b[0-9[:upper:]_]+\b/"                /* all-caps words */
175                 ],
176                 'comments',     [
177                         [ '|/\*|', '|\*/|' ],                   /* C-like */
178                         '|//.*$|m',                             /* C++ */
179                         '/^\s*#[a-z]+/m'                        /* CPP directives */
180                 ]
181         ]
184 mp.syntax.perl = {
185         'id'            =>      'perl',
186         'name'          =>      'Perl',
187         'filenames'     =>      [ '/\.pl$/i', '/\.pm$/i' ],
188         'help'          =>      [ 'perldoc -f %s', 'perldoc %s' ],
189         'help_word_regex' =>    '/[A-Z_][A-Z0-9_:]*/i',
190         'defs'  =>      [
191                 'word1',        [
192                                 mp.syn_token_list( [
193                                 "for", "if", "next", "last", "else", "elsif",
194                                 "unless", "while", "shift", "unshift", "push",
195                                 "pop", "delete", "new", "bless", "return",
196                                 "foreach", "keys", "values", "sort", "grep",
197                                 "tr", "length", "system", "exec", "fork", "map",
198                                 "print", "write", "open", "close", "chop",
199                                 "chomp", "exit", "sleep", "split", "join",
200                                 "sub", "printf", "sprintf", "s", "glob",
201                                 "scalar", "my", "local", "undef", "defined",
202                                 "use", "package", "require", "ref", "can", "isa",
203                                 "qw", "qq", "eq", "ne", "or", "exists",
204                                 "and", "not", "import", "our", "caller" ]),
205                                 '/->/'
206                 ],
207                 'word2',        [
208                                 '/[:\?\+\*\/\!\$@\%&\|~\.]+/',
209                                 '/[\$@%]\w+/'
210                 ],
211                 'quotes',       [
212                         /* from http://ad.hominem.org/log/2005/05/quoted_strings.php */
213                         "/\"([^\"\\\\\n]*(\\\\.[^\"\\\\\n]*)*)\"/",     /* double-quoted strings */
214                         "/'([^'\\\\\n]*(\\\\.[^'\\\\\n]*)*)'/",         /* single-quoted strings */
215                         "/\b-?[0-9]+\b/",                       /* numbers */
216                         "/\b0x[0-9a-f]+\b/i",                   /* hex numbers */
217                         "/\b[0-9[:upper:]_]+\b/",               /* all-caps words */
218                         [ "/q\(/", "/\)/" ],                    /* quote */
219                         [ "/qw\(/", "/\)/" ],                   /* quote word */
220                         '/\w+\s*=>/',                           /* barewords as hash keys 1 */
221                         '/\{\s*-?\w+\s*\}/',                    /* barewords as hash keys 2 */
222                         [ "/`/", "/`/" ],                       /* backticks */
223                         [ "/<<[\"']?EOF.*$/m", "/^EOF$/m" ]     /* 'document here' */
224                 ],
225                 /* color all => as word2 */
226                 'word2',        [ '/=>/' ],
227                 /* color curly brackets as word */
228                 'word',         [ '/[{}]/' ],
229                 'comments',     [
230                         "/#.*$/m"                               /* Comments */
231                 ],
232                 'documentation',        [
233                         "/__END__\n.*$/",                       /* __END__ */
234                         '/^## .*$/m',                           /* section mark */
235                         [ "/^=(head[1-4]|over|item|back|pod|begin|end|for)/m",
236                                 "/^=cut$/m" ]                   /* POD */
237                 ]       
238         ],
239         'detect'        =>      sub (d) {
240                 /* take the first line */
241                 local f = d.txt.lines[0];
243                 /* is it a 'she-bang' for Perl? */
244                 return regex('/^#!\s*/usr/bin/(env )?perl/', f);
245         },
246         'section'       =>      [ '/(^sub \w+|^package|^## )/' ]
250 mp.syntax.mpsl = {
251         'id'            =>      'mpsl',
252         'name'          =>      'MPSL',
253         'filenames'     =>      [ '/\.mpsl?$/i' ],
254         'defs'          =>      [
255                 'word1',        [
256                                 mp.syn_token_list( [
257                                         'if', 'else', 'while', 'foreach',
258                                         'sub', 'break', 'return', 'eq', 'ne' ]),
259                                 mp.syn_token_list( keys(MPSL.CORE) ),
260                                 '/[\{\}]/'
261                 ],
262                 'word2',        [
263                                 "/(NULL|local)/",
264                                 '/[-=<>:\?\+\*\/\!\%&\|]+/'
265                 ],
266                 'quotes',       [
267                         /* from http://ad.hominem.org/log/2005/05/quoted_strings.php */
268                         "/\"([^\"\\\\\n]*(\\\\.[^\"\\\\\n]*)*)\"/",     /* double-quoted strings */
269                         "/'([^'\\\\\n]*(\\\\.[^'\\\\\n]*)*)'/",         /* single-quoted strings */
270                         "/\b-?[0-9]+\b/",                       /* numbers */
271                         "/\b0x[0-9a-f]+\b/i",                   /* hex numbers */
272                         "/\b[0-9[:upper:]_]+\b/"                /* all-caps words */
273                 ],
274                 'comments',     [
275                         [ '|/\*|', '|\*/|' ]                    /* C-like */
276                 ],
277                 'documentation',        [
278                         [ "|/\*\*\n|", '|\*/|' ],               /* mp_doccer */
279                         '/^/\*\*.*\*\*/$/m'                     /* section mark */
280                 ]
281         ],
282         'section'       =>      [ '/(^sub \w+|^\/\*\*.*\*\*\/$)/' ]
285 mp.syntax.sh = {
286         'id'            =>      'sh',
287         'name'          =>      'Shell script',
288         'filenames'     =>      [ '/\.sh$/i', '/makefile/i' ],
289         'defs'          =>      [
290                 'word1',        [
291                                 mp.syn_token_list( [
292                                 "if", "then", "else", "elif",
293                                 "fi", "case", "do", "done", "esac",
294                                 "for", "until", "while", "break",
295                                 "in", "source", "alias", "cd",
296                                 "continue", "echo", "eval", "exec",
297                                 "exit", "export", "kill", "logout",
298                                 "printf", "pwd", "read", "return",
299                                 "shift", "test", "trap", "ulimit",
300                                 "umask", "unset", "wait", "cp", "rm" ]),
301                                 '/[\{\}]/'
303                 ],
304                 'word2',        [
305                                 '/\b(local|let|set)\b/',
306                                 '/[-=<>:\?\+\*\!\%&\|]+/',
307                                 '/\$\w+/',
308                                 '/\$\{\w+\}/',
309                                 "/\b[0-9[:upper:]_]+\b/"        /* all-caps words */
310                 ],
311                 'quotes',       [
312                         "/\"([^\"\\\\\n]*(\\\\.[^\"\\\\\n]*)*)\"/",     /* double-quoted strings */
313                         "/'([^'\\\\\n]*(\\\\.[^'\\\\\n]*)*)'/",         /* single-quoted strings */
314                         "/\b-?[0-9]+\b/",                       /* numbers */
315                         "/\b0x[0-9a-f]+\b/i",                   /* hex numbers */
316                         "/\([A-Za-z0-9_]+\)/",                  /* parens */
317                         [ "/`/", "/`/" ],                       /* backticks */
318                         [ "/<<[\"']?EOF[\"']?;$/m", "/^EOF$/m" ]        /* 'document here' */
319                 ],
320                 'comments',     [ "/#.*$/m" ]
321         ],
322         'detect'        =>      sub (d) {
323                 /* take the first line */
324                 local f = d.txt.lines[0];
326                 /* is it a 'she-bang' for usual shells? */
327                 return regex('/^#!\s*/bin/(sh|bash|csh|dash|ksh)/', f) ||
328                        regex('/^#!\s*/usr/bin/make -f/', f);
329         },
330         'section'       =>      [ '/(^\w+\(\))/', '/^[A-Za-z0-9_\.-]+:/' ]
334 mp.syntax.html = {
335         'id'            =>      'html',
336         'name'          =>      'HTML',
337         'filenames'     =>      [ '/\.html$/i', '/\.htm$/i' ],
338         'defs'          =>      [
339                 'word1',        [
340                                 "/<[\/]?[ \t]*(" ~
341                                 join("|", [
342                                 "a", "abbr", "acronym", "address",
343                                 "area", "b", "base", "bdo", "big",
344                                 "blockquote", "body", "br", "button",
345                                 "caption", "center", "cite", "code", "col",
346                                 "colgroup", "dd", "del", "dfn", "div",
347                                 "dl", "dt", "em", "fieldset", "form",
348                                 "h1", "h2", "h3", "h4", "h5", "h6",
349                                 "head", "hr", "html", "i", "img",
350                                 "input", "ins", "kbd", "label", "legend",
351                                 "li", "link", "map", "meta", "noscript",
352                                 "object", "ol", "optgroup", "option",
353                                 "p", "param", "pre", "q", "samp",
354                                 "script", "select", "small", "span",
355                                 "strong", "style", "sub", "sup", "table",
356                                 "tbody", "td", "textarea", "tfoot", "th",
357                                 "thead", "title", "tr", "tt", "ul",
358                                 "var" ] ) ~
359                                 ")[^<>]*>/i"
360                 ],
361                 'word2',        [
362                                 mp.syn_token_list( [
363                                  "!DOCTYPE", "class", "type",
364                                 "cellspacing", "cellpadding",
365                                 "href", "align", "valign", "name", "lang",
366                                 "value", "action", "width", "height",
367                                 "content", "http-equiv", "src", "alt",
368                                 "bgcolor", "text", "link", "vlink", "alink",
369                                 "media" ])
370                 ],
371                 'quotes',       [
372                         "/\"([^\"\\\\\n]*(\\\\.[^\"\\\\\n]*)*)\"/",     /* double-quoted strings */
373                         "/'([^'\\\\\n]*(\\\\.[^'\\\\\n]*)*)'/"          /* single-quoted strings */
374                 ],
375                 'comments',     [
376                                 [ '/<!--/', '/-->/' ]
377                 ]
378         ],
379         'section'       =>      [ '/<\s*h[0-9]\s*>/' ]
383 mp.syntax.conf = {
384         'id'            =>      'conf',
385         'name'          =>      'Config file',
386         'filenames'     =>      [ '/\.conf$/i', '/\.cfg$/i', '/^.*\/?\.[0-9a-z_-]+rc$/i' ],
387         'defs'          =>      [
388                 'word1',        [ '/^\[.+\]$/m' ],
389                 'word2',        [ "/^[^:=\n]+[:=]/m" ],
390                 'quotes',       [
391                         "/\"([^\"\\\\\n]*(\\\\.[^\"\\\\\n]*)*)\"/",     /* double-quoted strings */
392                         "/'([^'\\\\\n]*(\\\\.[^'\\\\\n]*)*)'/",         /* single-quoted strings */
393                         "/\b-?[0-9]+\b/",                       /* numbers */
394                         "/\b0x[0-9a-f]+\b/i"                    /* hex numbers */
395                 ],
396                 'comments',     [ "/#.*$/m" ]
397         ]
401 mp.syntax.php = {
402         'id'            =>      'php',
403         'name'          =>      'PHP',
404         'filenames'     =>      [ '/\.php[345]?$/i', '/\.inc$/i' ],
405         'defs'          =>      [
406                 'word1',        [
407                                 mp.syn_token_list( [
408                                 "and", "array", "as",
409                                 "bool", "boolean", "break", "case", "class",
410                                 "const", "continue", "declare", "default",
411                                 "die", "do", "double", "echo", "else", "elseif",
412                                 "empty", "enddeclare", "endfor", "endforeach",
413                                 "endif", "endswitch", "endwhile", "eval",
414                                 "exit", "extends", "__FILE__", "float", "for",
415                                 "foreach", "function", "cfunction", "global",
416                                 "if", "include", "include_once", "int",
417                                 "integer", "isset", "__LINE__", "list", "new",
418                                 "object", "old_function", "or", "print", "real",
419                                 "require", "require_once", "return",
420                                 "static", "string", "switch", "unset", "use",
421                                 "var", "while", "xor", 'true', 'false' ]
422                                 )
423                 ],
424                 'word2',        [ '/\$\w+/', '/[-=<>:\?\+\*\!\%&\|]+/' ],
425                 'quotes',       [
426                         "/\"([^\"\\\\\n]*(\\\\.[^\"\\\\\n]*)*)\"/",     /* double-quoted strings */
427                         "/'([^'\\\\\n]*(\\\\.[^'\\\\\n]*)*)'/",         /* single-quoted strings */
428                         "/\b-?[0-9]+\b/",                       /* numbers */
429                         "/\b0x[0-9a-f]+\b/i",                   /* hex numbers */
430                         "/\b[0-9[:upper:]_]+\b/",               /* all-caps words */
431                         [ "/`/", "/`/" ]                        /* backticks */
432                 ],
433                 'comments',     [
434                         [ '|/\*|', '|\*/|' ],                   /* C-like */
435                         '|//.*$|m'                              /* C++ */
436                 ]
437         ]
440 mp.syntax.python = {
441         'id'            =>      'python',
442         'name'          =>      'Python',
443         'filenames'     =>      [ '/\.py$/i' ],
444         'defs'          =>      [
445                 'word1',        [
446                         mp.syn_token_list( [
447                                 "and", "assert", "break", "class", "continue",
448                                 "def", "del", "elif", "else", "except", "exec",
449                                 "finally", "for", "from", "if", "import", "in",
450                                 "is", "lambda", "not", "or", "pass", "print",
451                                 "raise", "return", "try", "while", "yield"
452                                 ]
453                         )
454                 ],
455                 'word2',        [ '/global/', '/\$\w+/', '/[-=<>:\?\+\*\!\%&\|{}]+/' ],
456                 'quotes',       [
457                         "/\"([^\"\\\\\n]*(\\\\.[^\"\\\\\n]*)*)\"/",     /* double-quoted strings */
458                         "/'([^'\\\\\n]*(\\\\.[^'\\\\\n]*)*)'/",         /* single-quoted strings */
459                         "/\b-?[0-9]+\b/",                       /* numbers */
460                         "/\b0x[0-9a-f]+\b/i",                   /* hex numbers */
461                         "/\b[0-9[:upper:]_]+\b/",               /* all-caps words */
462                         [ "/`/", "/`/" ]                        /* backticks */
463                 ],
464                 'comments',             [ "/#.*$/m" ],
465                 'documentation',        [ [ '/""".+[^"]$/m', '/"""$/m' ] ]
466         ],
467         'detect'        =>      sub (d) {
468                 /* take the first line */
469                 local f = d.txt.lines[0];
471                 /* is it a 'she-bang'? */
472                 return regex('/^#!\s*/usr/bin/(env )?python/', f);
473         },
474         'section'       =>      [ '/^[ \t]*def/' ]
477 mp.syntax.ruby = {
478         'id'            =>      'ruby',
479         'name'          =>      'Ruby',
480         'filenames'     =>      [ '/\.rb$/i' ],
481         'defs'          =>      [
482                 'word1',        [
483                         mp.syn_token_list( [
484                                 "BEGIN", "END", "alias", "and", "begin",
485                                 "break", "case", "class", "def", "defined",
486                                 "do", "else", "elsif", "end", "ensure", 
487                                 "false", "for", "if", "in", "module", "next",
488                                 "nil", "not", "or", "redo", "rescue", "retry",
489                                 "return", "self", "super", "then", "true",
490                                 "undef", "unless", "until", "when", "while",
491                                 "yield", "require", "include" ]
492                         )
493                 ],
494                 'word2',        [ '/[-=<>:\?\+\*\!\%&\|{}]+/', '/=(begin|end)/' ],
495                 'quotes',       [
496                         "/\"([^\"\\\\\n]*(\\\\.[^\"\\\\\n]*)*)\"/",     /* double-quoted strings */
497                         "/'([^'\\\\\n]*(\\\\.[^'\\\\\n]*)*)'/",         /* single-quoted strings */
498                         "/\b-?[0-9]+\b/",                       /* numbers */
499                         "/\b0x[0-9a-f]+\b/i",                   /* hex numbers */
500                         "/\b[0-9[:upper:]_]+\b/",               /* all-caps words */
501                         [ "/`/", "/`/" ]                        /* backticks */
502                 ],
503                 'comments',     [ "/#.*$/m" ]
504         ],
505         'detect'        =>      sub (d) {
506                 /* take the first line */
507                 local f = d.txt.lines[0];
509                 /* is it a 'she-bang'? */
510                 return regex('/^#!\s*/usr/bin/(env )?ruby/', f);
511         }
514 mp.syntax.diff = {
515         'id'            =>      'diff',
516         'name'          =>      'diff',
517         'filenames'     =>      [ '/\.diff$/i', '/\.patch$/i' ],
518         'defs'          =>      [
519                 'word1',        [ '/^\+.+$/m' ],
520                 'word2',        [ '/^\-.+$/m' ],
521                 'quotes',       [ '/^@@.+@@$/m' ]
522         ],
523         'section'       =>      [ '/^--- ' ]
526 mp.syntax.commit_msg = {
527         'id'            =>      'commit_msg',
528         'name'          =>      'VCS commit message',
529         'filenames'     =>      [ '/sv[kn]-commit.*\./' ],
530         'defs'          =>      [
531                 'word1',        [ '/^AM? .+$/m' ],
532                 'word2',        [ '/^D .+$/m' ],
533                 'quotes',       [ '/^M .+$/m' ],
534                 'comments',     [ '/^=== .+$/m', '/^--.+$/m' ]
535         ]
538 mp.syntax.po = {
539         'id'            =>      'po',
540         'name'          =>      'Gettext file',
541         'filenames'     =>      [ '/\.po$/i' ],
542         'defs'          =>      [
543                 'word1',        [ '/^msgid/m' ],
544                 'word2',        [ '/^msgstr/m' ],
545                 'comments',     [ "/#.*$/m" ],
546                 'quotes',       [
547                         "/\"([^\"\\\\\n]*(\\\\.[^\"\\\\\n]*)*)\"/"      /* double-quoted strings */
548                 ]
549         ]
552 mp.syntax.xml = {
553         'id'            =>      'xml',
554         'name'          =>      'XML / XGML',
555         'filenames'     =>      [ '/\.xml$/i', '/\.sgml$/i' ],
556         'defs'          =>      [
557                 'word1',        [ '/<[^>]+>/' ],
558                 'word2',        [ '/<\?[^\?]+\?>/' ],
559                 'quotes',       [
560                         "/\"([^\"\\\\\n]*(\\\\.[^\"\\\\\n]*)*)\"/",     /* double-quoted strings */
561                         "/'([^'\\\\\n]*(\\\\.[^'\\\\\n]*)*)'/"          /* single-quoted strings */
562                 ],
563                 'comments',     [
564                                 [ '/<!--/', '/-->/' ]
565                 ]
566         ],
567         'detect'        =>      sub (d) {
568                 /* take the first line */
569                 local f = d.txt.lines[0];
571                 return regex('/<\?xml/', f);
572         }
575 mp.syntax.make_output = {
576         'id'            =>      'make_output',
577         'name'          =>      'Make output',
578         'defs'          =>      [
579                 'word1',        [ "/^.*warning:.*$/m" ],
580                 'word2',        [ "/^.*error:.*$/m" ]
581         ]
584 mp.syntax.euphoria = {
585         'id'            =>      'euphoria',
586         'name'          =>      'euphoria',
587         'filenames'     =>      [ '/\.e$/', '/\.eu$/', '/\.ew$/', '/\.ed$/',
588                                 '/\.ex$/', '/\.exw$/', '/\.exu$/' ],
589         'defs'          =>      [
590                 'word1',        [
591                         mp.syn_token_list( [
592                                 "as", "and", "break", "by", "case", "constant", "continue", "do", "end",
593                                 "else", "elsif", "elsifdef",
594                                 "exit", "entry", "enum", "export", "for", "function", "global", "include",
595                                 "if", "ifdef", "label",
596                                 "not", "or", "procedure", "return", "retry", "switch", "then", "type",
597                                 "to", "while", "with", "without", "xor"
598                         ] )
599                 ],
600                 'word2',        [
601                         mp.syn_token_list( [
602                                 "atom", "integer", "sequence", "object"
603                         ] )
604                 ],
605                 'quotes',       [
606                         "/\"([^\"\\\\\n]*(\\\\.[^\"\\\\\n]*)*)\"/",    /* double-quoted strings */
607                         "/'([^'\\\\\n]*(\\\\.[^'\\\\\n]*)*)'/",        /* single-quoted strings */
608                         "/\b-?#[0-9A-F]+\b/",                /* hex numbers */
609                         "/\b-?[0-9]+\b/",                /* numbers */
610                         "/\b[0-9[:upper:]_]+\b/"            /* all-caps words */
611                 ],
612                 'comments',             [ "/--.*$/m" ]
613         ],
614         'section'       =>      [ '/^[ \t]*(global|export)*[ \t]*(function|procedure)/' ]
618 mp.syntax.mp_templates = {
619         'id'            => 'mp_templates',
620         'name'          => 'Minimum Profit template file',
621         'filenames'     => [ '/\.mp_templates$/' ],
622         'defs'          => [
623                 'documentation',        [ '/^%%.*$/m' ]
624         ],
625         'section'       => [ '/^%%/' ]
629 mp.syntax.hex_view = {
630         'id'            => 'hex_view',
631         'name'          => 'Hexadecimal view',
632         'defs'          => [
633                 'word1',                [ "/^\| [0-9A-F]+ \|/m" ],
634                 'word2',                [ "/\|/" ]
635         ]
639 /** code **/
641 sub mp.detect_syntax(doc)
642 /* tries to detect the syntax of a document */
644         doc.syntax = NULL;
646         /* loops the syntax highlight definitions */
647         foreach (n, keys(mp.syntax)) {
648                 local s = mp.syntax[n];
650                 /* test the extensions */
651                 foreach (ext, s.filenames) {
652                         if (regex(ext, doc.name)) {
653                                 doc.syntax = s;
654                                 return;
655                         }
656                 }
657         }
659         /* not by extension? try the 'detect' subroutine */
660         foreach (n, keys(mp.syntax)) {
661                 local s = mp.syntax[n];
663                 if (is_exec(s.detect) && s.detect(doc)) {
664                         doc.syntax = s;
665                         return;
666                 }
667         }
671 sub mp.help(doc, word)
673         local h;
675         foreach (c, doc.syntax.help) {
676                 local f;
678                 /* format the command */
679                 c = sprintf(c, word);
681                 /* pipe from it */
682                 if ((f = popen(c, "r")) != NULL) {
683                         local l;
684                         h = [];
686                         while ((l = read(f)) != NULL)
687                                 push(h, mp.chomp(l));
689                         /* fails? */
690                         if (pclose(f) != 0)
691                                 h = NULL;
692                 }
694                 /* is there already help? don't look for more */
695                 if (h != NULL)
696                         break;
697         }
699         return h;
704  * mp.section_list - Returns the list of sections of a document.
705  * @doc: the document
707  * Applies the `section' array of regular expressions of the
708  * document's syntax definition and returns it as an array of
709  * line and line number pairs.
711  * If the document has no syntax highlight definition, or it has
712  * one without a `section' definition, NULL is returned. Otherwise,
713  * an array of line, line number pairs is returned (it can be
714  * an empty list if the document has no recognizable sections).
715  */
716 sub mp.section_list(doc)
718         local r;
720         if (doc.syntax.section) {
721                 local n, l;
723                 r = [];
725                 while ((l = doc.txt.lines[n]) != NULL) {
726                         foreach (ex, doc.syntax.section) {
727                                 if (regex(ex, l)) {
728                                         push(r, [ l, n ]);
729                                         break;
730                                 }
731                         }
733                         n++;
734                 }
735         }
737         return r;