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

Passing strings(with spaces) from one script to another

Started by RickiHN, 16 August 2014 - 12:46 PM
RickiHN #1
Posted 16 August 2014 - 02:46 PM
I wrote a script to interact with Enhanced Portals 3 through touch screen monitors to simulate elevators. It all works beautifully.

However I predict that I might want to use the code multiple places and I have been sharing the code as well. To that end I would greatly prefer that I could add the details(text for the touchscreen buttons) through a separate piece of code and then refer to the same main bit of coding(so that I only have to manage/update one main program). What I came up with was this:

Unique startercode that can be customized for each individual use:

local buttontext = {}
buttontext[1]="Floor 1		 "
buttontext[2]="Floor 2		 "
buttontext[3]="Floor 3		 "
buttontext[4]="Floor 4		 "
buttontext[5]="Floor 5		 "
buttontext[6]="Floor 6		 "
buttontext[7]="Floor 7		 "
buttontext[8]="Floor 8		 "
buttontext[9]="Floor 9		 "

shell.run("rm", "elevator")
shell.run("pastebin", "get", "1M5sgXpT", "elevator")

shell.run("elevator", buttontext[1], buttontext[2], buttontext[3], buttontext[4], buttontext[5], buttontext[6], buttontext[7], buttontext[8], buttontext[9])


Core program:

local buttontext = {...}

--Load floor location from disk
local FloorFile = fs.open("disk/floor", "r")

if FloorFile then
ThisFloor = tonumber(FloorFile.readLine())
print("This floor: "..ThisFloor)
FloorFile.close()
else
print("No Floor File/disk found")
return
end

os.setComputerLabel("Elevator"..ThisFloor)
local buttoncolours={}
for k=1, #buttontext do
buttoncolours[k]=8192 --8192=green
end
buttoncolours[ThisFloor]=32 --32=lime
mouseWidth = 0
mouseHeight = 0
monitor = peripheral.wrap("bottom")

monitor.clear()
monitor.setCursorPos(1,1)
w,h=monitor.getSize()
print(w)
print(h)
--Draw buttons
for k=1, #buttontext do
monitor.setBackgroundColour((buttoncolours[k]))
monitor.setCursorPos(2,k*2)
monitor.write(buttontext[k])
monitor.setBackgroundColour((colours.black))
end --for

function checkClickPosition()
for k=1, #buttontext do
  if mouseWidth > 1 and mouseWidth < 18 and mouseHeight == k*2 and k~=ThisFloor then
   redstone.setOutput("top", true)
   sleep(1)
   redstone.setAnalogOutput("back", k)
   sleep(2)
   redstone.setOutput("top", false)
   redstone.setAnalogOutput("back", 0)
  end
end
end

repeat
		event,p1,p2,p3 = os.pullEvent()
				if event=="monitor_touch" then
						mouseWidth = p2 -- sets mouseWidth
						mouseHeight = p3 -- and mouseHeight
						checkClickPosition() -- this runs our function
				end
until event=="char" and p1==("x")

