PHP 8.4.1 Released!

Readline Functions

Table of Contents

add a note

User Contributed Notes 10 notes

up
4
david at acz dot org
17 years ago
Readline only reads the window size on startup or on SIGWINCH. This means if the window is resized when not in a readline() call, the next call will have odd behavior due to confusion about the window size.

The work-around is to force Readline to re-read the window size by sending it SIGWINCH. This is accomplished using the async interface, which installs the signal handler but returns control to PHP.

The following function is a drop-in replacement for readline(), but re-reads the window size every time:

<?
function xreadline($prompt)
{
global $xreadline, $xreadline_line;
$code = '$GLOBALS["xreadline"] = false;' .
'$GLOBALS["xreadline_line"] = $line;' .
'readline_callback_handler_remove();';
$cb = create_function('$line', $code);
readline_callback_handler_install($prompt, $cb);
$signal = defined("SIGWINCH") ? SIGWINCH : 28;
posix_kill(posix_getpid(), $signal);
$xreadline = true;
while ($xreadline)
readline_callback_read_char();
return is_null($xreadline_line) ? false : $xreadline_line;
}
?>
up
1
flobee
18 years ago
re to: ds at NOSPAM dot undesigned dot org dot za

cool program! note when trying to exec() something:
in the while loop you need to reset exec() returns or you will get all results of all executions (on my my windows and or cygwin :-(
like:
<?php
// your class prompt()

echo "Enter something or 'exit' to quit\n";
do {
$cmdline = new prompt();
$buffer = $cmdline->get('shell command: ');
// init/ reset first!
$data = null;
$return = null;
// now start:
echo "You said: $buffer\n";
if (!empty(
$buffer)) {
$x = exec($buffer, $data, $return);
print_r($data);
}
} while (
$buffer !== "exit");
echo
"Goodbye\n";
up
1
jcastromail at yahoo dot es
2 years ago
Windows.
To the current date, PHP 8.1 64bits under Windows does not support all the functions:

supported:
readline_add_history
readline_clear_history
readline_completion_function
readline_info
readline_list_history
readline_read_history
readline_write_history
readline

no supported: (the function is not even defined)

readline_callback_handler_install
readline_callback_handler_remove
readline_callback_read_char
readline_on_new_line
readline_redisplay

if you want to read a key in windows (without blocking), you can use the next code:

$out='';
$ret='';
$keys='1234567890abcdefghijklmnopqrstuvwxyz'."á";
$default="á";
while(true) {
exec("choice /N /C $keys /D $default /T 1",$out,$ret);
if($out[0]!=="á") {
var_dump($out[0]);
}
$out=[];
}

It is not elegant and it calls choice every 1 second but it does the job (at least with some keys).
up
0
jewfish at jewfish dot net
22 years ago
There is a simpler way to do a multiline read than above:

function multiline() {
while(($in = readline("")) != ".")
$story .= ($PHP_OS == "WINNT") ? "\r\n".$in :
"\n".$in;

return $story;
}
up
0
Anonymous
22 years ago
[Ed. note: you can use fopen("php://stdin", "w") to achieve the same thing, works on both Windows and Unix)]

I wanted to get console input in a PHP script running on windows, so I made a little hack, which is so simple, it is clearly public domain. What I did was write a C++ program to get a line, then output it. Then all that is needed is to exec() that program and capture the output - readline() for windows. The C++ source is as follows:

#include <iostream.h>
#include <string>
void main()
{
string input;
cin >> input;
cout << input;
}

It works wonderfully for my purposes, since I love the PHP language and want to have console input.

Justin Henck
up
-1
jeffrey at thompsonic dot com
19 years ago
Here's an easy way without readline() if you don't have it compiled in already:

$fp = fopen("php://stdin","r");
$line = rtrim(fgets($fp, 1024);
up
-1
ds at NOSPAM dot undesigned dot org dot za
20 years ago
You can open /dev/tty on unix systems or \con in windows, with ob_implicit_flush(true) to write output unbuffered. Works like a charm :-)

-------------------------------

#!/usr/local/bin/php -q
<?php

set_time_limit
(0);
@
ob_end_flush();
ob_implicit_flush(true);

class
prompt {
var
$tty;

function
prompt() {
if (
substr(PHP_OS, 0, 3) == "WIN") {
$this->tty = fOpen("\con", "rb");
} else {
if (!(
$this->tty = fOpen("/dev/tty", "r"))) {
$this->tty = fOpen("php://stdin", "r");
}
}
}

function
get($string, $length = 1024) {
echo
$string;
$result = trim(fGets($this->tty, $length));
echo
"\n";
return
$result;
}
}

echo
"Enter something or 'exit' to quit\n";
do {
$cmdline = new prompt();
$buffer = $cmdline->get("Something: ");
echo
"You said: $buffer\n";
} while (
$buffer !== "exit");
echo
"Goodbye\n";

?>
up
-1
jcl atNOSPAM jcl dot name
19 years ago
Even better than 'plz at dont dot spam' in only one line :) :

@c:\\php\\cli\\php.exe script.php %*

Cheers,
Jean-Charles
up
-1
joshua at neocodesoftware.com
22 years ago
Here's an example simple readline-like way to input from command line on windows - the single line is from http://www.phpbuilder.com/columns/darrell20000319.php3, the multiline is something I added...

<?
function read () {
# 4092 max on win32 fopen

$fp=fopen("php://stdin", "r");
$in=fgets($fp,4094);
fclose($fp);

# strip newline
(PHP_OS == "WINNT") ? ($read = str_replace("\r\n", "", $in)) : ($read = str_replace("\n", "", $in));

return $read;
}

function multilineread () {
do {
$in = read();

# test exit
if ($in == ".") return $read;

# concat input
(PHP_OS == "WINNT") ? ($read = $read . ($read ? "\r\n" : "") . $in) : ($read = $read . "\n" . $in);

} while ($inp != ".");

return $read;
}

print("End input with . on line by itself.\n");

print("What is your first name?\n");
$first_name = multilineread();

print("What is your last name?\n");
$last_name = read();

print("\nHello, $first_name $last_name! Nice to meet you! \n");
?>
up
-2
plz at dont dot spam
20 years ago
To get all arguments passed to a batch file in one variable
rather than using %1 %2 %3 etc;

:LOOP
if "%1" == "" goto DONE
set args=%args% %1
shift
goto LOOP
:DONE
@c:\\php\\cli\\php.exe script.php %args%
set args=
To Top