Posted 16 April 2012 - 08:49 PM
Is it possible to use a coroutine to keep a loop going (clock or timer) while waiting for input from the user with Read()?
What you suggest is possible, regardless of the above fact. Try using the parallel.waitForAll(function1, function2) command in the parallel API. You would supply it with two separate functions, each of which has a loop inside. One which keeps a timer going, the other that checks for input using "read" and does something based on that input.
local function Time()
while true do
--term.clear()
--term.setCursorPos(1,1)
print(textutils.formatTime(os.time(), false))
sleep(0.25)
end
end
local function Input()
while true do
print("Waiting for Input")
userInput = read()
if userInput ~= nill then
print("Got Input")
break
end
end
end
parallel.waitForAll( Time(), Input() )
What you suggest is possible, regardless of the above fact. Try using the parallel.waitForAll(function1, function2) command in the parallel API. You would supply it with two separate functions, each of which has a loop inside. One which keeps a timer going, the other that checks for input using "read" and does something based on that input.
I'd like to have a running clock going, during a menu that takes userInput.
How can I have it wait for input, but not halt the other function while it does? Not what I'm going to end up with, but this is the effect I want:
The parallel API uses coroutines. Coroutines are cooperative multitasking - provided you pass control back to each thread after getting the actual events, it works fine - and that's what the parallel API does.
Look into Lua coroutines. Sure, reimplementing read would work (copy the read from the bios and alter that, rather than doing it from scratch) however, it is in most cases easier just to use the parallel API or handle the coroutines manually.
local line = 1
local cursorPos = 1
local input = ""
local length = 0
local keys = {}
keys[14] = function() -- Backspace
if cursorPos~=1 then
input = string.sub(input,0,cursorPos-2)..(string.sub(input,cursorPos) or "")
cursorPos = cursorPos - 1
length = length - 1
term.setCursorPos(cursorPos+2,line)
term.write(string.sub(input,cursorPos).." ")
end
end
keys[203] = function() -- Left Arrow
if cursorPos~=1 then cursorPos = cursorPos - 1 end
end
keys[205] = function() -- Right Arrow
if cursorPos~=length+1 then cursorPos = cursorPos + 1 end
end
keys[28] = function() -- Enter
-- replace this with whatever you want to do with your input.
term.setCursorPos(cursorPos+2,line+1)
term.write(" ")
term.setCursorPos(1,line+1)
shell.run(input)
_,line = term.getCursorPos()
input=""
length=0
cursorPos=1
term.setCursorPos(1,line)
term.write(">")
term.setCursorPos(3,line+1)
term.write("^")
timer = os.startTimer(0.25)
end
term.clear()
term.setCursorPos(1,1)
term.write(">")
term.setCursorPos(3,2)
term.write("^")
local timer = os.startTimer(0.25)
while true do
local eventType, p1 = os.pullEvent()
if eventType=="char" then
term.setCursorPos(cursorPos+2,line+1)
term.write(" ")
if cursorPos-1==length then
input = input..p1
term.setCursorPos(cursorPos+2,line)
term.write(p1)
elseif cursorPos==1 then
input = p1..input
else
input = string.sub(input,0,cursorPos-1)..p1..string.sub(input,cursorPos)
term.setCursorPos(cursorPos+2,line)
term.write(string.sub(input,cursorPos))
end
cursorPos = cursorPos + 1
length = length + 1
if cursorPos<length then
term.setCursorPos(cursorPos+2,line)
print(string.sub(input,cursorPos))
end
term.setCursorPos(cursorPos+2,line+1)
print("^")
elseif eventType=="key" then
local f = keys[p1]
if type(f) == "function" then
term.setCursorPos(cursorPos+2,line+1)
term.write(" ")
f()
end
elseif eventType=="timer" and p1==timer then
term.setCursorPos(42,1)
print(" ")
term.setCursorPos(42,1)
print(textutils.formatTime(os.time(), false))
timer = os.startTimer(0.25)
end
end
local function read( _sReplaceChar, _tHistory )
term.setCursorBlink( true )
local timer = os.startTimer(0.25) -- OminousPenguin
local sLine = ""
local nHistoryPos = nil
local nPos = 0
if _sReplaceChar then
_sReplaceChar = string.sub( _sReplaceChar, 1, 1 )
end
local w, h = term.getSize()
local sx, sy = term.getCursorPos()
local function redraw()
local nScroll = 0
if sx + nPos >= w then
nScroll = (sx + nPos) - w
end
term.setCursorPos( sx, sy )
term.write( string.rep(" ", w - sx + 1) )
term.setCursorPos( sx, sy )
if _sReplaceChar then
term.write( string.rep(_sReplaceChar, string.len(sLine) - nScroll) )
else
term.write( string.sub( sLine, nScroll + 1 ) )
end
term.setCursorPos( sx + nPos - nScroll, sy )
end
while true do
local sEvent, param = os.pullEvent()
if sEvent == "char" then
sLine = string.sub( sLine, 1, nPos ) .. param .. string.sub( sLine, nPos + 1 )
nPos = nPos + 1
redraw()
elseif sEvent == "key" then
if param == 28 then
-- Enter
break
elseif param == 203 then
-- Left
if nPos > 0 then
nPos = nPos - 1
redraw()
end
elseif param == 205 then
-- Right
if nPos < string.len(sLine) then
nPos = nPos + 1
redraw()
end
elseif param == 200 or param == 208 then
-- Up or down
if _tHistory then
if param == 200 then
-- Up
if nHistoryPos == nil then
if #_tHistory > 0 then
nHistoryPos = #_tHistory
end
elseif nHistoryPos > 1 then
nHistoryPos = nHistoryPos - 1
end
else
-- Down
if nHistoryPos == #_tHistory then
nHistoryPos = nil
elseif nHistoryPos ~= nil then
nHistoryPos = nHistoryPos + 1
end
end
if nHistoryPos then
sLine = _tHistory[nHistoryPos]
nPos = string.len( sLine )
else
sLine = ""
nPos = 0
end
redraw()
end
elseif param == 14 then
-- Backspace
if nPos > 0 then
sLine = string.sub( sLine, 1, nPos - 1 ) .. string.sub( sLine, nPos + 1 )
nPos = nPos - 1
redraw()
end
end
elseif sEvent == "timer" and param==timer then -- OminousPenguin
term.setCursorPos(42,1)
print(" ")
term.setCursorPos(42,1)
print(textutils.formatTime(os.time(), false))
timer = os.startTimer(0.25)
redraw()
end
end
term.setCursorBlink( false )
term.setCursorPos( w + 1, sy )
print()
return sLine
end
function getInput()
local input
while true do
input = io.read()
if input == "blah" then
--do stuff
end
end
end
function updateTimer()
local timer = os.startTimer(10)
local event, param
while true do
event, param = os.pullEvent()
if event == "timer" and param == timer then
timer = os.startTimer(10)
-- do stuff
end
end
end
while true do
parralel.waitForAll(getInput, updateTimer)
end
function getInput()
local input
while true do
input = io.read()
if input == "blah" then
--do stuff
end
end
end
function updateTimer()
local timer = os.startTimer(3)
local event, param
local x, y
while true do
event, param = os.pullEvent()
if event == "timer" and param == timer then
x, y = term.getCursorPos()
term.setCursorPos(42,1)
timer = os.startTimer(3)
term.setCursorPos(42,1)
print(" ")
term.setCursorPos(42,1)
print(textutils.formatTime(os.time(), false))
term.setCursorPos(x,y)
end
end
end
while true do
parallel.waitForAll(getInput, updateTimer)
end
timer = os.startTimer(0.25) -- change the time to whatever you want
os.pullEvent = function(filter)
local evt, p1, p2, p3, p4, p5 = os.pullEventRaw(filter)
if evt == "terminate" then
print( "Terminated" )
error()
elseif evt == "timer" and p1 == timer then
x,y = term.getCursorPos()
term.setCursorPos(42,1)
print(" ")
term.setCursorPos(42,1)
print(textutils.formatTime(os.time(), false))
timer = os.startTimer(0.25)
term.setCursorPos(x,y)
end
return evt, p1, p2, p3, p4, p5
end
Far better to use this:timer = os.startTimer(0.25) -- change the time to whatever you want os.pullEvent = function(filter) local evt, p1, p2, p3, p4, p5 = os.pullEventRaw(filter) if evt == "terminate" then print( "Terminated" ) error() elseif evt == "timer" and p1 == timer then x,y = term.getCursorPos() term.setCursorPos(42,1) print(" ") term.setCursorPos(42,1) print(textutils.formatTime(os.time(), false)) timer = os.startTimer(0.25) term.setCursorPos(x,y) end return evt, p1, p2, p3, p4, p5 end