diff options
author | Hugo Hörnquist <hugo@lysator.liu.se> | 2023-07-12 23:14:23 +0200 |
---|---|---|
committer | Hugo Hörnquist <hugo@lysator.liu.se> | 2023-07-12 23:14:23 +0200 |
commit | f333cae22e1d19119b1aa9ee9d30daa21243d1d8 (patch) | |
tree | 28cbef38210abb01284a54041250342f556bd8e9 /rainbow_parenthesis/__init__.py | |
parent | Remove black from the pool of colors. (diff) | |
download | rainbow-parenthesis-f333cae22e1d19119b1aa9ee9d30daa21243d1d8.tar.gz rainbow-parenthesis-f333cae22e1d19119b1aa9ee9d30daa21243d1d8.tar.xz |
Move project to a proper module layout.
Diffstat (limited to 'rainbow_parenthesis/__init__.py')
-rw-r--r-- | rainbow_parenthesis/__init__.py | 112 |
1 files changed, 112 insertions, 0 deletions
diff --git a/rainbow_parenthesis/__init__.py b/rainbow_parenthesis/__init__.py new file mode 100644 index 0000000..ad8eb51 --- /dev/null +++ b/rainbow_parenthesis/__init__.py @@ -0,0 +1,112 @@ +"""Simple script which adds matching rainbow colors to data read on stdin.""" + +import io +from typing import Literal +from dataclasses import dataclass + + +@dataclass +class Stackpointer(): + """A "fancy" integer which implements pre-and post decrement.""" + + depth: int = 0 + + def __call__(self, c: int): + """ + Update and return current state. + + :param c: + An integer. + Positive integers increment the value after returning it, + negative integers decrement the value before returning it, + 0 returns the value as is. + """ + ret: int + if c > 0: + ret = self.depth + self.depth += 1 + elif c < 0: + self.depth -= 1 + ret = self.depth + else: + ret = self.depth + return ret + + +@dataclass +class Colored: + """ + Tag an item with a color "depth". + + Depth is an arbitarary (positive) integer, from 0 and + incrementing by up. Each distinct value should correspond to a + color. The colors may repeat. + """ + + depth: int + item: str + + +def color(depth: int, c: str) -> Colored: + """Write a highlighted string.""" + return Colored(depth, c) + + +def colorize(strm: io.TextIOBase) -> list[str | Colored]: + """ + Colorize a given string. + + :param strm: + Text stream to get contents from. + + Use ``io.StringIO`` if you want to pass a string. + :returns: + A list where each item is either a plain string, or a + ``Colored`` object. + """ + in_string: Literal[False] | Literal['"'] | Literal["'"] = False + + paren = 0 + brace = 0 + brack = 0 + + depth = Stackpointer() + + out: list[str | Colored] = [] + while c := strm.read(1): + match c: + case '(': + out.append(color(depth(1), c)) + paren += 1 + case ')': + out.append(color(depth(-1), c)) + paren -= 1 + case '[': + out.append(color(depth(1), c)) + brack += 1 + case ']': + out.append(color(depth(-1), c)) + brack -= 1 + case '{': + out.append(color(depth(1), c)) + brace += 1 + case '}': + out.append(color(depth(-1), c)) + brace -= 1 + case "'": + if in_string == "'": + in_string = False + else: + in_string = "'" + out.append(c) + case '"': + if in_string == '"': + in_string = False + else: + in_string = '"' + out.append(c) + case '\\': + out.append(strm.read(1)) + case c: + out.append(c) + return out |