2
* ***** BEGIN GPL LICENSE BLOCK *****
4
* This program is free software; you can redistribute it and/or
5
* modify it under the terms of the GNU General Public License
6
* as published by the Free Software Foundation; either version 2
7
* of the License, or (at your option) any later version.
9
* This program is distributed in the hope that it will be useful,
10
* but WITHOUT ANY WARRANTY; without even the implied warranty of
11
* GNU General Public License for more details.
13
* You should have received a copy of the GNU General Public License
14
* along with this program; if not, write to the Free Software Foundation,
15
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
17
* The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
18
* All rights reserved.
20
* The Original Code is: all of this file.
22
* Contributor(s): none yet.
24
* ***** END GPL LICENSE BLOCK *****
27
/** \file blender/editors/space_text/text_format_lua.c
33
#include "BLI_blenlib.h"
35
#include "DNA_text_types.h"
36
#include "DNA_space_types.h"
40
#include "text_format.h"
42
/* *** Lua Keywords (for format_line) *** */
44
/* Checks the specified source string for a Lua keyword (minus boolean & 'nil').
45
* This name must start at the beginning of the source string and must be
46
* followed by a non-identifier (see text_check_identifier(char)) or null char.
48
* If a keyword is found, the length of the matching word is returned.
49
* Otherwise, -1 is returned.
52
* http://www.lua.org/manual/5.1/manual.html#2.1
55
static int txtfmt_lua_find_keyword(const char *string)
59
if (STR_LITERAL_STARTSWITH(string, "and", len)) i = len;
60
else if (STR_LITERAL_STARTSWITH(string, "break", len)) i = len;
61
else if (STR_LITERAL_STARTSWITH(string, "do", len)) i = len;
62
else if (STR_LITERAL_STARTSWITH(string, "else", len)) i = len;
63
else if (STR_LITERAL_STARTSWITH(string, "elseif", len)) i = len;
64
else if (STR_LITERAL_STARTSWITH(string, "end", len)) i = len;
65
else if (STR_LITERAL_STARTSWITH(string, "for", len)) i = len;
66
else if (STR_LITERAL_STARTSWITH(string, "function", len)) i = len;
67
else if (STR_LITERAL_STARTSWITH(string, "if", len)) i = len;
68
else if (STR_LITERAL_STARTSWITH(string, "in", len)) i = len;
69
else if (STR_LITERAL_STARTSWITH(string, "local", len)) i = len;
70
else if (STR_LITERAL_STARTSWITH(string, "not", len)) i = len;
71
else if (STR_LITERAL_STARTSWITH(string, "or", len)) i = len;
72
else if (STR_LITERAL_STARTSWITH(string, "repeat", len)) i = len;
73
else if (STR_LITERAL_STARTSWITH(string, "return", len)) i = len;
74
else if (STR_LITERAL_STARTSWITH(string, "then", len)) i = len;
75
else if (STR_LITERAL_STARTSWITH(string, "until", len)) i = len;
76
else if (STR_LITERAL_STARTSWITH(string, "while", len)) i = len;
79
/* If next source char is an identifier (eg. 'i' in "definate") no match */
80
if (i == 0 || text_check_identifier(string[i]))
85
/* Checks the specified source string for a Lua special name/function. This
86
* name must start at the beginning of the source string and must be followed
87
* by a non-identifier (see text_check_identifier(char)) or null character.
89
* If a special name is found, the length of the matching name is returned.
90
* Otherwise, -1 is returned.
93
* http://www.lua.org/manual/5.1/manual.html#5.1
96
static int txtfmt_lua_find_specialvar(const char *string)
100
if (STR_LITERAL_STARTSWITH(string, "assert", len)) i = len;
101
else if (STR_LITERAL_STARTSWITH(string, "collectgarbage", len)) i = len;
102
else if (STR_LITERAL_STARTSWITH(string, "dofile", len)) i = len;
103
else if (STR_LITERAL_STARTSWITH(string, "error", len)) i = len;
104
else if (STR_LITERAL_STARTSWITH(string, "_G", len)) i = len;
105
else if (STR_LITERAL_STARTSWITH(string, "getfenv", len)) i = len;
106
else if (STR_LITERAL_STARTSWITH(string, "getmetatable", len)) i = len;
107
else if (STR_LITERAL_STARTSWITH(string, "__index", len)) i = len;
108
else if (STR_LITERAL_STARTSWITH(string, "ipairs", len)) i = len;
109
else if (STR_LITERAL_STARTSWITH(string, "load", len)) i = len;
110
else if (STR_LITERAL_STARTSWITH(string, "loadfile", len)) i = len;
111
else if (STR_LITERAL_STARTSWITH(string, "loadstring", len)) i = len;
112
else if (STR_LITERAL_STARTSWITH(string, "next", len)) i = len;
113
else if (STR_LITERAL_STARTSWITH(string, "pairs", len)) i = len;
114
else if (STR_LITERAL_STARTSWITH(string, "pcall", len)) i = len;
115
else if (STR_LITERAL_STARTSWITH(string, "print", len)) i = len;
116
else if (STR_LITERAL_STARTSWITH(string, "rawequal", len)) i = len;
117
else if (STR_LITERAL_STARTSWITH(string, "rawget", len)) i = len;
118
else if (STR_LITERAL_STARTSWITH(string, "rawset", len)) i = len;
119
else if (STR_LITERAL_STARTSWITH(string, "select", len)) i = len;
120
else if (STR_LITERAL_STARTSWITH(string, "setfenv", len)) i = len;
121
else if (STR_LITERAL_STARTSWITH(string, "setmetatable", len)) i = len;
122
else if (STR_LITERAL_STARTSWITH(string, "tonumber", len)) i = len;
123
else if (STR_LITERAL_STARTSWITH(string, "tostring", len)) i = len;
124
else if (STR_LITERAL_STARTSWITH(string, "type", len)) i = len;
125
else if (STR_LITERAL_STARTSWITH(string, "unpack", len)) i = len;
126
else if (STR_LITERAL_STARTSWITH(string, "_VERSION", len)) i = len;
127
else if (STR_LITERAL_STARTSWITH(string, "xpcall", len)) i = len;
130
/* If next source char is an identifier (eg. 'i' in "definate") no match */
131
if (i == 0 || text_check_identifier(string[i]))
136
static int txtfmt_lua_find_bool(const char *string)
140
if (STR_LITERAL_STARTSWITH(string, "nil", len)) i = len;
141
else if (STR_LITERAL_STARTSWITH(string, "true", len)) i = len;
142
else if (STR_LITERAL_STARTSWITH(string, "false", len)) i = len;
145
/* If next source char is an identifier (eg. 'i' in "Nonetheless") no match */
146
if (i == 0 || text_check_identifier(string[i]))
151
static char txtfmt_lua_format_identifier(const char *str)
154
if ((txtfmt_lua_find_specialvar(str)) != -1) fmt = FMT_TYPE_SPECIAL;
155
else if ((txtfmt_lua_find_keyword(str)) != -1) fmt = FMT_TYPE_KEYWORD;
156
else fmt = FMT_TYPE_DEFAULT;
160
static void txtfmt_lua_format_line(SpaceText *st, TextLine *line, const int do_next)
165
char cont_orig, cont, find, prev = ' ';
168
/* Get continuation from previous line */
169
if (line->prev && line->prev->format != NULL) {
170
fmt = line->prev->format;
171
cont = fmt[strlen(fmt) + 1]; /* Just after the null-terminator */
172
BLI_assert((FMT_CONT_ALL & cont) == cont);
178
/* Get original continuation from this line */
179
if (line->format != NULL) {
181
cont_orig = fmt[strlen(fmt) + 1]; /* Just after the null-terminator */
182
BLI_assert((FMT_CONT_ALL & cont_orig) == cont_orig);
188
len = flatten_string(st, &fs, line->line);
190
if (!text_check_format_len(line, len)) {
191
flatten_string_free(&fs);
197
/* Handle escape sequences by skipping both \ and next char */
199
*fmt = prev; fmt++; str++;
200
if (*str == '\0') break;
201
*fmt = prev; fmt++; str += BLI_str_utf8_size_safe(str);
204
/* Handle continuations */
206
/* Multi-line comments */
207
if (cont & FMT_CONT_COMMENT_C) {
208
if (*str == ']' && *(str + 1) == ']') {
209
*fmt = FMT_TYPE_COMMENT; fmt++; str++;
210
*fmt = FMT_TYPE_COMMENT;
214
*fmt = FMT_TYPE_COMMENT;
216
/* Handle other comments */
219
find = (cont & FMT_CONT_QUOTEDOUBLE) ? '"' : '\'';
220
if (*str == find) cont = 0;
221
*fmt = FMT_TYPE_STRING;
224
str += BLI_str_utf8_size_safe(str) - 1;
226
/* Not in a string... */
228
/* Multi-line comments */
229
if (*str == '-' && *(str + 1) == '-' &&
230
*(str + 2) == '[' && *(str + 3) == '[')
232
cont = FMT_CONT_COMMENT_C;
233
*fmt = FMT_TYPE_COMMENT; fmt++; str++;
234
*fmt = FMT_TYPE_COMMENT; fmt++; str++;
235
*fmt = FMT_TYPE_COMMENT; fmt++; str++;
236
*fmt = FMT_TYPE_COMMENT;
238
/* Single line comment */
239
else if (*str == '-' && *(str + 1) == '-') {
240
text_format_fill(&str, &fmt, FMT_TYPE_COMMENT, len - (int)(str - fs.buf));
242
else if (*str == '"' || *str == '\'') {
245
cont = (*str == '"') ? FMT_CONT_QUOTEDOUBLE : FMT_CONT_QUOTESINGLE;
246
*fmt = FMT_TYPE_STRING;
248
/* Whitespace (all ws. has been converted to spaces) */
249
else if (*str == ' ') {
250
*fmt = FMT_TYPE_WHITESPACE;
252
/* Numbers (digits not part of an identifier and periods followed by digits) */
253
else if ((prev != FMT_TYPE_DEFAULT && text_check_digit(*str)) ||
254
(*str == '.' && text_check_digit(*(str + 1))))
256
*fmt = FMT_TYPE_NUMERAL;
259
else if (prev != FMT_TYPE_DEFAULT && (i = txtfmt_lua_find_bool(str)) != -1) {
261
text_format_fill_ascii(&str, &fmt, FMT_TYPE_NUMERAL, i);
264
str += BLI_str_utf8_size_safe(str) - 1;
265
*fmt = FMT_TYPE_DEFAULT;
269
else if ((*str != '#') && text_check_delim(*str)) {
270
*fmt = FMT_TYPE_SYMBOL;
272
/* Identifiers and other text (no previous ws. or delims. so text continues) */
273
else if (prev == FMT_TYPE_DEFAULT) {
274
str += BLI_str_utf8_size_safe(str) - 1;
275
*fmt = FMT_TYPE_DEFAULT;
277
/* Not ws, a digit, punct, or continuing text. Must be new, check for special words */
279
/* Special vars(v) or built-in keywords(b) */
280
/* keep in sync with 'txtfmt_osl_format_identifier()' */
281
if ((i = txtfmt_lua_find_specialvar(str)) != -1) prev = FMT_TYPE_SPECIAL;
282
else if ((i = txtfmt_lua_find_keyword(str)) != -1) prev = FMT_TYPE_KEYWORD;
285
text_format_fill_ascii(&str, &fmt, prev, i);
288
str += BLI_str_utf8_size_safe(str) - 1;
289
*fmt = FMT_TYPE_DEFAULT;
293
prev = *fmt; fmt++; str++;
296
/* Terminate and add continuation char */
300
/* If continuation has changed and we're allowed, process the next line */
301
if (cont != cont_orig && do_next && line->next) {
302
txtfmt_lua_format_line(st, line->next, do_next);
305
flatten_string_free(&fs);
308
void ED_text_format_register_lua(void)
310
static TextFormatType tft = {0};
311
static const char *ext[] = {"lua", NULL};
313
tft.format_identifier = txtfmt_lua_format_identifier;
314
tft.format_line = txtfmt_lua_format_line;
317
ED_text_format_register(&tft);