【问题标题】:Is there a list of ANSI color escape codes somewhere in the standard libraries?标准库中某处是否有 ANSI 颜色转义码列表?
【发布时间】:2016-05-11 18:47:07
【问题描述】:

我写了很多小帮助脚本,这些脚本通常会在终端中打印彩色文本。为了简化它们的打包和分发,我经常希望这些小脚本没有任何依赖关系。

因此,我在脚本中经常复制这样的数据:

ansi_colors = {
    None: '\x1b[0m',  # actually black but whatevs
    'red': '\x1b[31m',
    'green' : '\x1b[32m',
    ...
}

这些数据是否存在于核心库中的任何位置?我四处寻找,发现curses 有一些COLOR_* 常量,但它们只是整数,它们如何转换为ANSI 转义码并不明显。

我已经知道termcolorcoloramablessings 等模块,所以请不要建议使用这些模块——我只想依赖标准库。

【问题讨论】:

  • man terminfo 有点帮助,显示两个标准颜色图。

标签: python curses python-curses ansi-colors


【解决方案1】:

您可以查看手册页console_codes(4)。您想要的是 ECMA-48 集图形再现:

ECMA-48 SGR 序列ESC [ parameters m 设置显示属性。 可以按相同的顺序设置多个属性,以 分号。空参数(分号或字符串之间) 引发剂或终止剂)是 解释为零。

   param   result
   0       reset all attributes to their defaults
   1       set bold
   2       set half-bright (simulated with color on a color display)
   4       set  underscore (simulated with color on a color display) (the colors used to
           simulate dim or underline are set using ESC ] ...)
   5       set blink
   7       set reverse video
   10      reset selected mapping, display control flag, and toggle meta  flag  (ECMA-48
           says "primary font").
   11      select  null  mapping,  set  display  control  flag,  reset  toggle meta flag
           (ECMA-48 says "first alternate font").
   12      select null mapping, set display control flag, set toggle meta flag  (ECMA-48
           says "second alternate font").  The toggle meta flag causes the high bit of a
           byte to be toggled before the mapping table translation is done.
   21      set normal intensity (ECMA-48 says "doubly underlined")
   22      set normal intensity
   24      underline off
   25      blink off
   27      reverse video off
   30      set black foreground
   31      set red foreground
   32      set green foreground
   33      set brown foreground
   34      set blue foreground
   35      set magenta foreground
   36      set cyan foreground
   37      set white foreground
   38      set underscore on, set default foreground color
   39      set underscore off, set default foreground color
   40      set black background
   41      set red background
   42      set green background
   43      set brown background
   44      set blue background
   45      set magenta background
   46      set cyan background
   47      set white background
   49      set default background color

我认为它们在任何标准 Python 模块中都不可用。但如果你仔细看,你会注意到前景色是30 加上curses 常数,而背景色是40 加上curses 常数。所以你可以这样写:

import curses
def fcolor(c):
    return '\x1B[{0}m'.format(30 + c)
def bcolor(c):
    return '\x1B[{0}m'.format(40 + c)
def fbcolor(f, b):
    return '\x1B[{0};{1}m'.format(30 + f, 40 + b)

print(fbcolor(curses.COLOR_RED, curses.COLOR_YELLOW) + "hello!")

【讨论】:

    【解决方案2】:

    这取决于你想要什么。 ANSI 颜色 在技术上指的是 ECMA-48 (ISO-6429) 隐含的 8 色调色板,它在 curses 中命名了常量。库不存储转义序列;这些在数据库中。对于 ANSI (sic) 终端,它们对应于 设置图形再现 的转义序列(视频属性,例如粗体、下划线、反转和颜色)。

    termcap、terminfo 和 curses 使用更一般的概念,您从颜色编号开始并生成可以产生相应颜色的转义序列。终端可以没有颜色,也可以有多种颜色(例如 8 种,但对于 xterm 和类似的终端可能有 16、88、256)。告诉如何执行此操作的信息存储在终端数据库中,名为 capabilities。要设置 ANSI 前景色,您可以使用 setaf,或者使用库调用或命令行应用程序,例如 tput,例如,

    tput setaf 4
    

    用于颜色 4(蓝色)。简单的应用程序使用低级 termcap 或 terminfo 接口,通常使用 terminfo 数据库。虽然您可能倾向于格式化自己的转义序列,但这些接口提供了格式化功能,让您避免知道终端可能支持多少种颜色。终端数据库告诉您的程序,使用TERM 环境变量来选择实际的终端描述。如果您的终端支持超过 8 种颜色,则转义序列不是通过在颜色编号上加 30 或 40 形成的。

    这是一个使用 Python 的低级 terminfo 接口的示例:

    import curses
    
    curses.setupterm()
    curses.putp(curses.tparm(curses.tigetstr("setaf"), curses.COLOR_RED))
    curses.putp(curses.tparm(curses.tigetstr("setab"), curses.COLOR_YELLOW))
    curses.putp("hello!")
    curses.putp(curses.tigetstr("sgr0"))
    curses.putp("\n")
    

    进一步阅读:

    【讨论】:

      【解决方案3】:

      Rodrigo 给出了一个很好的答案,尽管颜色仅限于前 8 种颜色。这是我处理16种前景色的一点小贡献

      def fcolor(c):
          if c>7:
              return '\x1B[1;{0}m'.format(22 + c)
          else:
              return '\x1B[0;{0}m'.format(30 + c)
      def bcolor(c):
          return '\x1B[{0}m'.format(40 + c)
      def fbcolor(f, b):
          if f>7:
              return '\x1B[1;{0};{1}m'.format(22 + f, 40 + b)
          else:
              return '\x1B[0;{0};{1}m'.format(30 + f, 40 + b)
      

      【讨论】:

      • 我想知道为什么我的扩展之前的答案是负1
      • +1 来自我。将来,如果您有较小的改进,最好只更新现有答案,而不是发布单独的答案。
      猜你喜欢
      • 2011-06-18
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-01-14
      • 2014-09-25
      • 2014-09-26
      • 2020-09-29
      相关资源
      最近更新 更多