php.net |  support |  documentation |  report a bug |  advanced search |  search howto |  statistics |  random bug |  login
Bug #73292 readline_info returns empty/old line_buffer info
Submitted: 2016-10-11 15:03 UTC Modified: 2016-10-12 08:20 UTC
Votes:6
Avg. Score:4.3 ± 0.7
Reproduced:5 of 5 (100.0%)
Same Version:2 (40.0%)
Same OS:2 (40.0%)
From: me at xbug dot de Assigned: remi (profile)
Status: Assigned Package: Readline related
PHP Version: 5.6.26 OS: Debian
Private report: No CVE-ID: None
Welcome back! If you're the original bug submitter, here's where you can edit the bug or add additional notes.
If this is not your bug, you can add a comment by following this link.
If this is your bug, but you forgot your password, you can retrieve your password here.
Password:
Status:
Package:
Bug Type:
Summary:
From: me at xbug dot de
New email:
PHP Version: OS:

 

 [2016-10-11 15:03 UTC] me at xbug dot de
Description:
------------
Under php5.4 (ubuntu 14.04) the function readline_info returned the correct values. But since (possible 5.5) php5.6 (debian jessie) it returns empty and sometimes old values.
I've tested it also under php7.0 (Mint) and the behaviour is the same as in php5.6.



Test script:
---------------
<?php
readline_completion_function(
    function ($input) {
        $info = readline_info();
        $text = substr($info['line_buffer'], 0, $info['end']);
        var_dump($info);
        if ($info['point'] !== $info['end']) {
            return [];
        }
        // task name?
        if (false === strpos($text, ' ') || !$text) {
            return ['one', 'three'];
        }
        // This is never called since php 5.6
        $cmd = substr($text, 0, strpos($text, ' '));

        if ($cmd === 'one') {
            return ['two'];
        } elseif ($cmd === 'three') {
            return ['four'];
        }

        return [];
    }
);

while (true) {
    readline('cmd: ');
}

Expected result:
----------------
$ php readline.php 
cmd: onearray(6) {
  ["line_buffer"]=>
  string(3) "one"
  ["point"]=>
  int(3)
  ["end"]=>
  int(3)
  ["library_version"]=>
  string(16) "EditLine wrapper"
  ["readline_name"]=>
  string(0) ""
  ["attempted_completion_over"]=>
  int(0)
}

Actual result:
--------------
$ php readline.php 
cmd: onearray(6) {
  ["line_buffer"]=>
  string(0) ""
  ["point"]=>
  int(3)
  ["end"]=>
  int(3)
  ["library_version"]=>
  string(16) "EditLine wrapper"
  ["readline_name"]=>
  string(0) ""
  ["attempted_completion_over"]=>
  int(0)
}

Patches

Add a Patch

Pull Requests

Add a Pull Request

History

AllCommentsChangesGit/SVN commitsRelated reports
 [2016-10-12 03:19 UTC] pollita@php.net
-Assigned To: +Assigned To: remi
 [2016-10-12 03:19 UTC] pollita@php.net
There's two substantive (and likely causative) changes in the Readline extension between PHP 5.4 and PHP 5.5 (there are none between 5.5 and 5.6).

https://github.com/php/php-src/commit/31d67bd35362c1ab570caccedfec3e24257b55c5
https://github.com/php/php-src/commit/b8d88bf2c588dcaec185468da8db306cd7e6ab8d

Could you clarify two things:
1) Do you have libreadline or libedit installed on your system?
2) Did you compile ext/readline against libedit or libreadline? (Or did you install from stock Debian Jesse package?)

In the mean time, assigning to Remi since both those commits are his.
 [2016-10-12 06:52 UTC] remi@php.net
I don't understand why you want to use readline_info() output instead of $input, which contains the pending input, and works as expected.

<?php
readline_completion_function(
    function ($input) {
		$words = ['albert', 'alfred', 'bob', 'remi', 'foo'];
		$ret = [];
		foreach($words as $word) {
			if ($input == substr($word, 0, strlen($input))) {
				$ret[] = $word;
			}
		}
		return $ret;
    }
);
while (readline('cmd: '));
 [2016-10-12 06:53 UTC] remi@php.net
-Status: Assigned +Status: Feedback
 [2016-10-12 07:54 UTC] me at xbug dot de
-Status: Feedback +Status: Assigned
 [2016-10-12 07:54 UTC] me at xbug dot de
Your are right, $input works like expected. But I want to go one step further and make an autocomplete for the arguments of commands. Therefore I need the whole current line to get the first word, which is the command. And this seems not be possible with the $input arg of the function, which always just contains the current underling word.
For example the Shell class of the symfony console component uses the readline_info() this way, too. (https://github.com/symfony/console/blob/2.7/Shell.php#L168)
 [2016-10-12 08:20 UTC] me at xbug dot de
Just to give the wanted information about php and libreadline. Every php version I tested was installed from the official repository. And it seems that the ubuntu, mint and debian version uses libedit2.

Ubuntu 14.04:  libedit2 (3.1-20130712-2)
Debian Jessie: libedit2 (3.1-20140620-2 and others)
Linux Mint 18: libedit2 (3.1-20150325-1ubuntu2)
 [2018-08-29 06:02 UTC] thflori at gmail dot com
I can confirm that the behaviour with editline wrapper completely differs from lib readline. I tried it on win 8.1 with php7.1 and 7.2; Alpine Linux 3.6 with php 7.1 and Arch with php 7.2.

The only one that is working "correct" is Arch with 7.2 and the difference is clearly editline vs readline 7.0.
 
PHP Copyright © 2001-2019 The PHP Group
All rights reserved.
Last updated: Sun Jul 21 11:01:25 2019 UTC