跳转到主要内容

使用xml-like标记生成彩色终端文本

项目描述

Ansimarkup

pypi version Build status License

Ansimarkup是一个用于生成彩色终端文本的XML-like标记。

from ansimarkup import ansiprint as print

print("<b>bold text</b>"))
print("<red>red text</red>", "<red,green>red text on a green background</red,green>")
print("<fg #ffaf00>orange text</fg #ffaf00>")

安装

可以从PyPi安装ansimarkup的最新稳定版本。

python3 -m pip install ansimarkup

使用方法

基本

from ansimarkup import parse, ansiprint

# parse() converts the tags to the corresponding ansi escape sequence.
parse("<b>bold</b> <d>dim</d>")

# ansiprint() works exactly like print(), but first runs parse() on all arguments.
ansiprint("<b>bold</b>", "<d>dim</d>")
ansiprint("<b>bold</b>", "<d>dim</d>", sep=":", file=sys.stderr)

颜色和样式

# Colors may be specified in one of several ways.
parse("<red>red foreground</red>")
parse("<RED>red background</RED>")
parse("<fg red>red foreground</fg red>")
parse("<bg red>red background</bg red>")

# Xterm, hex and rgb colors are accepted by the <fg> and <bg> tags.
parse("<fg 86>aquamarine foreground</fg 86>")
parse("<bg #00005f>dark blue background</bg #00005f>")
parse("<fg 0,95,0>dark green foreground</fg 0,95,0>")

# Tags may be nested.
parse("<r><Y>red text on a yellow foreground</Y></r>")

# The above may be more concisely written as:
parse("<r,y>red text on a yellow background</r,y>")

# This shorthand also supports style tags.
parse("<b,r,y>bold red text on a yellow background</b,r,y>")
parse("<b,r,>bold red text</b,r,>")
parse("<b,,y>bold regular text on a yellow background</b,,y>")

# Unrecognized tags are left as-is.
parse("<b><element1></element1></b>")

有关标记标签的列表,请参阅tags.py

用户定义的标签

可以通过创建一个新的AnsiMarkup实例来定义自定义标签或现有标签的覆盖

from ansimarkup import AnsiMarkup, parse

user_tags = {
    # Add a new tag (e.g. we want <info> to expand to "<bold><green>").
    "info": parse("<b><g>")

    # The ansi escape sequence can be used directly.
    "info": "e\x1b[32m\x1b[1m",

    # Tag names may also be callables.
    "err":  lambda: parse("<r>")

    # Colors may also be given convenient tag names.
    "orange": parse("<fg #d78700>"),

    # User-defined tags always take precedence over existing tags.
    "bold": parse("<dim>")
}

am = AnsiMarkup(tags=user_tags)

am.parse("<info>bold green</info>")
am.ansiprint("<err>red</err>")

# Calling the instance is equivalent to calling its parse method.
am("<b>bold</b>") == am.parse("<b>bold</b>")

对齐和长度

对齐格式化的字符串可能具有挑战性,因为渲染的字符串长度与可打印字符数不同。考虑以下示例

>>> a = '| {:30} |'.format('abc')
>>> b = '| {:30} |'.format(parse('<b>abc</b>'))
>>> print(a, b, sep='\n')
| abc                    |
| abc                            |

可以使用ansistring函数或AnsiMarkup.string(markup)方法来解决这个问题,它具有以下有用的属性

