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

Save result of shell.run() in a var instead of boolean

Started by First_One, 11 January 2015 - 04:14 PM
First_One #1
Posted 11 January 2015 - 05:14 PM
I'd like to know if it is possible to save what is printed in the screen in a var instead of the boolean returned
In the wiki:
shell.run()
Runs program with as many specified arguments as are provided.
Essentially takes all parameters passed to it and runs them as one line - for eg, shell.run("monitor","top","alongtimeago") is the same as shell.run("monitor top alongtimeago"), and you can use whichever syntax happens to suit you.
Returns boolean sucess

For example:
shell.run("dir")
Prints whatever is in the folder

A = shell.run("dir")
Still prints the folder's content and A = boolean

Is there a way to put what would appear to the user in a variable? Something like this:
A = shell.run("dir")
--Content of A:
A = {[1] = "rom", [2] = "program1",}
-- or maybe
A = "rom program1"
Also not printing what the command would print

I mean, it's kinda 'easy' to do this with one specific command , but it would only work for "DIR" in this case, and i'm looking for something more complex, so it's possible to use any shell.run(command) and still get the RESULT instead of the RETURN.

Any hintzzz? ^_^/>
KingofGamesYami #2
Posted 11 January 2015 - 06:55 PM
What you are trying to do is really, really strange. The problem is the program doesn't have a result. The other problem is shell.run won't return a result even if there was one. The best way is to modify the program in question. The other way involves creating a redirect object for the entire screen, and comparing before/after the program was run to get the results.

Neither of these is very good, I would recommend looking at the program code to learn the actual command. Additionally, shell.run is not something you want to be using a lot.
wieselkatze #3
Posted 11 January 2015 - 07:25 PM
By the way: It is 'list' what you're looking for on KingofGamesYami's link - dir and ls are just aliases.

I don't know why you'd actually want to get the things displayed, but the format you want is exactly the one from fs.list().
To get the list of the directory the user is currently in you'd want to use fs.list( shell.dir() ).
That is also the code in 'list', duh. The result would look like this:


{
  "rom";
  "program1";
  "startup";
  "whatever";
}
First_One #4
Posted 11 January 2015 - 09:00 PM
What you are trying to do is really, really strange. The problem is the program doesn't have a result. The other problem is shell.run won't return a result even if there was one. The best way is to modify the program in question. The other way involves creating a redirect object for the entire screen, and comparing before/after the program was run to get the results.

Neither of these is very good, I would recommend looking at the program code to learn the actual command. Additionally, shell.run is not something you want to be using a lot.

I don't think that these options are actually possible because my program is going to run on background, so nothing should 'appear' to the user on the screen.
About the link you provided, i've already looked at some codes and I know that I could use them, but i would have to implement, let's say, one by one so they respond as i wish, but i'd quit this project before doing that. :unsure:/> .

Also, why is it that bad to use shell.run?

Oh, and bear with me pls, english is not my native language, i can understand but sometimes my words are just weirdly used. ^^

By the way: It is 'list' what you're looking for on KingofGamesYami's link - dir and ls are just aliases.

I don't know why you'd actually want to get the things displayed, but the format you want is exactly the one from fs.list().
To get the list of the directory the user is currently in you'd want to use fs.list( shell.dir() ).
That is also the code in 'list', duh. The result would look like this:


{
  "rom";
  "program1";
  "startup";
  "whatever";
}

Actually i don't want things to be displayed. I want things to be placed into a variable instead of showing off on the screen.
I took a look at those codes and kinda understood them, but i'd have to change one by one.

i'd like something that could be used in a more generic way, to be possible to get the result of any shell.run() i use instead of needing to check for every program and see how it works. I just used the 'dir' command as an example, but thks for the effort.
safetyscissors #5
Posted 12 January 2015 - 05:15 AM
wieselkatze is correct. you're looking for fs.list

local files=fs.list('/')
--# the variable files looks like {'rom','prog1','prog2'}. not displayed.

for _,filename in pairs(files) do
   --# do something with filename
end
asking for a shell.run that returns a value sounds like the job of a function.

shell.run looks like it has to create a new runtime environment and memory stack to execute a command. This adds overhead thats unneccessary when the api lets us do it directly.

Why dont you outline what you're trying to do and we might be able to point you in a faster direction or verify that you're doing it right.
InDieTasten #6
Posted 12 January 2015 - 07:03 AM
What you are trying to do is really, really strange. The problem is the program doesn't have a result. The other problem is shell.run won't return a result even if there was one. The best way is to modify the program in question. The other way involves creating a redirect object for the entire screen, and comparing before/after the program was run to get the results.

Neither of these is very good, I would recommend looking at the program code to learn the actual command. Additionally, shell.run is not something you want to be using a lot.

I don't think that these options are actually possible because my program is going to run on background, so nothing should 'appear' to the user on the screen.
About the link you provided, i've already looked at some codes and I know that I could use them, but i would have to implement, let's say, one by one so they respond as i wish, but i'd quit this project before doing that. :unsure:/> .

Also, why is it that bad to use shell.run?

Oh, and bear with me pls, english is not my native language, i can understand but sometimes my words are just weirdly used. ^^

By the way: It is 'list' what you're looking for on KingofGamesYami's link - dir and ls are just aliases.

