Colorlib design

New in version 1.6.

The purpose of this document is to describe the system that plumbum.colors implements. This system was designed to be flexible and to allow implementing new color backends. Hopefully this document will allow future work on colorlib to be as simple as possible.

Note

Enabling color

plumbum.colors tries to guess the color output settings of your system. You can force the use of color globally by setting colors.use_color=True See 256 Color Support for more options.

Generating colors

Styles are accessed through the colors object, which is an instance of a StyleFactory. The colors object is actually an imitation module that wraps plumbum.colorlib.ansicolors with module-like access. Thus, things like from plumbum.colors.bg import red work also. The library actually lives in plumbum.colorlib.

Style Factory

The colors object has the following available objects:

fg and bg

The foreground and background colors, reset to default with colors.fg.reset or ~colors.fg and likewise for bg. These are ColorFactory instances.

bold, dim, underline, italics, reverse, strikeout, and hidden

All the ANSI modifiers are available, as well as their negations, such as ~colors.bold or colors.bold.reset, etc. (These are generated automatically based on the Style attached to the factory.)

reset

The global reset will restore all properties at once.

do_nothing

Does nothing at all, but otherwise acts like any Style object. It is its own inverse. Useful for cli properties.

The colors object can be used in a with statement, which resets all styles on leaving the statement body. Although factories do support some of the same methods as a Style, their primary purpose is to generate Styles. The colors object has a use_color property that can be set to force the use of color. A stdout property is provided to make changing the output of color statement easier. A colors.from_ansi(code) method allows you to create a Style from any ansi sequence, even complex or combined ones.

Color Factories

The colors.fg and colors.bg are ColorFactory’s. In fact, the colors object itself acts exactly like the colors.fg object, with the exception of the properties listed above.

Named foreground colors are available directly as methods. The first 16 primary colors, black, red, green, yellow, blue, magenta, cyan, etc, as well as reset, are available. All 256 color names are available, but do not populate factory directly, so that auto-completion gives reasonable results. You can also access colors using strings and do colors[string]. Capitalization, underscores, and spaces (for strings) will be ignored.

You can also access colors numerically with colors(n) or colors[n] with the extended 256 color codes. The former will default to simple versions of colors for the first 16 values. The later notation can also be used to slice. Full hex codes can be used, too. If no match is found, these will be the true 24 bit color value.

The fg and bg also can be put in with statements, and they will restore the foreground and background color only, respectively.

colors.rgb(r,g,b) will create a color from an input red, green, and blue values (integers from 0-255). colors.rgb(code) will allow you to input an html style hex sequence. These work on fg and bg too. The repr of styles is smart and will show you the closest color to the one you selected if you didn’t exactly select a color through RGB.

Style manipulations

Safe color manipulations refer to changes that reset themselves at some point. Unsafe manipulations must be manually reset, and can leave your terminal color in an unreadable state if you forget to reset the color or encounter an exception. If you do get the color unset on a terminal, the following, typed into the command line, will restore it:

$ python3 -m plumbum.colors

This also supports command line access to unsafe color manipulations, such as

$ python3 -m plumbum.colors blue
$ python3 -m plumbum.colors bg red
$ python3 -m plumbum.colors fg 123
$ python3 -m plumbum.colors bg reset
$ python3 -m plumbum.colors underline

You can use any path or number available as a style.

Unsafe Manipulation

Styles have two unsafe operations: Concatenation (with + and a string) and calling .now() without arguments (directly calling a style without arguments is also a shortcut for .now()). These two operations do not restore normal color to the terminal by themselves. To protect their use, you should always use a context manager around any unsafe operation.

An example of the usage of unsafe colors manipulations inside a context manager:

from plumbum import colors

with colors:
    colors.fg.red.now()
    print('This is in red')
    colors.green.now()
    print('This is green ' + colors.underline + 'and now also underlined!')
    print('Underlined' + colors.underline.reset + ' and not underlined but still red')
print('This is completely restored, even if an exception is thrown!')

Output:

This is in red
This is in green and now also underlined!
Underlined and not underlined but still green.
This is completely restored, even if an exception is thrown!

