Skip to content

Commit 97f10fc

Browse files
committed
Allow overriding completion in auto_prepend_file
Currently, it's possible to override `php -a`s completion functionality to provide an alternative to the C implementation, with `readline_completion_function()`. However, that surprisingly gets overridden when called from `auto_prepend_file`, because those scripts get run before the interactive shell is started. I believe that not overriding it would be more consistent with what happens when you override the completion function **after** the interactive shell. CLI is the only built-in API that uses this (See discussion in GH-5872). I believe MINIT and RINIT will only run once when invoked with `php -a`. Add documentation about the architecture of how php uses readline/libedit Closes GH-5872
1 parent ec22e5a commit 97f10fc

File tree

5 files changed

+39
-3
lines changed

5 files changed

+39
-3
lines changed

UPGRADING

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -932,6 +932,12 @@ PHP 8.0 UPGRADE NOTES
932932
- PGSQL / PDO PGSQL:
933933
. The PGSQL and PDO PGSQL extensions now require at least libpq 9.1.
934934

935+
- Readline:
936+
. Calling readline_completion_function() before the interactive prompt starts
937+
(e.g. in auto_prepend_file) will now override the default interactive prompt
938+
completion function. Previously, readline_completion_function() only worked
939+
when called after starting the interactive prompt.
940+
935941
- SimpleXML:
936942
. SimpleXMLElement now implements RecursiveIterator and absorbed the
937943
functionality of SimpleXMLIterator. SimpleXMLIterator is an empty extension

ext/readline/README.md

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
readline
2+
========
3+
4+
Provides generic line editing, history, and tokenization functions.
5+
See https://www.php.net/manual/en/book.readline.php
6+
7+
Implementation Details
8+
----------------------
9+
10+
C variables starting with `rl_*` are declared by the readline library
11+
(or are macros referring to variables from the libedit library).
12+
See http://web.mit.edu/gnu/doc/html/rlman_2.html
13+
14+
This should only be used in the CLI SAPI.
15+
Historically, the code lived in sapi/cli,
16+
but many distributions build readline as a shared extension.
17+
Therefore, that code was split into ext/readline so that this can dynamically
18+
be loaded. With other SAPIs, readline is/should be disabled.
19+
20+
`readline_cli.c` implements most of the interactive shell(`php -a`).

ext/readline/readline.c

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -437,7 +437,7 @@ static void _readline_long_zval(zval *ret, long l)
437437
ZVAL_LONG(ret, l);
438438
}
439439

440-
static char **_readline_completion_cb(const char *text, int start, int end)
440+
char **php_readline_completion_cb(const char *text, int start, int end)
441441
{
442442
zval params[3];
443443
char **matches = NULL;
@@ -479,7 +479,8 @@ PHP_FUNCTION(readline_completion_function)
479479
zval_ptr_dtor(&_readline_completion);
480480
ZVAL_COPY(&_readline_completion, &fci.function_name);
481481

482-
rl_attempted_completion_function = _readline_completion_cb;
482+
/* NOTE: The rl_attempted_completion_function variable (and others) are part of the readline library, not php */
483+
rl_attempted_completion_function = php_readline_completion_cb;
483484
if (rl_attempted_completion_function == NULL) {
484485
RETURN_FALSE;
485486
}

ext/readline/readline_cli.c

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -603,7 +603,14 @@ static int readline_shell_run(void) /* {{{ */
603603
#else
604604
spprintf(&history_file, MAX_PATH, "%s/.php_history", getenv("USERPROFILE"));
605605
#endif
606-
rl_attempted_completion_function = cli_code_completion;
606+
/* Install the default completion function for 'php -a'.
607+
*
608+
* But if readline_completion_function() was called by PHP code prior to the shell starting
609+
* (e.g. with 'php -d auto_prepend_file=prepend.php -a'),
610+
* then use that instead of PHP's default. */
611+
if (rl_attempted_completion_function != php_readline_completion_cb) {
612+
rl_attempted_completion_function = cli_code_completion;
613+
}
607614
#ifndef PHP_WIN32
608615
rl_special_prefixes = "$";
609616
#endif

ext/readline/readline_cli.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,4 +34,6 @@ extern PHP_MINIT_FUNCTION(cli_readline);
3434
extern PHP_MSHUTDOWN_FUNCTION(cli_readline);
3535
extern PHP_MINFO_FUNCTION(cli_readline);
3636

37+
char **php_readline_completion_cb(const char *text, int start, int end);
38+
3739
ZEND_EXTERN_MODULE_GLOBALS(cli_readline)

0 commit comments

Comments
 (0)