MineOS/lib/syntax.lua
Igor Timofeev 88c4a3e2d0 Ы
2015-11-20 12:06:53 +03:00

218 lines
9.3 KiB
Lua
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

local gpu = require("component").gpu
local buffer = require("doubleBuffering")
local unicode = require("unicode")
local syntax = {}
----------------------------------------------------------------------------------------------------------------
--Стандартные цветовые схемы
syntax.colorSchemes = {
midnight = {
recommendedBackground = 0x262626,
text = 0xffffff,
strings = 0xff2024,
loops = 0xffff98,
comments = 0xa2ffb7,
boolean = 0xffcc66,
logic = 0xffcc66,
numbers = 0x24c0ff,
functions = 0xffcc66,
compares = 0xffff98,
},
sunrise = {
recommendedBackground = 0xffffff,
text = 0x262626,
strings = 0x880000,
loops = 0x24c0ff,
comments = 0xa2ffb7,
boolean = 0x19c0cc,
logic = 0x880000,
numbers = 0x24c0ff,
functions = 0x24c0ff,
compares = 0x880000,
},
}
--Текущая цветовая схема
local currentColorScheme = {}
--Шаблоны поиска
local patterns
--Размер массива шаблонов поиска
local sPatterns
----------------------------------------------------------------------------------------------------------------
--Пересчитать цвета шаблонов
--Приоритет поиска шаблонов снижается сверху вниз
local function definePatterns()
patterns = {
--Комментарии
{ pattern = "%-%-.*", color = currentColorScheme.comments, cutFromLeft = 0, cutFromRight = 0 },
--Строки
{ pattern = "\"[^\"\"]*\"", color = currentColorScheme.strings, cutFromLeft = 0, cutFromRight = 0 },
--Циклы, условия, объявления
{ pattern = "while ", color = currentColorScheme.loops, cutFromLeft = 0, cutFromRight = 1 },
{ pattern = "do$", color = currentColorScheme.loops, cutFromLeft = 0, cutFromRight = 0 },
{ pattern = "do ", color = currentColorScheme.loops, cutFromLeft = 0, cutFromRight = 1 },
{ pattern = "end$", color = currentColorScheme.loops, cutFromLeft = 0, cutFromRight = 0 },
{ pattern = "end ", color = currentColorScheme.loops, cutFromLeft = 0, cutFromRight = 1 },
{ pattern = "for ", color = currentColorScheme.loops, cutFromLeft = 0, cutFromRight = 1 },
{ pattern = " in ", color = currentColorScheme.loops, cutFromLeft = 0, cutFromRight = 1 },
{ pattern = "repeat ", color = currentColorScheme.loops, cutFromLeft = 0, cutFromRight = 1 },
{ pattern = "if ", color = currentColorScheme.loops, cutFromLeft = 0, cutFromRight = 1 },
{ pattern = "then", color = currentColorScheme.loops, cutFromLeft = 0, cutFromRight = 0 },
{ pattern = "until ", color = currentColorScheme.loops, cutFromLeft = 0, cutFromRight = 1 },
{ pattern = "return", color = currentColorScheme.loops, cutFromLeft = 0, cutFromRight = 0 },
{ pattern = "local ", color = currentColorScheme.loops, cutFromLeft = 0, cutFromRight = 1 },
{ pattern = "function ", color = currentColorScheme.loops, cutFromLeft = 0, cutFromRight = 1 },
{ pattern = "else$", color = currentColorScheme.loops, cutFromLeft = 0, cutFromRight = 0 },
{ pattern = "else ", color = currentColorScheme.loops, cutFromLeft = 0, cutFromRight = 1 },
{ pattern = "elseif ", color = currentColorScheme.loops, cutFromLeft = 0, cutFromRight = 1 },
--Состояния переменной
{ pattern = "true", color = currentColorScheme.boolean, cutFromLeft = 0, cutFromRight = 0 },
{ pattern = "false", color = currentColorScheme.boolean, cutFromLeft = 0, cutFromRight = 0 },
{ pattern = "nil", color = currentColorScheme.boolean, cutFromLeft = 0, cutFromRight = 0 },
--Функции
{ pattern = "%s([%a%d%_%-%.]*)%(", color = currentColorScheme.functions, cutFromLeft = 0, cutFromRight = 1 },
--And, or, not, break
{ pattern = " and ", color = currentColorScheme.logic, cutFromLeft = 0, cutFromRight = 1 },
{ pattern = " or ", color = currentColorScheme.logic, cutFromLeft = 0, cutFromRight = 1 },
{ pattern = " not ", color = currentColorScheme.logic, cutFromLeft = 0, cutFromRight = 1 },
{ pattern = " break$", color = currentColorScheme.logic, cutFromLeft = 0, cutFromRight = 0 },
{ pattern = "^break", color = currentColorScheme.logic, cutFromLeft = 0, cutFromRight = 0 },
{ pattern = " break ", color = currentColorScheme.logic, cutFromLeft = 0, cutFromRight = 0 },
--Числа
{ pattern = "%s(0x)(%w*)", color = currentColorScheme.numbers, cutFromLeft = 0, cutFromRight = 0 },
{ pattern = "(%s)([%d%.]*)", color = currentColorScheme.numbers, cutFromLeft = 0, cutFromRight = 0 },
--Сравнения и мат. операции
{ pattern = "<=", color = currentColorScheme.compares, cutFromLeft = 0, cutFromRight = 0 },
{ pattern = ">=", color = currentColorScheme.compares, cutFromLeft = 0, cutFromRight = 0 },
{ pattern = "<", color = currentColorScheme.compares, cutFromLeft = 0, cutFromRight = 0 },
{ pattern = ">", color = currentColorScheme.compares, cutFromLeft = 0, cutFromRight = 0 },
{ pattern = "==", color = currentColorScheme.compares, cutFromLeft = 0, cutFromRight = 0 },
{ pattern = "~=", color = currentColorScheme.compares, cutFromLeft = 0, cutFromRight = 0 },
{ pattern = "=", color = currentColorScheme.compares, cutFromLeft = 0, cutFromRight = 0 },
{ pattern = "%+", color = currentColorScheme.compares, cutFromLeft = 0, cutFromRight = 0 },
{ pattern = "%-", color = currentColorScheme.compares, cutFromLeft = 0, cutFromRight = 0 },
{ pattern = "%*", color = currentColorScheme.compares, cutFromLeft = 0, cutFromRight = 0 },
{ pattern = "%/", color = currentColorScheme.compares, cutFromLeft = 0, cutFromRight = 0 },
{ pattern = "%.%.", color = currentColorScheme.compares, cutFromLeft = 0, cutFromRight = 0 },
{ pattern = "%#", color = currentColorScheme.compares, cutFromLeft = 0, cutFromRight = 0 },
{ pattern = "#^", color = currentColorScheme.compares, cutFromLeft = 0, cutFromRight = 0 },
}
--Ну, и размер массива шаблонов тоже
sPatterns = #patterns
end
--Костыльная замена обычному string.find()
--Работает медленнее, но хотя бы поддерживает юникод
function unicode.find(str, pattern, init, plain)
-- checkArg(1, str, "string")
-- checkArg(2, pattern, "string")
-- checkArg(3, init, "number", "nil")
if init then
if init < 0 then
init = -#unicode.sub(str,init)
elseif init > 0 then
init = #unicode.sub(str,1,init-1)+1
end
end
a, b = string.find(str, pattern, init, plain)
if a then
local ap,bp = str:sub(1,a-1), str:sub(a,b)
a = unicode.len(ap)+1
b = a + unicode.len(bp)-1
return a,b
else
return a
end
end
--Проанализировать строку и создать на ее основе цветовую карту
function syntax.highlight(x, y, text, limit)
--Кароч вооот, хыыы
local searchFrom, starting, ending
--Загоняем в буффер всю строку базового цвета
buffer.text(x, y, currentColorScheme.text, limit and unicode.sub(text, 1, limit) or text)
limit = limit or math.huge
--Перебираем шаблоны
for i = #patterns, 1, -1 do
searchFrom = 1
--Перебираем весь текст, а то мало ли шаблон дохуя раз встречается
while true do
starting, ending = unicode.find(text, patterns[i].pattern, searchFrom)
if starting and ending then
if ending <= limit then
buffer.text(x + starting - 1, y, patterns[i].color, unicode.sub(text, starting, ending - patterns[i].cutFromRight))
searchFrom = ending + 1
else
buffer.text(x + starting - 1, y, patterns[i].color, unicode.sub(text, starting, limit))
break
end
else
break
end
end
end
end
--Объявить новую цветовую схему
function syntax.setColorScheme(colorScheme)
--Выбранная цветовая схема
currentColorScheme = colorScheme
--Пересчитываем шаблоны
definePatterns()
end
--Открыть файл для чтения и отобразить первые строки из него, чтобы чекнуть, как работает подсветка
function syntax.highlightFileForDebug(pathToFile)
--Получаем размер экрана
local xSize, ySize = gpu.getResolution()
--Очищаем экран рекомендуемым цветом
buffer.square(1, 1, xSize, ySize, currentColorScheme.recommendedBackground, currentColorScheme.text, " ")
buffer.draw(true)
--Открываем файлик
local file = io.open(pathToFile, "r")
--Счетчик строк
local lineCounter = 1
--Читаем строки
for line in file:lines() do
--Подсвечиваем строку и рисуем
syntax.highlight(2, lineCounter + 1, line)
--Счетчик в плюс
lineCounter = lineCounter + 1
--Разрываем цикл, если кол-во строк превысило высоту экрана
if lineCounter > ySize then break end
--ecs.wait()
end
--Закрываем файл
file:close()
buffer.draw()
end
----------------------------------------------------------------------------------------------------------------
--Стартовое объявление цветовой схемы при загрузке библиотеки
syntax.setColorScheme(syntax.colorSchemes.midnight)
--Епты бля!
syntax.highlightFileForDebug("MineOS/Applications/Highlight.app/Resources/TestFile.txt", "midnight")
return syntax