Newsgroups: php.internals Path: news.php.net Xref: news.php.net php.internals:15407 Return-Path: Mailing-List: contact internals-help@lists.php.net; run by ezmlm Delivered-To: mailing list internals@lists.php.net Received: (qmail 85215 invoked by uid 1010); 12 Mar 2005 23:18:17 -0000 Delivered-To: ezmlm-scan-internals@lists.php.net Delivered-To: ezmlm-internals@lists.php.net Received: (qmail 85200 invoked from network); 12 Mar 2005 23:18:17 -0000 Received: from unknown (HELO php.net) (127.0.0.1) by localhost with SMTP; 12 Mar 2005 23:18:17 -0000 X-Host-Fingerprint: 82.165.35.142 thinkforge.org Linux 2.4/2.6 Received: from ([82.165.35.142:16028] helo=mail.mayflowersystem.com) by pb1.pair.com (ecelerity HEAD r(5124)) with SMTP id E4/AF-31540-8B873324 for ; Sat, 12 Mar 2005 18:18:16 -0500 Received: (qmail 4683 invoked by uid 60010); 12 Mar 2005 23:18:13 -0000 Received: from 62.158.201.40 by mail (envelope-from , uid 89) with qmail-scanner-1.24 (uvscan: v4.3.20/v4362. spamassassin: 2.63. Clear:RC:1(62.158.201.40):. Processed in 0.946506 secs); 12 Mar 2005 23:18:13 -0000 Received: from unknown (HELO ?192.168.1.7?) (schlueter@mayflower.de@62.158.201.40) by 0 with (RC4-MD5 encrypted) SMTP; 12 Mar 2005 23:18:12 -0000 To: internals@lists.php.net Date: Sun, 13 Mar 2005 00:16:14 +0100 User-Agent: KMail/1.7.1 Cc: smith@backendmedia.com MIME-Version: 1.0 Content-Type: Multipart/Mixed; boundary="Boundary-00=_/g3MCYLYb5prcFH" Message-ID: <200503130016.15221.johannes@php.net> Subject: [patch] highlight_[file|string] and line numbers From: johannes@php.net (Johannes Schlueter) --Boundary-00=_/g3MCYLYb5prcFH Content-Type: text/plain; charset="iso-8859-1" Content-Transfer-Encoding: quoted-printable Content-Disposition: inline Hi, some days (or even weeks?) ago Lukas asked on IRC wether there is a way to = get=20 PHP code highlighted with linenumbers. The first reaction of most people=20 (including me) was "no" since you can't copy&paste the code but after=20 thinking I found out that
    works really fine. So I've implemented it th= at=20 way and added an optional bool parameter to the highlight functions.=20 Additionally I've added two other parameters to these functions: The first= =20 one is a bool that adds jump targets (), second one is a= =20 prefix to this number () which is needed to make = sure=20 the jump target is unique even if more than one snippet is added to the=20 output. This doesn't work with .phps yet since we would a new php.ini setting which= I=20 didn't want to add or numbered output would need to become default. My patch is attached and, if it doesn't come through, available on=20 http://www.schlueters.de/zend_highlight_20050312_1.diff a sample output is = at=20 http://www.schlueters.de/highlight_pma.html johannes =2D-=20 Johannes Schl=FCter Mayflower GmbH / ThinkPHP http://thinkphp.de http://blog.thinkphp.de --Boundary-00=_/g3MCYLYb5prcFH Content-Type: text/x-diff; charset="iso-8859-1"; name="zend_highlight_20050312_1.diff" Content-Transfer-Encoding: 7bit Content-Disposition: attachment; filename="zend_highlight_20050312_1.diff" Index: Zend/zend_highlight.h =================================================================== RCS file: /repository/ZendEngine2/zend_highlight.h,v retrieving revision 1.24 diff -u -r1.24 zend_highlight.h --- Zend/zend_highlight.h 8 Jan 2004 17:31:47 -0000 1.24 +++ Zend/zend_highlight.h 12 Mar 2005 14:40:12 -0000 @@ -41,11 +41,16 @@ BEGIN_EXTERN_C() ZEND_API void zend_highlight(zend_syntax_highlighter_ini *syntax_highlighter_ini TSRMLS_DC); +ZEND_API void zend_highlight_numbered(zend_syntax_highlighter_ini *syntax_highlighter_ini, zend_bool mark_lines, char *line_prefix TSRMLS_DC); ZEND_API void zend_strip(TSRMLS_D); ZEND_API int highlight_file(char *filename, zend_syntax_highlighter_ini *syntax_highlighter_ini TSRMLS_DC); +ZEND_API int highlight_file_ex(char *filename, zend_syntax_highlighter_ini *syntax_highlighter_ini, zend_bool numbered, zend_bool mark_lines, char *line_prefix TSRMLS_DC); ZEND_API int highlight_string(zval *str, zend_syntax_highlighter_ini *syntax_highlighter_ini, char *str_name TSRMLS_DC); +ZEND_API int highlight_string_ex(zval *str, zend_syntax_highlighter_ini *syntax_highlighter_ini, char *str_name, zend_bool numbered, zend_bool mark_lines, char *line_prefix TSRMLS_DC); ZEND_API void zend_html_putc(char c); +ZEND_API void zend_html_putc_ex(char c, char *last_color, int *line, char *line_prefix); ZEND_API void zend_html_puts(const char *s, uint len TSRMLS_DC); +ZEND_API void zend_html_puts_ex(const char *s, uint len, char *last_color, int *line, char *line_prefix TSRMLS_DC); END_EXTERN_C() extern zend_syntax_highlighter_ini syntax_highlighter_ini; Index: Zend/zend_highlight.c =================================================================== RCS file: /repository/ZendEngine2/zend_highlight.c,v retrieving revision 1.47 diff -u -r1.47 zend_highlight.c --- Zend/zend_highlight.c 2 Jan 2005 23:53:43 -0000 1.47 +++ Zend/zend_highlight.c 12 Mar 2005 14:40:12 -0000 @@ -53,9 +53,35 @@ } } +ZEND_API void zend_html_putc_ex(char c, char *last_color, int *line, char *line_prefix) +{ + if (c == '\n') { + /* the   is needed to work around https://bugzilla.mozilla.org/show_bug.cgi?id=194831 */ + zend_printf(" \n
  1. "); + if (last_color != NULL) { + if (line && *line) { + if (line_prefix) { + zend_printf("", line_prefix, ++*line); + } else { + zend_printf("", ++*line); + } + } + zend_printf("", last_color); + } else { + zend_printf(""); + } + } else { + zend_html_putc(c); + } +} ZEND_API void zend_html_puts(const char *s, uint len TSRMLS_DC) { + zend_html_puts_ex(s, len, NULL, NULL, NULL TSRMLS_CC); +} + +ZEND_API void zend_html_puts_ex(const char *s, uint len, char *last_color, int *line, char *line_prefix TSRMLS_DC) +{ const char *ptr=s, *end=s+len; #ifdef ZEND_MULTIBYTE @@ -83,7 +109,11 @@ ptr++; } } else { - zend_html_putc(*ptr++); + if (last_color == NULL) { + zend_html_putc(*ptr++); + } else { + zend_html_putc_ex(*ptr++, last_color, line, line_prefix); + } } } @@ -196,6 +226,108 @@ } +ZEND_API void zend_highlight_numbered(zend_syntax_highlighter_ini *syntax_highlighter_ini, zend_bool mark_lines, char *line_prefix TSRMLS_DC) +{ + zval token; + int token_type; + char *last_color = syntax_highlighter_ini->highlight_html; + char *next_color; + int in_string=0, post_heredoc = 0; + int line = 0; + + if (mark_lines) { + line = 1; + if (line_prefix) { + zend_printf("
    1. ", line_prefix, line, last_color); + } else { + zend_printf("
      1. ", line, last_color); + } + } else { + zend_printf("
        1. ", last_color); + } + /* highlight stuff coming back from zendlex() */ + token.type = 0; + while ((token_type=lex_scan(&token TSRMLS_CC))) { + switch (token_type) { + case T_INLINE_HTML: + next_color = syntax_highlighter_ini->highlight_html; + break; + case T_COMMENT: + case T_DOC_COMMENT: + next_color = syntax_highlighter_ini->highlight_comment; + break; + case T_OPEN_TAG: + case T_OPEN_TAG_WITH_ECHO: + next_color = syntax_highlighter_ini->highlight_default; + break; + case T_CLOSE_TAG: + next_color = syntax_highlighter_ini->highlight_default; + break; + case T_CONSTANT_ENCAPSED_STRING: + next_color = syntax_highlighter_ini->highlight_string; + break; + case '"': + next_color = syntax_highlighter_ini->highlight_string; + in_string = !in_string; + break; + case T_WHITESPACE: + zend_html_puts_ex(LANG_SCNG(yy_text), LANG_SCNG(yy_leng), last_color, &line, line_prefix TSRMLS_CC); /* no color needed */ + token.type = 0; + continue; + break; + default: + if (in_string) { + next_color = syntax_highlighter_ini->highlight_string; + } else if (token.type == 0) { + next_color = syntax_highlighter_ini->highlight_keyword; + } else { + next_color = syntax_highlighter_ini->highlight_default; + } + break; + } + + if (last_color != next_color) { + last_color = next_color; + zend_printf("", last_color); + + } + switch (token_type) { + case T_END_HEREDOC: + zend_html_puts_ex(token.value.str.val, token.value.str.len, last_color, &line, line_prefix TSRMLS_CC); + post_heredoc = 1; + break; + default: + zend_html_puts_ex(LANG_SCNG(yy_text), LANG_SCNG(yy_leng), last_color, &line, line_prefix TSRMLS_CC); + if (post_heredoc) { + zend_html_putc_ex('\n', last_color, &line, line_prefix); + post_heredoc = 0; + } + break; + } + + if (token.type == IS_STRING) { + switch (token_type) { + case T_OPEN_TAG: + case T_OPEN_TAG_WITH_ECHO: + case T_CLOSE_TAG: + case T_WHITESPACE: + case T_COMMENT: + case T_DOC_COMMENT: + break; + default: + efree(token.value.str.val); + break; + } + } else if (token_type == T_END_HEREDOC) { + efree(token.value.str.val); + } + token.type = 0; + } + zend_printf(""); + zend_printf("
        "); +} + + ZEND_API void zend_strip(TSRMLS_D) { Index: Zend/zend_language_scanner.l =================================================================== RCS file: /repository/ZendEngine2/zend_language_scanner.l,v retrieving revision 1.124 diff -u -r1.124 zend_language_scanner.l --- Zend/zend_language_scanner.l 7 Mar 2005 16:48:49 -0000 1.124 +++ Zend/zend_language_scanner.l 12 Mar 2005 14:40:13 -0000 @@ -557,11 +557,11 @@ BEGIN_EXTERN_C() -int highlight_file(char *filename, zend_syntax_highlighter_ini *syntax_highlighter_ini TSRMLS_DC) +int highlight_file_ex(char *filename, zend_syntax_highlighter_ini *syntax_highlighter_ini, zend_bool numbered, zend_bool mark_lines, char *line_prefix TSRMLS_DC) { zend_lex_state original_lex_state; zend_file_handle file_handle; - + file_handle.type = ZEND_HANDLE_FILENAME; file_handle.filename = filename; file_handle.free_filename = 0; @@ -571,7 +571,11 @@ zend_message_dispatcher(ZMSG_FAILED_HIGHLIGHT_FOPEN, filename); return FAILURE; } - zend_highlight(syntax_highlighter_ini TSRMLS_CC); + if (numbered) { + zend_highlight_numbered(syntax_highlighter_ini, mark_lines, line_prefix TSRMLS_CC); + } else { + zend_highlight(syntax_highlighter_ini TSRMLS_CC); + } #ifdef ZEND_MULTIBYTE if (SCNG(script_org)) { efree(SCNG(script_org)); @@ -587,7 +591,12 @@ return SUCCESS; } -int highlight_string(zval *str, zend_syntax_highlighter_ini *syntax_highlighter_ini, char *str_name TSRMLS_DC) +int highlight_file(char *filename, zend_syntax_highlighter_ini *syntax_highlighter_ini TSRMLS_DC) +{ + return highlight_file_ex(filename, syntax_highlighter_ini, 0, 0, NULL TSRMLS_CC); +} + +int highlight_string_ex(zval *str, zend_syntax_highlighter_ini *syntax_highlighter_ini, char *str_name, zend_bool numbered, zend_bool mark_lines, char *line_prefix TSRMLS_DC) { zend_lex_state original_lex_state; zval tmp = *str; @@ -598,7 +607,11 @@ if (zend_prepare_string_for_scanning(str, str_name TSRMLS_CC)==FAILURE) { return FAILURE; } - zend_highlight(syntax_highlighter_ini TSRMLS_CC); + if (numbered) { + zend_highlight_numbered(syntax_highlighter_ini, mark_lines, line_prefix TSRMLS_CC); + } else { + zend_highlight(syntax_highlighter_ini TSRMLS_CC); + } #ifdef ZEND_MULTIBYTE if (SCNG(script_org)) { efree(SCNG(script_org)); @@ -613,6 +626,11 @@ zval_dtor(str); return SUCCESS; } + +int highlight_string(zval *str, zend_syntax_highlighter_ini *syntax_highlighter_ini, char *str_name TSRMLS_DC) +{ + return highlight_string_ex(str, syntax_highlighter_ini, str_name, 0, 0, NULL TSRMLS_CC); +} END_EXTERN_C() #ifdef ZEND_MULTIBYTE Index: ext/standard/basic_functions.c =================================================================== RCS file: /repository/php-src/ext/standard/basic_functions.c,v retrieving revision 1.705 diff -u -r1.705 basic_functions.c --- ext/standard/basic_functions.c 7 Mar 2005 19:37:26 -0000 1.705 +++ ext/standard/basic_functions.c 12 Mar 2005 14:40:14 -0000 @@ -2353,15 +2353,19 @@ syntax_highlighter_ini->highlight_string = INI_STR("highlight.string"); } -/* {{{ proto bool highlight_file(string file_name [, bool return] ) +/* {{{ proto bool highlight_file(string file_name [, bool return [, bool numbered [, bool mark_lines [, string mark_prefix]]]] ) Syntax highlight a source file */ PHP_FUNCTION(highlight_file) { zval *filename; zend_syntax_highlighter_ini syntax_highlighter_ini; zend_bool i = 0; + zend_bool numbered = 0; + zend_bool mark_lines = 0; + char *line_prefix = NULL; + int line_prefix_len = 0; - if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "z|b", &filename, &i) == FAILURE) { + if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "z|bbbs", &filename, &i, &numbered, &mark_lines, &line_prefix, &line_prefix_len) == FAILURE) { RETURN_FALSE; } convert_to_string(filename); @@ -2380,7 +2384,7 @@ php_get_highlight_struct(&syntax_highlighter_ini); - if (highlight_file(Z_STRVAL_P(filename), &syntax_highlighter_ini TSRMLS_CC) == FAILURE) { + if (highlight_file_ex(Z_STRVAL_P(filename), &syntax_highlighter_ini, numbered, mark_lines, line_prefix TSRMLS_CC) == FAILURE) { RETURN_FALSE; } @@ -2472,7 +2476,7 @@ } /* }}} */ -/* {{{ proto bool highlight_string(string string [, bool return] ) +/* {{{ proto bool highlight_string(string string [, bool return [, bool mark_lines [, string mark_prefix]]] ) Syntax highlight a string or optionally return it */ PHP_FUNCTION(highlight_string) { @@ -2480,9 +2484,13 @@ zend_syntax_highlighter_ini syntax_highlighter_ini; char *hicompiled_string_description; zend_bool i = 0; + zend_bool numbered = 0; + zend_bool mark_lines = 0; + char *line_prefix = NULL; + int line_prefix_len = 0; int old_error_reporting = EG(error_reporting); - if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "z|b", &expr, &i) == FAILURE) { + if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "z|bbbs", &expr, &i, &numbered, &mark_lines, &line_prefix, &line_prefix_len) == FAILURE) { RETURN_FALSE; } convert_to_string(expr); @@ -2497,7 +2505,7 @@ hicompiled_string_description = zend_make_compiled_string_description("highlighted code" TSRMLS_CC); - if (highlight_string(expr, &syntax_highlighter_ini, hicompiled_string_description TSRMLS_CC) == FAILURE) { + if (highlight_string_ex(expr, &syntax_highlighter_ini, hicompiled_string_description, numbered, mark_lines, line_prefix TSRMLS_CC) == FAILURE) { efree(hicompiled_string_description); RETURN_FALSE; } --Boundary-00=_/g3MCYLYb5prcFH--