We can use colors instead of colors.fg for foreground colors. If we had used colors.fg as the context manager, then non-foreground properties, such as colors.underline or colors.bg.yellow, would not have reset those properties. Each attribute, as well as fg, bg, and colors all have inverses in the ANSI standard. They are accessed with ~ or .reset, and can be used to manually make these operations safer, but there is a better way.

Safe Manipulation

All other operations are safe; they restore the color automatically. The first, and hopefully already obvious one, is using a Style rather than a colors or colors.fg object in a with statement. This will set the color (using sys.stdout by default) to that color, and restore color on leaving.

The second method is to manually wrap a string. This can be done with color.wrap("string") or color["string"]. These produce strings that can be further manipulated or printed.

Finally, you can also print a color to stdout directly using color.print("string"). This has the same syntax as the print function.

An example of safe manipulations:

colors.fg.yellow('This is yellow', end='')
print(' And this is normal again.')
with colors.red:
    print('Red color!')
    with colors.bold:
        print("This is red and bold.")
    print("Not bold, but still red.")
print("Not red color or bold.")
print((colors.magenta & colors.bold)["This is bold and colorful!"], "And this is not.")

Output:

This is yellow And this is normal again.
Red color!
This is red and bold.
Not bold, but still red.
Not red color or bold.
This is bold and colorful! And this is not.

Style Combinations

You can combine styles with & and they will create a new combined Style object. Colors will not be “summed” or otherwise combined; the rightmost color will be used (this matches the expected effect of applying the Styles individually to the strings). However, combined Styles are intelligent and know how to reset just the properties that they contain. As you have seen in the example above, the combined style (colors.magenta & colors.bold) can be used in any way a normal Style can. Since wrapping is done with |, the Python order of operations causes styles to be combined first, then wrapping is done last.

256 Color Support

