【Python】ターミナル表示で色を付けたい。

## はじめに
Python で 「ターミナル表示で色を付けたいなぁ〜〜」と思った。

## 探索

調べたところ、たくさんのライブラリが出てきた。

- print-color

https://github.com/xy3/print-color

- colorprint

https://github.com/rembish/colorprint

- termcolor

https://github.com/hfeeki/termcolor

うーん、どれもイマイチ。。。。

[3-bit and 4-bit](https://en.wikipedia.org/wiki/ANSI_escape_code#3-bit_and_4-bit) の一部しか対応してない。

[8-bit color](https://en.wikipedia.org/wiki/ANSI_escape_code#8-bit) だったり、[24-bit color (RGB)](https://en.wikipedia.org/wiki/ANSI_escape_code#24-bit) といったもっと細かく色指定ができるのに（蛇足になるかもしれないが）。

また、`'gray'` とか `'red'` とか 文字列で指定しないといけないので、スペルミスが予想されたり、使える色を調べるのにソースレベルで見ないといけない。
　
とても不便。

## なので、作った。


※後々分かったが、windowsだとctypesでwin32api呼んで、わちゃわちゃしないといけないので非対応（使える色が少ない。既にcoloramaというものがあった）

**3-bit, 4-bit, 8-bit, 24-bit color フル対応**

`color-printer` とか、`print-color` とか既に使われているから命名に困った。
**`term-printer`** にした。

https://github.com/nanato12/term-printer


## 使用方法

至って簡単。

まずは、pipでインストール。

```bash
$ pip install term-printer
```


#### 1. 単純に全文色付け。
term_printer (モジュール名はアンスコ (_) なので要注意) から、`Color`と`cprint`をimportする。

あとは、cprintの引数に`attrs=[]`で使用したい色を指定。

`attrs` は必ず **list** でないといけないので注意。

```python
from term_printer import Color, cprint

cprint("これは赤色になります。", attrs=[Color.RED])
cprint("これは明るい赤色になります。", attrs=[Color.BRIGHT_RED])
cprint("これは背景色が赤色になります。", attrs=[Color.BG_RED])
cprint("これは背景色が明るい赤色になります。", attrs=[Color.BG_BRIGHT_RED])
```

![スクリーンショット 2021-06-17 0.21.35.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/437282/3c8994f3-0b13-7499-c755-6b18b607b00e.png)

ちゃんとしたエディタだと、写真のように補完されるのでスペルミスが起きることはない。
![スクリーンショット 2021-06-17 0.21.15.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/437282/f4bb6fdf-a6fd-89a5-6899-fb00d1e90439.png)


Colorには、
`BLACK`, `RED`, `GREEN`, `YELLOW`, `BLUE`, `MAGENTA`, `CYAN`, `WHITE` の8色

- フォントカラー (XXX)
- 明るいフォントカラー (BRIGHT_XXX)
- 背景カラー (BG_XXX)
- 明るい背景カラー (BG_BRIGHT_XXX)

の4パターン、**計32色** 用意されている。

#### 2 . フォーマットを変更してみる

次は、`Format` も import する。

太字にしたり、薄くしたり、斜体にしたり。

```python
from term_printer import Color, Format, cprint

cprint("これは赤色になります。", attrs=[Color.RED])
cprint("これは赤色で太字になります。", attrs=[Color.RED, Format.BOLD])
cprint("これは赤色で薄くなります。", attrs=[Color.RED, Format.FAINT])
cprint("これは赤色で斜体になります。", attrs=[Color.RED, Format.ITALIC])
```

![スクリーンショット 2021-06-17 0.05.31.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/437282/e26c5a66-80a7-2812-90a5-2cd96300f80f.png)

Formatの指定はこんな感じ

| プロパティ | 説明 |
| :-- | :-- |
| BOLD | 太字 |
| FAINT | 薄字 |
| ITALIC | 斜体 |
| UNDERLINE | 下線 |
| BLINK | 点滅 |
| FAST_BLINK | 速い点滅 |
| REVERSE | 反転 |
| CONCEAL | 非表示 |
| STRIKE | 取消線 |

OSや使用しているターミナルによって、使えたり使えなかったりする。

#### 3 . もっとこまかく色指定

ここからが他のライブラリにはできないこと。

8-bit の 256色を使用するときは、`Color256` を import して使う。

第一引数は、`0-255の間`で指定。
範囲外の数字を渡すと Exception 吐くようにしている。

第二引数は、背景色にするかどうか。
背景色にしたい場合は、`True` を渡す。（デフォルトでは`False`）

`cprint` は内部でビルトイン関数の `print` を呼んでいるので、そのまま `end=` などの引数も問題なく使える。

```python
from term_printer import Color256, cprint

for c in range(0, 256):
    cprint("{: ^4}".format(c), attrs=[Color256(c)], end="")
print()

for c in range(0, 256):
    cprint(" " * 4, attrs=[Color256(c, is_bg=True)], end="")
print()
```

結果はこんな感じ。
![スクリーンショット 2021-06-17 0.31.53.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/437282/d18e222c-b99c-9aec-9d6b-71eb91a256a7.png)

#### 4 . さらに細かく色を指定

24-bit, すなわち 16,777,216色を使用するとき (絶対こんなに使わないw) は、`ColorRGB` を import して使う。

引数は`R`, `G`, `B`の順番、`0-255の間`で指定。こちらも範囲外の数字を渡すと Exception 吐くようにしている。

グラデーション表示してみよ。

```python
from term_printer import ColorRGB, cprint

STEP = 8

for r in reversed(range(0, 256, STEP)):
    b = 255 - r
    for g in range(0, 256, STEP):
        cprint(" " * 4, attrs=[ColorRGB(r, g, b, is_bg=True)], end="")
```

わーお。
![スクリーンショット 2021-06-17 1.25.16.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/437282/e81a8093-ca4e-577a-30c8-0054275eef41.png)

普通に使うと。

```python
from term_printer import ColorRGB, cprint

cprint("赤: 0, 緑: 0, 青: 0", attrs=[ColorRGB(0, 0, 0)])
cprint("赤: 255, 緑: 0, 青: 0", attrs=[ColorRGB(255, 0, 0)])
cprint("赤: 0, 緑: 255, 青: 0", attrs=[ColorRGB(0, 255, 0)])
cprint("赤: 0, 緑: 0, 青: 255", attrs=[ColorRGB(0, 0, 255)])
cprint("赤: 255, 緑: 255, 青: 255", attrs=[ColorRGB(255, 255, 255)])
cprint("赤: 255, 緑: 255, 青: 0", attrs=[ColorRGB(255, 255, 0)])
cprint("赤: 255, 緑: 0, 青: 255", attrs=[ColorRGB(255, 0, 255)])
cprint("赤: 0, 緑: 255, 青: 255", attrs=[ColorRGB(0, 255, 255)])
```

![スクリーンショット 2021-06-17 0.48.46.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/437282/e2c83256-59b4-99a2-02a8-49dfdfb986bf.png)

#### 5 . 一部の文字だけ変更

計算の答えとか、一部のみ色変更したいとき、`StdText` を import する。

```python
from term_printer import Color, Format, StdText, cprint

cprint("1 + 1 =", StdText("2", Color.CYAN))
cprint(StdText("[success]", Color.GREEN), "completed !")
cprint(StdText("[failure]", Color.RED), "failed !")
cprint(StdText("[waring]", Color.YELLOW), "alert !")

cprint(f"This is {StdText('bold', Format.BOLD)} text !")
```

![スクリーンショット 2021-06-17 0.57.31.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/437282/7303e6af-d311-910c-0ff8-7ad27daa09b4.png)

#### 6 . 既存のコードに導入

もう現在、使用しているコードに色を付けたい！　や
`cprint` 書くのめんどくさい！ って時に使えます。

たとえば、50%の確率プログラムがあったとき。
`[成功]` と `[失敗]` だけ色を付けたい。

```python
from random import randint

for _ in range(10):
    if 50 > randint(0,99):
        print("[成功] 50未満の数字を引きました！")
    else:
        print("[失敗] 50以上の数字を引いたよ...")
```
![スクリーンショット 2021-06-17 1.08.56.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/437282/1aec4a9c-32be-b889-e8cb-2bc4f83c7f4d.png)


ただ、`cprint` を `print` にエイリアス張って、`StdText` 使うだけ。

```python
from random import randint

from term_printer import Color, StdText
from term_printer import cprint as print

for _ in range(10):
    if 50 > randint(0, 99):
        print(StdText("[成功]", Color.GREEN), "50未満の数字を引きました！")
    else:
        print(StdText("[失敗]", Color.RED), "50以上の数字を引いたよ...")
```
![スクリーンショット 2021-06-17 1.09.41.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/437282/7ebb8653-06a5-9793-2aed-a58fd0742b55.png)

結局、`cprint` は内部でビルトイン関数の `print` を呼んでいるので（2回目）、既存コードを改修することなく使える。

## おわりに
メンテ待ってます。
英語よわよわなのでおかしい英語あったり、不具合など見つけたら PR か issue ください。


https://github.com/nanato12/term-printer