mirror of
https://github.com/Nanaloveyuki/py-logiliteal.git
synced 2025-09-05 19:16:22 +00:00
✨ 增加了message
参数对于md/html部分富文本语法的支持和改进了HEX着色
This commit is contained in:
@ -40,7 +40,9 @@ class Logger:
|
|||||||
with open(_get_full_path(file_path, file_name), "a", encoding=file_encoding) as f:
|
with open(_get_full_path(file_path, file_name), "a", encoding=file_encoding) as f:
|
||||||
f.write(fmt_file(lvn, fmt_message(msg, no_placeholder=True), pf))
|
f.write(fmt_file(lvn, fmt_message(msg, no_placeholder=True), pf))
|
||||||
if is_enable_console:
|
if is_enable_console:
|
||||||
print(fmt_console(lvn, fmt_message(msg, no_placeholder=True), pf))
|
console_output = fmt_console(lvn, fmt_message(msg, no_placeholder=True), pf)
|
||||||
|
if console_output is not None:
|
||||||
|
print(console_output)
|
||||||
return fmt_console(lvn, fmt_message(msg, no_placeholder=True), pf)
|
return fmt_console(lvn, fmt_message(msg, no_placeholder=True), pf)
|
||||||
|
|
||||||
def debug(self, message: Any, prefix: str | None = None, level: int = 0) -> Optional[str]:
|
def debug(self, message: Any, prefix: str | None = None, level: int = 0) -> Optional[str]:
|
||||||
|
@ -12,7 +12,10 @@ from .time import get_asctime, get_time, get_weekday, get_date
|
|||||||
from .styles import set_color, set_bg_color
|
from .styles import set_color, set_bg_color
|
||||||
import re
|
import re
|
||||||
|
|
||||||
time_color = get_config("time_color")
|
if get_config("time_color") is None:
|
||||||
|
time_color = "#28ffb6"
|
||||||
|
else:
|
||||||
|
time_color = get_config("time_color")
|
||||||
|
|
||||||
def fmt_level(level: str) -> int:
|
def fmt_level(level: str) -> int:
|
||||||
"""
|
"""
|
||||||
@ -89,34 +92,17 @@ def fmt_message(message: Any, no_placeholder: bool = False, no_color: bool = Fal
|
|||||||
"""
|
"""
|
||||||
|
|
||||||
def process_color_tags(msg: str) -> str:
|
def process_color_tags(msg: str) -> str:
|
||||||
from io import StringIO
|
# 优化处理顺序,确保链接和基础格式优先处理
|
||||||
output = StringIO()
|
processed = _process_color_formatting(
|
||||||
stack = []
|
_process_special_tags(
|
||||||
last_end = 0
|
_process_html_styles(
|
||||||
pattern = re.compile(r'(<#([0-9a-fA-F]{6})>|</>)')
|
_process_markdown_formats(
|
||||||
current_color = None
|
_process_links(msg)
|
||||||
|
)
|
||||||
for match in pattern.finditer(msg):
|
)
|
||||||
output.write(msg[last_end:match.start()])
|
)
|
||||||
tag = match.group(1)
|
)
|
||||||
last_end = match.end()
|
return processed
|
||||||
|
|
||||||
if tag.startswith('<#'):
|
|
||||||
stack.append(current_color)
|
|
||||||
current_color = match.group(2)
|
|
||||||
else:
|
|
||||||
if stack:
|
|
||||||
current_color = stack.pop()
|
|
||||||
else:
|
|
||||||
output.write(tag)
|
|
||||||
|
|
||||||
output.write(msg[last_end:])
|
|
||||||
result = output.getvalue()
|
|
||||||
output.close()
|
|
||||||
|
|
||||||
if current_color:
|
|
||||||
result += ''.join(f'<#{color}>' for color in reversed(stack)) if stack else f'<#{current_color}>'
|
|
||||||
return result
|
|
||||||
if no_color:
|
if no_color:
|
||||||
processed_message = str(message)
|
processed_message = str(message)
|
||||||
else:
|
else:
|
||||||
@ -181,3 +167,101 @@ def fmt_file(level: int, message: Any, prefix: str | None = None) -> Optional[st
|
|||||||
prefix = fmt_message(prefix, no_placeholder=True, no_color=True),
|
prefix = fmt_message(prefix, no_placeholder=True, no_color=True),
|
||||||
message = fmt_message(message, no_placeholder=True, no_color=True)
|
message = fmt_message(message, no_placeholder=True, no_color=True)
|
||||||
)}\n"
|
)}\n"
|
||||||
|
|
||||||
|
def _process_links(text: str) -> str:
|
||||||
|
from collections import deque
|
||||||
|
|
||||||
|
link_stack = deque()
|
||||||
|
placeholder_count = 0
|
||||||
|
placeholders = {}
|
||||||
|
|
||||||
|
def replace_link(m):
|
||||||
|
nonlocal placeholder_count
|
||||||
|
placeholder_count += 1
|
||||||
|
if len(m.groups()) == 2 and m.group(2) and not m.group(1).startswith('http'):
|
||||||
|
# Markdown链接 [text](url)
|
||||||
|
url = m.group(2).strip()
|
||||||
|
text = m.group(1)
|
||||||
|
else:
|
||||||
|
url = m.group(1)
|
||||||
|
text = m.group(2)
|
||||||
|
placeholder = f"__LINK_PLACEHOLDER_{placeholder_count}__"
|
||||||
|
placeholders[placeholder] = (url if url else "#", text)
|
||||||
|
link_stack.append(placeholder)
|
||||||
|
return placeholder
|
||||||
|
|
||||||
|
text = re.sub(r'<a\s+href="([^"]+)">(.*?)</a>', replace_link, text, flags=re.DOTALL)
|
||||||
|
text = re.sub(r'<link\s+href="([^"]+)">(.*?)</link>', replace_link, text, flags=re.DOTALL)
|
||||||
|
text = re.sub(r'\[(.*?)\]\((.*?)\)', replace_link, text)
|
||||||
|
|
||||||
|
for placeholder, (url, text_content) in placeholders.items():
|
||||||
|
ansi_link = f'\033]8;;{url}\033\\{set_color("\033[4m" + text_content, "#5f93ff")}\033]8;;\033\\'
|
||||||
|
text = text.replace(placeholder, ansi_link)
|
||||||
|
|
||||||
|
return text
|
||||||
|
|
||||||
|
def _process_markdown_formats(text: str) -> str:
|
||||||
|
# Markdown粗体 (**text**)
|
||||||
|
text = re.sub(r'\*\*(.*?)\*\*', '\033[1m\\g<1>\033[22m', text)
|
||||||
|
# Markdown斜体 (*text*)
|
||||||
|
text = re.sub(r'\*(.*?)\*', '\033[3m\\g<1>\033[23m', text)
|
||||||
|
# Markdown下划线 (__text__)
|
||||||
|
text = re.sub(r'__(.*?)__', '\033[4m\\g<1>\033[24m', text)
|
||||||
|
# Markdown删除线 (~~text~~)
|
||||||
|
text = re.sub(r'~~(.*?)~~', '\033[9m\\g<1>\033[29m', text)
|
||||||
|
return text
|
||||||
|
|
||||||
|
def _process_html_styles(text: str) -> str:
|
||||||
|
text = re.sub(r'<i>([^<]*?)(</i>|$)',
|
||||||
|
lambda m: '\033[3m' + m.group(1) + '\033[23m', text, flags=re.DOTALL)
|
||||||
|
text = re.sub(r'<b>([^<]*?)</b>',
|
||||||
|
lambda m: '\033[1m' + m.group(1) + '\033[22m', text)
|
||||||
|
text = re.sub(r'<u>([^<]*?)</u>',
|
||||||
|
lambda m: '\033[4m' + m.group(1) + '\033[24m', text)
|
||||||
|
text = re.sub(r'<s>([^<]*?)(</s>|$)',
|
||||||
|
lambda m: '\033[9m' + m.group(1) + '\033[29m', text, flags=re.DOTALL)
|
||||||
|
return text
|
||||||
|
|
||||||
|
def _process_special_tags(text: str) -> str:
|
||||||
|
text = re.sub(r'<br>', '\n', text)
|
||||||
|
text = re.sub(r'<c>', '\033[0m', text)
|
||||||
|
text = re.sub(r'<p>(.*?)</p>', r'\n\033[0m\g<1>\033[0m\n', text, flags=re.DOTALL)
|
||||||
|
text = re.sub(r'<p>(.*?)(</p>|$)', r'\n\033[0m\g<1>\033[0m\n', text, flags=re.DOTALL)
|
||||||
|
text = re.sub(r'</p>', '\033[0m\n', text)
|
||||||
|
return text
|
||||||
|
|
||||||
|
def _process_color_formatting(text: str) -> str:
|
||||||
|
import re
|
||||||
|
|
||||||
|
color_pattern = r'<#([0-9a-fA-F]{6})>'
|
||||||
|
close_pattern = r'</>'
|
||||||
|
|
||||||
|
parts = re.split(f'({color_pattern}|{close_pattern})', text)
|
||||||
|
result = []
|
||||||
|
color_stack = []
|
||||||
|
|
||||||
|
for part in parts:
|
||||||
|
if part and re.fullmatch(color_pattern, part):
|
||||||
|
color = re.match(color_pattern, part).group(1)
|
||||||
|
color_stack.append(color)
|
||||||
|
continue
|
||||||
|
elif part == '</>':
|
||||||
|
if color_stack:
|
||||||
|
color_stack.pop()
|
||||||
|
continue
|
||||||
|
elif part:
|
||||||
|
if color_stack:
|
||||||
|
current_color = color_stack[-1]
|
||||||
|
r = int(current_color[0:2], 16)
|
||||||
|
g = int(current_color[2:4], 16)
|
||||||
|
b = int(current_color[4:6], 16)
|
||||||
|
ansi_code = f'\033[38;2;{r};{g};{b}m'
|
||||||
|
reset_code = '\033[0m'
|
||||||
|
result.append(f'{ansi_code}{part}{reset_code}')
|
||||||
|
else:
|
||||||
|
result.append(part)
|
||||||
|
|
||||||
|
processed_text = ''.join(result)
|
||||||
|
processed_text = re.sub(f'{color_pattern}|{close_pattern}|[0-9a-fA-F]{{6}}', '', processed_text)
|
||||||
|
|
||||||
|
return processed_text
|
||||||
|
@ -57,13 +57,15 @@ def set_bg_color(text: str|None, color: str|None) -> str:
|
|||||||
ansi = ansi.replace("38;", "48;")
|
ansi = ansi.replace("38;", "48;")
|
||||||
return f"{ansi}{text}\033[0m"
|
return f"{ansi}{text}\033[0m"
|
||||||
|
|
||||||
def set_style(text: str|None, bold: bool = False, underline: bool = False, reverse: bool = False) -> str:
|
def set_style(text: str|None, bold: bool = False, italic: bool = False, underline: bool = False, strikethrough: bool = False, reverse: bool = False) -> str:
|
||||||
"""
|
"""
|
||||||
设置文本样式
|
设置文本样式
|
||||||
Set text style
|
Set text style
|
||||||
:param text: 文本内容 Text content
|
:param text: 文本内容 Text content
|
||||||
:param bold: 是否加粗 Is bold
|
:param bold: 是否加粗 Is bold
|
||||||
|
:param italic: 是否斜体 Is italic
|
||||||
:param underline: 是否下划线 Is underline
|
:param underline: 是否下划线 Is underline
|
||||||
|
:param strikethrough: 是否划线 Is strikethrough
|
||||||
:param reverse: 是否反相 Is reverse
|
:param reverse: 是否反相 Is reverse
|
||||||
:return: 格式化后的文本 Formatted text
|
:return: 格式化后的文本 Formatted text
|
||||||
"""
|
"""
|
||||||
@ -72,8 +74,12 @@ def set_style(text: str|None, bold: bool = False, underline: bool = False, rever
|
|||||||
ansi = ""
|
ansi = ""
|
||||||
if bold:
|
if bold:
|
||||||
ansi += "\033[1m"
|
ansi += "\033[1m"
|
||||||
|
if italic:
|
||||||
|
ansi += "\033[3m"
|
||||||
if underline:
|
if underline:
|
||||||
ansi += "\033[4m"
|
ansi += "\033[4m"
|
||||||
|
if strikethrough:
|
||||||
|
ansi += "\033[9m"
|
||||||
if reverse:
|
if reverse:
|
||||||
ansi += "\033[7m"
|
ansi += "\033[7m"
|
||||||
return f"{ansi}{text}\033[0m"
|
return f"{ansi}{text}\033[0m"
|
||||||
|
Reference in New Issue
Block a user