terminal.lua 4.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128
  1. local lume = require("libraries.lume")
  2. local Terminal = {}
  3. Terminal.blinktime = 0.5
  4. Terminal.blinktimer = 0
  5. Terminal.blinkstate = false
  6. Terminal.textbuffer = {}
  7. Terminal.textcolors = {}
  8. Terminal.linesLimit = 14
  9. Terminal.lengthLimit = 43
  10. Terminal.currentLine = 1
  11. Terminal.rootDir = "/"
  12. function Terminal:wrap_string(str,ml)
  13. local ml = ml or (Terminal.lengthLimit-5)-(self.rootDir:len()+1)
  14. local lt = api.floor(str:len()/ml+0.99)
  15. if lt <= 1 then return {str} end
  16. local t = {}
  17. for i = 1, lt+1 do
  18. table.insert(t,str:sub(0,ml-1))
  19. str=str:sub(ml,-1)
  20. end
  21. return t
  22. end
  23. function Terminal:tout(text,col,skipnl,pathLen)
  24. local text = text or ""
  25. local length = pathLen and (Terminal.lengthLimit-5)-(self.rootDir:len()+1) or Terminal.lengthLimit
  26. for _,line in ipairs(lume.split(text, "\n")) do
  27. for _,wrapped_line in ipairs(self:wrap_string(line,length)) do
  28. self:tout_line(wrapped_line,col,skipnl)
  29. end
  30. end
  31. end
  32. function Terminal:tout_line(text,col,skipnl)
  33. self.textcolors[self.currentLine] = col or self.textcolors[self.currentLine]
  34. if skipnl then
  35. self.textbuffer[self.currentLine] = self.textbuffer[self.currentLine]..(text or "")
  36. if self.textbuffer[self.currentLine]:len() >= self.lengthLimit then self.textbuffer[self.currentLine] = self.textbuffer[self.currentLine]:sub(0,self.lengthLimit) end
  37. else
  38. self.textbuffer[self.currentLine] = self.textbuffer[self.currentLine]..(text or "")
  39. if self.textbuffer[self.currentLine]:len() >= self.lengthLimit then self.textbuffer[self.currentLine] = self.textbuffer[self.currentLine]:sub(0,self.lengthLimit) end
  40. if self.currentLine == self.linesLimit then
  41. for i=2,self.linesLimit do self.textbuffer[i-1] = self.textbuffer[i] end --Shiftup all the text
  42. for i=2,self.linesLimit do self.textcolors[i-1] = self.textcolors[i] end
  43. self.textbuffer[self.currentLine] = "" --Add a new line
  44. else
  45. self.currentLine = self.currentLine + 1
  46. end
  47. end
  48. self:_redraw()
  49. end
  50. function Terminal:setLine(l) self.currentLine = api.floor(l or 1) if self.currentLine > 20 then self.currentLine = 20 elseif self.currentLine < 1 then self.currentLine = 1 end end
  51. function Terminal:splitCommand(str)
  52. local t = {}
  53. for val in str:gmatch("%S+") do
  54. if not t[0] then t[0] = val else table.insert(t, val) end
  55. end
  56. return t
  57. end
  58. function Terminal:_init()
  59. for i=1,self.linesLimit do table.insert(self.textbuffer,"") end --Clean the framebuffer
  60. for i=1,self.linesLimit do table.insert(self.textcolors,8) end
  61. api.keyrepeat(true)
  62. self:tout("-[[liko12]]-")
  63. self:tout(_LK12VER,_LK12VERC)
  64. self:tout()
  65. self:tout("A PICO-8 CLONE WITH EXTRA ABILITIES",7)
  66. self:tout("TYPE HELP FOR HELP",10)
  67. self:tout(self.rootDir.."> ",8,true)
  68. end
  69. function Terminal:_update(dt)
  70. self.blinktimer = self.blinktimer+dt if self.blinktimer > self.blinktime then self.blinktimer = self.blinktimer - self.blinktime self.blinkstate = not self.blinkstate end
  71. local curlen = self.textbuffer[self.currentLine]:len()
  72. api.color(self.blinkstate and 5 or 1)
  73. api.rect(curlen > 0 and ((curlen)*4+8+3) or 10,(self.currentLine)*8+2,4,5)
  74. end
  75. function Terminal:_redraw()
  76. api.clear(1)
  77. for line,text in ipairs(self.textbuffer) do
  78. api.color(self.textcolors[line])
  79. if text == "-[[liko12]]-" then --THE SECRET PHASE
  80. api.SpriteGroup(49,9,line*8,6,1,1,1,api.EditorSheet)
  81. else
  82. api.print_grid(text,2,line+1)
  83. end
  84. end
  85. end
  86. function Terminal:_kpress(k,sc,ir)
  87. if k == "return" then
  88. self:tout()
  89. local splitted = self:splitCommand(self.textbuffer[self.currentLine-1])
  90. local CMDFunc = require("terminal_commands")[string.lower(splitted[1] or "")]
  91. if CMDFunc then
  92. CMDFunc(unpack(splitted))
  93. elseif splitted[1] then
  94. self:tout("UNKNOWN COMMAND '"..splitted[1].."' !",15)
  95. end
  96. self:tout(self.rootDir.."> ",8,true,true)
  97. end
  98. if k == "backspace" then self.textbuffer[self.currentLine] = self.textbuffer[self.currentLine]:sub(0,-2) self:_redraw() end
  99. end
  100. function Terminal:_tinput(t)
  101. if t == "\\" then return end --This thing is so bad, so GO AWAY
  102. if self.textbuffer[self.currentLine]:len() < self.lengthLimit then self:tout(t,8,true) end
  103. end
  104. function Terminal:_tpress()
  105. --This means the user is using a touch device
  106. self.linesLimit = 7
  107. api.showkeyboard(true)
  108. end
  109. function Terminal:setRoot(path)
  110. self.rootDir = path or "/"
  111. end
  112. return Terminal