While this library supports full 24 bit colors through escape sequences, the library has special support for the “full” 256 colorset through numbers, names or HEX html codes. Even if you use 24 bit color, the closest name is displayed in the repr. You can access the colors as as colors.fg.Light_Blue, colors.fg.lightblue, colors.fg[12], colors.fg('Light_Blue'), colors.fg('LightBlue'), or colors.fg('#0000FF'). You can also iterate or slice the colors, colors.fg, or colors.bg objects. Slicing even intelligently downgrades to the simple version of the codes if it is within the first 16 elements. The supported colors are:

  1. #000000 Black

  2. #C00000 Red

  3. #00C000 Green

  4. #C0C000 Yellow

  5. #0000C0 Blue

  6. #C000C0 Magenta

  7. #00C0C0 Cyan

  8. #C0C0C0 LightGray

  9. #808080 DarkGray

  10. #FF0000 LightRed

  11. #00FF00 LightGreen

  12. #FFFF00 LightYellow

  13. #0000FF LightBlue

  14. #FF00FF LightMagenta

  15. #00FFFF LightCyan

  16. #FFFFFF White

  17. #000000 Grey0

  18. #00005F NavyBlue

  19. #000087 DarkBlue

  20. #0000AF Blue3

  21. #0000D7 Blue3A

  22. #0000FF Blue1

  23. #005F00 DarkGreen

  24. #005F5F DeepSkyBlue4

  25. #005F87 DeepSkyBlue4A

  26. #005FAF DeepSkyBlue4B

  27. #005FD7 DodgerBlue3

  28. #005FFF DodgerBlue2

  29. #008700 Green4

  30. #00875F SpringGreen4

  31. #008787 Turquoise4

  32. #0087AF DeepSkyBlue3

  33. #0087D7 DeepSkyBlue3A

  34. #0087FF DodgerBlue1

  35. #00AF00 Green3

  36. #00AF5F SpringGreen3

  37. #00AF87 DarkCyan

  38. #00AFAF LightSeaGreen

  39. #00AFD7 DeepSkyBlue2

  40. #00AFFF DeepSkyBlue1

  41. #00D700 Green3A

  42. #00D75F SpringGreen3A

  43. #00D787 SpringGreen2

  44. #00D7AF Cyan3

  45. #00D7D7 DarkTurquoise

  46. #00D7FF Turquoise2

  47. #00FF00 Green1

  48. #00FF5F SpringGreen2A

  49. #00FF87 SpringGreen1

  50. #00FFAF MediumSpringGreen

  51. #00FFD7 Cyan2

  52. #00FFFF Cyan1

  53. #5F0000 DarkRed

  54. #5F005F DeepPink4

  55. #5F0087 Purple4

  56. #5F00AF Purple4A

  57. #5F00D7 Purple3

  58. #5F00FF BlueViolet

  59. #5F5F00 Orange4

  60. #5F5F5F Grey37

  61. #5F5F87 MediumPurple4

  62. #5F5FAF SlateBlue3

  63. #5F5FD7 SlateBlue3A

  64. #5F5FFF RoyalBlue1

  65. #5F8700 Chartreuse4

  66. #5F875F DarkSeaGreen4

  67. #5F8787 PaleTurquoise4

  68. #5F87AF SteelBlue

  69. #5F87D7 SteelBlue3

  70. #5F87FF CornflowerBlue

  71. #5FAF00 Chartreuse3

  72. #5FAF5F DarkSeaGreen4A

  73. #5FAF87 CadetBlue

  74. #5FAFAF CadetBlueA

  75. #5FAFD7 SkyBlue3

  76. #5FAFFF SteelBlue1

  77. #5FD700 Chartreuse3A

  78. #5FD75F PaleGreen3

  79. #5FD787 SeaGreen3

  80. #5FD7AF Aquamarine3

  81. #5FD7D7 MediumTurquoise

  82. #5FD7FF SteelBlue1A

  83. #5FFF00 Chartreuse2A

  84. #5FFF5F SeaGreen2

  85. #5FFF87 SeaGreen1

  86. #5FFFAF SeaGreen1A

  87. #5FFFD7 Aquamarine1

  88. #5FFFFF DarkSlateGray2

  89. #870000 DarkRedA

  90. #87005F DeepPink4A

  91. #870087 DarkMagenta

  92. #8700AF DarkMagentaA

  93. #8700D7 DarkViolet

  94. #8700FF Purple

  95. #875F00 Orange4A

  96. #875F5F LightPink4

  97. #875F87 Plum4

  98. #875FAF MediumPurple3

  99. #875FD7 MediumPurple3A

  100. #875FFF SlateBlue1

  101. #878700 Yellow4

  102. #87875F Wheat4

  103. #878787 Grey53

  104. #8787AF LightSlateGrey

  105. #8787D7 MediumPurple

  106. #8787FF LightSlateBlue

  107. #87AF00 Yellow4A

  108. #87AF5F DarkOliveGreen3

  109. #87AF87 DarkSeaGreen

  110. #87AFAF LightSkyBlue3

  111. #87AFD7 LightSkyBlue3A

  112. #87AFFF SkyBlue2

  113. #87D700 Chartreuse2

  114. #87D75F DarkOliveGreen3A

  115. #87D787 PaleGreen3A

  116. #87D7AF DarkSeaGreen3

  117. #87D7D7 DarkSlateGray3

  118. #87D7FF SkyBlue1

  119. #87FF00 Chartreuse1

  120. #87FF5F LightGreenA

  121. #87FF87 LightGreenB

  122. #87FFAF PaleGreen1

  123. #87FFD7 Aquamarine1A

  124. #87FFFF DarkSlateGray1

  125. #AF0000 Red3

  126. #AF005F DeepPink4B

  127. #AF0087 MediumVioletRed

  128. #AF00AF Magenta3

  129. #AF00D7 DarkVioletA

  130. #AF00FF PurpleA

  131. #AF5F00 DarkOrange3

  132. #AF5F5F IndianRed

  133. #AF5F87 HotPink3

  134. #AF5FAF MediumOrchid3

  135. #AF5FD7 MediumOrchid

  136. #AF5FFF MediumPurple2

  137. #AF8700 DarkGoldenrod

  138. #AF875F LightSalmon3

  139. #AF8787 RosyBrown

  140. #AF87AF Grey63

  141. #AF87D7 MediumPurple2A

  142. #AF87FF MediumPurple1

  143. #AFAF00 Gold3

  144. #AFAF5F DarkKhaki

  145. #AFAF87 NavajoWhite3

  146. #AFAFAF Grey69

  147. #AFAFD7 LightSteelBlue3

  148. #AFAFFF LightSteelBlue

  149. #AFD700 Yellow3

  150. #AFD75F DarkOliveGreen3B

  151. #AFD787 DarkSeaGreen3A

  152. #AFD7AF DarkSeaGreen2

  153. #AFD7D7 LightCyan3

  154. #AFD7FF LightSkyBlue1

  155. #AFFF00 GreenYellow

  156. #AFFF5F DarkOliveGreen2

  157. #AFFF87 PaleGreen1A

  158. #AFFFAF DarkSeaGreen2A

  159. #AFFFD7 DarkSeaGreen1

  160. #AFFFFF PaleTurquoise1

  161. #D70000 Red3A

  162. #D7005F DeepPink3

  163. #D70087 DeepPink3A

  164. #D700AF Magenta3A

  165. #D700D7 Magenta3B

  166. #D700FF Magenta2

  167. #D75F00 DarkOrange3A

  168. #D75F5F IndianRedA

  169. #D75F87 HotPink3A

  170. #D75FAF HotPink2

  171. #D75FD7 Orchid

  172. #D75FFF MediumOrchid1

  173. #D78700 Orange3

  174. #D7875F LightSalmon3A

  175. #D78787 LightPink3

  176. #D787AF Pink3

  177. #D787D7 Plum3

  178. #D787FF Violet

  179. #D7AF00 Gold3A

  180. #D7AF5F LightGoldenrod3

  181. #D7AF87 Tan

  182. #D7AFAF MistyRose3

  183. #D7AFD7 Thistle3

  184. #D7AFFF Plum2

  185. #D7D700 Yellow3A

  186. #D7D75F Khaki3

  187. #D7D787 LightGoldenrod2

  188. #D7D7AF LightYellow3

  189. #D7D7D7 Grey84

  190. #D7D7FF LightSteelBlue1

  191. #D7FF00 Yellow2

  192. #D7FF5F DarkOliveGreen1

  193. #D7FF87 DarkOliveGreen1A

  194. #D7FFAF DarkSeaGreen1A

  195. #D7FFD7 Honeydew2

  196. #D7FFFF LightCyan1

  197. #FF0000 Red1

  198. #FF005F DeepPink2

  199. #FF0087 DeepPink1

  200. #FF00AF DeepPink1A

  201. #FF00D7 Magenta2A

  202. #FF00FF Magenta1

  203. #FF5F00 OrangeRed1

  204. #FF5F5F IndianRed1

  205. #FF5F87 IndianRed1A

  206. #FF5FAF HotPink

  207. #FF5FD7 HotPinkA

  208. #FF5FFF MediumOrchid1A

  209. #FF8700 DarkOrange

  210. #FF875F Salmon1

  211. #FF8787 LightCoral

  212. #FF87AF PaleVioletRed1

  213. #FF87D7 Orchid2

  214. #FF87FF Orchid1

  215. #FFAF00 Orange1

  216. #FFAF5F SandyBrown

  217. #FFAF87 LightSalmon1

  218. #FFAFAF LightPink1

  219. #FFAFD7 Pink1

  220. #FFAFFF Plum1

  221. #FFD700 Gold1

  222. #FFD75F LightGoldenrod2A

  223. #FFD787 LightGoldenrod2B

  224. #FFD7AF NavajoWhite1

  225. #FFD7D7 MistyRose1

  226. #FFD7FF Thistle1

  227. #FFFF00 Yellow1

  228. #FFFF5F LightGoldenrod1

  229. #FFFF87 Khaki1

  230. #FFFFAF Wheat1

  231. #FFFFD7 Cornsilk1

  232. #FFFFFF Grey100

  233. #080808 Grey3

  234. #121212 Grey7

  235. #1C1C1C Grey11

  236. #262626 Grey15

  237. #303030 Grey19

  238. #3A3A3A Grey23

  239. #444444 Grey27

  240. #4E4E4E Grey30

  241. #585858 Grey35

  242. #626262 Grey39

  243. #6C6C6C Grey42

  244. #767676 Grey46

  245. #808080 Grey50

  246. #8A8A8A Grey54

  247. #949494 Grey58

  248. #9E9E9E Grey62

  249. #A8A8A8 Grey66

  250. #B2B2B2 Grey70

  251. #BCBCBC Grey74

  252. #C6C6C6 Grey78

  253. #D0D0D0 Grey82

  254. #DADADA Grey85

  255. #E4E4E4 Grey89

  256. #EEEEEE Grey93

