Advertisement
faubiguy

Calculator+ v1.3

Oct 12th, 2012
157
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Lua 22.75 KB | None | 0 0
  1. local isColor = term.isColor or function() end
  2. local tArgs = {...}
  3. local mode = tArgs[1]=="advanced" and 2 or 1
  4. local debugOn = false
  5. local log = false
  6. local debugFile = "/calc-debug"
  7. if log then file=fs.open(debugFile, "w") file.close() end
  8. local termX, termY = term.getSize()
  9. local function logText(...)
  10.  text = {...}
  11.  for i=1,#text do text[i] = tostring(text[i]) end
  12.  text = table.concat(text)
  13.  local file = fs.open(debugFile, "a")
  14.  file.writeLine(text)
  15.  file.close()
  16. end
  17. local function display(color, ...)
  18.  if isColor() then term.setTextColor(colors[color]) end
  19.  local args={...}
  20.  for i=1,#args do
  21.   args[i] = tostring(args[i])
  22.  end
  23.  local text = table.concat(args)
  24.  if mode==2 then
  25.   term.clearLine()
  26.   print(...)
  27.   if ({term.getCursorPos()})[2] == termY then
  28.    term.scroll(1)
  29.    term.setCursorPos(1, termY-1)
  30.    term.write(string.rep("-", termX))
  31.    term.setCursorPos(1, termY-1)
  32.   end
  33.  elseif mode==1 then
  34.   term.setCursorPos(1,1)
  35.   term.clearLine()
  36.   if #text > termX then
  37.    local newText = text:sub(#text-termX)
  38.   else newText = text
  39.   end
  40.   term.write(newText)
  41.  end
  42.  if log then
  43.   logText(text)
  44.  end
  45.  if isColor() then term.setTextColor(colors.black) end
  46. end
  47.  
  48. if isColor() then term.setTextColor(colors.black) end
  49. if isColor() then term.setBackgroundColor(colors.lightGray) end
  50.  
  51. local function debug(...) if debugOn then display("black", ...) else logText(...) end return ... end
  52.  
  53. local defaultFile = [=[
  54. --[[
  55. This is the custom settings file. Custom operators
  56. functions, and constants can be added like this:
  57.  
  58. Operator{
  59.   symbol = "+",
  60.   precedence = 32,
  61.   func = function(a,b) return a+b end,
  62.   associativity = "left"
  63. }
  64.  
  65. The fields precedence and associativity are
  66. optional. Precedence is a positive number, and
  67. operators with higher precedences are evaluated
  68. first. Default for precedence is 1. Associativity
  69. may be "left" or "right, and determines the
  70. operands to evaluate when two operators have equal
  71. precedence. Default for associativity is "left".
  72. In addition, there is another optional field,
  73. variables. If it is set to true, variables will
  74. be passed to operator function as the the name,
  75. as a string, instead of the value. Unless you're
  76. doing something special, you shouldn't use this.
  77. If you do need to interact with variables, they
  78. are stored in the table vars, and may be accessed
  79. by vars[name].
  80.  
  81. You may also add custom constants, like this:
  82.  
  83. Constant{
  84.   name = "thirteen",
  85.   value = 13
  86. }
  87.  
  88. Lastly, you can add custom functions:
  89.  
  90. Function{
  91.   name = "rand",
  92.   arguments = 1,
  93.   func = math.rand
  94. }
  95.  
  96. Functions must have a specified number of
  97. arguments, and any other arguments passed to them
  98. will be ignored. The variables field also applies
  99. to functions.
  100. ]]
  101.  
  102. --Content goes below here:
  103. ]=]
  104.  
  105. local function tokenize(expression) -- Done
  106.  debug("Tokenizing expression: " .. expression)
  107.  expression = string.gsub(expression, "%s+", "")
  108.  debug("Removed Whitespace\nNew expression: ".. expression)
  109.  local tokens = {}
  110.  local matched = false
  111.  for token1, number, token2 in string.gmatch(expression, "([^%d]*)(%d*%.?%d+)([^%d]*)") do
  112.   matched = true
  113.   debug("Found match\nSeperating first set of tokens")
  114.   while token1 ~= "" do
  115.    local match, pos = string.match(token1, "^(%a+)()")
  116.    if match then
  117.     table.insert(tokens, match)
  118.     token1 = token1:sub(pos)
  119.    else
  120.     table.insert(tokens ,token1:sub(1,1))
  121.     token1 = token1:sub(2)
  122.    end
  123.   end
  124.   table.insert(tokens, number)
  125.   debug("Seperating second set of tokens")
  126.   while token2 ~= "" do
  127.    local match, pos = string.match(token2, "^(%a+)()")
  128.    if match then
  129.     table.insert(tokens, match)
  130.     token2 = token2:sub(pos)
  131.    else
  132.     table.insert(tokens ,token2:sub(1,1))
  133.     token2 = token2:sub(2)
  134.    end
  135.   end
  136.  end
  137.  if not matched then
  138.   while expression ~= "" do
  139.    local match, pos = string.match(expression, "^(%a+)()")
  140.    if match then
  141.     table.insert(tokens, match)
  142.     expression = expression:sub(pos)
  143.    else
  144.     table.insert(tokens ,expression:sub(1,1))
  145.     expression = expression:sub(2)
  146.    end
  147.   end
  148.  end
  149.  debug("Returning from tokenize")
  150.  if tokens == {} then display("red", "Unable to parse expression") return else return tokens end
  151. end
  152.  
  153. local functions = {
  154. sin = {func = math.sin, args = 1},
  155. cos = {func = math.cos, args = 1},
  156. tan = {func = math.tan, args = 1},
  157. random = {func = math.random, args = 0},
  158. abs = {func = math.abs, args = 1},
  159. acos = {func = math.acos, args = 1},
  160. asin = {func = math.asin, args = 1},
  161. atan = {func = math.atan, args = 1},
  162. atan2 = {func = math.atan2, args = 2},
  163. ceil = {func = math.ceil, args = 1},
  164. cosh = {func = math.cosh, args = 1},
  165. deg = {func = math.deg, args = 1},
  166. exp = {func = math.exp, args = 1},
  167. floor = {func = math.floor, args = 1},
  168. fmod = {func = math.fmod, args = 2},
  169. frexp = {func = math.frexp, args = 1},
  170. ldexp = {func = math.ldexp, args = 2},
  171. log = {func = math.log, args = 1},
  172. logten = {func = function(num) return math.log(num, 10) end, args = 1},
  173. logtwo = {func = function(num) return math.log(num, 2) end, args = 1},
  174. logbase = {func = math.log, args = 2},
  175. min = {func = math.min, args = 2},
  176. max = {func = math.max, args = 2},
  177. pow = {func = math.pow, args = 2},
  178. rad = {func = math.rad, args = 1},
  179. randomseed = {func = math.randomseed, args = 1},
  180. sinh = {func = math.sinh, args = 1},
  181. sqrt = {func = math.sqrt, args = 1},
  182. tanh = {func = math.tanh, args = 1},
  183. randomrange = {func = math.random, args = 2}
  184. }
  185.  
  186. local constants = {
  187. pi = math.pi,
  188. e = math.exp(1),
  189. inf = math.huge
  190. }
  191.  
  192. local operators = {
  193. ["+"] = {func = function(a,b) return a+b end, precedence = 32, leftAssociative = true, args = 2},
  194. ["-"] = {func = function(a,b) return a-b end, precedence = 32, leftAssociative = true, args = 2},
  195. ["*"] = {func = function(a,b) return a*b end, precedence = 64, leftAssociative = true, args = 2},
  196. ["/"] = {func = function(a,b) return a/b end, precedence = 64, leftAssociative = true, args = 2},
  197. ["^"] = {func = function(a,b) return a^b end, precedence = 96, leftAssociative = false, args = 2},
  198. ["%"] = {func = function(a,b) return a%b end, precedence = 64, leftAssociative = true, args = 2},
  199. ["="] = {func = function(a,b) debug("= recieved args: ",a," and ",b) if not tonumber(a) then vars[a] = vars[b] debug("Set variable ",a," to ",vars[b]) else debug("Did not set variable: ",a," to ",vars[b]) end return b end, precedence = 16, leftAssociative = false, args = 2, getVars = true}
  200. }
  201.  
  202. setmetatable(functions, {__index = operators})
  203.  
  204. vars = {}
  205. setmetatable(vars, {__index = function(_, value) return tonumber(value) end})
  206.  
  207. local function shuntingYard(tokens) -- Done
  208.  debug("Shunting yard input: ", table.concat(tokens, " "))
  209.  local output = {}
  210.  local stack = {}
  211.  local x = #tokens
  212.  while #tokens>0 do
  213.   if x>0 then debug("Tokens left: ",#tokens) x=x-1 end
  214.   debug("Stack: ",table.concat(stack, " "))
  215.   local token = table.remove(tokens, 1)
  216.   if tonumber(token) and token~="-" then debug("Token is a number: ",token)
  217.    table.insert(output, tonumber(token))
  218.   elseif operators[token] then debug("Token is an operator: ",token)
  219.    while operators[stack[#stack]] and ((operators[token].leftAssociative and operators[token].precedence <= operators[stack[#stack]].precedence) or operators[token].precedence < operators[stack[#stack]].precedence) do
  220.     table.insert(output, table.remove(stack))
  221.    end
  222.    table.insert(stack, token)
  223.   elseif functions[token] then debug("Token is a function: ",token)
  224.    table.insert(stack, token)
  225.   elseif token == "," then debug("Token is a comma")
  226.    local leftParen = false
  227.    while #stack > 0 do
  228.     if stack[#stack] == "(" then
  229.      leftParen = true
  230.      break
  231.     end
  232.     table.insert(output, table.remove(stack))
  233.    end
  234.    if not leftParen then
  235.     display("red", "Error: misplaced comma or parentheses")
  236.     return false
  237.    end
  238.   elseif token == "(" then debug("Token is a left parentheses")
  239.    table.insert(stack, token)
  240.   elseif token == ")" then debug("Token is a right parentheses")
  241.    local leftParen = false
  242.    while #stack > 0 do
  243.     if stack[#stack] == "(" then
  244.      table.remove(stack)
  245.      leftParen = true
  246.      if functions[stack[#stack]] then
  247.       table.insert(output, table.remove(stack))
  248.      end
  249.      break
  250.     else
  251.      table.insert(output, table.remove(stack))
  252.     end
  253.    end
  254.    if not leftParen then
  255.     display("red", "Error: mismatched parentheses")
  256.     return false
  257.    end
  258.   elseif constants[token] then debug("Token is a constant: ",constants[token])
  259.    table.insert(output, constants[token])
  260.   elseif vars[token] ~= token then debug("Token is a variable: ",token)
  261.    table.insert(output, "var:"..token)
  262.   elseif token == string.match(token, "%a+") then debug("Token is a possible variable: ",token)
  263.    table.insert(output, "var:"..token)
  264.   else
  265.    display("red", "Error: unknown symbol or identifier")
  266.    return false
  267.   end
  268.  end
  269.  x=#stack
  270.  debug("Items in stack = ",x)
  271.  while #stack > 0 do
  272.   if x>0 then debug("Token in stack: ",stack[#stack]) x=x-1 end
  273.   if stack[#stack] == "(" or stack[#stack] == ")" then
  274.    display("red", "Error: mismatched parentheses")
  275.    return false
  276.   end
  277.   table.insert(output, table.remove(stack))
  278.  end
  279.  debug("Shunting yard output: ", table.concat(output, " "))
  280.  return output
  281. end
  282.    
  283. local function operator(op)
  284.  if type(op) ~= "table" then return end
  285.  if type(op.symbol) == "string" and #op.symbol==1 and not string.match(op.symbol, "%w") and type(op.func == "function") then
  286.   if type(op.precedence)~="number" or op.precedence<=0 then op.precedence = 1 end
  287.   if op.associativity ~= "left" and op.associativity ~= "right" then op.associativity = "left" end
  288.   operators[op.symbol] = {func = op.func, precedence = op.precedence, leftAssociative = op.associativity == "left", args = 2}
  289.   if op.variables then operators[op.symbol].getVars = true end
  290.   debug("Added operator: ",op.symbol)
  291.  end  
  292. end
  293.  
  294. local function constant(con)
  295.  if type(con) ~= "table" then return end
  296.  if type(con.name) == "string" and type(con.value) == "number" then
  297.   constants[name] = value
  298.  end
  299. end
  300.  
  301. local function func(fun)
  302.  if type(fun) ~= "table" then return end
  303.  if type(fun.name) == "string" and string.match(fun.name, "%a+") == fun.name and type(fun.arguments) == "number" and fun.arguments >= 0 and type(fun.func) == "function" then
  304.   functions[fun.name] = {func = fun.func, args = fun.arguments}
  305.   if fun.variables then functions[fun.name].getVars = true end
  306.  end
  307. end
  308.  
  309. local function loadCustom() -- Done
  310.  display("black", "Loading custom settings")
  311.  if not fs.exists("Programs/calculator/custom") then
  312.   if not pcall(fs.makeDir, "Programs/calculator") then
  313.    display("red", "Unable to create directory /Programs/calculator")
  314.    return false
  315.   end
  316.   local file = fs.open("Programs/calculator/custom", "w")
  317.   file.write(defaultFile)
  318.   file.close()
  319.   display("black", "Custom settings file created at /Programs/calculator/custom")
  320.  end
  321.  customFile = loadfile("Programs/calculator/custom")
  322.  if not customFile then display("red", "Error: failed to load custom settings")
  323.   return false
  324.  end
  325.  setfenv(customFile, {Operator = operator, Constant = constant, Function = func})
  326.  ok = pcall(customFile)
  327.  if not ok then display("red", "Error: failed to load custom settings")
  328.   return false
  329.  else display("black", "Successfully loaded custom settings")
  330.  end
  331. end
  332.  
  333. local function evaluate(expression) -- Done
  334.  local stack = {}
  335.  local x=#expression
  336.  while #expression > 0 do
  337.   if x>0 then debug("Evaluating for token: ",expression[#expression]) x=x-1 end
  338.   table.insert(stack, table.remove(expression, 1))
  339.   if functions[stack[#stack]] then
  340.    debug("Applying function: ",stack[#stack]," to stack: ",table.concat(stack," "))
  341.    local func = functions[table.remove(stack)]
  342.    if #stack<func.args then display("red", "Error: Invalid expression") return false end
  343.    local operands = {}
  344.    local newSize = #stack-func.args
  345.    while #stack > newSize do
  346.     table.insert(operands, table.remove(stack, newSize+1))
  347.    end
  348.    for index,operand in ipairs(operands) do
  349.     if string.sub(operand, 1, 4) == "var:" then
  350.      if not operand:sub(5):match("%a+") then display("red", "Error: Invalid expression") return false end
  351.      if func.getVars then operands[index] = string.sub(operand, 5) else operands[index] = vars[string.sub(operand, 5)] end
  352.     end
  353.     if not operands[index] then display("red", "Variable ", string.sub(operand, 5), " does not exist") return false end
  354.    end
  355.    if #operands ~= func.args then display("red", "An unknown error occured while evaluating") return false end
  356.    table.insert(stack, func.func(unpack(operands)))
  357.   elseif type(stack[#stack])~="number" and string.sub(stack[#stack], 1, 4) ~= "var:" then
  358.    display("red", "An unknown token was encountered while evaluating")
  359.    return false
  360.   end
  361.  end
  362.  if #stack ~= 1 then
  363.   display("red", "Error: Invalid expression")
  364.   return false
  365.  end
  366.  local result = stack[1] debug("Result is ",result)
  367.  if string.sub(result, 1, 4)=="var:" then if not result:sub(5):match("%a+") then display("red", "Error: Invalid expression") return false end debug("Result is variable: ",result) result = vars[string.sub(result,5)] debug("New result = ",result) end
  368.  if not result then result = "That variable is not defined" end
  369.  return result
  370. end
  371.  
  372. local function fixArgs(expression) -- Done
  373.  --[[local failed = false
  374.  expression = string.gsub(expression, "(%a+)%s*(%b%(%))",
  375.  function(func, args) debug("fixArgs found function: ", func.."("..table.concat(argList, ",")..")")
  376.   if not functions[func] then failed = true display("red", "No such function: ", func) return end
  377.   local args = functions[func].args
  378.   local argList = {}
  379.   for arg in string.gmatch(args, "[^%(%),]+") do table.insert(argList, arg) end
  380.   while argList[args+1] do
  381.    table.remove(argList, args+1)
  382.   end
  383.   if #argList < args then failed = true display("red", "Function ", func, " requires ", args, " arguments.") return end
  384.   return func.."("..table.concat(argList, ",")..")"
  385.  end)
  386.  if failed then return false else debug("fixArgs produced " .. expression) return expression end]]
  387.  --[[local function findIn(collection, item)
  388.   local postitons = {}
  389.   for i=1,#collection do
  390.    if collection[i] == item then table.insert(positions, i) end
  391.   end
  392.  end
  393.  local wordPos = {}
  394.  for i=1,#expression do
  395.   if expression[i] = string.match(expression[i], "%a+") then table.wordPos[i] = true end
  396.  end
  397.  local leftParen = findIn(expression, "(")
  398.  local rightParen = findIn(expression, ")")
  399.  if #leftParen ~= #rightParen then display("red", "Error: mismatched parentheses") return false end
  400.  local
  401.  for ]]
  402.  return expression
  403. end
  404.  
  405. local function fixNegative(expression)
  406.  local currentPos = 1
  407.  while true do
  408.   local startPos, endPos = string.find(expression, "%-%d+", currentPos)
  409.   if not startPos then break end
  410.   currentPos = endPos+1
  411.   if not string.match(string.sub(expression, startPos-1, startPos-1), "[%a%d%)]") then
  412.    expression = string.sub(expression, 1, startPos-1).."0"..string.sub(expression, startPos)
  413.   end
  414.  end
  415.  debug("fixNegative produced " .. expression)
  416.  return expression
  417. end
  418.  
  419. local function command(expression) -- Done
  420.  local cmd, param = string.match(expression, "(%a+)%s?(%a*)")
  421.  local commands = {
  422.   delete = function(var) if var == "" or var == " " then display("red", "No variable specifed to delete") return "delete" end if vars[var] then vars[var] = nil display("black", "Deleted variable: ",var) else display("red", var," is not a variable") end return "delete" end,
  423.   vars = function() local found = false for var,value in pairs(vars) do found = true display("black", var,"=",value) end if not found then display("black", "There are no variables") end return "vars" end,
  424.   ["exit"] = function(e) if e == "" then return "exit" end end,
  425.   get = function(param) if functions[param] then display("black", "Function") elseif constants[param] then display("black", "Constant: ", constants[param]) elseif vars[param] then display("black", "Variable: ", vars[param]) else display("black", "Not a function, constant, or variable") end return "get" end,
  426.   buttons = function() mode = 1 return "exit" end,
  427.   --debug = function(on) if on=="on" then debugOn=true display("black", "Debug Enabled") elseif on=="off" then debugOn=false display("black", "Debug Disabled") end return "debug" end,
  428.   --log = function(load) if load == "reload" then reload = true end shell.run("edit", debugFile) return "exit" end,
  429.   --reload = function() reload = true return "exit" end,
  430.  }
  431.  commands.commands = function() local cmds = {} for key in pairs(commands) do table.insert(cmds, key) end local list = "Commands: "..table.concat(cmds, ", ") display("black", list) return "commands" end
  432.  if commands[cmd] then return commands[cmd](param) end
  433. end
  434.  
  435. local function textUI() -- Done
  436.  local history = {}
  437.  term.clear()
  438.  if ({term.getCursorPos()})[2] == termY then term.scroll(1) end
  439.  term.setCursorPos(1, termY-1)
  440.  term.write(string.rep("-", termX))
  441.  term.setCursorPos(1, termY-1)
  442.  term.setCursorPos(1, termY)
  443.  loadCustom()
  444.  local running = true
  445.  term.setCursorBlink(true)
  446.  while running do
  447.  while running do
  448.   if ({term.getCursorPos()})[2] == termY then term.scroll(1) end
  449.   term.setCursorPos(1, termY-1)
  450.   term.write(string.rep("-", termX))
  451.   term.setCursorPos(1, termY-1)
  452.   term.setCursorPos(1, termY)
  453.   write("Input: ")
  454.   local expression = read(nil, history)
  455.   term.setCursorPos(1, termY-1)
  456.   term.scroll(1)
  457.   term.clearLine()
  458.   table.insert(history, expression)
  459.   local cmd = command(expression)
  460.   if cmd then if cmd == "exit" then running = false end break end
  461.   expression = fixNegative(expression)
  462.   if not expression then break end
  463.   expression = fixArgs(expression)
  464.   if not expression then break end
  465.   expression = tokenize(expression)
  466.   if not expression then break end
  467.   expression = shuntingYard(expression)
  468.   if not expression then break end
  469.   expression = evaluate(expression)
  470.   if not expression then break end
  471.   display("black", "Result: ", expression)
  472.  end
  473.  end
  474.  term.setCursorPos(1, termY)
  475. end
  476.  
  477. local function GUI()
  478.  if termY < 18 or termX < 23 then print("Error: Terminal is too small") return end
  479.  local running = true
  480.  term.setCursorBlink(false)
  481.  term.clear()
  482.  local row, column = 1, 1
  483.  local rowMax, columnMax = 5, 4
  484.  local symbols = {
  485.   {"<--", " ( ", " ) ", "adv"},
  486.   {" 7 ", " 8 ", " 9 ", " / "},
  487.   {" 4 ", " 5 ", " 6 ", " * "},
  488.   {" 1 ", " 2 ", " 3 ", " - "},
  489.   {" 0 ", " . ", " = ", " + "}
  490.  }
  491.  local function buttonFunctions(rowNum, columnNum)
  492.   if not rowNum or not columnNum or rowNum < 1 or rowNum > 5 or columnNum < 1 or columnNum > 4 then return function() end end
  493.   if rowNum == 1 and columnNum == 1 then return function(e) return string.sub(e, 1, #e-1) end
  494.   elseif rowNum == 1 and columnNum == 4 then return function() running = false mode = 2 return "" end
  495.   elseif rowNum == 5 and columnNum == 3 then return function(expression)
  496.    term.setCursorPos(1,1) term.clearLine()
  497.    for _=1,1 do
  498.     expression = fixNegative(expression)
  499.     if not expression then break end
  500.     expression = fixArgs(expression)
  501.     if not expression then break end
  502.     expression = tokenize(expression)
  503.     if not expression then break end
  504.     expression = shuntingYard(expression)
  505.     if not expression then break end
  506.     expression = evaluate(expression)
  507.     if not expression then break end
  508.     display("black", "Result: ",expression)
  509.    end
  510.    sleep(2)--while true do local e,p=os.pullEvent("key") if p~=1 then break end end
  511.    return ""
  512.   end
  513.   else return function(e) return e..symbols[rowNum][columnNum]:sub(2,2) end end
  514.  end
  515.  local yPos = {4, 7, 10, 13, 16}
  516.  local xPos = {1, 7, 13, 19}
  517.  for i=1,4 do xPos[i] = xPos[i] + math.floor((termX-23)/2) end
  518.  xPosReverse = {}
  519.  local yPosReverse = {}
  520.  for value,key in ipairs(yPos) do yPosReverse[key] = value end
  521.  for value,key in ipairs(xPos) do xPosReverse[key] = value end
  522.  local function button(y, x, symbol, highlight)
  523.   local border = highlight and "=====" or "-----"
  524.   term.setCursorPos(x, y)
  525.   term.write(border)
  526.   term.setCursorPos(x, y+1)
  527.   term.write("|"..symbol.."|")
  528.   term.setCursorPos(x, y+2)
  529.   term.write(border)
  530.  end
  531.  local function getButton(x, y)
  532.   debug("getButton called with: ",x,", ",y)
  533.   x, y = x - (math.floor((termX-23)/2)+1), y - 4
  534.   x, y = x%6 ~=5 and (x-(x%6))+math.floor((termX-23)/2)+1 or nil, (y-(y%3))+4
  535.   x, y = xPosReverse[x], yPosReverse[y]
  536.   debug("getButton returned: ",x or "nil",", ",y or "nil")
  537.   return y, x
  538.  end
  539.  local allowedChars = {["+"]= true, ["-"] = true, ["*"] = true, ["/"] = true, ["."] = true}
  540.  for char=0,9 do allowedChars[tostring(char)] = true end
  541.  for row=1,rowMax do
  542.  for column=1,columnMax do
  543.   button(yPos[row], xPos[column], symbols[row][column], (row == 1 and column == 1) and true)
  544.  end
  545.  end
  546.  local expression = "Calculator+. Press CTRL to exit."
  547.  local msg = true
  548.  local timer = os.startTimer(2)
  549.  term.setCursorPos(1, 2) term.clearLine() term.write(string.rep("-", termX))
  550.  while running do
  551.  while running do
  552.   display("black", expression)
  553.   local e,p,p2,p3 = os.pullEvent()
  554.   if e == "timer" and p==timer then
  555.    if msg then msg = false expression = "" end
  556.   elseif e == "key" then
  557.    if msg then msg = false expression = "" end
  558.    if p == keys.enter then
  559.     expression = buttonFunctions(row, column)(expression)
  560.    elseif p == keys.up and row > 1 then
  561.     button(yPos[row], xPos[column], symbols[row][column], false)
  562.     row = row - 1
  563.     button(yPos[row], xPos[column], symbols[row][column], true)
  564.    elseif p == keys.down and row < rowMax then
  565.     button(yPos[row], xPos[column], symbols[row][column], false)
  566.     row = row + 1
  567.     button(yPos[row], xPos[column], symbols[row][column], true)
  568.    elseif p == keys.left and column > 1 then
  569.     button(yPos[row], xPos[column], symbols[row][column], false)
  570.     column = column - 1
  571.     button(yPos[row], xPos[column], symbols[row][column], true)
  572.    elseif p == keys.right and column < columnMax then
  573.     button(yPos[row], xPos[column], symbols[row][column], false)
  574.     column = column + 1
  575.     button(yPos[row], xPos[column], symbols[row][column], true)
  576.    elseif p == keys.backspace then
  577.     expression = string.sub(expression, 1, #expression-1)
  578.    elseif p == keys.leftCtrl or p == keys.rightCtrl then
  579.     display("black", "Thank you for using Calculator+")
  580.     running = false
  581.     sleep(2)
  582.    end
  583.   elseif e == "char" then
  584.    if msg then msg = false expression = "" end
  585.    if allowedChars[p] then expression = expression..p
  586.    elseif p == "=" then expression = buttonFunctions(5,3)(expression) end
  587.   elseif e == "click" then
  588.    if msg then msg = false expression = "" end
  589.    expression = buttonFunctions(getButton(p, p2))(expression) or expression
  590.   end
  591.  end
  592.  end
  593.  term.clear()
  594.  term.setCursorPos(1,1)
  595. end
  596.  
  597. local function main()
  598.  local currentMode
  599.  local modes = {GUI, textUI}
  600.  repeat
  601.   currentMode = mode
  602.   modes[mode]()
  603.  until currentMode == mode
  604. end
  605.  
  606. main()
  607.  
  608. if isColor() then term.setBackgroundColor(colors.black) end
  609. term.clear()
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement