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

[LUA][Question]Going to a specific point on exit

Started by remiX, 11 October 2012 - 12:17 PM
remiX #1
Posted 11 October 2012 - 02:17 PM
Is there a way to make a computer do something on exit (after clicking escape) or is there a function for it like os.exit() or something?

And when you click esc it will call a function. I guess I could use this code but how would I make it loop whilst other functions have been called?


while true do
  local k, kp = os.pullEvent("key")
  if k == "key" then
	if kp == 1 then -- If im not mistaken, 1 is escape?
	  begin() -- this is my startup function
	  break
	end
  end
end
Ditto8353 #2
Posted 11 October 2012 - 02:29 PM
Going to need some more details for this one.
If I understand you, you want to have a menu, and when you finish with one of the menu options, you want the program to return to the menu?
remiX #3
Posted 11 October 2012 - 02:42 PM
Going to need some more details for this one.
If I understand you, you want to have a menu, and when you finish with one of the menu options, you want the program to return to the menu?

nonono, if at ANY point of time you quit exit the computer while it is still in a function and the begin() function isn't the current function that is being called, it will call begin()
Ditto8353 #4
Posted 11 October 2012 - 03:10 PM
Use the line:
os.pullEvent = os.pullEventRaw

That will prevent people from terminating your program.
After that, just add your own event handling for the "terminate" event, and add quit options.
Espen #5
Posted 11 October 2012 - 03:17 PM
[...] how would I make it loop whilst other functions have been called
If I understand you correctly then you want to check for someone pressing ESC while other functions are running, yes?

If so, then what you want are coroutines. Computercraft has a built-in function to let functions run in parallel, succinctly called "parallel".
Type "help parallel" for info.

Explanation:
parallel.waitForAny( function1, function2, … )
As the name suggests, it runs all the provided functions in (quasi-)parallel, waiting for any of them to end.
parallel.waitForAll( function1, function2, … )
This one on the other hand waits for all functions to end.

Try it with something simple first to wrap your head around it, like making two functions that run in a loop, waiting for a key to be pressed.
Have one function print some text A on a key-press and the other function print some other text B on a key-press, etc.
Then provide both their names to one of the two parallel-functions and see what happens.^^

