Log In  


A simple terminal implementation for 251 tokens (I'm pretty sure you can find some clever ways to reduce this), for your dev tools.

Currently I'm working on some editors for my game, I had to implement mouse controls, buttons and layout. However I have missed a crucial part: text input.

I have looked inside the community wiki and found out how to read the keyboard buffer. I have made this simple terminal which I'm really satisfied with, and I thought maybe it is worth to share. Nothing fancy just a shell ready to interpret whatever command you type in and hit enter.

function new_terminal(text_color, bg_color, error_color)
  local t = {}
  t.history,
  t.buffer,
  t.t_col,
  t.bg_col,
  t.err_col,
  t.commands,
  t.append,
  t.render 
  = 
  {},
  "",
  text_color or 11,
  bg_color or 0,
  error_color or 8,
  { cls = function(_ENV) history = {} end },

  function(_ENV, str, err)
    for line in all(split(tostr(str), "\n")) do
      add(history, { s = line, c = err and err_col or t_col }, 1)
    end
  end,

  function(_ENV, x, y, h)
    -- while there is a character in the keyboard buffer
    while stat(30) do
      -- read the next character
      local c = stat(31)
      -- backspace
      if c == "\b" then
        buffer = sub(buffer, 1, #buffer - 1)
        -- enter
      elseif c == "\r" then
        -- prevent pico-8's pop-up window
        poke(0x5f30, 1)
        append(_ENV, buffer)
        local parts = split(buffer, " ")
        buffer = ""
        local p1 = parts[1]
        if p1 ~= "" then
          if commands[p1] then
            local res, code = commands[p1](_ENV, parts)
            if (res) append(_ENV, res, code)
          else
            append(_ENV, "unknown command: " .. p1, 1)
          end
        end
      else
        buffer = buffer .. c
      end
    end

    rectfill(x, y, 127, y + h * 6, bg_col)
    -- you can remove these but then the terminal will look a bit ugly
    x += 1
    y += 1
    local lines = min(#history, h - 1)
    for i = lines, 1, -1 do
      print(history[i].s, x, y + (lines - i) * 6, history[i].c)
    end
    print(">" .. buffer .. "_", x, y + lines * 6, t_col)
  end

  return setmetatable(t, { __index = _ENV })
end

-- example usage
function _init()
  -- turn on the dev kit so we can access the keyboard
  poke(0x5f2d, 0x1)

  term = new_terminal()

  -- attach a command to the terminal
  term.commands.hello = function(_ENV, args)
    return "hello" .. (args[2] and " " .. args[2] or "") .. "!"
  end

  -- attach a command with multiline results
  term.commands.ls = function()
    return "a\nb\nc"
  end

  -- attach a command with possible error results
  term.commands.ok = function(_ENV, args)
    local ok = rnd() < .5
    return ok and "success" or "error", not ok
  end
end

function _draw()
  cls(1)
  -- draw the terminal starting from y, y with height in rows (each row is 6 pixel tall)
  -- the terminal always spans to the right edge of the screen
  term:render(0, 22, 10)
end



[Please log in to post a comment]