bluesoul/text_highlighter

Text_Highlighter,修复了 PHP >= 7.2 中 [] 操作符引起的致命错误。更多信息请访问:http://pear.php.net/package/Text_Highlighter

1.0.0 2020-06-15 15:54 UTC

This package is auto-updated.

Last update: 2024-09-23 23:39:16 UTC


README

Build Status

注意:此软件包目前仅存在,用于修复在主线 pear 软件包中发现的 Fatal error: Uncaught Error: [] operator not supported for strings in /usr/share/php/Text/Highlighter/Renderer/Array.php:154 错误。详细信息请访问此处

使用 composer 安装:"bluesoul/Text_Highlighter"

简介

Text_Highlighter 是一个用于语法高亮的类。主要思想是简化实现特定语言语法高亮的子类的创建。子类不实现任何新功能,它们只提供语法高亮规则。规则来源是 XML 格式。要创建一种语言的语法高亮器,不需要手动编写新类。只需在 XML 文件中描述规则,并使用 Text_Highlighter_Generator 创建新类。

此文档不包含 API 的正式描述——它非常简单,我相信提供一些代码示例就足够了。

高亮器 XML 源

基础知识

创建新的语法高亮器从描述高亮规则开始。有两个基本元素:块和区域。块是文本的一部分,匹配正则表达式,并以单色高亮显示。关键字是一个块的例子。区域由两个正则表达式定义:一个用于区域的开始,另一个用于区域的结束。与块的主要区别是区域可以包含块和区域(包括同名区域)。区域的一个例子是括号内的语句组(在许多语言中,例如 PHP 和 C 中使用)。此外,匹配区域开始和结束的字符也可以用它们自己的颜色高亮显示,区域内容可以用另一种颜色。

块和区域可以声明为包含。包含的块和区域只能出现在区域内。如果一个区域或块没有被声明为包含,它既可以在顶层出现,也可以在区域内出现。被声明为非包含的块或区域只能在顶层出现。

对于任何区域,可以指定可以出现在该区域内的块和区域的列表。

在此文档中,术语“颜色组”被使用。分配给相同颜色组的文本块将以相同的颜色高亮显示。请注意,在版本 0.5.0 之前,颜色组被称为 CSS 类,但自 0.5.0 以来,不仅支持 HTML 输出,因此“颜色组”是一个更合适的术语。

元素

顶层元素是 。属性 lang 是必需的,表示语言的名称。其值用作生成类名称的一部分,并且只能包含字母、数字和下划线。可选属性 case,如果值为 yes,则使语言区分大小写(默认为不区分大小写)。允许的子元素包括

* <authors>: Information about the authors of the file.
    <author>: Information about a single author of the file. (May be used
    multiple times, one per author.)
            - name="...": Author's name. Required.
            - email="...": Author's email address. Optional.

* <default>: Default color group.
      - innerGroup="...": color group name. Required.

* <region>: Region definition
      - name="...": Region name. Required.
      - innerGroup="...": Default color group of region contents. Required.
      - delimGroup="...": color group of start and end of region. Optional,
        defaults to value of innerGroup attribute.
      - start="...", end="...": Regular expression matching start and end
        of region. Required. Regular expression delimiters are optional, but
        if you need to specify delimiter, use /. The only case when the
        delimiters are needed, is specifying regular expression modifiers,
        such as m or U. Examples: \/\* or /$/m.
      - contained="yes": Marks region as contained.
      - never-contained="yes": Marks region as not-contained.
      - <contains>: Elements allowed inside this region.
            - all="yes" Region can contain any other region or block
            (except not-contained). May be used multiple times.
                  - <but> Do not allow certain regions or blocks.
                        - region="..." Name of region not allowed within
                          current region.
                        - block="..." Name of block not allowed within
                          current region.
            - region="..." Name of region allowed within current region.
            - block="..." Name of block allowed within current region.
      - <onlyin> Only allow this region within certain regions. May be
        used multiple times.
            - block="..." Name of parent region

* <block>: Block definition
      - name="...": Block name. Required.
      - innerGroup="...": color group of block contents. Optional. If not
        specified, color group of parent region or default color group will be
        used. One would only want to omit this attribute if there are
        keyword groups (see below) inherited from this block, and no special
        highlighting should apply when the block does not match the keyword.
      - match="..." Regular expression matching the block. Required.
        Regular expression delimiters are optional, but if you need to
        specify delimiter, use /. The only case when the delimiters are
        needed, is specifying regular expression modifiers, such as m or U.
        Examples: #|\/\/ or /$/m.
      - contained="yes": Marks block as contained.
      - never-contained="yes": Marks block as not-contained.
      - <onlyin> Only allow this block within certain regions. May be used
          multiple times.
            - block="..." Name of parent region
      - multiline="yes": Marks block as multi-line. By default, whole
        blocks are assumed to reside in a single line. This make the things
        faster. If you need to declare a multi-line block, use this
        attribute.
      - <partgroup>: Assigns another color group to a part of the block that
          matched a subpattern.
            - index="n": Subpattern index. Required.
            - innerGroup="...": color group name. Required.

          This is an example from CSS highlighter: the measure is matched as
          a whole, but the measurement units are highlighted with different
          color.

            <block name="measure"  match="\d*\.?\d+(\%|em|ex|pc|pt|px|in|mm|cm)"
                    innerGroup="number" contained="yes">
                <onlyin region="property"/>
                <partGroup index="1" innerGroup="string" />
            </block>

