mirror of
https://github.com/IgorTimofeev/MineOS.git
synced 2025-12-20 11:09:21 +01:00
321 lines
15 KiB
Lua
Executable File
321 lines
15 KiB
Lua
Executable File
if not _G.buffer then _G.buffer = require("doubleBuffering") end
|
||
if not _G.unicode then _G.unicode = require("unicode") end
|
||
|
||
local syntax = {}
|
||
|
||
----------------------------------------------------------------------------------------------------------------------------------------
|
||
|
||
syntax.colorSchemes = {
|
||
midnight = {
|
||
background = 0x1b1b1b,
|
||
text = 0xffffff,
|
||
strings = 0xff2024,
|
||
loops = 0xffff98,
|
||
comments = 0xa2ffb7,
|
||
boolean = 0xffcc66,
|
||
logic = 0xffcc66,
|
||
numbers = 0x24c0ff,
|
||
functions = 0xffcc66,
|
||
compares = 0xffff98,
|
||
lineNumbers = 0x262626,
|
||
lineNumbersText = 0xDDDDDD,
|
||
scrollBar = 0x444444,
|
||
scrollBarPipe = 0x24c0ff,
|
||
selection = 0x99B2F2,
|
||
}
|
||
}
|
||
|
||
local currentColorScheme, patterns
|
||
|
||
----------------------------------------------------------------------------------------------------------------------------------------
|
||
|
||
--Пересчитать цвета шаблонов
|
||
--Приоритет поиска шаблонов снижается сверху вниз
|
||
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 },
|
||
{ pattern = "^[%a%d%_%-%.%=]+%(", color = currentColorScheme.functions, cutFromLeft = 0, cutFromRight = 1 },
|
||
|
||
--Логические выражения
|
||
{ 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 = "<=", 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 },
|
||
{ pattern = "%%", color = currentColorScheme.compares, cutFromLeft = 0, cutFromRight = 0 },
|
||
|
||
--Числа
|
||
{ pattern = "[%s%(%,]0x%w+", color = currentColorScheme.numbers, cutFromLeft = 1, cutFromRight = 0 },
|
||
{ pattern = "[%s%(%,][%d%.]+", color = currentColorScheme.numbers, cutFromLeft = 1, cutFromRight = 0 },
|
||
}
|
||
end
|
||
|
||
local function convertFileToStrings(path)
|
||
local array = {}
|
||
local maximumStringWidth = 0
|
||
local file = io.open(path, "r")
|
||
for line in file:lines() do
|
||
line = string.gsub(line, " ", string.rep(" ", 4))
|
||
maximumStringWidth = math.max(maximumStringWidth, unicode.len(line))
|
||
table.insert(array, line)
|
||
end
|
||
file:close()
|
||
return array, maximumStringWidth
|
||
end
|
||
|
||
--Костыльная замена обычному string.find()
|
||
--Работает медленнее, но хотя бы поддерживает юникод
|
||
function unicode.find(str, pattern, init, plain)
|
||
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.setColorScheme(colorScheme)
|
||
currentColorScheme = colorScheme
|
||
definePatterns()
|
||
end
|
||
|
||
----------------------------------------------------------------------------------------------------------------------------------------
|
||
|
||
--Нарисовать и подсветить строку
|
||
function syntax.highlightString(x, y, text, fromSymbol, limit)
|
||
--Кароч вооот, хыыы
|
||
local searchFrom, starting, ending
|
||
--Загоняем в буфер всю строку базового цвета
|
||
buffer.text(x - fromSymbol + 1, y, currentColorScheme.text, text)
|
||
--Перебираем шаблоны
|
||
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
|
||
buffer.text(x + starting - fromSymbol + patterns[i].cutFromLeft, y, patterns[i].color, unicode.sub(text, starting + patterns[i].cutFromLeft, ending - patterns[i].cutFromRight))
|
||
if ending > limit then break end
|
||
searchFrom = ending + 1
|
||
else
|
||
break
|
||
end
|
||
end
|
||
end
|
||
end
|
||
|
||
-- Открыть окно-просмотрщик кода
|
||
--x, y, width, height, strings, maximumStringWidth, fromSymbol, fromString, highlightLuaSyntax, selection, highlightedStrings
|
||
function syntax.viewCode(args)
|
||
--Рассчитываем максимальное количество строк, которое мы будем отображать
|
||
local countOfStringsOnDisplay, maximumNumberOfAvailableStrings
|
||
if args.strings[args.fromString + args.height - 1] then
|
||
countOfStringsOnDisplay = args.scrollbars.horizontal and args.height - 1 or args.height
|
||
maximumNumberOfAvailableStrings = args.fromString + args.height - 1
|
||
else
|
||
countOfStringsOnDisplay = #args.strings
|
||
maximumNumberOfAvailableStrings = #args.strings
|
||
end
|
||
|
||
--Рассчитываем ширину полоски с номерами строк
|
||
local lineNumbersWidth = unicode.len(args.fromStringOnLineNumbers + countOfStringsOnDisplay) + 2
|
||
|
||
--Рассчитываем стратовую позицию текстового поля
|
||
local textFieldPosition = args.x + lineNumbersWidth
|
||
local widthOfText = args.width - lineNumbersWidth - 3
|
||
local xEnd, yEnd = args.x + args.width - 1, args.y + args.height - 1
|
||
|
||
--Рисуем подложку под текст
|
||
buffer.square(args.x, args.y, args.width, args.height, currentColorScheme.background, 0xFFFFFF, " ")
|
||
--Рисуем подложку под номера строк
|
||
buffer.square(args.x, args.y, lineNumbersWidth, args.height, currentColorScheme.lineNumbers, 0xFFFFFF, " ")
|
||
|
||
--Подсвечиваем некоторые строки, если указано
|
||
if args.highlightedStrings then
|
||
for stringNumber, color in pairs(args.highlightedStrings) do
|
||
if stringNumber >= args.fromStringOnLineNumbers and stringNumber < args.fromStringOnLineNumbers + countOfStringsOnDisplay then
|
||
buffer.square(args.x, args.y + stringNumber - args.fromStringOnLineNumbers, args.width - 1, 1, color, 0xFFFFFF, " ")
|
||
buffer.square(args.x, args.y + stringNumber - args.fromStringOnLineNumbers, lineNumbersWidth, 1, currentColorScheme.lineNumbers, 0xFFFFFF, " ", 60)
|
||
end
|
||
end
|
||
end
|
||
|
||
--Рисуем номера строк
|
||
local yPos = args.y
|
||
for i = args.fromStringOnLineNumbers, args.fromStringOnLineNumbers + countOfStringsOnDisplay - 1 do
|
||
buffer.text(args.x + lineNumbersWidth - unicode.len(i) - 1, yPos, currentColorScheme.text, tostring(i))
|
||
yPos = yPos + 1
|
||
end
|
||
|
||
--Рисуем выделение, если оно имеется
|
||
if args.selection then
|
||
--Считаем высоту выделения
|
||
local heightOfSelection = args.selection.to.y - args.selection.from.y + 1
|
||
--Если высота выделения > 1
|
||
if heightOfSelection > 1 then
|
||
--Верхнее выделение
|
||
if args.selection.from.x < args.fromSymbol + widthOfText and args.selection.from.y >= args.fromString and args.selection.from.y < args.fromString + args.height then
|
||
local cyka = textFieldPosition + args.selection.from.x - args.fromSymbol
|
||
if cyka < textFieldPosition then
|
||
cyka = textFieldPosition
|
||
end
|
||
buffer.square(cyka, args.y + args.selection.from.y - args.fromString, widthOfText - cyka + lineNumbersWidth + 2 + args.x, 1, currentColorScheme.selection, 0xFFFFFF, " ")
|
||
end
|
||
--Средние выделения
|
||
if heightOfSelection > 2 then
|
||
for i = 1, heightOfSelection - 2 do
|
||
if args.selection.from.y + i >= args.fromString and args.selection.from.y + i < args.fromString + args.height then
|
||
buffer.square(textFieldPosition, args.y + args.selection.from.y + i - args.fromString, widthOfText + 2, 1, currentColorScheme.selection, 0xFFFFFF, " ")
|
||
end
|
||
end
|
||
end
|
||
--Нижнее выделение
|
||
if args.selection.to.x >= args.fromSymbol and args.selection.to.y >= args.fromString and args.selection.to.y < args.fromString + args.height then
|
||
buffer.square(textFieldPosition, args.y + args.selection.to.y - args.fromString, args.selection.to.x - args.fromSymbol + 1, 1, currentColorScheme.selection, 0xFFFFFF, " ")
|
||
end
|
||
elseif heightOfSelection == 1 then
|
||
local cyka = args.selection.to.x
|
||
if cyka > args.fromSymbol + widthOfText - 1 then cyka = args.fromSymbol + widthOfText - 1 end
|
||
buffer.square(textFieldPosition + args.selection.from.x, args.selection.from.y, cyka - args.selection.from.x, 1, currentColorScheme.selection, 0xFFFFFF, " ")
|
||
|
||
end
|
||
end
|
||
|
||
--Выставляем ограничение прорисовки буфера
|
||
textFieldPosition = textFieldPosition + 1
|
||
buffer.setDrawLimit(textFieldPosition, args.y, widthOfText, args.height)
|
||
|
||
--Рисуем текст
|
||
yPos = args.y
|
||
for i = args.fromString, maximumNumberOfAvailableStrings do
|
||
--Учитываем опциональную подсветку ситнаксиса
|
||
if args.highlightLuaSyntax then
|
||
syntax.highlightString(textFieldPosition, yPos, args.strings[i], args.fromSymbol, widthOfText)
|
||
else
|
||
buffer.text(textFieldPosition, yPos, currentColorScheme.text, unicode.sub(args.strings[i], args.fromSymbol, widthOfText))
|
||
end
|
||
|
||
yPos = yPos + 1
|
||
end
|
||
|
||
--Убираем ограничение отрисовки
|
||
buffer.resetDrawLimit()
|
||
|
||
--Рисуем вертикальный скроллбар
|
||
if args.scrollbars.vertical then buffer.scrollBar(xEnd, args.y, 1, args.height, #args.strings, args.fromString, currentColorScheme.scrollBar, currentColorScheme.scrollBarPipe) end
|
||
--Рисуем горизонтальный скроллбар
|
||
if args.scrollbars.horizontal then buffer.horizontalScrollBar(args.x + lineNumbersWidth, yEnd, args.width - lineNumbersWidth - 1, args.maximumStringWidth, args.fromSymbol, currentColorScheme.scrollBar, currentColorScheme.scrollBarPipe) end
|
||
|
||
--Для всяких майнкодов, чтоб курсор можно было ставит и ТОПЕ
|
||
return textFieldPosition
|
||
end
|
||
|
||
----------------------------------------------------------------------------------------------------------------
|
||
|
||
-- Стартовое объявление цветовой схемы при загрузке библиотеки
|
||
syntax.setColorScheme(syntax.colorSchemes.midnight)
|
||
|
||
----------------------------------------------------------------------------------------------------------------
|
||
|
||
-- buffer.start()
|
||
-- buffer.clear(0xFF8888)
|
||
|
||
-- local strings, maximumStringWidth = convertFileToStrings("/OS.lua")
|
||
|
||
-- local args = {
|
||
-- x = 1,
|
||
-- y = 1,
|
||
-- width = 100,
|
||
-- height = 40,
|
||
-- strings = strings,
|
||
-- fromString = 1,
|
||
-- fromSymbol = 1,
|
||
-- fromStringOnLineNumbers = 6,
|
||
-- maximumStringWidth = maximumStringWidth,
|
||
-- highlightLuaSyntax = true,
|
||
-- selection = {
|
||
-- from = {x = 8, y = 6},
|
||
-- to = {x = 16, y = 12}
|
||
-- },
|
||
-- highlightedStrings = {
|
||
-- [31] = 0xFF4444,
|
||
-- [33] = 0x55FF55,
|
||
-- },
|
||
-- scrollbars = {
|
||
-- vertical = true,
|
||
-- horizontal = true,
|
||
-- }
|
||
-- }
|
||
|
||
-- syntax.viewCode(args)
|
||
-- buffer.draw()
|
||
|
||
----------------------------------------------------------------------------------------------------------------
|
||
|
||
return syntax
|
||
|
||
|
||
|
||
|