Daniel_I_Am

highlighterAPI

Feb 25th, 2018
154
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Lua 9.33 KB | None | 0 0
  1. local component = require("component")
  2. local fs = require("filesystem")
  3. local os = require("os")
  4. local term = require("term")
  5.  
  6. if not component.isAvailable("gpu") then io.stderr:write("Do you really think you can use a program that uses color to display stuff without even bringing a GPU... what were you thinking?!"); io.stderr:write("You're such a moron that I won't even let you try to run this fancy program...");os.exit() end
  7. local gpu = component.gpu
  8.  
  9. methods = {}
  10.  
  11. methods.patterns = {
  12.   ".*%]%]", --check for closing multiline comments
  13.   "%-%-%[%[.-%]%]", --check for one line multiline comments
  14.   "%-%-%[%[.*", --check for opening multiline comments
  15.   "%-%-.*", --check for normal comments (like this one)
  16.   "[%w%p]+%b()", --check for functions
  17.   "(\'(.-)\')", --check for strings with backed out ' (single quotes)
  18.   "(\"(.-)\")", --check for strings with backed out " (duoble quotes)
  19.   "0x%x%x%x%x%x%x", --check for hexadecimal numbers
  20.   "%w+", --check for any left over words, like variables
  21.   "." --check for any leftover symbols, spaces, etc (cleanup)
  22. }
  23.  
  24. methods.pickColor = {
  25.     "comment",
  26.     "comment",
  27.     "comment",
  28.     "comment",
  29.     "func",
  30.     "str",
  31.     "str",
  32.     "hex",
  33.     "words",
  34.     "leftover"
  35. }
  36.  
  37. methods.colors = {
  38.     comment = 0x696969,
  39.     func = 0x0000ff,
  40.     str = 0x00ff00,
  41.     hex = 0x00ffff,
  42.     words = 0xffffff,
  43.     leftover = 0xffffff
  44. }
  45.  
  46. function methods.parsefile(file, startLine, stopLine)
  47.     if startLine < 1 then startLine = 1 end
  48.     local w, h = gpu.getResolution()
  49.     term.clear()
  50.    
  51.     local function fileRead(fileLocation)
  52.         local text = {}
  53.         if fs.exists(tostring(fileLocation)) then
  54.             local f = io.open(tostring(fileLocation), "r")
  55.             repeat
  56.                 local line = f:read("*line")
  57.                 if line ~= nil then
  58.                     table.insert(text, line)
  59.                 end
  60.             until line == nil
  61.             f:close()
  62.         end
  63.         f = nil
  64.         return text
  65.     end
  66.    
  67.     local function parseLine(line, isStartComment)
  68.         local toReturn = {}
  69.         local nextLineIsComment = false
  70.         if isStartComment then
  71.             if line:find(methods.patterns[1]) ~= nil then
  72.                 local a, b = line:find(methods.patterns[1])
  73.                 --closing comment
  74.                 table.insert(toReturn, {1, methods.colors["comment"], line:sub(1, b)})
  75.                 line = line:sub(b + 1)
  76.             else
  77.                 --no closing comment, so entirely comment
  78.                 nextLineIsComment = true
  79.                 return {{1, methods.colors["comment"], line}}, true
  80.             end
  81.         end
  82.         --now the line does not start with a comment and we run the formats from top to bottom
  83.         --no need to check the first, since that is dealt with up there
  84.         for i = 2, #methods.patterns do
  85.             shouldRep = true
  86.             ::startLoop::
  87.             while shouldRep do
  88.                 local a, b = line:find(methods.patterns[i]) --find the current pattern
  89.                 if a == nil then
  90.                     shouldRep = false
  91.                     goto startLoop
  92.                 end
  93.                 --There is a pattern matching
  94.                 --the pattern is located in a to b
  95.                 if i == 3 then nextLineIsComment = true end
  96.                 table.insert(toReturn, {a, methods.colors[methods.pickColor[i]], line:sub(a,b)})
  97.                 line = line:sub(1, a-1) .. line:sub(b+1)
  98.             end
  99.         end
  100.         return toReturn, nextLineIsComment
  101.     end
  102.    
  103.     local function escapeSequences(str)
  104.         local estr = str
  105.         estr, _ = estr:gsub("%%", "%%%%")
  106.         estr, _ = estr:gsub("%^", "%%^")
  107.         estr, _ = estr:gsub("%$", "%%$")
  108.         estr, _ = estr:gsub("%(", "%%(")
  109.         estr, _ = estr:gsub("%)", "%%)")
  110.         estr, _ = estr:gsub("%.", "%%.")
  111.         estr, _ = estr:gsub("%[", "%%[")
  112.         estr, _ = estr:gsub("%]", "%%]")
  113.         estr, _ = estr:gsub("%*", "%%*")
  114.         estr, _ = estr:gsub("%+", "%%+")
  115.         estr, _ = estr:gsub("%-", "%%-")
  116.         estr, _ = estr:gsub("%?", "%%?")
  117.         --estr, _ = estr:gsub("%%%-%%%-", "--")
  118.         return estr
  119.     end
  120.    
  121.     local function printLine(height, originalLine, splitLine)
  122.         --[[local l = 0
  123.         for i = 1, #splitLine do
  124.             l = l + string.len(splitLine[i][3])
  125.         end
  126.         --now we have the length of the complete sentence
  127.         --Is that useful at all?
  128.         --I kinda doubt it...
  129.         --Can I remove it?
  130.         --Might just need to leave it in, might be used somewhere...]]--
  131.         gpu.set(1, height, originalLine)
  132.         for i = 1, #splitLine do
  133.             gpu.setForeground(splitLine[i][2])
  134.             if originalLine:find(escapeSequences(splitLine[i][3])) ~= nil then
  135.                 gpu.set(originalLine:find(escapeSequences(splitLine[i][3])), height, splitLine[i][3])
  136.             end
  137.         end
  138.     end
  139.    
  140.     local function getLines(linesInFile, start, stop)
  141.         toReturn = {}
  142.         for i = start, math.min(stop, #linesInFile) do
  143.             table.insert(toReturn, linesInFile[i])
  144.         end
  145.         return toReturn
  146.     end
  147.    
  148.     linesInFile = fileRead(file)
  149.     linesToShow = getLines(linesInFile, startLine, math.min(stopLine, startLine + h - 2))
  150.     prevLineEndedInAComment = false
  151.     for i = 1, #linesToShow do
  152.         originalLine = linesToShow[i]
  153.         toShow, prevLineEndedInAComment = parseLine(originalLine, prevLineEndedInAComment)
  154.         term.write("\n")
  155.         printLine(i, originalLine, toShow)
  156.     end
  157. end
  158.  
  159. function methods.parseline(xOff, yOff, str)
  160.    
  161.     local function parseLine(line, isStartComment)
  162.         local toReturn = {}
  163.         local nextLineIsComment = false
  164.         if isStartComment then
  165.             if line:find(methods.patterns[1]) ~= nil then
  166.                 local a, b = line:find(methods.patterns[1])
  167.                 --closing comment
  168.                 table.insert(toReturn, {1, methods.colors["comment"], line:sub(1, b)})
  169.                 line = line:sub(b + 1)
  170.             else
  171.                 --no closing comment, so entirely comment
  172.                 nextLineIsComment = true
  173.                 return {{1, methods.colors["comment"], line}}, true
  174.             end
  175.         end
  176.         --now the line does not start with a comment and we run the formats from top to bottom
  177.         --no need to check the first, since that is dealt with up there
  178.        
  179.         local function wordColorPicker(word)
  180.             local colors = {black = 0x000000, white = 0xf8f8ff, blue = 0x0000ff, lightGray = 0xd9d9d9, red = 0xff0000, purple = 0x9b30ff, carrot = 0xffa500, magenta = 0xcd00cd, lightBlue = 0x87cefa, yellow = 0xffff00, lime = 0x32cd32, pink = 0xffc0cb, gray = 0x696969, brown = 0x8b4500, green = 0x006400, cyan = 0x008b8b, olive = 0x6b8e23, gold = 0x8b6914, orangered = 0xdb4e02, diamond = 0x0fa7c7,crimson = 0xaf002a,fuchsia = 0xfd3f92, folly = 0xff004f, frenchBlue = 0x0072bb, lilac = 0x86608e, flax = 0xeedc82, darkGray = 0x563c5c, englishGreen = 0x1b4d3e, eggplant = 0x614051, deepPink  = 0xff1493, ruby = 0x843f5b, orange = 0xf5c71a, lemon = 0xffd300, darkBlue = 0x002e63, bitterLime = 0xbfff00}
  181.            
  182.             local function pick(word)
  183.                 if word == "if" then return colors.red end
  184.                 if word == "then" then return colors.red end
  185.                 if word == "else" then return colors.red end
  186.                 if word == "end" then return colors.red end
  187.                 if word == "local" then return colors.red end
  188.                 if word == "nil" then return colors.red end
  189.                 if word == "repeat" then return colors.red end
  190.                 if word == "until" then return colors.red end
  191.                 if word == "while" then return colors.red end
  192.                 if word == "function" then return colors.red end
  193.                 if word == "return" then return colors.red end
  194.                 if word == "true" then return colors.yellow end
  195.                 if word == "false" then return colors.yellow end
  196.                 if word == "for" then return colors.red end
  197.                 if word == "in" then return colors.red end
  198.                 if word == "do" then return colors.red end
  199.                 if word == "or" then return colors.gold end
  200.                 if word == "and" then return colors.gold end
  201.                 if word == "not" then return colors.gold end
  202.                 return methods.colors["words"]
  203.             end
  204.            
  205.             return pick(word)
  206.         end
  207.        
  208.         for i = 2, #methods.patterns do
  209.             shouldRep = true
  210.             ::startLoop::
  211.             while shouldRep do
  212.                 local a, b = line:find(methods.patterns[i]) --find the current pattern
  213.                 if a == nil then
  214.                     shouldRep = false
  215.                     goto startLoop
  216.                 end
  217.                 --There is a pattern matching
  218.                 --the pattern is located in a to b
  219.                 if i == 3 then nextLineIsComment = true end
  220.                 local color = methods.colors[methods.pickColor[i]]
  221.                 if methods.pickColor[i] == "words" then
  222.                     color = wordColorPicker(line:sub(a,b))
  223.                 end
  224.                 table.insert(toReturn, {a, color, line:sub(a,b)})
  225.                 line = line:sub(1, a-1) .. line:sub(b+1)
  226.             end
  227.         end
  228.         return toReturn, nextLineIsComment
  229.     end
  230.    
  231.     local function escapeSequences(str)
  232.         local estr = str
  233.         estr, _ = estr:gsub("%%", "%%%%")
  234.         estr, _ = estr:gsub("%^", "%%^")
  235.         estr, _ = estr:gsub("%$", "%%$")
  236.         estr, _ = estr:gsub("%(", "%%(")
  237.         estr, _ = estr:gsub("%)", "%%)")
  238.         estr, _ = estr:gsub("%.", "%%.")
  239.         estr, _ = estr:gsub("%[", "%%[")
  240.         estr, _ = estr:gsub("%]", "%%]")
  241.         estr, _ = estr:gsub("%*", "%%*")
  242.         estr, _ = estr:gsub("%+", "%%+")
  243.         estr, _ = estr:gsub("%-", "%%-")
  244.         estr, _ = estr:gsub("%?", "%%?")
  245.         --estr, _ = estr:gsub("%%%-%%%-", "--")
  246.         return estr
  247.     end
  248.    
  249.     local function printLine(xOff, yOff, originalLine, splitLine)
  250.         --[[local l = 0
  251.         for i = 1, #splitLine do
  252.             l = l + string.len(splitLine[i][3])
  253.         end
  254.         --now we have the length of the complete sentence
  255.         --Is that useful at all?
  256.         --I kinda doubt it...
  257.         --Can I remove it?
  258.         --Might just need to leave it in, might be used somewhere...]]
  259.         --indeed, I ended up 'deleting' it
  260.         gpu.set(xOff, yOff, originalLine)
  261.         for i = 1, #splitLine do
  262.             gpu.setForeground(splitLine[i][2])
  263.             if originalLine:find(escapeSequences(splitLine[i][3])) ~= nil then
  264.                 gpu.set(xOff + originalLine:find(escapeSequences(splitLine[i][3])) - 1, yOff, splitLine[i][3])
  265.             end
  266.         end
  267.     end
  268.    
  269.     prevLineEndedInAComment = false
  270.     originalLine = str
  271.     toShow, prevLineEndedInAComment = parseLine(originalLine, prevLineEndedInAComment)
  272.     printLine(xOff, yOff, originalLine, toShow)
  273. end
  274.  
  275. return methods
Advertisement
Add Comment
Please, Sign In to add comment