* <keywords>: Keyword group definition. Keyword groups are useful when you
  want to highlight some words that match a condition for a block with a
  different color. Keywords are defined with literal match, not regular
  expressions. For example, you have a block named identifier matching a
  general identifier, and want to highlight reserved words (which match
  this block as well) with different color. You inherit a keyword group
  "reserved" from "identifier" block.
      - name="...": Keyword group. Required.
      - ifdef="...", ifndef="..." : Conditional declaration. See
        "Conditions" below.
      - inherits="...": Inherited block name. Required.
      - innerGroup="...": color group of keyword group. Required.
      - case="yes|no": Overrides case-sensitivity of the language.
        Optional, defaults to global value.
      - <keyword>: Single keyword definition.
            - match="..." The keyword. Note: this is not a regular
              expression, but literal match (possibly case insensitive).

请注意,出于向后兼容的原因,元素 partClass 是 partGroup 的别名,属性 innerClass 和 delimClass 分别是 innerGroup 和 delimGroup 的别名。

条件

条件声明允许在运行时启用或禁用某些高亮规则。例如,Java 高亮器有一个非常大的匹配 Java 标准类的关键字列表。在这个列表中找到匹配项可能需要很长时间。因此,相应的关键字组被声明为具有 "ifdef" 属性

... ...

此关键字组仅在 "java.builtins" 被作为 "defines" 选项的元素传递时启用

$options = array(
    'defines' => array(
        'java.builtins',
    ),
    'numbers' => HL_NUMBERS_TABLE,
);
$highlighter = Text_Highlighter::factory('java', $options);

"ifndef" 属性具有相反的意义。

目前,"ifdef" 和 "ifndef" 属性仅支持标签。

类生成

创建高亮规则的XML描述是整个过程中最复杂的一部分。要生成类,只需几行代码即可。

<?php
require_once 'Text/Highlighter/Generator.php';
$generator = new Text_Highlighter_Generator('php.xml');
$generator->generate();
$generator->saveCode('PHP.php');
?>

命令行类生成工具

前一部分的示例看起来很简单,但它没有处理在解析XML源时可能出现的任何错误。这个包提供了一个命令行脚本,使得类的生成更加简单,并处理了可能出现的错误。在Unix/Linux上称为generate,在Windows上称为generate.bat。此脚本能够在一次运行中处理多个文件,并能够处理标准输入中的XML,并将生成的代码写入标准输出。

Usage:
generate options

Options:
  -x filename, --xml=filename
        source XML file. Multiple input files can be specified, in which
        case each -x option must be followed by -p unless -d is specified
        Defaults to stdin
  -p filename, --php=filename
        destination PHP file. Defaults to stdout. If specied multiple times,
        each -p must follow -x
  -d dirname, --dir=dirname
        Default destination directory. File names will be taken from XML input
        ("lang" attribute of <highlight> tag)
  -h, --help
        This help

示例

Read from php.xml, write to PHP.php

    generate -x php.xml -p PHP.php

Read from php.xml, write to standard output

    generate -x php.xml

Read from php.xml, write to PHP.php, read from xml.xml, write to XML.php

    generate -x php.xml -p PHP.php -x xml.xml -p XML.php

Read from php.xml, write to /some/dir/PHP.php, read from xml.xml, write to
/some/dir/XML.php (assuming that xml.xml contains <highlight lang="xml">, and
php.xml contains <highlight lang="php">)

    generate -x php.xml -x xml.xml -d /some/dir/

渲染器

简介

Text_Highlighter支持渲染器。使用渲染器,您可以得到不同格式的输出。该包包含两个渲染器。

- HTML renderer. Generates HTML output. A style sheet should be linked to
  the document to display colored text

- Console renderer. Can be used to output highlighted text to
  color-capable terminals, either directly or trough less -r

渲染器API

渲染器是Text_Highlighter_Renderer的子类。渲染器至少应该重写两个方法 - acceptToken和getOutput。根据渲染器输出的性质和实现的细节,重写其他方法是可选的。

