Newsgroups: php.internals Path: news.php.net Xref: news.php.net php.internals:58926 Return-Path: Mailing-List: contact internals-help@lists.php.net; run by ezmlm Delivered-To: mailing list internals@lists.php.net Received: (qmail 64824 invoked from network); 14 Mar 2012 14:45:24 -0000 Received: from unknown (HELO lists.php.net) (127.0.0.1) by localhost with SMTP; 14 Mar 2012 14:45:24 -0000 Received: from [127.0.0.1] ([127.0.0.1:4735]) by pb1.pair.com (ecelerity 2.1.1.9-wez r(12769M)) with ECSTREAM id 6E/42-51575-30FA06F4 for ; Wed, 14 Mar 2012 09:45:24 -0500 Authentication-Results: pb1.pair.com smtp.mail=osama.sorour@eformations.net; spf=permerror; sender-id=unknown Authentication-Results: pb1.pair.com header.from=osama.sorour@eformations.net; sender-id=unknown Received-SPF: error (pb1.pair.com: domain eformations.net from 74.125.83.42 cause and error) X-PHP-List-Original-Sender: osama.sorour@eformations.net X-Host-Fingerprint: 74.125.83.42 mail-ee0-f42.google.com Received: from [74.125.83.42] ([74.125.83.42:57582] helo=mail-ee0-f42.google.com) by pb1.pair.com (ecelerity 2.1.1.9-wez r(12769M)) with ESMTP id 8B/21-32271-7871F5F4 for ; Tue, 13 Mar 2012 04:46:48 -0500 Received: by eekb57 with SMTP id b57so68481eek.29 for ; Tue, 13 Mar 2012 02:46:45 -0700 (PDT) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20120113; h=from:content-type:content-transfer-encoding:subject:date:message-id :to:mime-version:x-mailer:x-gm-message-state; bh=ziAUApI43KIf0vg5xyCdMUIvzWVop3yjCXSfxiQeXRM=; b=Nk8sr9JQ/O1nmVqKtFD/lxnaHuYJkterg4BZvx7Y6BWeqZZ9van5b1EUUrcbK2/jcz UfQLFmwF5j//9wIzqe91YGBVCcuhJN/CDpVRucnuinUorN5+mq6Tv7/AWldIt/3Wx8GW 6a4lTcNoq1bQEOA1dZxpSi1S2IndzJnrsVXmrXSJLelmEeepy95aE35W5YfB2Y1KtTy5 qyve+xHN5HeyAZ2zCgyEUnGYay9Zj8WxLXkpwjq7Tx90qxzNlLy3zq/8M+8KrGPaGuse ZHsTiuxPF6fHele8Dx78yWew+yupoSyWGgZaetcxOXfOltZTm+oBlYPLgvUa/KhV4AjR z2Bw== Received: by 10.213.12.211 with SMTP id y19mr1153036eby.130.1331632005099; Tue, 13 Mar 2012 02:46:45 -0700 (PDT) Received: from [10.229.174.231] ([197.134.96.37]) by mx.google.com with ESMTPS id z47sm42798een.5.2012.03.13.02.46.41 (version=TLSv1/SSLv3 cipher=OTHER); Tue, 13 Mar 2012 02:46:44 -0700 (PDT) Content-Type: text/plain; charset=us-ascii Content-Transfer-Encoding: quoted-printable Date: Tue, 13 Mar 2012 11:46:38 +0200 Message-ID: <012912E5-1FDA-4CBA-9EBD-5224B04A3A78@eformations.net> To: internals@lists.php.net Mime-Version: 1.0 (Apple Message framework v1257) X-Mailer: Apple Mail (2.1257) X-Gm-Message-State: ALoCoQlw6qiQQa7rb5wufhs4Yj+eWaxMCHxOw1IFvSSAvxWqSpU5wBsRVn7J0FtJG9PtxcNGmv2S Subject: [PATCH] readline extension rl_bind_key addition and other enhancements From: osama.sorour@eformations.net (Osama Abu Elsorour) I was recently involved in a project that relied heavily on readline to = provide console text input capabilities. However I soon noticed that the = current readline is lacking some important functionality. This patch applies only to PHP compiled with libreadline (and don't have = an effect if compiled with libeditline). It adds/modified the following: - Adds support for rl_bind_key function by exposing: function readline_bind_key_function($key, $callback_func) where: $key: Key code to bind to. $callback_func: A callback function in the form: function callback($key, $count) where $key and $count are the same = parameters passed from rl_bind_key() Setting $callback_func to null will cause the binding to be removed for = $key. - Modifies the behavior of readline_info() to allow for setting the = readline properties "point" and "end" (it used to only read them but not = set them). Patch below: --- php-5.3.10/ext/readline/readline.c 2012-01-01 15:15:04.000000000 = +0200 +++ php-5.3.10-patched/ext/readline/readline.c 2012-03-13 = 09:35:43.000000000 +0200 @@ -57,9 +57,12 @@ PHP_FUNCTION(readline_callback_read_char PHP_FUNCTION(readline_callback_handler_remove); PHP_FUNCTION(readline_redisplay); PHP_FUNCTION(readline_on_new_line); +PHP_FUNCTION(readline_bind_key_function); =20 static zval *_prepped_callback =3D NULL; =20 +static HashTable *_bind_key_functions_ht =3D NULL; + #endif =20 static zval *_readline_completion =3D NULL; @@ -121,6 +124,12 @@ ZEND_END_ARG_INFO() =20 ZEND_BEGIN_ARG_INFO(arginfo_readline_on_new_line, 0) ZEND_END_ARG_INFO() + +ZEND_BEGIN_ARG_INFO_EX(arginfo_readline_bind_key_function, 0, 0, 2) + ZEND_ARG_INFO(0, key) + ZEND_ARG_INFO(0, funcname) +ZEND_END_ARG_INFO() + #endif /* }}} */ =20 @@ -142,6 +151,7 @@ static const zend_function_entry php_rea PHP_FE(readline_callback_handler_remove, = arginfo_readline_callback_handler_remove) PHP_FE(readline_redisplay, arginfo_readline_redisplay) PHP_FE(readline_on_new_line, arginfo_readline_on_new_line) + PHP_FE(readline_bind_key_function, = arginfo_readline_bind_key_function) #endif PHP_FE_END }; @@ -165,6 +175,9 @@ ZEND_GET_MODULE(readline) =20 PHP_MINIT_FUNCTION(readline) { + ALLOC_HASHTABLE(_bind_key_functions_ht); + zend_hash_init(_bind_key_functions_ht, 255, NULL, ZVAL_PTR_DTOR, = 0); +=09 using_history(); return SUCCESS; } @@ -181,6 +194,9 @@ PHP_RSHUTDOWN_FUNCTION(readline) zval_ptr_dtor(&_prepped_callback); _prepped_callback =3D 0; } +=09 + zend_hash_destroy(_bind_key_functions_ht); + FREE_HASHTABLE(_bind_key_functions_ht); #endif =20 return SUCCESS; @@ -254,8 +270,16 @@ PHP_FUNCTION(readline_info) } RETVAL_STRING(SAFE_STRING(oldstr),1); } else if (!strcasecmp(what, "point")) { + if (value) { + convert_to_long_ex(value); + rl_point =3D Z_LVAL_PP(value); + } RETVAL_LONG(rl_point); } else if (!strcasecmp(what, "end")) { + if (value) { + convert_to_long_ex(value); + rl_end =3D Z_LVAL_PP(value); + } RETVAL_LONG(rl_end); #ifdef HAVE_LIBREADLINE } else if (!strcasecmp(what, "mark")) { @@ -612,6 +636,74 @@ PHP_FUNCTION(readline_on_new_line) } /* }}} */ =20 +/* {{{ proto bool readline_bind_key_function(string funcname)=20 + Readline rl_bind_key */ + +static int _readline_bind_key_cb(int count, int key) +{=20 + zval *params[2]; + TSRMLS_FETCH(); +=09 + params[0]=3D_readline_long_zval(key); + params[1]=3D_readline_long_zval(count); +=09 + zval **_callback_func =3D NULL; + long _key =3D key; + int r =3D zend_hash_find(_bind_key_functions_ht, (char *) &_key, = sizeof(_key), (void **)&_callback_func); + if (r =3D=3D -1) + return -1; +=09 + int _return_int =3D 0; + zval *_callback_return =3D NULL; + MAKE_STD_ZVAL(_callback_return); + if (call_user_function(CG(function_table), NULL, = *_callback_func, _callback_return, 2, params TSRMLS_CC) =3D=3D SUCCESS) = { + _return_int =3D _callback_return->value.lval; + zval_dtor(_callback_return); + FREE_ZVAL(_callback_return); + } + + return _return_int;=20 +} + +PHP_FUNCTION(readline_bind_key_function) +{ + long key; + zval *arg =3D NULL; + char *name =3D NULL; +=09 + if (FAILURE =3D=3D zend_parse_parameters(ZEND_NUM_ARGS() = TSRMLS_CC, "l!z", &key, &arg)) { + RETURN_FALSE; + } +=09 + if (Z_TYPE_P(arg) =3D=3D IS_NULL) { + zend_hash_del(_bind_key_functions_ht, (char *)&key, = sizeof(key)); + rl_bind_key(key, rl_insert); + } + else { + if (!zend_is_callable(arg, 0, &name TSRMLS_CC)) { + php_error_docref(NULL TSRMLS_CC, E_WARNING, "%s = is not callable", name); + efree(name); + RETURN_FALSE; + } + efree(name); + =09 + zval *_temp_callback =3D NULL; + MAKE_STD_ZVAL(_temp_callback); + *_temp_callback =3D *arg; + zval_copy_ctor(_temp_callback); + =09 + zend_hash_add(_bind_key_functions_ht, (char *)&key, = sizeof(key), &_temp_callback, sizeof(zval *), NULL);=20 + =09 + rl_bind_key(key, &_readline_bind_key_cb); + } +=09 + RETURN_TRUE; +} + +/* }}} */ + #endif