>>> s = ansistring('<b>abc</b>')
>>> print(repr(s), '->', s)
<b>abc</b> -> abc  # abc is printed in bold
>>> len(s), len(am.parse('<b>abc</b>'), s.delta
3, 11, 8

借助delta属性,可以轻松对齐上述示例中的字符串

>>> s = ansistring('<b>abc</b>')
>>> a = '| {:{width}} |'.format('abc', width=30)
>>> b = '| {:{width}} |'.format(s, width=(30 + s.delta))
>>> print(a, b, sep='\n')
| abc                            |
| abc                            |

转义原始字符串

ansiprint()parse()都会原样传递类型为raw的参数。

>>> from ansimarkup import ansiprint, parse, raw
>>> ansiprint("<b><r>", raw("<l type='V'>2.0</l>"), "</r></b>")
 <l type='V'>2.0</l>  # printed in bold red (note the leading space caused)

>>> s = parse("<b><r>", raw("<l type='V'>2.0</l>"), "</r></b>")
>>> print(s)
<l type='V'>2.0</l>  # printed in bold red

构建模板字符串也可能足够

>>> from ansimarkup import parse
>>> s = parse("<b><r>%s</r></b>")
>>> print(s % "<l type='V'>2.0</l>")
<l type='V'>2.0</l>  # printed in bold red

其他功能

可以通过将tag_sep参数传递给AnsiMarkup来更改默认的标签分隔符

from ansimarkup import AnsiMarkup

am = AnsiMarkup(tag_sep="{}")
am.parse("{b}{r}bold red{/b}{/r}")

可以使用strip()方法删除标记标签

from ansimarkup import AnsiMarkup

am = AnsiMarkup()
am.strip("<b><r>bold red</b></r>")

strict选项指示解析器在开标签没有相应的闭标签时引发MismatchedTag

from ansimarkup import AnsiMarkup

am = AnsiMarkup(strict=True)
am.parse("<r><b>bold red")
# ansimarkup.MismatchedTag: opening tag "<r>" has no corresponding closing tag

命令行

Ansimarkup 还可以在命令行中使用。这相当于将所有参数都传递给了 ansiprint()

$ python -m ansimarkup
Usage: python -m ansimarkup [<arg> [<arg> ...]]

Example usage:
  python -m ansimarkup '<b>Bold</b>' '<r>Red</r>'
  python -m ansimarkup '<b><r>Bold Red</r></b>'
  python -m ansimarkup < input-with-markup.txt
  echo '<b>Bold</b>' | python -m ansimarkup

日志格式化器

Ansimarkup 还附带了一个用于标准库 logging 模块的格式化器。它可以这样使用

import logging
from ansimarkup.logformatter import AnsiMarkupFormatter

log = logging.getLogger()
hdl = logging.StreamHandler()
fmt = AnsiMarkupFormatter()
hdl.setFormatter(fmt)
log.addHandler(hdl)

log.info("<b>bold text</b>")

Windows

Ansimarkup 在内部使用 colorama 库,这意味着通过先运行

import colorama
colorama.init()

有关 Windows 支持的更多信息,请参阅 colorama 文档中的“使用”部分。

性能

虽然 Ansimarkup 的重点是方便,但它确实试图将处理降到最低。benchmark.py 脚本试图对不同的 ansi 转义代码库进行基准测试

Benchmark 1: <r><b>red bold</b></r>
  colorama     0.1959 μs
  colr         1.8022 μs
  ansimarkup   3.1681 μs
  termcolor    5.3734 μs
  rich         9.0673 μs
  pastel       10.7440 μs
  plumbum      14.0620 μs

Benchmark 2: <r><b>red bold</b>red</r><b>bold</b>
  colorama     0.5360 μs
  colr         4.5575 μs
  ansimarkup   4.5727 μs
  termcolor    15.8462 μs
  rich         21.2631 μs
  pastel       22.9391 μs
  plumbum      33.1179 μs

限制

Ansimarkup 是围绕 colorama 的一个简单包装器。它在验证标记字符串是否正确形成方面做得很少。这是一个有意识的决策,目的是保持简单和快速。

不匹配的嵌套,如下例所示,将产生不正确的输出

<r><Y>1</r>2</Y>

待办事项

  • 许多角落案例仍需修复。
  • 更详细的测试。当前的测试套件主要覆盖“快乐路径”。
  • sub_end 中用更有效的方法替换 tag_list.index(例如,类似于有序的 MultiDict)。

类似库

  • pastel:为您的终端带来颜色
  • plumbum.colors:适用于类似 shell 脚本的 Python 程序的小型但功能丰富的库
  • colr:简单终端颜色,具有链式方法
  • rich:在终端中进行丰富文本和美观格式化(请参阅 rich.print()rich.markup.render()

许可证

Ansimarkup 在 修订版 BSD 许可证 的条款下发布。

项目详情


下载文件

下载您平台上的文件。如果您不确定要选择哪一个,请了解有关 安装软件包 的更多信息。

源分布

ansimarkup-2.1.0.tar.gz (16.7 kB 查看哈希值)

上传时间

构建分布

ansimarkup-2.1.0-py3-none-any.whl (11.8 kB 查看哈希值)

上传时间 Python 3

由以下支持

AWSAWS云计算和安全赞助商DatadogDatadog监控FastlyFastlyCDNGoogleGoogle下载分析MicrosoftMicrosoftPSF赞助商PingdomPingdom监控SentrySentry错误日志StatusPageStatusPage状态页面