-- mod-version:3
-- Support for the Fennel programming language: https://fennel-lang.org
-- Covers all the keywords up to Fennel version 1.2.0

-- Currently only covers highlighting, not indentation, delimiter
-- matching, or evaluation.

local syntax = require("core.syntax")

syntax.add({
    comment = ";",
    files = "%.fnl$",
    name = "Fennel",
    patterns = {
        { pattern = ";.-\n", type = "comment" },
        { pattern = { '"', '"', "\\" }, type = "string" },
        { pattern = "0x[%da-fA-F]+", type = "number" },
        { pattern = "-?%d+[%d%.]*", type = "number" },
        { pattern = "-?%.?%d+", type = "number" },
        { pattern = "%f[^(][^()'%s\"]+", type = "function" },
        { pattern = "[^()'%s\"]+", type = "symbol" },
    },
    symbols = {
        ["#"] = "keyword",
        ["%"] = "keyword",
        ["*"] = "keyword",
        ["+"] = "keyword",
        ["-"] = "keyword",
        ["->"] = "keyword",
        ["->>"] = "keyword",
        ["-?>"] = "keyword",
        ["-?>>"] = "keyword",
        ["."] = "keyword",
        [".."] = "keyword",
        ["/"] = "keyword",
        ["//"] = "keyword",
        [":"] = "keyword",
        ["<"] = "keyword",
        ["<="] = "keyword",
        ["="] = "keyword",
        [">"] = "keyword",
        [">="] = "keyword",
        ["?."] = "keyword",
        ["^"] = "keyword",
        _G = "keyword",
        accumulate = "keyword2",
        ["and"] = "keyword2",
        arg = "keyword2",
        assert = "keyword2",
        band = "keyword2",
        bit32 = "keyword2",
        ["bit32.arshift"] = "keyword2",
        ["bit32.band"] = "keyword2",
        ["bit32.bnot"] = "keyword2",
        ["bit32.bor"] = "keyword2",
        ["bit32.btest"] = "keyword2",
        ["bit32.bxor"] = "keyword2",
        ["bit32.extract"] = "keyword2",
        ["bit32.lrotate"] = "keyword2",
        ["bit32.lshift"] = "keyword2",
        ["bit32.replace"] = "keyword2",
        ["bit32.rrotate"] = "keyword2",
        ["bit32.rshift"] = "keyword2",
        bnot = "keyword2",
        bor = "keyword2",
        bxor = "keyword2",
        collect = "keyword2",
        collectgarbage = "keyword2",
        comment = "keyword2",
        coroutine = "keyword2",
        ["coroutine.create"] = "keyword2",
        ["coroutine.resume"] = "keyword2",
        ["coroutine.running"] = "keyword2",
        ["coroutine.status"] = "keyword2",
        ["coroutine.wrap"] = "keyword2",
        ["coroutine.yield"] = "keyword2",
        debug = "keyword2",
        ["debug.debug"] = "keyword2",
        ["debug.gethook"] = "keyword2",
        ["debug.getinfo"] = "keyword2",
        ["debug.getlocal"] = "keyword2",
        ["debug.getmetatable"] = "keyword2",
        ["debug.getregistry"] = "keyword2",
        ["debug.getupvalue"] = "keyword2",
        ["debug.getuservalue"] = "keyword2",
        ["debug.sethook"] = "keyword2",
        ["debug.setlocal"] = "keyword2",
        ["debug.setmetatable"] = "keyword2",
        ["debug.setupvalue"] = "keyword2",
        ["debug.setuservalue"] = "keyword2",
        ["debug.traceback"] = "keyword2",
        ["debug.upvalueid"] = "keyword2",
        ["debug.upvaluejoin"] = "keyword2",
        ["do"] = "keyword2",
        dofile = "keyword2",
        doto = "keyword2",
        each = "keyword2",
        error = "keyword2",
        ["eval-compiler"] = "keyword2",
        ["false"] = "literal",
        fcollect = "keyword2",
        fn = "keyword2",
        ["for"] = "keyword2",
        getmetatable = "keyword2",
        global = "keyword2",
        hashfn = "keyword2",
        icollect = "keyword2",
        ["if"] = "keyword2",
        ["import-macros"] = "keyword2",
        include = "keyword2",
        io = "keyword2",
        ["io.close"] = "keyword2",
        ["io.flush"] = "keyword2",
        ["io.input"] = "keyword2",
        ["io.lines"] = "keyword2",
        ["io.open"] = "keyword2",
        ["io.output"] = "keyword2",
        ["io.popen"] = "keyword2",
        ["io.read"] = "keyword2",
        ["io.tmpfile"] = "keyword2",
        ["io.type"] = "keyword2",
        ["io.write"] = "keyword2",
        ipairs = "keyword2",
        lambda = "keyword2",
        length = "keyword2",
        let = "keyword2",
        load = "keyword2",
        loadfile = "keyword2",
        loadstring = "keyword2",
        ["local"] = "keyword2",
        lshift = "keyword2",
        lua = "keyword2",
        macro = "keyword2",
        macrodebug = "keyword2",
        macros = "keyword2",
        match = "keyword2",
        ["match-try"] = "keyword2",
        math = "keyword2",
        ["math.abs"] = "keyword2",
        ["math.acos"] = "keyword2",
        ["math.asin"] = "keyword2",
        ["math.atan"] = "keyword2",
        ["math.atan2"] = "keyword2",
        ["math.ceil"] = "keyword2",
        ["math.cos"] = "keyword2",
        ["math.cosh"] = "keyword2",
        ["math.deg"] = "keyword2",
        ["math.exp"] = "keyword2",
        ["math.floor"] = "keyword2",
        ["math.fmod"] = "keyword2",
        ["math.frexp"] = "keyword2",
        ["math.ldexp"] = "keyword2",
        ["math.log"] = "keyword2",
        ["math.log10"] = "keyword2",
        ["math.max"] = "keyword2",
        ["math.min"] = "keyword2",
        ["math.modf"] = "keyword2",
        ["math.pow"] = "keyword2",
        ["math.rad"] = "keyword2",
        ["math.random"] = "keyword2",
        ["math.randomseed"] = "keyword2",
        ["math.sin"] = "keyword2",
        ["math.sinh"] = "keyword2",
        ["math.sqrt"] = "keyword2",
        ["math.tan"] = "keyword2",
        ["math.tanh"] = "keyword2",
        module = "keyword2",
        next = "keyword2",
        ["nil"] = "literal",
        ["not"] = "keyword2",
        ["not="] = "keyword2",
        ["or"] = "keyword2",
        os = "keyword2",
        ["os.clock"] = "keyword2",
        ["os.date"] = "keyword2",
        ["os.difftime"] = "keyword2",
        ["os.execute"] = "keyword2",
        ["os.exit"] = "keyword2",
        ["os.getenv"] = "keyword2",
        ["os.remove"] = "keyword2",
        ["os.rename"] = "keyword2",
        ["os.setlocale"] = "keyword2",
        ["os.time"] = "keyword2",
        ["os.tmpname"] = "keyword2",
        package = "keyword2",
        ["package.loadlib"] = "keyword2",
        ["package.searchpath"] = "keyword2",
        ["package.seeall"] = "keyword2",
        pairs = "keyword2",
        partial = "keyword2",
        pcall = "keyword2",
        ["pick-args"] = "keyword2",
        ["pick-values"] = "keyword2",
        print = "keyword2",
        quote = "keyword2",
        rawequal = "keyword2",
        rawget = "keyword2",
        rawlen = "keyword2",
        rawset = "keyword2",
        require = "keyword2",
        ["require-macros"] = "keyword2",
        rshift = "keyword2",
        select = "keyword2",
        set = "keyword2",
        ["set-forcibly!"] = "keyword2",
        setmetatable = "keyword2",
        string = "keyword2",
        ["string.byte"] = "keyword2",
        ["string.char"] = "keyword2",
        ["string.dump"] = "keyword2",
        ["string.find"] = "keyword2",
        ["string.format"] = "keyword2",
        ["string.gmatch"] = "keyword2",
        ["string.gsub"] = "keyword2",
        ["string.len"] = "keyword2",
        ["string.lower"] = "keyword2",
        ["string.match"] = "keyword2",
        ["string.rep"] = "keyword2",
        ["string.reverse"] = "keyword2",
        ["string.sub"] = "keyword2",
        ["string.upper"] = "keyword2",
        table = "keyword2",
        ["table.concat"] = "keyword2",
        ["table.insert"] = "keyword2",
        ["table.maxn"] = "keyword2",
        ["table.pack"] = "keyword2",
        ["table.remove"] = "keyword2",
        ["table.sort"] = "keyword2",
        ["table.unpack"] = "keyword2",
        tonumber = "keyword2",
        tostring = "keyword2",
        ["true"] = "literal",
        tset = "keyword2",
        type = "keyword2",
        unpack = "keyword2",
        values = "keyword2",
        var = "keyword2",
        when = "keyword2",
        ["while"] = "keyword2",
        ["with-open"] = "keyword2",
        xpcall = "keyword2",
        ["~="] = "keyword",
        ["λ"] = "keyword",
    },
})

-- To regenerate the syntax from the compiler:
-- (macro s []
--   (let [{: syntax} (require :fennel)
--         symbols {:nil :literal
--                  :true :literal
--                  :false :literal}]
--     `(syntax.add {:name "Fennel"
--                   :files "%.fnl$"
--                   :comment ";"
--                   :patterns [{:type :comment :pattern ";.-\n"}
--                              {:type :string :pattern {1 "\"" 2 "\"" 3 "\\"}}
--                              {:type :number :pattern "0x[%da-fA-F]+"}
--                              {:type :number :pattern "-?%d+[%d%.]*"}
--                              {:type :number :pattern "-?%.?%d+"}
--                              {:type :function :pattern "%f[^(][^()'%s\"]+"}
--                              {:type :symbol :pattern "[^()'%s\"]+"}]
--                   :symbols ,(collect [name (pairs (syntax)) :into symbols]
--                               (values name
--                                       (if (name:find "[a-z]")
--                                           :keyword2 :keyword)))}))) (s)

-- and reformat the output, of course