If you want to enforce a specific representation, you can use .basic (8 color), .simple (16 color), .full (256 color), or .true (24 bit color) on a Style, and the colors in that Style will conform to the output representation and name of the best match color. The internal RGB colors are remembered, so this is a non-destructive operation.

To limit the use of color to one of these styles, set colors.use_color to 1 for 8 colors, 2 for 16 colors, 3 for 256 colors, or 4 for true color. It will be guessed based on your system on initialisation.

The Classes

The library consists of three primary classes, the Color class, the Style class, and the StyleFactory class. The following portion of this document is primarily dealing with the working of the system, and is meant to facilitate extensions or work on the system.

The Color class provides meaning to the concept of color, and can provide a variety of representations for any color. It can be initialised from r,g,b values, or hex codes, 256 color names, or the simple color names via classmethods. If initialized without arguments, it is the reset color. It also takes an fg True/False argument to indicate which color it is. You probably will not be interacting with the Color class directly, and you probably will not need to subclass it, though new extensions to the representations it can produce are welcome.

The Style class hold two colors and a dictionary of attributes. It is the workhorse of the system and is what is produced by the colors factory. It holds Color as .color_class, which can be overridden by subclasses (again, this usually is not needed). To create a color representation, you need to subclass Style and give it a working __str__ definition. ANSIStyle is derived from Style in this way.

