/* * lang_lua.hpp * Lua highlighting * Shared by the MontaukOS text editor (GUI) and edit.elf (CLI) * Copyright (c) 2026 Daniel Hammer */ // Included by ; not standalone. #pragma once // ============================================================================ // Keyword / builtin classification // ============================================================================ inline SynToken syn_classify_lua_word(const char* buf, int len) { static const char* keywords[] = { "and", "break", "do", "else", "elseif", "end", "false", "for", "function", "goto", "if", "in", "local", "nil", "not", "or", "repeat", "return", "then", "true", "until", "while", }; static const char* builtins[] = { "_ENV", "_G", "_VERSION", "assert", "collectgarbage", "coroutine", "debug", "dofile", "error", "getmetatable", "io", "ipairs", "load", "loadfile", "math", "next", "os", "package", "pairs", "pcall", "print", "rawequal", "rawget", "rawlen", "rawset", "require", "select", "setmetatable", "string", "table", "tonumber", "tostring", "type", "utf8", "warn", "xpcall", }; for (int i = 0; i < (int)(sizeof(keywords) / sizeof(keywords[0])); i++) { if (syn_streq(buf, len, keywords[i])) return SYN_KEYWORD; } for (int i = 0; i < (int)(sizeof(builtins) / sizeof(builtins[0])); i++) { if (syn_streq(buf, len, builtins[i])) return SYN_TYPE; } return SYN_NORMAL; } // ============================================================================ // Lua long bracket matching // ============================================================================ inline bool syn_match_lua_long_bracket_open(const char* line, int len, int i, int& eqs, int& span) { if (i >= len || line[i] != '[') return false; int j = i + 1; while (j < len && line[j] == '=') j++; if (j < len && line[j] == '[') { eqs = j - i - 1; span = j - i + 1; return true; } return false; } inline bool syn_match_lua_long_bracket_close(const char* line, int len, int i, int eqs, int& span) { if (i >= len || line[i] != ']') return false; int j = i + 1; for (int k = 0; k < eqs; k++) { if (j >= len || line[j] != '=') return false; j++; } if (j < len && line[j] == ']') { span = j - i + 1; return true; } return false; } // ============================================================================ // Per-line highlighter // ============================================================================ inline void syn_highlight_line_lua(const char* line, int len, SynToken* out, int out_len, SynState& state) { int i = 0; while (i < len) { if (state.long_token != SYN_NORMAL) { int span = 0; if (syn_match_lua_long_bracket_close(line, len, i, state.long_bracket_eqs, span)) { syn_fill_tokens(out, out_len, i, i + span, state.long_token); i += span; state.long_token = SYN_NORMAL; state.long_bracket_eqs = -1; continue; } syn_set_token(out, out_len, i, state.long_token); i++; continue; } char c = line[i]; if (c == '-' && i + 1 < len && line[i + 1] == '-') { int eqs = 0; int span = 0; if (i + 2 < len && syn_match_lua_long_bracket_open(line, len, i + 2, eqs, span)) { syn_fill_tokens(out, out_len, i, i + 2 + span, SYN_COMMENT); i += 2 + span; state.long_token = SYN_COMMENT; state.long_bracket_eqs = eqs; continue; } syn_fill_tokens(out, out_len, i, len, SYN_COMMENT); break; } if (c == '"' || c == '\'') { char quote = c; syn_set_token(out, out_len, i, SYN_STRING); i++; while (i < len) { if (line[i] == '\\' && i + 1 < len) { syn_set_token(out, out_len, i, SYN_STRING); syn_set_token(out, out_len, i + 1, SYN_STRING); i += 2; continue; } syn_set_token(out, out_len, i, SYN_STRING); if (line[i] == quote) { i++; break; } i++; } continue; } int eqs = 0; int span = 0; if (syn_match_lua_long_bracket_open(line, len, i, eqs, span)) { syn_fill_tokens(out, out_len, i, i + span, SYN_STRING); i += span; state.long_token = SYN_STRING; state.long_bracket_eqs = eqs; continue; } if (syn_is_digit(c) || (c == '.' && i + 1 < len && syn_is_digit(line[i + 1]))) { syn_consume_number(line, len, i, out, out_len, 0); continue; } if (syn_is_alpha(c)) { int start = i; while (i < len && syn_is_alnum(line[i])) i++; SynToken tok = syn_classify_word(SYN_LANG_LUA, line + start, i - start); syn_fill_tokens(out, out_len, start, i, tok); continue; } if (c == '+' || c == '-' || c == '*' || c == '/' || c == '%' || c == '^' || c == '#' || c == '=' || c == '<' || c == '>' || c == '~' || c == ':' || c == '.' || c == ',' || c == ';' || c == '(' || c == ')' || c == '{' || c == '}' || c == '[' || c == ']') { syn_set_token(out, out_len, i, SYN_OPERATOR); i++; continue; } syn_set_token(out, out_len, i, SYN_NORMAL); i++; } }