I don't know why you'd actually want to get the things displayed, but the format you want is exactly the one from fs.list().
To get the list of the directory the user is currently in you'd want to use fs.list( shell.dir() ).
That is also the code in 'list', duh. The result would look like this:


{
  "rom";
  "program1";
  "startup";
  "whatever";
}

Actually i don't want things to be displayed. I want things to be placed into a variable instead of showing off on the screen.
I took a look at those codes and kinda understood them, but i'd have to change one by one.

i'd like something that could be used in a more generic way, to be possible to get the result of any shell.run() i use instead of needing to check for every program and see how it works. I just used the 'dir' command as an example, but thks for the effort.
You could temporarily overwrite the term io functions to capture the output and not display them.
This would be the way you need to go when you really really want to be doing it this way, although I don't recommend that.
It's fairly complicated and I don't see the point in doing that. After execution you would have like a renderbuffer to read off the contents of each "pixel" in the term,
but other than to display them later I don't see any point.

Why don't you give us like a more concrete or defined example of what you want to achieve, because I have a feeling that theres a much better way to do it.
ElvishJerricco #7
Posted 12 January 2015 - 09:03 AM
What you're asking for is something we UNIX users are spoiled with. Pipelining! Output from programs is put through a file based stdout, which we can pipe into other programs, or which you can save to variables. It's a little awkward to use this functionality from within a program in a UNIX environment, but it's not bad.

CC, however, has no such ability. Many people here are calling your intentions strange and unnecessary, but I find the UNIX way of doing things to be spectacular. That's why SquidDev and I have been working on ClamShell, a UNIX-like shell for ComputerCraft. I'm not exactly sure if a program could make use of the pipe in Lua code, but it does use a full scripting language that will let you do pipelining.
First_One #8
Posted 12 January 2015 - 03:03 PM
Before anything, I'm trying to learn, and there is no better way of doing it than trying it myself. I've done things as shown below cause I wanned to test how far I could push it and to understand how some functionalities work. To be honest, some codes there aren't even necessary lol. But i'm testing - pls, bear with me.

Ok, so, i came up with a quick fix to keep the computer functioning and run a program on background (not using any sort of shell injection or so that i've seen around, i dont think that's actually necessary here, as this is only for learning purposes)

This would be the 'Main Computer'
'startup file'This file would allow the 'background running', per say

function startShell()
	shell.run("shell")
end
function startCentral()
	shell.run("central")
end
parallel.waitForAll(startCentral, startShell)

It runs another shell so it's possible to continue to use it while the 'central' program is running.

central fileThis is the background runner
The comments that AREN'T indented (processing section) show the particular code for my problem
rednet.open("right")
mon = peripheral.wrap("top")
-- monitor thing is just to log. If the shell is running, i'm printing stuffs somewhere else - the monitor - so i can see incoming messages/commands

function main()
	monClear()
	monWrite(" -- PROGRAM RUNNING -- ")
	while true do
		doStuff(receive())
	end
end


-- REDNET - -
function receive()
	received = newReceived()
	received.id, received.msg, received.p = rednet.receive()
	monWrite(received.id.."-> "..received.msg)
	os.sleep(1/2) -- not really needed here
	return received
end

function sendAnswer(sent)

end
-- END REDNET - -


-- PROCESSING - -
function doStuff(received)
	if(string.sub(received.msg, 1, 5) == "cntrl") then -- msg starting with this is a command (prevent undesired broadcast-message processing)
		command = string.sub(received.msg, 6) -- remove the "cntrl" from the message, leaving only the command
		monWrite("Executing Command '"..command.."'")
		answer = shell.run(command)
-- here is what i meant. if the above line worked (save as 'answer' the RESULT instead of BOOLEAN), it could maybe work mainly as a 'remote prompt/shell' thing.
-- The computer would receive ANY command from rednet and execute. It wouldn't be necessary to create key-words for each of the programs available and a bunch of IFs.
		if(type(answer) == "table") then
			monWrite("Result: '"..textutils.serialize(answer).."'")
		else
			monWrite("Result: '"..tostring(answer).."'")
		end

		sendMsg = newMsg()
		sendMsg.id = received.id
		sendMsg.msg = answer -- Here the program would send the RESULT (not boolean) to the client that made the request. E.G: 'cntrldir' would get as answer the list of files and folders
		sendMsg.p = receiver.p
		sendAnswer(sendMsg) -- still no reason for this if the RESULT thing doesn't work
	end
end

function newReceived(var1)
	var1 = {}
	var1 = {id = -1,
		  msg = "",
		  p = 0}
	return var1
end
function newMsg(var1)
	var1 = {}
	var1 = {id = -1,
		  msg = "",
		  p = 0}
	return var1
end
-- END PROCESSING - -


-- MONITOR - -
function monWrite(text)
	x,y = mon.getCursorPos()
	mon.setCursorPos(1,y+1)
	mon.write(text)
end
function monClear()
	mon.clear()
	mon.setCursorPos(1,1)
end
-- END - -

main()
Ok, that's one hard thing to indent. I don't know if the 'Increase Indent' is not working properly, but for me, i just couldn't use it. It would set the whole text to the right. Everything LOL.

That's my little beast. I'm tired of typing, hungry and not really hopeful it'll work, but…

I'm open for discussions :)/>