From a9dcde33e21fa0de43d9b98bb2df01ce05b1a036 Mon Sep 17 00:00:00 2001 From: "Thies C. Arntzen" Date: Sat, 23 Oct 1999 17:36:45 +0000 Subject: [PATCH] one can now use callbacks for custom completion functions (still work-in-progress) --- ext/readline/readline.c | 166 +++++++++++++++++++++++++++++++++++++--- 1 file changed, 155 insertions(+), 11 deletions(-) diff --git a/ext/readline/readline.c b/ext/readline/readline.c index 0fae8d1b31..b9601dd934 100644 --- a/ext/readline/readline.c +++ b/ext/readline/readline.c @@ -29,25 +29,32 @@ #include PHP_FUNCTION(readline); -PHP_FUNCTION(readline_version); - PHP_FUNCTION(readline_add_history); +PHP_FUNCTION(readline_info); +PHP_FUNCTION(readline_clear_history); PHP_FUNCTION(readline_list_history); PHP_FUNCTION(readline_read_history); PHP_FUNCTION(readline_write_history); +PHP_FUNCTION(readline_completion_function); + +static char *_readline_completion = NULL; +static zval _readline_array; PHP_MINIT_FUNCTION(readline); +PHP_RSHUTDOWN_FUNCTION(readline); /* }}} */ /* {{{ module stuff */ static zend_function_entry php_readline_functions[] = { PHP_FE(readline, NULL) - PHP_FE(readline_version, NULL) + PHP_FE(readline_info, NULL) PHP_FE(readline_add_history, NULL) + PHP_FE(readline_clear_history, NULL) PHP_FE(readline_list_history, NULL) PHP_FE(readline_read_history, NULL) PHP_FE(readline_write_history, NULL) + PHP_FE(readline_completion_function,NULL) {NULL, NULL, NULL} }; @@ -55,15 +62,24 @@ zend_module_entry readline_module_entry = { "PHP-Readline", php_readline_functions, PHP_MINIT(readline), - NULL, - NULL, - NULL, + NULL, + NULL, + PHP_RSHUTDOWN(readline), NULL, STANDARD_MODULE_PROPERTIES }; PHP_MINIT_FUNCTION(readline) { + using_history(); + return SUCCESS; +} + +PHP_RSHUTDOWN_FUNCTION(readline) +{ + if (_readline_completion) + efree(_readline_completion); + return SUCCESS; } @@ -86,22 +102,34 @@ PHP_FUNCTION(readline) if (! result) { RETURN_FALSE; } else { - RETURN_STRING(result,1); + RETVAL_STRING(result,1); + free(result); } } /* }}} */ -/* {{{ proto string readline_version() */ +/* {{{ proto array|long|string readline_info([string varname][, string newvalue ]) + gets/sets various internal readline variables. */ + +#define SAFE_STRING(s) ((s)?(s):"") -PHP_FUNCTION(readline_version) +PHP_FUNCTION(readline_info) { int ac = ARG_COUNT(ht); if (ac) { WRONG_PARAM_COUNT; } - - RETURN_STRING(rl_library_version?rl_library_version:"unknown",1); + + array_init(return_value); + add_assoc_string(return_value,"line_buffer",SAFE_STRING(rl_line_buffer),1); + add_assoc_long(return_value,"point",rl_point); + add_assoc_long(return_value,"end",rl_end); + add_assoc_long(return_value,"mark",rl_mark); + add_assoc_string(return_value,"prompt",SAFE_STRING(rl_prompt),1); + add_assoc_string(return_value,"library_version",SAFE_STRING(rl_library_version),1); + add_assoc_string(return_value,"terminal_name",SAFE_STRING(rl_terminal_name),1); + add_assoc_string(return_value,"readline_name",SAFE_STRING(rl_readline_name),1); } /* }}} */ @@ -122,6 +150,22 @@ PHP_FUNCTION(readline_add_history) RETURN_TRUE; } +/* }}} */ +/* {{{ proto void readline_clear_history() */ + +PHP_FUNCTION(readline_clear_history) +{ + int ac = ARG_COUNT(ht); + + if (ac < 0 || ac > 0) { + WRONG_PARAM_COUNT; + } + + clear_history(); + + RETURN_TRUE; +} + /* }}} */ /* {{{ proto array readline_list_history() */ @@ -198,6 +242,106 @@ PHP_FUNCTION(readline_write_history) } } +/* }}} */ +/* {{{ proto void readline_completion_function(string funcname) */ + +char *test[] = { "bleibt", "da", "helfen", "keine", "pillen", "und" , "heissen", "umsclaege","hallo", "pallo", "thies", "ist", "doof", "tubu", "tata",0 }; + +static char *_readline_command_generator(char *text,int state) +{ + HashTable *myht = _readline_array.value.ht; + zval **entry; + + /* + printf("\n_readline_command_generator(\"%s\",%d)\n",text,state); + */ + + if (! state) { + zend_hash_internal_pointer_reset(myht); + } + + while (zend_hash_get_current_data(myht, (void **)&entry) == SUCCESS) { + zend_hash_move_forward(myht); + + convert_to_string_ex(entry); + if (strncmp ((*entry)->value.str.val, text, strlen(text)) == 0) { + return (strdup((*entry)->value.str.val)); + } + } + + return NULL; +} + +static zval *_readline_string_zval(const char *str) +{ + zval *ret; + int len = strlen(str); + MAKE_STD_ZVAL(ret); + + ret->type = IS_STRING; + ret->value.str.len = len; + ret->value.str.val = estrndup(str, len); + return ret; +} + +static zval *_readline_long_zval(long l) +{ + zval *ret; + MAKE_STD_ZVAL(ret); + + ret->type = IS_LONG; + ret->value.lval = l; + return ret; +} + +static char **_readline_completion_cb(char *text, int start, int end) +{ + zval *params[4]; + int i; + char **matches = NULL; + ELS_FETCH(); + + params[0]=_readline_string_zval(_readline_completion); + params[1]=_readline_string_zval(text); + params[2]=_readline_long_zval(start); + params[3]=_readline_long_zval(end); + + if (call_user_function(CG(function_table), NULL, params[0], &_readline_array, 3, params+1) == SUCCESS) { + if (_readline_array.type == IS_ARRAY) { + matches = completion_matches(text,_readline_command_generator); + } + } + + for (i = 0; i < 4; i++) { + zval_del_ref(¶ms[i]); + } + zval_dtor(&_readline_array); + + return matches; +} + +PHP_FUNCTION(readline_completion_function) +{ + pval **arg; + int ac = ARG_COUNT(ht); + + if (ac < 0 || ac > 1 || getParametersEx(ac, &arg) == FAILURE) { + WRONG_PARAM_COUNT; + } + + if (ac == 1) { + convert_to_string_ex(arg); + + if (_readline_completion) + efree(_readline_completion); + + _readline_completion = estrdup((*arg)->value.str.val); + rl_attempted_completion_function = _readline_completion_cb; + } + + RETURN_TRUE; +} + /* }}} */ #endif /* HAVE_LIBREADLINE */ -- 2.40.0