Now in theory this works, but whenever there is a space in the button text, it is treated as separate arguments (http://computercraft.&#46;&#46;/wiki/Shell.run)
This means that "Floor 1" becomes "Floor" and "1".

Is there anything I can do to prevent/circumvent this?
Yevano #2
Posted 16 August 2014 - 03:24 PM
Quoted arguments were added somewhat recently I think. If you surround your arguments in quotes then they will be treated specially so that spaces will not separate them.
Something like

local withquotes = { }
for i = 1, 9 do
	withquotes[i] = '"' .. buttontext[i] .. '"'
end
shell.run("elevator", unpack(withquotes))
should work.
Edited on 16 August 2014 - 05:42 PM
Link149 #3
Posted 16 August 2014 - 03:38 PM
Huh… If I get what you're saying, you say you'd like to 'import' some variables from a file to another, right ?
If so, why not use the os.loadApi function ?

 os.loadApi("somefile") 

If you do so, every global variables and functions defined in "somefile" will be available as "somefile.variable".
Edited on 16 August 2014 - 01:39 PM
RickiHN #4
Posted 16 August 2014 - 03:41 PM
Quoted arguments were added somewhat recently I think. If you surround your arguments in quotes then they will be treated specially so that spaces will not separate them.
Something like

local withquotes = { }
for i = 1, 9 do
	withquotes[i] = '"' .. buttontext[i] .. '"'
end
shell.run("elevator", unwrap(withquotes))
should work.
Hmm sadly cant get this to work. Probably because I am still using CC 1.58. (Value my bundled cables too highly :(/> )

Huh… If I get what you're saying, you say you'd like to 'import' some variables from a file to another, right ?
If so, why not use the os.loadApi function ?

 os.loadApi("somefile") 

If you do so, every global variables and functions defined in "somefile" will be available as "somefile.variable".
This sounds exactly like what I need!
RickiHN #5
Posted 16 August 2014 - 06:41 PM
Ok I modified the code to use the os.loadAPI, but simply cannot get it to work for some reason:

Startup script:

buttons = {}
buttons[1]="Floor 1		 "
buttons[2]="Floor 2		 "
buttons[3]="Floor 3		 "
buttons[4]="Floor 4		 "
buttons[5]="Floor 5		 "
buttons[6]="Floor 6		 "
buttons[7]="Floor 7		 "
buttons[8]="Floor 8		 "
buttons[9]="Floor 9		 "

shell.run("rm", "elevator")
shell.run("pastebin", "get", "1M5sgXpT", "elevator")
shell.run("elevator")

Elevator script:

local buttontext = {}
os.loadAPI("startup")
buttontext = startup.buttons
os.unloadAPI("startup")
--Load floor location from disk
local FloorFile = fs.open("disk/floor", "r")

if FloorFile then
ThisFloor = tonumber(FloorFile.readLine())
print("This floor: "..ThisFloor)
FloorFile.close()
else
print("No Floor File/disk found")
return
end

os.setComputerLabel("Elevator"..ThisFloor)
local buttoncolours={}
for k=1, #buttontext do
buttoncolours[k]=8192 --8192=green
end
buttoncolours[ThisFloor]=32 --32=lime
mouseWidth = 0
mouseHeight = 0
monitor = peripheral.wrap("bottom")

monitor.clear()
monitor.setCursorPos(1,1)
w,h=monitor.getSize()
print(w)
print(h)
--Draw buttons
for k=1, #buttontext do
monitor.setBackgroundColour((buttoncolours[k]))
monitor.setCursorPos(2,k*2)
monitor.write(buttontext[k])
monitor.setBackgroundColour((colours.black))
end --for

function checkClickPosition()
for k=1, #buttontext do
  if mouseWidth > 1 and mouseWidth < 18 and mouseHeight == k*2 and k~=ThisFloor then
   redstone.setOutput("top", true)
   sleep(1)
   redstone.setAnalogOutput("back", k)
   sleep(2)
   redstone.setOutput("top", false)
   redstone.setAnalogOutput("back", 0)
  end
end
end

repeat
		event,p1,p2,p3 = os.pullEvent()
				if event=="monitor_touch" then
						mouseWidth = p2 -- sets mouseWidth
						mouseHeight = p3 -- and mouseHeight
						checkClickPosition() -- this runs our function
				end
until event=="char" and p1==("x")

I keep getting the error:
API startup is already being loaded
elevator:3: attempt to index ? (a nil value)

Is there some problem with loading the program named "startup"? Or can you not use tables from the API?
Yevano #6
Posted 16 August 2014 - 07:18 PM
You're running the elevator script from startup, so loading startup again is pointless. You should instead load the elevator script as an API from the startup script and call some function in it to start it instead of using shell.run.

EDIT: Just realized I used "unwrap" instead of "unpack" in my code above. I don't think that's the code you should use anyways but just thought I should point that out.
Edited on 16 August 2014 - 05:41 PM
RickiHN #7
Posted 16 August 2014 - 08:14 PM
You're running the elevator script from startup, so loading startup again is pointless. You should instead load the elevator script as an API from the startup script and call some function in it to start it instead of using shell.run.

Ofc…

Was a long struggle(mostly me being a complete noob) but finally got it to work:

Startup:

	buttontext = {}
	buttontext[1]="Floor 1		 "
	buttontext[2]="Floor 2		 "
	buttontext[3]="Floor 3		 "
	buttontext[4]="Floor 4		 "
	buttontext[5]="Floor 5		 "
	buttontext[6]="Floor 6		 "
	buttontext[7]="Floor 7		 "
	buttontext[8]="Floor 8		 "
	buttontext[9]="Floor 9		 "
	
	
	
	
	shell.run("rm", "elevator")
	
	shell.run("pastebin", "get", "1M5sgXpT", "elevator")
	
	os.loadAPI("elevator")
	
	elevator.elevator(buttontext)


Elevator:

	function elevator(buttontext)
			--Load floor location from disk
			local FloorFile = fs.open("disk/floor", "r")
	
	
			if FloorFile then
					ThisFloor = tonumber(FloorFile.readLine())
					print("This floor: "..ThisFloor)
					FloorFile.close()
			else
					print("No Floor File/disk found")
					return
			end
	
			os.setComputerLabel("Elevator"..ThisFloor)
	
			buttoncolours={}
			for k=1, #buttontext do
					buttoncolours[k]=8192 --8192=green
			end
			buttoncolours[ThisFloor]=32 --32=lime
	
			mouseWidth = 0
			mouseHeight = 0
	
			monitor = peripheral.wrap("bottom")
	
			monitor.clear()
			monitor.setCursorPos(1,1)
			w,h=monitor.getSize()
			print(w)
			print(h)
	
			--Draw buttons
			for k=1, #buttontext do
	
					monitor.setBackgroundColour((buttoncolours[k]))
					monitor.setCursorPos(2,k*2)
					monitor.write(buttontext[k])
					monitor.setBackgroundColour((colours.black))
			end --for
	
			repeat
					event,p1,p2,p3 = os.pullEvent()
							if event=="monitor_touch" then
									mouseWidth = p2 -- sets mouseWidth
									mouseHeight = p3 -- and mouseHeight
									for k=1, #buttontext do
											if mouseWidth > 1 and mouseWidth < 18 and mouseHeight == k*2 and k~=ThisFloor then
													redstone.setOutput("top", true)
													sleep(1)
													redstone.setAnalogOutput("back", k)
													sleep(2)
													redstone.setOutput("top", false)
													redstone.setAnalogOutput("back", 0)
											end
									end
							end
			until event=="char" and p1==("x")
	end



Thanks a lot for the help :)/>
Edited on 16 August 2014 - 06:14 PM