CFC-Servers / GLuaTest

An exciting and nimble unit testing framework for GLua projects
https://discord.gg/epJK9Xx3pc
GNU General Public License v3.0
52 stars 3 forks source link

Add GLua syntax highlighting to the Error output #10

Open brandonsturgeon opened 2 years ago

brandonsturgeon commented 2 years ago

It would be really cool if we could syntax highlight the error output.

Since we've monkey-patched MsgC to write everything in ANSI, it's doable.

I think the best place to start would be finding the source for some existing syntax highlighter (gcompute? luapad? some css highlighter?) written in lua and hack it to output ANSI color codes instead.

It'll be tricky, but it would be a really cool addition.

brandonsturgeon commented 3 months ago

Here's some code I found in Luapad that seems simple enough to get started with:

local colors = {
    ["none"] = { Color( 0, 0, 0, 255 ), false },
    ["number"] = { Color( 218, 165, 32, 255 ), false },
    ["function"] = { Color( 100, 100, 255, 255 ), false },
    ["enumeration"] = { Color( 184, 134, 11, 255 ), false },
    ["metatable"] = { Color( 140, 100, 90, 255 ), false },
    ["string"] = { Color( 120, 120, 120, 255 ), false },
    ["expression"] = { Color( 0, 0, 255, 255 ), false },
    ["operator"] = { Color( 0, 0, 128, 255 ), false },
    ["comment"] = { Color( 0, 120, 0, 255 ), false },
}

function PANEL:SyntaxColorLine( row )
    local cols = {}
    local lasttable
    self.line = self.Rows[row]
    self.pos = 0
    self.char = ""
    self.str = ""

    colors["string2"] = colors["string"]
    self:NextChar()

    while self.char do
        token = ""
        self.str = ""

        while self.char and self.char == " " do
            self:NextChar()
        end

        if not self.char then break end

        if self.char >= "0" and self.char <= "9" then
            while self.char and ( self.char >= "0" and self.char <= "9" or self.char == "." or self.char == "_" ) do
                self:NextChar()
            end

            token = "number"
        elseif self.char >= "a" and self.char <= "z" or self.char >= "A" and self.char <= "Z" then
            while self.char and ( self.char >= "a" and self.char <= "z" or self.char >= "A" and self.char <= "Z" or self.char >= "0" and self.char <= "9" or self.char == "_" ) do
                self:NextChar()
            end

            local sstr = string.Trim( self.str )

            if sstr == "if" or sstr == "elseif" or sstr == "else" or sstr == "then" or sstr == "end" or sstr == "function" or sstr == "do" or sstr == "while" or sstr == "break" or sstr == "for" or sstr == "in" or sstr == "local" or sstr == "true" or sstr == "false" or sstr == "nil" or sstr == "NULL" or sstr == "and" or sstr == "not" or sstr == "or" or sstr == "||" or sstr == "&&" then
                token = "expression"
            elseif luapad.CheckGlobal( sstr ) and ( type( luapad.CheckGlobal( sstr ) ) == "function" or luapad.CheckGlobal( sstr ) == "f" or luapad.CheckGlobal( sstr ) == "e" or luapad.CheckGlobal( sstr ) == "m" or type( luapad.CheckGlobal( sstr ) ) == "table" ) or lasttable and lasttable[sstr] then
                -- Could be better code, but what the hell; it works
                if type( luapad.CheckGlobal( sstr ) ) == "table" then
                    lasttable = luapad.CheckGlobal( sstr )
                end

                if ( luapad.CheckGlobal( sstr ) == "e" or _E and _E[sstr] ) and sstr == string.upper( sstr ) then
                    token = "enumeration"
                elseif luapad.CheckGlobal( sstr ) == "m" then
                    token = "metatable"
                else
                    token = "function"
                end
            else
                lasttable = nil
                token = "none"
            end
        elseif self.char == "\"" then
            -- TODO: Fix multiline strings, and add support for [[stuff]]!
            self:NextChar()

            while self.char and self.char ~= "\"" do
                if self.char == "\\" then
                    self:NextChar()
                end

                self:NextChar()
            end

            self:NextChar()
            token = "string"
        elseif self.char == "'" then
            self:NextChar()

            while self.char and self.char ~= "'" do
                if self.char == "\\" then
                    self:NextChar()
                end

                self:NextChar()
            end

            self:NextChar()
            token = "string2"
        elseif self.char == "/" or self.char == "-" then
            -- TODO: Multiline comments!
            local lastchar = self.char
            self:NextChar()

            if self.char == lastchar then
                while self.char do
                    self:NextChar()
                end

                token = "comment"
            else
                token = "none"
            end
        else
            self:NextChar()
            token = "operator"
        end

        color = colors[token]

        if #cols > 1 and color == cols[#cols][2] then
            cols[#cols][1] = cols[#cols][1] .. self.str
        else
            cols[#cols + 1] = { self.str, color }
        end
    end

    return cols
end