The factories, ColorFactory and StyleFactory, are factory classes that are meant to provide simple access to 1 style Style classes. To use, you need to initialize an object of StyleFactory with your intended Style. For example, colors is created by:

colors = StyleFactory(ANSIStyle)

Subclassing Style

For example, if you wanted to create an HTMLStyle and HTMLcolors, you could do:

class HTMLStyle(Style):
    attribute_names = dict(bold='b', li='li', code='code')
    end = '<br/>\n'

    def __str__(self):
        result = ''

        if self.bg and not self.bg.reset:
            result += f'<span style="background-color: {self.bg.hex_code}">'
        if self.fg and not self.fg.reset:
            result += f'<font color="{self.fg.hex_code}">'
        for attr in sorted(self.attributes):
            if self.attributes[attr]:
                result += '<' + self.attribute_names[attr] + '>'

        for attr in reversed(sorted(self.attributes)):
            if not self.attributes[attr]:
                result += '</' + self.attribute_names[attr].split()[0] + '>'
        if self.fg and self.fg.reset:
            result += '</font>'
        if self.bg and self.bg.reset:
            result += '</span>'

        return result

htmlcolors = StyleFactory(HTMLStyle)

This doesn’t support global resets, since that’s not how HTML works, but otherwise is a working implementation. This is an example of how easy it is to add support for other output formats.

An example of usage:

>>>  htmlcolors.bold & htmlcolors.red | "This is colored text"
'<font color="#800000"><b>This is colored text</b></font>'

The above color table can be generated with:

for color in htmlcolors:
    htmlcolors.li(
        "&#x25a0;" | color,
        color.fg.hex_code | htmlcolors.code,
        color.fg.name_camelcase)

Note

HTMLStyle is implemented in the library, as well, with the htmlcolors object available in plumbum.colorlib. It was used to create the colored output in this document, with small changes because colors.reset cannot be supported with HTML.

See Also

  • colored Another library with 256 color support

  • colorama A library that supports colored text on Windows,

    can be combined with Plumbum.colors (if you force use_color, doesn’t support all extended colors)