string reset()
    resets renderer state. This method is called every time before a new
    source file is highlighted.

string preprocess(string $code)
    preprocesses code. Can be used, for example, to normalize whitespace
    before highlighting. Returns preprocessed string.

void acceptToken(string $group, string $content)
    the core method of the renderer. Highlighter passes chunks of text to
    this method in $content, and color group in $group

void finalize()
    signals the renderer that no more tokens are available.

mixed getOutput()
    returns generated output.

设置渲染器选项

渲染器接受一个可选的构造函数参数 - 选项数组。数组的元素是渲染器特定的。

HTML渲染器

HTML渲染器产生带有可选行号的HTML输出。渲染器本身不提供关于高亮文本实际颜色的信息。相反,使用标签,其中XXX被替换为颜色组名称(hl-var、hl-string等)。您需要自己创建CSS样式表。如果传递了值为true的'使用语言'('use_language')选项,则类名将以"LANG-hl-XXX"的格式格式化,其中LANG是高亮器XML源中定义的语言名称(标签的"lang"属性)的小写。

有3个特殊的CSS类

hl-main - this class applies to whole output or right table column,
          depending on 'numbers' option
hl-gutter - applies to left column in table
hl-table - applies to whole table

HTML渲染器接受以下选项(每个都是可选的)

* numbers - line numbering style.
    0 - no numbering (default)
    HL_NUMBERS_LI - use <ol></ol> for line numbering
    HL_NUMBERS_TABLE  - create a 2-column table, with line numbers in left
                        column and highlighted text in right column

* tabsize - tabulation size. Defaults to 4

Example:
    
    require_once 'Text/Highlighter/Renderer/Html.php';
    $options = array(
        'numbers' => HL_NUMBERS_LI,
        'tabsize' => 8,
    );
    $renderer = new Text_Highlighter_Renderer_HTML($options);

控制台渲染器

控制台渲染器产生在支持颜色的终端上显示的输出,可以直接使用或通过less -r使用ANSI转义序列。默认情况下,此渲染器仅高亮显示最常见的颜色组。可以使用'colors'选项指定额外的颜色。此渲染器还接受'numbers'选项 - 一个布尔值,以及'tabsize'选项。

Example :

    require_once 'Text/Highlighter/Renderer/Console.php';
    $colors = array(
        'prepro' => "\033[35m",
        'types' => "\033[32m",
    );
    $options = array(
        'numbers' => true,
        'tabsize' => 8,
        'colors' => $colors,
    );
    $renderer = new Text_Highlighter_Renderer_Console($options);

ANSI颜色转义序列的格式如下

ESC[#;#;....;#m

其中ESC是ASCII码为27的字符(八进制033,十六进制0x1B)。#是以下之一

    0 for normal display
    1 for bold on
    4 underline (mono only)
    5 blink on
    7 reverse video on
    8 nondisplayed (invisible)
    30 black foreground
    31 red foreground
    32 green foreground
    33 yellow foreground
    34 blue foreground
    35 magenta foreground
    36 cyan foreground
    37 white foreground
    40 black background
    41 red background
    42 green background
    43 yellow background
    44 blue background
    45 magenta background
    46 cyan background
    47 white background

如何使用Text_Highlighter类

创建高亮器对象

要为某种语言创建高亮器,请使用Text_Highlighter::factory()静态方法。

require_once 'Text/Highlighter.php';
$hl = Text_Highlighter::factory('php');

设置渲染器

实际输出由渲染器产生。

require_once 'Text/Highlighter.php';
require_once 'Text/Highlighter/Renderer/Html.php';
$options = array(
    'numbers' => HL_NUMBERS_LI,
    'tabsize' => 8,
);
$renderer = new Text_Highlighter_Renderer_HTML($options);
$hl = Text_Highlighter::factory('php');
$hl->setRenderer($renderer);

请注意,出于向后兼容性原因,可以在不设置渲染器的情况下使用高亮器。如果没有设置渲染器,则默认使用HTML渲染器。在这种情况下,您应该将选项作为factory方法的第二个参数传递。以下示例与上一个示例完全相同

require_once 'Text/Highlighter.php';
$options = array(
    'numbers' => HL_NUMBERS_LI,
    'tabsize' => 8,
);
$hl = Text_Highlighter::factory('php', $options);

获取输出

最后,进行高亮并获取输出。

require_once 'Text/Highlighter.php';
require_once 'Text/Highlighter/Renderer/Html.php';
$options = array(
    'numbers' => HL_NUMBERS_LI,
    'tabsize' => 8,
);
$renderer = new Text_Highlighter_Renderer_HTML($options);
$hl = Text_Highlighter::factory('php');
$hl->setRenderer($renderer);
$html = $hl->highlight(file_get_contents('example.php'));