update
This commit is contained in:
parent
f1efca7ea8
commit
bfe7dedd6f
3 changed files with 148 additions and 12 deletions
3
.gitignore
vendored
Normal file
3
.gitignore
vendored
Normal file
|
@ -0,0 +1,3 @@
|
|||
/result*
|
||||
/.venv
|
||||
__pycache__
|
157
jlog/__init__.py
157
jlog/__init__.py
|
@ -1,6 +1,9 @@
|
|||
"""Configure logging."""
|
||||
|
||||
import base64
|
||||
from enum import Enum
|
||||
from enum import IntEnum
|
||||
from enum import auto
|
||||
import logging
|
||||
import pathlib
|
||||
import re
|
||||
|
@ -23,7 +26,65 @@ class ANSIColor(IntEnum):
|
|||
WHITE = 8
|
||||
|
||||
|
||||
class Mode(Enum):
|
||||
C0 = auto()
|
||||
C1 = auto()
|
||||
|
||||
|
||||
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:
|
||||
return self.color(item)
|
||||
|
||||
|
@ -42,7 +103,7 @@ class ANSI:
|
|||
|
||||
try:
|
||||
color = ANSIColor[item]
|
||||
return f"\u001b[1;{color+offset:d}{extra}m"
|
||||
return f"{self.CSI}1;{color+offset:d}{extra}m"
|
||||
except KeyError:
|
||||
return self.fg24bitrgb(*(getrgb(item)[:3]))
|
||||
|
||||
|
@ -54,6 +115,10 @@ class ANSI:
|
|||
def white(self: Self) -> str:
|
||||
return self.color("white")
|
||||
|
||||
@property
|
||||
def green(self: Self) -> str:
|
||||
return self.color("green")
|
||||
|
||||
@property
|
||||
def blue(self: Self) -> str:
|
||||
return self.color("blue")
|
||||
|
@ -64,37 +129,76 @@ class ANSI:
|
|||
|
||||
@property
|
||||
def reset(self: Self) -> str:
|
||||
return "\u001b[0m"
|
||||
return f"{self.CSI}0m"
|
||||
|
||||
@property
|
||||
def bold(self: Self) -> str:
|
||||
return "\u001b[1m"
|
||||
return f"{self.CSI}1m"
|
||||
|
||||
@property
|
||||
def faint(self: Self) -> str:
|
||||
return "\u001b[2m"
|
||||
return f"{self.CSI}2m"
|
||||
|
||||
@property
|
||||
def italic(self: Self) -> str:
|
||||
return "\u001b[3m"
|
||||
return f"{self.CSI}3m"
|
||||
|
||||
@property
|
||||
def underline(self: Self) -> str:
|
||||
return "\u001b[4m"
|
||||
return f"{self.CSI}4m"
|
||||
|
||||
@property
|
||||
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:
|
||||
assert code >= 0
|
||||
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:
|
||||
assert code >= 0
|
||||
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:
|
||||
assert red >= 0
|
||||
|
@ -103,7 +207,7 @@ class ANSI:
|
|||
assert green < 256
|
||||
assert blue >= 0
|
||||
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:
|
||||
assert red >= 0
|
||||
|
@ -112,7 +216,7 @@ class ANSI:
|
|||
assert green < 256
|
||||
assert blue >= 0
|
||||
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:
|
||||
# assert cyan >= 0
|
||||
|
@ -121,12 +225,41 @@ class ANSI:
|
|||
# assert magenta < 256
|
||||
# assert yellow >= 0
|
||||
# assert yellow < 256
|
||||
# return f"\u001b[38:2::{cyan};{magenta};{yellow}:::m"
|
||||
# return f"{self.OSC}38:2::{cyan};{magenta};{yellow}:::m"
|
||||
|
||||
|
||||
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):
|
||||
"""Format time the way it SHOULD be done."""
|
||||
|
||||
|
|
Binary file not shown.
Loading…
Reference in a new issue