As for being able to run something when someone presses ESC: Sure that works, just like you figured with listening for key 1.
In your code though you don't need to check if k == "key", since you're already filtering for "key" events (i.e. you've provided os.pullEvent() with that filter already).
Edited on 11 October 2012 - 01:20 PM
remiX #6
Posted 11 October 2012 - 05:09 PM
[...] how would I make it loop whilst other functions have been called
If I understand you correctly then you want to check for someone pressing ESC while other functions are running, yes?

Yes, thats what I want.

If so, then what you want are coroutines. Computercraft has a built-in function to let functions run in parallel, succinctly called "parallel".
Type "help parallel" for info.

Explanation:
parallel.waitForAny( function1, function2, … )
As the name suggests, it runs all the provided functions in (quasi-)parallel, waiting for any of them to end.
parallel.waitForAll( function1, function2, … )
This one on the other hand waits for all functions to end.

Try it with something simple first to wrap your head around it, like making two functions that run in a loop, waiting for a key to be pressed.
Have one function print some text A on a key-press and the other function print some other text B on a key-press, etc.
Then provide both their names to one of the two parallel-functions and see what happens.^^

Hmm… I'll have to read a tutorial about this parallel function. I only have one function happening at once while the program is running (excluding ones that clear etc)

More questions: whats the difference between defining a function local or not?
And, what does 'return' do and where exactly do you place them?
Ditto8353 #7
Posted 11 October 2012 - 05:21 PM
Local Variables

Return Statement
Basically you can put a return statement anywhere in a function. If that statement is executed then the function will end there. The program will return to the line of code which called the function, taking any return values with it.

function largest(x,y)
	 if x > y then
		  return x
	 elseif y > x then
		  return y
	 else
		  return			  -->If the numbers are equal, nothing is returned
	 end
end

big = largest(4,7)	 --> 'big' will have the value '7'
big = largest(5,5)	 --> 'big' will have the value 'nil'
remiX #8
Posted 11 October 2012 - 06:11 PM
Local Variables

Return Statement
Basically you can put a return statement anywhere in a function. If that statement is executed then the function will end there. The program will return to the line of code which called the function, taking any return values with it.

function largest(x,y)
	 if x > y then
		  return x
	 elseif y > x then
		  return y
	 else
		  return			  -->If the numbers are equal, nothing is returned
	 end
end

big = largest(4,7)	 --> 'big' will have the value '7'
big = largest(5,5)	 --> 'big' will have the value 'nil'

Thanks :> I'm going to start using returns now lol :3
Lyqyd #9
Posted 11 October 2012 - 07:44 PM
Please note that in future versions of ComputerCraft, pressing Esc to exit the computer interface will no longer throw an event.
remiX #10
Posted 11 October 2012 - 08:22 PM
Please note that in future versions of ComputerCraft, pressing Esc to exit the computer interface will no longer throw an event.

Damn … lol well thanks for the heads up! Wasn't amped to do it anyway :P/>/>
Espen #11
Posted 11 October 2012 - 10:22 PM
[…] Hmm… I'll have to read a tutorial about this parallel function. I only have one function happening at once while the program is running (excluding ones that clear etc) […]
If you'd like a little working demo to play around with and see how it all fits together, here's some example:

--[[
    Function Definitions
]]
function cmdInput()
    term.clear()
    term.setCursorPos( 1, 2 )
    
    while true do
	    write(">: ")
	    local input = read()    -- User input.
	    
	    if input == "hi" then print("Hi yourself!") end
	    if ( string.lower( input ) == "quit" ) or ( string.lower( input ) == "exit" ) then
		    term.setCursorPos( 1, 1 )
		    term.clear()
		    print("Typed '"..input.."' -> stopping cmdInput...")
		    break   -- out of the while-block
	    end
    end
end

-- Little helper function for keyListener() to reduce some redundancy.
function printTypedChar( char )
    local currX, currY = term.getCursorPos()    -- Store current cursor position.
    term.setCursorPos( 1, 1 )
    term.clearLine()
    write( "Typed character: "..tostring(char) )
    term.setCursorPos( currX, currY )   -- Reset cursor position to where it was before.
end

function keyListener()
    local sEvent, param
    
    printTypedChar("")
    while true do
	    sEvent, param = os.pullEvent()
	    
	    -- Some character was entered.
	    if (sEvent == "char") then
		    printTypedChar( param )
	    end
	    
	    -- ESC was pressed.
	    if ( (sEvent == "key") and (param == 1) ) then
		    term.setCursorPos( 1, 1 )
		    term.clear()
		    print("Pressed ESC -> stopping keyListener...")
		    break   -- out of the while-block
	    end
    end
end


--[[
    Start
]]
local ok, err = pcall( function()
    parallel.waitForAny(
        function()
            cmdInput()
        end,
        function()
            keyListener()
        end
    )
end )
if not ok then
    print( err )
end
It basically listens for and reacts to char/key events while the user is entering some text into the read().
If you enter " quit " or "exit", then the progra m ends because of the cmdInput() function.
If you press ESC, then the program ends because of the keyListener() function.
If you change parallel.waitForAny to parallel.waitForAll, then the program will only end if you have terminated both functions, i.e. if you have entered "quit"/"exit" and pressed ESC.

Hope this helps. If anything is unclear, let me know. :P/>/>
Cheers
remiX #12
Posted 12 October 2012 - 02:18 PM
[…] Hmm… I'll have to read a tutorial about this parallel function. I only have one function happening at once while the program is running (excluding ones that clear etc) […]
If you'd like a little working demo to play around with and see how it all fits together, here's some example:
Spoiler

--[[
	Function Definitions
]]
function cmdInput()
	term.clear()
	term.setCursorPos( 1, 2 )
	
	while true do
		write(">: ")
		local input = read()	-- User input.
		
		if input == "hi" then print("Hi yourself!") end
		if ( string.lower( input ) == "quit" ) or ( string.lower( input ) == "exit" ) then
			term.setCursorPos( 1, 1 )
			term.clear()
			print("Typed '"..input.."' -> stopping cmdInput...")
			break   -- out of the while-block
		end
	end
end

-- Little helper function for keyListener() to reduce some redundancy.
function printTypedChar( char )
	local currX, currY = term.getCursorPos()	-- Store current cursor position.
	term.setCursorPos( 1, 1 )
	term.clearLine()
	write( "Typed character: "..tostring(char) )
	term.setCursorPos( currX, currY )   -- Reset cursor position to where it was before.
end

function keyListener()
	local sEvent, param
	
	printTypedChar("")
	while true do
		sEvent, param = os.pullEvent()
		
		-- Some character was entered.
		if (sEvent == "char") then
			printTypedChar( param )
		end
		
		-- ESC was pressed.
		if ( (sEvent == "key") and (param == 1) ) then
			term.setCursorPos( 1, 1 )
			term.clear()
			print("Pressed ESC -> stopping keyListener...")
			break   -- out of the while-block
		end
	end
end


--[[
	Start
]]
local ok, err = pcall( function()
	parallel.waitForAny(
		function()
			cmdInput()
		end,
		function()
			keyListener()
		end
	)
end )
if not ok then
	print( err )
end
It basically listens for and reacts to char/key events while the user is entering some text into the read().
If you enter " quit " or "exit", then the progra m ends because of the cmdInput() function.
If you press ESC, then the program ends because of the keyListener() function.
If you change parallel.waitForAny to parallel.waitForAll, then the program will only end if you have terminated both functions, i.e. if you have entered "quit"/"exit" and pressed ESC.

Hope this helps. If anything is unclear, let me know. :)/>/>
Cheers

Ooh.. that is awesome :)/>/> Is there a way to make it when you type a character on the screen, it deletes it or something? If that makes sense lol

Thanks for this, going to mess around with it and see what I can do with it :)/>/>
Espen #13
Posted 13 October 2012 - 12:10 PM
You mean you want to intercept what a user is typing while he is in the read() of the cmdInput() function? Sure that should be possible.
One way would be to add the characters that you don't want to be printed on the screen to the keyListener() function.
Once such a character is recognized by keyListener() you move the cursor back by one, write a blank space and then move the cursor back by one again.

Mind you though that this only changes what is printed/seen on the screen! The read() function within cmdInput() (into which the user has entered that character as well) doesn't know about any of this and still has that character stored as part of the input!
E.g. you enter "ABCDE" and it shows only "ACE" on the screen, but read() still thinks you've entered "ABCDE" regardless of what's on the screen, since only the screen output has been manipulated, not the input of read().

So if you want to prevent the input of certain characters to begin with, then you might have to implement your own read() function.
That way you can intercept the user input right at the source, so to speak. And this is just as simple as copying the code of the original read() function (which you can find in /rom/bios.lua), modify it to your liking and then best store in a utility file which you can use for more that just one program and which takes a table of characters as an argument to determine dynamically which characters to ignore.

There might probably be easier ways of achieving the same, but I'm pretty caught up in a little Java project at the moment, so that computercraft-specific LUA trickery is not that fresh in my mind. Ergo that's all I've got right now, sorry.^^

Maybe later today I'll post a little example of the above (modified read()) and how to include it in the previous code.
Cheers