This is a read-only snapshot of the ComputerCraft forums, taken in April 2020.
Bobder22's profile picture

read() without wiping the rest of the line?

Started by Bobder22, 23 October 2012 - 11:09 PM
Bobder22 #1
Posted 24 October 2012 - 01:09 AM
So currently I'm setting up a password door for a friend's house. He wanted me to put a logo and such in an ASCII "box" The problem is the place that he want's the password to go into is part of said "box" and it deletes all the text following the starting line of input. If it's hard to follow, here's my current code:


print("|==================|")
print("|									|")
print("| HexHem Incorporated |")
print("|   Enter Access Code  |")
print("|									|")
print("|									|") -- This line is where the access code would be shown
print("|									|")
print("|==================|")
term.setCursorPos(2,6)
input = read("*")
And then the usual password door stuff. Obviously not all of the code is included, just parts I need help with.

The line where the access code is shown is the only place I have trouble at, the "|" is deleted, and leaves the "box" open, making it look bad. If there's a way to fix this I'd love to know! Thanks in advance!

EDIT: Note that the box of code is uneven because of the font, I'm going to assume.
KillaVanilla #2
Posted 24 October 2012 - 01:16 AM
You'll need to make your own version of read().

I actually have one, but it has a ridiculous amount of arguments that need to be passed (frankly, I'm not sure what I have to pass to the function most of the time), but if you need it I could post the source here.
Bobder22 #3
Posted 24 October 2012 - 01:54 AM
If you'd be willing to post it, feel free! I'd love to see it, and hopefully learn from it.
ChunLing #4
Posted 24 October 2012 - 04:13 AM
I wrote one for use with the CCPortable PDA (cause it uses custom "pda_key" events and thus can't use read()).

The code looks like this:
local rdpdln = function()
    local txtln = ""
    if pdamtd.connected() > 0 then
        write("input from PDA")
        for i,v in pairs(pdat.pda) do pdamtd.setIcon(5,i) pdamtd.setTitle("Enter Text",i) end
        repeat tvnt = {os.pullEvent()}
            if tvnt[1] == "pda_char" then txtln = txtln..tvnt[3]
            elseif tvnt[1] == "pda_key" and tvnt[3] == 14 then
                txtln = txtln:sub(1,#txtln-1)
            end
            for i = 0,math.floor(#txtln/27) do
                pdamtd.setText(i,txtln:sub(i*27+1,(i+1)*27),tvnt[2])
            end
        until tvnt[1] == "pda_key" and tvnt[3] == 28
        for i,v in pairs(pdat.pda) do pdamtd.setIcon(7,i) pdamtd.setTitle("...",i) end
        pdamtd.setTitle("Entered",tvnt[2]) pdamtd.setIcon(6,tvnt[2])
    else write("input>") txtln = read() end
  return txtln
end
It's pretty basic but gets the job done.
zekesonxx #5
Posted 30 October 2012 - 06:26 PM
You need to use os.pullEvent and store each keypress in a variable, then when the enter key is pressed check the variable to see if it is the access code.
pielover88888 #6
Posted 08 January 2013 - 12:15 PM
Have it set the cursor position to where the last | should be between the..somewheres… and then have it read(), that might work if you could follow the thought that I couldn't lol!
Kingdaro #7
Posted 08 January 2013 - 12:30 PM
A little bit of a hacky workaround, but I'd probably just use a parallel to redraw that "|" while reading, instead of rewriting an implementation.


term.setCursorPos(2,6)
local input
parallel.waitForAny(
  function()
    input = read '*'
  end,
  function()
    while true do
      os.pullEvent 'key'
      term.setCursorPos(2,20)
    end
  end
)

Though the default read() really should have a limit option, because that issue is popping up a lot lately.
theoriginalbit #8
Posted 08 January 2013 - 01:45 PM
I use this all the time when I want a read function that cant be terminated

function readInput( )
  local input = ""

  while true do
    event = { os.pullEventRaw() }


    if event[1] == "char" then
      input = input..event[2]
    elseif event[1] == "key" then
      local key = event[2]
      if key == keys.backspace then
        input = input:sub( 1, input:len( ) - 1 )
      elseif key == keys.enter then
        return input
      end
    end

    term.setCursorPos( 1, 4 )
    for i = 1, input:len() do
      write( "*" )
    end
  end
end