Advertisement
konalisp

terminal.lua

Jul 19th, 2017
80
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Lua 10.73 KB | None | 0 0
  1. terminal = { }
  2. terminal.cx = 10 --X origin
  3. terminal.cy = 10 --Y origin
  4. terminal.cpw = 530 --total width
  5. terminal.cph = 310 --total height
  6. terminal.bw = 24 --titlebar width, minus X button
  7. terminal.bh = 22 --titlebar height
  8. terminal.bwidth = 3 --boarder width
  9. terminal.render = true --if terminal should render
  10. terminal.focus = true --if terminal has focus
  11. terminal.inputt = "" --terminal text
  12. terminal.command = "" --command to interpret
  13. terminal.curstimer = 0 --cursor blinking timer
  14. terminal.dir = "C:\\"
  15. terminal.prompt = "\n" .. terminal.dir .. "> \0"
  16. terminal.tcursor = "█" --the blinking cursor
  17. terminal.cursor = " "
  18. terminal.linebreaks = 0
  19. terminal.copyright = "Command Prompt [Version 6.0.1]\n"
  20. terminal.env = {} --lua enviornment
  21. terminal.dragging = { active = false, diffX = 0, diffY = 0 }
  22.  
  23. local utf8 = require("utf8")
  24.  
  25. function terminal:update(dt)
  26. if self.render == true then
  27.     self.prompt = "\n" .. self.dir .. "> \0"
  28.     self.curstimer = self.curstimer - dt*100
  29.     if self.dragging.active then
  30.         self.focus = true
  31.         local xx, yy
  32.         xx = love.mouse.getX() - self.dragging.diffX
  33.         yy = love.mouse.getY() - self.dragging.diffY
  34.         --check if X/Y is even, for more reliable rendering
  35.         if (xx % 2 == 0) then else
  36.             xx = xx - 1 end
  37.         if (yy % 2 == 0) then else
  38.             yy = yy - 1 end
  39.         self.cx = xx
  40.         self.cy = yy
  41.     end
  42.    
  43.     --check if the terminal is leaving the upper/left part of the screen
  44.     --don't remove this, the terminal renders incorrectly if it's upperleft corner
  45.     --leaves the screen.
  46.     if self.cx <= 4 then self.cx = 4 end
  47.     if self.cy <= 4 then self.cy = 4 end
  48.     --check if the terminal leaves the lower/right side of the screen.
  49.     --this is optional, and can be disabled
  50.     --if self.cx >= love.window.getWidth()-self.cpw then self.cx = love.window.getWidth()-self.cpw-1 end
  51.     --if self.cy >= love.window.getHeight()-self.cph then self.cy = love.window.getHeight()-self.cph-1 end
  52. else end
  53. end
  54.  
  55. function terminal:mousepress(x, y, button)
  56. if self.render == true then
  57.     --boarder dragging
  58.     if button == "l"
  59.     and ((x > self.cx and x < self.cx + self.cpw-self.bw)
  60.     and (y > self.cy and y < self.cy + self.bh))
  61.     then
  62.         self.dragging.active = true
  63.         self.dragging.diffX = x - self.cx
  64.         self.dragging.diffY = y - self.cy
  65.     end
  66.    
  67.     --lose focus if clicking anywhere that isn't the window
  68.     if button == "l"
  69.     and ((x > self.cx or x < self.cx + self.cpw)
  70.     or (y < self.cy or y > self.cy + self.cph))
  71.     then
  72.         self.focus = false
  73.     end
  74.    
  75.     --get focus if clicking anywhere on the window
  76.     if button == "l"
  77.     and ((x > self.cx and x < self.cx + self.cpw)
  78.     and (y > self.cy and y < self.cy + self.cph))
  79.     then
  80.         self.focus = true
  81.     end
  82.    
  83.     --X button functionality
  84.     if button == "l"
  85.     and ((x > self.cx+self.cpw-self.bw and x < self.cx+self.cpw)
  86.     and (y > self.cy and y < self.cy + self.bh))
  87.     then
  88.         self.render = false
  89.     end
  90.    
  91. else end
  92. end
  93.  
  94. function terminal:mouserelease(x, y, button)
  95. if self.render == true then
  96.     if button == "l" then self.dragging.active = false end
  97. else end
  98. end
  99.  
  100. function terminal:print(text)
  101.     self.inputt = self.inputt .. text
  102. end
  103.  
  104. function terminal:printn(text)
  105.     self.inputt = self.inputt .. "\n" .. text
  106.     self.linebreaks = self.linebreaks + 1
  107. end
  108.  
  109. function terminal:commands()
  110.     local cc = function(s)
  111.         if string.find(self.command, s, 1, string.len(s)) then
  112.             return 1
  113.         end
  114.         return nil
  115.     end
  116.     if cc("sing") then
  117.         self:printn("la la la")
  118.         self:print(string.sub(self.command, 5, -1))
  119.     elseif cc("help") then
  120.         self:printn("= taller\n- shorter\n. wider\n, thinner\nF1 spawn/toggle terminal\nControls only work when terminal doesn't have focus.")
  121.     else
  122.         return nil
  123.     end
  124.     return 1
  125. end
  126.  
  127. function terminal:interp()
  128. --check for obvious blunders like redefining love callbacks
  129. --and do not allow them unless the string contains "sudo"
  130. --in which point ask if they're sure they want to do that.
  131. --
  132. --use pcall here.
  133.     if self.command ~= "" and not self:commands() then
  134.         local rs = "return " .. self.command
  135.         if string.find(self.command, "=") then
  136.             rs = self.command .. " return \"" .. self.command .. "\""
  137.         end
  138.         local pout,err = load(rs)
  139.         if pout ~= nil then
  140.             local out = setfenv(pout, getfenv(0))
  141.             self:printn(tostring(out()))
  142.         else
  143.             self:printn("nil\n" .. err)
  144.         end
  145.     end
  146. end
  147.  
  148. function terminal:textinput(t)
  149. if self.render == true and self.focus == true then
  150.     if t == "\"" then t = "'" end
  151.     self.inputt = self.inputt .. t
  152.     self.command = self.command .. t
  153. else end
  154. end
  155.  
  156. function terminal:keyboard(key)
  157.     if key == "f1" then
  158.         self.render = not self.render
  159.     end
  160. if self.render == true and self.focus == true then
  161.     if key == "backspace" and string.sub(self.inputt, -1) ~= '\0' then
  162.         -- get the byte offset to the last UTF-8 character in the string.
  163.         local byteoffset1 = utf8.offset(self.inputt, -1)
  164.         local byteoffset2 = utf8.offset(self.command, -1)
  165.         if byteoffset1 then
  166.             -- remove the last UTF-8 character.
  167.             -- string.sub operates on bytes rather than UTF-8 characters, so we couldn't do string.sub(text, 1, -2).
  168.             self.inputt = string.sub(self.inputt, 1, byteoffset1 - 1)
  169.         end
  170.         if byteoffset2 then
  171.             self.command = string.sub(self.command, 1, byteoffset2 - 1)
  172.         end
  173.     elseif key == "return" then
  174.         self:interp()
  175.         self:print(self.prompt)
  176.         self.command = ""
  177.     end
  178.  
  179. else
  180.     if key == "." then self.cpw = self.cpw + 10 end
  181.     if key == "," then if self.cpw > 100 then self.cpw = self.cpw - 10 else end end
  182.     if key == "=" then self.cph = self.cph + 10 end
  183.     if key == "-" then if self.cph > 100 then self.cph = self.cph - 10 else end end
  184. end
  185. end
  186.  
  187. function terminal:init(x,y,o)
  188.     o.cx = x
  189.     o.cy = y
  190.     return o
  191. end
  192.  
  193. function terminal:spawn(x,y)
  194.     return self:init(x,y,table.copy(terminal))
  195. end
  196.  
  197. function terminal:drawterm()
  198.     local x, y = self.cx, self.cy
  199.     local pw,ph = self.cpw, self.cph
  200.     local w, h = x+pw,y+ph
  201.    
  202.     local name = "Command Prompt" --.. " X:" .. self.cx .. " Y:" .. self.cy
  203.     local font = love.graphics.newFont("assets/console.ttf", 14)
  204.     local inputfont = love.graphics.newFont("assets/console.ttf", 15)
  205.     local canvas = love.graphics.newCanvas(w, h)
  206.     local textcanvas = love.graphics.newCanvas(w-self.bwidth-1, h-self.bwidth-1)
  207.    
  208.     love.graphics.setCanvas(canvas)
  209.     canvas:clear()
  210.     love.graphics.setFont(font)
  211.    
  212.     --boarder
  213.     love.graphics.setColor(60, 60, 60, 255)
  214.     love.graphics.rectangle('fill', x-self.bwidth, y-self.bwidth, w, h)
  215.    
  216.     --terminal
  217.     love.graphics.setColor(20, 20, 20, 255)
  218.     love.graphics.rectangle('fill', x, y, pw-self.bwidth, ph-self.bwidth)
  219.    
  220.     --title bar
  221.     love.graphics.setColor(60, 60, 60, 255)
  222.     love.graphics.rectangle('fill', x, y, w, self.bh)
  223.     if self.focus == true then love.graphics.setColor(200, 200, 200, 255)
  224.     else love.graphics.setColor(120, 120, 120, 255) end
  225.     love.graphics.print(name, x+4, y+4)
  226.    
  227.     --X button
  228.     love.graphics.setColor(100, 20, 20, 255)
  229.     love.graphics.rectangle('fill', x+pw-22, y+2, 16, 15)
  230.     love.graphics.setColor(180, 0, 0, 255)
  231.     love.graphics.rectangle('fill', x+pw-21, y+3, 14, 13)
  232.     love.graphics.setColor(200, 100, 100, 255)
  233.     love.graphics.line(x+pw-21, y+3, x+pw-7, y+16)
  234.     love.graphics.line(x+pw-7, y+3, x+pw-21, y+16)
  235.    
  236.     --terminal canvas
  237.     love.graphics.setCanvas(textcanvas)
  238.     textcanvas:clear()
  239.     love.graphics.setFont(font)
  240.     love.graphics.setColor(200, 200, 200, 255)
  241.    
  242.     --blinking cursor
  243.     if self.curstimer <= 0 then
  244.         self.curstimer = 100
  245.     elseif self.curstimer <= 60 and self.focus == true then
  246.         self.cursor = self.tcursor
  247.     else
  248.         self.cursor = " "
  249.     end
  250.    
  251.     --text scrolling
  252.     local nlcheck = function(s)
  253.         local nln = 1 --number of newlines
  254.         for i=1,string.len(s) do
  255.             if string.sub(s, i, i) == "\n" then
  256.             nln = nln + 1 end
  257.         end
  258.         return nln
  259.     end
  260.    
  261.     local textwrap = function(stra, limit, indent)
  262.     limit = limit or 72
  263.     indent = indent or ""
  264.     return stra:gsub("(%s+)()(%S+)()",
  265.         function(sp, st, word, fi)
  266.             if (fi-1-#"") > limit then
  267.                 here = st - #indent
  268.                 return "\n"..indent..word
  269.             end
  270.         end)
  271.     end
  272.    
  273.     local llb = self.copyright .. self.prompt .. self.inputt .. self.cursor
  274.    
  275.     while nlcheck(llb) > self.cph / inputfont:getHeight("A") do
  276.         llb = string.sub(llb, self.cph / inputfont:getHeight("A"))
  277.         --llb = textwrap(llb, self.cpw / inputfont:getWidth("A"))
  278.     end
  279.    
  280.     --print everything
  281.     love.graphics.printf(llb, x+self.bwidth+2, y+self.bh+3, self.cpw-2, "left")
  282.    
  283.     --love.graphics.printf(str .. self.prompt .. self.inputt .. self.cursor, x+self.bwidth+2, y+self.bh+3, self.cpw-2, "left")
  284.    
  285.     --render everything
  286.     love.graphics.reset()
  287.     if self.render == true then
  288.         love.graphics.draw(canvas)
  289.         love.graphics.draw(textcanvas)
  290.     end
  291.     love.graphics.setCanvas()
  292. end
  293.  
  294.  
  295. --[[
  296.     --maybe forget all this and just make a function to check how many newlines there are
  297.     if string.len(string.sub(llb, self.cpw / inputfont:getWidth("A"))) >= (self.cpw / inputfont:getWidth("A")) then --perhaps while/do instead of if/then?
  298.         llb = string.sub(llb, self.cpw / inputfont:getWidth("A"))
  299.     end
  300.  
  301.     if string.len(self.command) > self.cpw / inputfont:getWidth("A") then
  302.         llb = string.sub(llb, string.len(llb) - self.cpw / inputfont:getWidth("A")) .. "\n" ..
  303.         string.sub(llb, -(self.cpw / inputfont:getWidth("A")))
  304.     end
  305.    
  306.     if string.len(self.command) > self.cpw / inputfont:getWidth("A") then
  307.         --get self.command up to self.cpw and put a newline there
  308.         llb = string.sub(llb, -(string.len(self.command))) ..
  309.         string.sub(self.command, self.cpw / inputfont:getWidth("A")) .. "\n" ..
  310.         string.sub(self.command, -(string.len(self.command)/2))
  311.     end
  312.    
  313.     local textwrap = function(stra, limit, indent)
  314.         limit = limit or 72
  315.         indent = indent or ""
  316.         return stra:gsub("(%s+)()(%S+)()",
  317.             function(sp, st, word, fi)
  318.                 if (fi-1-#"") > limit then
  319.                     here = st - #indent
  320.                     return "\n"..indent..word
  321.                 end
  322.             end)
  323.     end
  324. --]]
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement