This commit is contained in:
Jeffrey C. Ollie 2023-10-13 09:51:16 -05:00
parent f1efca7ea8
commit bfe7dedd6f
No known key found for this signature in database
GPG key ID: F936E4DCB7E25F15
3 changed files with 148 additions and 12 deletions

3
.gitignore vendored Normal file
View file

@ -0,0 +1,3 @@
/result*
/.venv
__pycache__

View file

@ -1,6 +1,9 @@
"""Configure logging.""" """Configure logging."""
import base64
from enum import Enum
from enum import IntEnum from enum import IntEnum
from enum import auto
import logging import logging
import pathlib import pathlib
import re import re
@ -23,7 +26,65 @@ class ANSIColor(IntEnum):
WHITE = 8 WHITE = 8
class Mode(Enum):
C0 = auto()
C1 = auto()
class ANSI: class ANSI:
mode: Mode
SOH = "\u0001"
STX = "\u0002"
BEL = "\u0007"
BS = "\u0008"
HT = "\u0009"
LF = "\u000a"
VT = "\u000b"
FF = "\u000c"
CR = "\u000d"
ESC = "\u001b"
DEL = "\u007f"
def __init__(self, mode: Mode = Mode.C0):
self.mode = mode
@property
def DCS(self: Self) -> str:
"""Device Control String"""
match self.mode:
case Mode.C1:
return "\u008d"
case Mode.C0 | _:
return f"{self.ESC}P"
@property
def CSI(self: Self) -> str:
"""Control Sequence Introducer"""
match self.mode:
case Mode.C1:
return "\u009b"
case Mode.C0 | _:
return f"{self.ESC}["
@property
def ST(self: Self) -> str:
"""String Terminator"""
match self.mode:
case Mode.C1:
return "\u009c"
case Mode.C0 | _:
return f"{self.ESC}\\"
@property
def OSC(self: Self) -> str:
"""Operating System Command"""
match self.mode:
case Mode.C1:
return "\u009d"
case Mode.C0 | _:
return f"{self.ESC}]"
def __getattr__(self: Self, item: str) -> str: def __getattr__(self: Self, item: str) -> str:
return self.color(item) return self.color(item)
@ -42,7 +103,7 @@ class ANSI:
try: try:
color = ANSIColor[item] color = ANSIColor[item]
return f"\u001b[1;{color+offset:d}{extra}m" return f"{self.CSI}1;{color+offset:d}{extra}m"
except KeyError: except KeyError:
return self.fg24bitrgb(*(getrgb(item)[:3])) return self.fg24bitrgb(*(getrgb(item)[:3]))
@ -54,6 +115,10 @@ class ANSI:
def white(self: Self) -> str: def white(self: Self) -> str:
return self.color("white") return self.color("white")
@property
def green(self: Self) -> str:
return self.color("green")
@property @property
def blue(self: Self) -> str: def blue(self: Self) -> str:
return self.color("blue") return self.color("blue")
@ -64,37 +129,76 @@ class ANSI:
@property @property
def reset(self: Self) -> str: def reset(self: Self) -> str:
return "\u001b[0m" return f"{self.CSI}0m"
@property @property
def bold(self: Self) -> str: def bold(self: Self) -> str:
return "\u001b[1m" return f"{self.CSI}1m"
@property @property
def faint(self: Self) -> str: def faint(self: Self) -> str:
return "\u001b[2m" return f"{self.CSI}2m"
@property @property
def italic(self: Self) -> str: def italic(self: Self) -> str:
return "\u001b[3m" return f"{self.CSI}3m"
@property @property
def underline(self: Self) -> str: def underline(self: Self) -> str:
return "\u001b[4m" return f"{self.CSI}4m"
@property @property
def reversed(self: Self) -> str: def reversed(self: Self) -> str:
return "\u001b[7m" return f"{self.CSI}7m"
def icon_name_and_window_title(self: Self, text: str) -> str:
return f"{self.OSC}0;{text}{self.ST}"
def icon_name(self: Self, text: str) -> str:
return f"{self.OSC}1;{text}{self.ST}"
def window_title(self: Self, text: str) -> str:
return f"{self.OSC}2;{text}{self.ST}"
def hyperlink(self: Self, link: str, text: str) -> str:
return f"{self.OSC}8;;{link}{self.ST}{text}{self.OSC}8;;{self.ST}"
def post_notification(self: Self, message: str) -> str:
return f"{self.OSC}9;{message}{self.ST}"
def write_to_pastboard(self: Self, pasteboard: str, data: str) -> str:
return f"{self.OSC}52;{pasteboard};{base64.b64encode(data).decode()}{self.ST}"
def query_pasteboard(self: Self, pasteboard: str) -> str:
return f"{self.OSC}52;{pasteboard};?{self.ST}"
def copy_to_clipboard(self: Self, clipboard_name: str) -> str:
return f"{self.OSC}1337;CopyToClipboard={clipboard_name}{self.ST}"
def end_copy(self: Self) -> str:
return f"{self.OSC}1337;EndCopy{self.ST}"
def clear_scrollback_history(self: Self) -> str:
return f"{self.OSC}1337;ClearScrollback{self.ST}"
def set_current_directory(self: Self, dir: str) -> str:
return f"{self.OSC}1337;CurrentDir={dir}{self.ST}"
def change_profile(self: Self, new_profile_name: str) -> str:
return f"{self.OSC}1337;SetProfile={new_profile_name}{self.ST}"
def steal_focus(self: Self) -> str:
return f"{self.OSC}1337;StealFocus{self.ST}"
def fg8bit(self: Self, code: int) -> str: def fg8bit(self: Self, code: int) -> str:
assert code >= 0 assert code >= 0
assert code < 256 assert code < 256
code = f"\u001b[38;5;{code}m" code = f"{self.CSI}38;5;{code}m"
def bg8bit(self: Self, code: int) -> str: def bg8bit(self: Self, code: int) -> str:
assert code >= 0 assert code >= 0
assert code < 256 assert code < 256
return f"\u001b[48;5;{code}m" return f"{self.CSI}48;5;{code}m"
def fg24bitrgb(self: Self, red: int, green: int, blue: int) -> str: def fg24bitrgb(self: Self, red: int, green: int, blue: int) -> str:
assert red >= 0 assert red >= 0
@ -103,7 +207,7 @@ class ANSI:
assert green < 256 assert green < 256
assert blue >= 0 assert blue >= 0
assert blue < 256 assert blue < 256
return f"\u001b[38;2;{red};{green};{blue}m" return f"{self.CSI}38;2;{red};{green};{blue}m"
def bg24bitrgb(self: Self, red: int, green: int, blue: int) -> str: def bg24bitrgb(self: Self, red: int, green: int, blue: int) -> str:
assert red >= 0 assert red >= 0
@ -112,7 +216,7 @@ class ANSI:
assert green < 256 assert green < 256
assert blue >= 0 assert blue >= 0
assert blue < 256 assert blue < 256
return f"\u001b[48;2;{red};{green};{blue}m" return f"{self.CSI}48;2;{red};{green};{blue}m"
# def fg24bitcmy(self, cyan: int, magenta: int, yellow: int) -> str: # def fg24bitcmy(self, cyan: int, magenta: int, yellow: int) -> str:
# assert cyan >= 0 # assert cyan >= 0
@ -121,12 +225,41 @@ class ANSI:
# assert magenta < 256 # assert magenta < 256
# assert yellow >= 0 # assert yellow >= 0
# assert yellow < 256 # assert yellow < 256
# return f"\u001b[38:2::{cyan};{magenta};{yellow}:::m" # return f"{self.OSC}38:2::{cyan};{magenta};{yellow}:::m"
ansi = ANSI() ansi = ANSI()
class BashPromptBuilder:
ansi: ANSI
ESC = "\\e"
BEL = "\\a"
prompt = "\\$"
current_working_directory = "\\w"
username = "\\u"
hostname_short = "\\h"
hostname_long = "\\H"
@property
def RL_PROMPT_START_IGNORE(self: Self) -> str:
return self.ansi.SOH
@property
def RL_PROMPT_END_IGNORE(self: Self) -> str:
return self.ansi.STX
def __init__(self: Self, ansi: ANSI = ansi) -> None:
self.ansi = ansi
def wrap_nonprinting(self: Self, text: str) -> str:
return f"{self.RL_PROMPT_START_IGNORE}{text}{self.RL_PROMPT_END_IGNORE}"
def title_bar(self: Self, text: str) -> str:
return self.wrap_nonprinting(self.ansi.icon_name_and_window_title(text))
class JLogFormatter(logging.Formatter): class JLogFormatter(logging.Formatter):
"""Format time the way it SHOULD be done.""" """Format time the way it SHOULD be done."""