ParadoxGate
ParadoxGate

Reputation: 61

Lua - popen 2x '&&' chained set /p - stdout takes a vacation

I'm working in an environment that has approximately zero functional ui while a lua script is running. This just isn't acceptable for the script I need to write, which relies heavily on user input. The only way I've found to circumvent this is using io.popen with some rather crafty commands.

I recognize that what I'm trying to do here is strange and very much wrong, and that I've brought this upon myself, but I can't figure out what's going wrong in this code snippet:

local a = 'f'
local p = io.popen(
    'echo      -~`~-,_,- Editing '..(a == 'f' and 'foreground' or 'background')..' -~`~-,_,- > con && '.. --display text to the user
    'set /p f= Find block: > con < con && '.. --user input
    'call echo %f% &&' .. --pass f back to the lua script
    'set /p r= Replace with: > con < con && '.. --user input
    'call echo %r% &&' .. --pass r back to the lua script
    'pause < con', "r")
local f = p:read("*a") --read what was passed back, later parse it back into 2 variables
p:close()

What I expect to happen:

  1. A 'command prompt window' is displayed to the user, asking for input.
  2. The user enters 2 values.
  3. The values are echoed back to the lua script as they are entered.
  4. The values are read from the pipe and stored for later use.
  5. The command line waits for a keypress, and then closes.

What actually happens:

  1. A 'command prompt window' is displayed to the user, asking for input.
  2. The user enters a value for f.
  3. f is echoed back to the lua script.
  4. The user enters a value for r.
  5. r is echoed back to the console. (!!!)
  6. f is read from the pipe. r is not present.
  7. The command line waits for a keypress, and then closes.

This very similar code sample works just fine, but only returns 1 variable:

p = io.popen(
    'echo What do you want to do? > con && '..
    'echo G: remove girders > con && '..
    'echo F: swap foreground > con && '..
    'echo B: swap background > con && '..
    'echo U: undo all edits > con && '..
    'echo C: cancel > con && '..
    'set /p a= Choose an option: > con < con && '..
    'call echo %a%', "r")
a = string.lower(p:read("*a"):gsub("\n",""))
p:close()

What am I doing wrong, and how can I rewrite this to work for my purposes? What in the world have I unleashed, and how do I put the genie back into the bottle?

Upvotes: 1

Views: 343

Answers (2)

ParadoxGate
ParadoxGate

Reputation: 61

After a good while googling, I found this:

(
 echo some output
 echo more output
)>"Your logfile

Redirecting Output from within Batch file

I had no clue you could wrap commands like that, and I've been tinkering with the Windows CLI since I first discovered it.


local a = 'f'
local p = io.popen(
    'echo      -~`~-,_,- Editing '..(a == 'f' and 'foreground' or 'background')..' -~`~-,_,- > con && '.. --display text to the user
    '( set /p f= Find block: && '.. --user input
    'set /p r= Replace with: ) > con < con && '.. --user input
    'call echo %f% &&' .. --pass f back to the lua script
    'call echo %r% &&' .. --pass r back to the lua script
    'pause < con > con', "r")
local f = p:read("*a") --read what was passed back, later parse it back into 2 variables
p:close()

Wrapping the two set /p statements as above works - I get the expected output of f, followed by a newline, and then r, all sent back to the lua script, where they belong.

Still, if anyone can clue me in on why this was a problem in the first place, I would be very much interested in the explanation.

Upvotes: 1

Egor Skriptunoff
Egor Skriptunoff

Reputation: 23767

local p = io.popen(
   -- create temporary .bat-file
   'set tmpf="%TEMP%\\TMP%RANDOM%.BAT" &&'.. 
   'cmd /c"(echo @set p=^%1&echo @set /p x= ^%p:~1,-1^%^>con&echo @call echo ^%x^%)>%tmpf%" &&'..
   -- Your main program
   'echo.      -~`~-,_,- Editing '..(a == 'f' and 'foreground' or 'background')..' -~`~-,_,- > con &&'.. --display text to the user
   'call %tmpf% "Find block:" < con &&'..  -- pass f back to the lua script
   'call %tmpf% "Replace with:" < con &&'..-- pass r back to the lua script
   -- delete temporary .bat-file
   'call del %tmpf% > con &&'.. 
   'pause < con', "r")
local f = p:read'*a'
p:close()

Upvotes: 0

Related Questions