views:

686

answers:

7

Specifically I have a PHP command-line script that at a certain point requires input from the user. I would like to be able to execute an external editor (such as vi), and wait for the editor to finish execution before resuming the script.

My basic idea was to use a temporary file to do the editing in, and to retrieve the contents of the file afterwards. Something along the lines of:

$filename = '/tmp/script_' . time() . '.tmp';

get_user_input ($filename);

$input = file_get_contents ($filename);
unlink ($filename);

I suspect that this isn't possible from a PHP command-line script, however I'm hoping that there's some sort of shell scripting trick that can be employed to achieve the same effect.

Suggestions for how this can be achieved in other scripting languages are also more than welcome.

A: 

system('vi');

http://www.php.net/system

lms
+2  A: 

I just tried this and it works fine in windows, so you can probably replicate with vi or whatever app you want on linux.

The key is that exec() hangs the php process while notepad (in this case) is running.

<?php

exec('notepad c:\test'); 
echo file_get_contents('c:\test');

?>

$ php -r test.php

Edit: As your attempt shows and bstark pointed out, my notepad test fires up a new window so all is fine, but any editor that runs in console mode fails because it has no terminal to attach to.

That being said, I tried on a linux box with exec('nano test'); echo file_get_contents('test'); and it doesn't fail as badly as vi, it just runs without displaying anything. I could type some stuff, press "ctrl-X, y" to close and save the file, and then the php script continued and displayed what I had written. Anyway.. I found the proper solution, so new answer coming in.

Seldaek
A: 

I can't get system('vi'); or exec('vi') to work correctly for me. I'm on Mac OS X, from the terminal:

~ > php -a
Interactive mode enabled

<?php

system('vi');
Vim: Warning: Output is not to a terminal

At this point I appear to be in vi, however the Terminal window does not update to reflect this at all.

Mathew Byrne
A: 

I don't know if it's at all possible to connect vi to the terminal php is running on, but the quick and easy solution is not to use a screen editor on the same terminal.

You can either use a line editor such as ed (you probably don't want that) or open a new window, like system("xterm -e vi") (replace xterm with the name of your terminal app).

Edited to add: In perl, system("vi") just works, because perl doesn't do the kind of fancy pipelining/buffering php does.

bstark
A: 

So it seems your idea of writing a file lead us to try crazy things while there is an easy solution :)

<?php

$out = fopen('php://stdout', 'w+');
$in = fopen('php://stdin', 'r+');

fwrite($out, "foo?\n");
$var = fread($in, 1024);
echo strtoupper($var);

The fread() call will hang the php process until it receives something (1024 bytes or end of line I think), producing this :

$ php test.php
foo?
bar <= my input
BAR
Seldaek
Sure, you can do this, but it's not exactly what I was after. My point was that I wanted to the flexibility of an external editor like vi or similar.
Mathew Byrne
Alright then sorry I thought you just came up with that idea as a hack to get user input, anyway it's settled I see.
Seldaek
A: 

You can redirect the editor's output to the terminal:

system("vim > `tty`");
Ole J. Helgesen
A: 

I have the same problem - I need to run an editor from within a PHP script (I'm reading some large text from a database, offering to the user for editing and the storing it back - I really need an editor), and just running vi using system() doesn't work well because PHP does not attach vi to the current terminal.

Using Ole J. Helgesen trick to attache the terminal back to vi works great! If I wanted a graphical editor (a-la Seldaek's notepad) then just running the program would probably work well, but I want a console terminal because not all the users have X11 servers.

Guss