helly           Sat May  7 08:24:18 2005 EDT

  Modified files:              
    /php-src    NEWS 
    /php-src/sapi/cli   php_cli.c 
  Log:
  - Improved interactive mode of CLI (php -a)
  
  
http://cvs.php.net/diff.php/php-src/NEWS?r1=1.1893&r2=1.1894&ty=u
Index: php-src/NEWS
diff -u php-src/NEWS:1.1893 php-src/NEWS:1.1894
--- php-src/NEWS:1.1893 Thu May  5 22:31:05 2005
+++ php-src/NEWS        Sat May  7 08:24:17 2005
@@ -31,6 +31,7 @@
   . added class File
   . added possibility to use a string with class_parents() and
     class_implements(). (Andrey)
+- Improved interactive mode of CLI (php -a). (Johannes, Marcus)
 - Added the tidy_get_opt_doc() function to return documentation for
   configuration options in tidy. (Patch by: [EMAIL PROTECTED])
 - Added support for .cc files in extensions. (Brian)
http://cvs.php.net/diff.php/php-src/sapi/cli/php_cli.c?r1=1.122&r2=1.123&ty=u
Index: php-src/sapi/cli/php_cli.c
diff -u php-src/sapi/cli/php_cli.c:1.122 php-src/sapi/cli/php_cli.c:1.123
--- php-src/sapi/cli/php_cli.c:1.122    Tue Mar 22 10:08:52 2005
+++ php-src/sapi/cli/php_cli.c  Sat May  7 08:24:18 2005
@@ -19,7 +19,7 @@
    +----------------------------------------------------------------------+
 */
 
-/* $Id: php_cli.c,v 1.122 2005/03/22 15:08:52 tony2001 Exp $ */
+/* $Id: php_cli.c,v 1.123 2005/05/07 12:24:18 helly Exp $ */
 
 #include "php.h"
 #include "php_globals.h"
@@ -69,6 +69,13 @@
 #include <unixlib/local.h>
 #endif
 
+#if HAVE_LIBREADLINE || HAVE_LIBEDIT
+#include <readline/readline.h>
+#if !HAVE_LIBEDIT
+#include <readline/history.h>
+#endif
+#endif
+
 #include "zend_compile.h"
 #include "zend_execute.h"
 #include "zend_highlight.h"
@@ -91,6 +98,9 @@
 
 static char *php_optarg = NULL;
 static int php_optind = 1;
+#if HAVE_LIBREADLINE || HAVE_LIBEDIT
+static char php_last_char = '\0';
+#endif
 
 static const opt_struct OPTIONS[] = {
        {'a', 0, "interactive"},
@@ -200,6 +210,10 @@
        uint remaining = str_length;
        size_t ret;
 
+#if HAVE_LIBREADLINE || HAVE_LIBEDIT
+       php_last_char = str[str_length-1];
+#endif
+
        while (remaining > 0)
        {
                ret = sapi_cli_single_write(ptr, remaining);
@@ -525,6 +539,216 @@
 }
 /* }}} */
 
+#if HAVE_LIBREADLINE || HAVE_LIBEDIT
+
+/* {{{ cli_is_valid_code
+ */
+typedef enum {
+       body,
+       sstring,
+       dstring,
+       sstring_esc,
+       dstring_esc,
+       comment_line,
+       comment_block,
+       heredoc_start,
+       heredoc,
+       outside,
+} php_code_type;
+
+static int cli_is_valid_code(char *code, int len, char **prompt TSRMLS_DC)
+{
+       int valid_end = 1;
+       int brackets_count = 0;
+       int brace_count = 0;
+       int i;
+       php_code_type code_type = body;
+       char *heredoc_tag;
+       int heredoc_len;
+
+       for (i = 0; i < len; ++i) {
+               switch(code_type) {
+                       default:
+                               switch(code[i]) {
+                                       case '{':
+                                               brackets_count++;
+                                               valid_end = 0;
+                                               break;
+                                       case '}':
+                                               if (brackets_count > 0) {
+                                                       brackets_count--;
+                                               }
+                                               valid_end = brackets_count ? 0 
: 1;
+                                               break;
+                                       case '(':
+                                               brace_count++;
+                                               valid_end = 0;
+                                               break;
+                                       case ')':
+                                               if (brace_count > 0) {
+                                                       brace_count--;
+                                               }
+                                               valid_end = 0;
+                                               break;
+                                       case ';':
+                                               valid_end = brace_count == 0 && 
brackets_count == 0;
+                                               break;
+                                       case ' ':
+                                       case '\n':
+                                       case '\t':
+                                               break;
+                                       case '\'':
+                                               code_type = sstring;
+                                               break;
+                                       case '"':
+                                               code_type = dstring;
+                                               break;
+                                       case '/':
+                                               if (code[i+1] == '/') {
+                                                       i++;
+                                                       code_type = 
comment_line;
+                                                       break;
+                                               }
+                                               if (code[i+1] == '*') {
+                                                       code_type = 
comment_block;
+                                                       i++;
+                                                       break;
+                                               }
+                                               valid_end = 0;
+                                               break;
+                                       case '%':
+                                               if (!CG(asp_tags)) {
+                                                       valid_end = 0;
+                                                       break;
+                                               }
+                                               /* no break */
+                                       case '?':
+                                               if (code[i+1] == '>') {
+                                                       i++;
+                                                       code_type = outside;
+                                                       break;
+                                               }
+                                               valid_end = 0;
+                                               break;
+                                       case '<':
+                                               valid_end = 0;
+                                               if (i + 2 < len && code[i+1] == 
'<' && code[i+2] == '<') {
+                                                       i += 2;
+                                                       code_type = 
heredoc_start;
+                                                       heredoc_len = 0;
+                                               }
+                                               break;
+                                       default:
+                                               valid_end = 0;
+                                               break;
+                               }
+                               break;
+                       case sstring:
+                               if (code[i] == '\\') {
+                                       code_type = sstring_esc;
+                               } else {
+                                       if (code[i] == '\'') {
+                                               code_type = body;
+                                       }
+                               }
+                               break;
+                       case sstring_esc:
+                               code_type = sstring;
+                               break;
+                       case dstring:
+                               if (code[i] == '\\') {
+                                       code_type = dstring_esc;
+                               } else {
+                                       if (code[i] == '"') {
+                                               code_type = body;
+                                       }
+                               }
+                               break;
+                       case dstring_esc:
+                               code_type = dstring;
+                               break;
+                       case comment_line:
+                               if (code[i] == '\n') {
+                                       code_type = body;
+                               }
+                               break;
+                       case comment_block:
+                               if (code[i-1] == '*' && code[i] == '/') {
+                                       code_type = body;
+                               }
+                               break;
+                       case heredoc_start:
+                               switch(code[i]) {
+                                       case ' ':
+                                       case '\t':
+                                               break;
+                                       case '\r':
+                                       case '\n':
+                                               code_type = heredoc;
+                                               break;
+                                       default:
+                                               if (!heredoc_len) {
+                                                       heredoc_tag = code+i;
+                                               }
+                                               heredoc_len++;
+                                               break;
+                               }
+                               break;
+                       case heredoc:
+                               if (code[i - (heredoc_len + 1)] == '\n' && 
!strncmp(code + i - heredoc_len, heredoc_tag, heredoc_len)) {
+                                       code_type = body;
+                               }
+                               break;
+                       case outside:
+                               if ((CG(short_tags) && !strncmp(code+i-1, "<?", 
2))
+                               ||  (CG(asp_tags) && !strncmp(code+i-1, "<%", 
2))
+                               ||  (i > 3 && !strncmp(code+i-4, "<?php", 5))
+                               ) {
+                                       code_type = body;
+                               }
+                               break;
+               }
+       }
+
+       switch (code_type) {
+               default:
+                       if (brace_count) {
+                               *prompt = "php ( ";
+                       } else if (brackets_count) {
+                               *prompt = "php { ";
+                       } else {
+                               *prompt = "php > ";
+                       }
+                       break;
+               case sstring:
+               case sstring_esc:
+                       *prompt = "php ' ";
+                       break;
+               case dstring:
+               case dstring_esc:
+                       *prompt = "php \" ";
+                       break;
+               case comment_block:
+                       *prompt = "/*  > ";
+                       break;
+               case heredoc:
+                       *prompt = "<<< > ";
+                       break;
+               case outside:
+                       *prompt = "    > ";
+                       break;
+       }
+
+       if (!valid_end || brackets_count) {
+               return 0;
+       } else {
+               return 1;
+       }
+}
+/* }}} */
+
+#endif /* HAVE_LIBREADLINE || HAVE_LIBEDIT */
+
 /* {{{ main
  */
 #ifdef PHP_CLI_WIN32_NO_CONSOLE
@@ -951,6 +1175,68 @@
                        if (strcmp(file_handle.filename, "-")) {
                                cli_register_file_handles(TSRMLS_C);
                        }
+
+#if HAVE_LIBREADLINE || HAVE_LIBEDIT
+                       if (interactive) {
+                               char *line;
+                               size_t size = 4096, pos = 0, len;
+                               char *code = emalloc(size);
+                               char *prompt = "php > ";
+                               char *history_file;
+
+                               history_file = tilde_expand("~/.php_history");
+                               read_history(history_file);
+
+                               /* it would be nicer to implement this correct 
*/
+                               rl_bind_key ('\t', rl_insert);
+
+                               EG(exit_status) = 0;
+                               while ((line = readline(pos ? prompt : "php > 
")) != NULL) {
+                                       if (strcmp(line, "exit") == 0 || 
strcmp(line, "quit") == 0) {
+                                               free(line);
+                                               break;
+                                       }
+
+                                       if (!pos && !*line) {
+                                               free(line);
+                                               continue;
+                                       }
+
+                                       len = strlen(line);
+                                       if (pos + len + 2 > size) {
+                                               size = pos + len + 2;
+                                               code = erealloc(code, size);
+                                       }
+                                       memcpy(&code[pos], line, len);
+                                       pos += len;
+                                       code[pos] = '\n';
+                                       code[++pos] = '\0';
+
+                                       if (*line) {
+                                               add_history(line);
+                                       }
+
+                                       free(line);
+
+                                       if (!cli_is_valid_code(code, pos, 
&prompt TSRMLS_CC)) {
+                                               continue;
+                                       }
+
+                                       zend_eval_string(code, NULL, "php shell 
code" TSRMLS_CC);
+                                       pos = 0;
+                                       
+                                       if (php_last_char != '\0' && 
php_last_char != '\n') {
+                                               sapi_cli_single_write("\n", 1);
+                                       }
+                                       php_last_char = '\0';
+                               }
+                               write_history(history_file);
+                               free(history_file);
+                               efree(code);
+                               exit_status = EG(exit_status);
+                               break;
+                       }
+#endif /* HAVE_LIBREADLINE || HAVE_LIBEDIT */
                        php_execute_script(&file_handle TSRMLS_CC);
                        exit_status = EG(exit_status);
                        break;

-- 
PHP CVS Mailing List (http://www.php.net/)
To unsubscribe, visit: http://www.php.net/unsub.php

Reply via email to