chore: standardize string quotes and fix import ordering across multiple modules

This commit is contained in:
2025-11-04 07:09:12 +00:00
parent ea29bdc403
commit e9ced4a493
82 changed files with 4963 additions and 3094 deletions
+8 -2
View File
@@ -1,5 +1,11 @@
from pr.ui.colors import Colors
from pr.ui.rendering import highlight_code, render_markdown
from pr.ui.display import display_tool_call, print_autonomous_header
from pr.ui.rendering import highlight_code, render_markdown
__all__ = ['Colors', 'highlight_code', 'render_markdown', 'display_tool_call', 'print_autonomous_header']
__all__ = [
"Colors",
"highlight_code",
"render_markdown",
"display_tool_call",
"print_autonomous_header",
]
+13 -13
View File
@@ -1,14 +1,14 @@
class Colors:
RESET = '\033[0m'
BOLD = '\033[1m'
RED = '\033[91m'
GREEN = '\033[92m'
YELLOW = '\033[93m'
BLUE = '\033[94m'
MAGENTA = '\033[95m'
CYAN = '\033[96m'
GRAY = '\033[90m'
WHITE = '\033[97m'
BG_BLUE = '\033[44m'
BG_GREEN = '\033[42m'
BG_RED = '\033[41m'
RESET = "\033[0m"
BOLD = "\033[1m"
RED = "\033[91m"
GREEN = "\033[92m"
YELLOW = "\033[93m"
BLUE = "\033[94m"
MAGENTA = "\033[95m"
CYAN = "\033[96m"
GRAY = "\033[90m"
WHITE = "\033[97m"
BG_BLUE = "\033[44m"
BG_GREEN = "\033[42m"
BG_RED = "\033[41m"
+106 -60
View File
@@ -1,5 +1,6 @@
import difflib
from typing import List, Tuple, Dict, Optional
from typing import Dict, List, Optional, Tuple
from .colors import Colors
@@ -19,8 +20,13 @@ class DiffStats:
class DiffLine:
def __init__(self, line_type: str, content: str, old_line_num: Optional[int] = None,
new_line_num: Optional[int] = None):
def __init__(
self,
line_type: str,
content: str,
old_line_num: Optional[int] = None,
new_line_num: Optional[int] = None,
):
self.line_type = line_type
self.content = content
self.old_line_num = old_line_num
@@ -28,27 +34,27 @@ class DiffLine:
def format(self, show_line_nums: bool = True) -> str:
color = {
'add': Colors.GREEN,
'delete': Colors.RED,
'context': Colors.GRAY,
'header': Colors.CYAN,
'stats': Colors.BLUE
"add": Colors.GREEN,
"delete": Colors.RED,
"context": Colors.GRAY,
"header": Colors.CYAN,
"stats": Colors.BLUE,
}.get(self.line_type, Colors.RESET)
prefix = {
'add': '+ ',
'delete': '- ',
'context': ' ',
'header': '',
'stats': ''
}.get(self.line_type, ' ')
"add": "+ ",
"delete": "- ",
"context": " ",
"header": "",
"stats": "",
}.get(self.line_type, " ")
if show_line_nums and self.line_type in ('add', 'delete', 'context'):
old_num = str(self.old_line_num) if self.old_line_num else ' '
new_num = str(self.new_line_num) if self.new_line_num else ' '
if show_line_nums and self.line_type in ("add", "delete", "context"):
old_num = str(self.old_line_num) if self.old_line_num else " "
new_num = str(self.new_line_num) if self.new_line_num else " "
line_num_str = f"{Colors.YELLOW}{old_num:>4} {new_num:>4}{Colors.RESET} "
else:
line_num_str = ''
line_num_str = ""
return f"{line_num_str}{color}{prefix}{self.content}{Colors.RESET}"
@@ -57,8 +63,9 @@ class DiffDisplay:
def __init__(self, context_lines: int = 3):
self.context_lines = context_lines
def create_diff(self, old_content: str, new_content: str,
filename: str = "file") -> Tuple[List[DiffLine], DiffStats]:
def create_diff(
self, old_content: str, new_content: str, filename: str = "file"
) -> Tuple[List[DiffLine], DiffStats]:
old_lines = old_content.splitlines(keepends=True)
new_lines = new_content.splitlines(keepends=True)
@@ -67,31 +74,38 @@ class DiffDisplay:
stats.files_changed = 1
diff = difflib.unified_diff(
old_lines, new_lines,
old_lines,
new_lines,
fromfile=f"a/{filename}",
tofile=f"b/{filename}",
n=self.context_lines
n=self.context_lines,
)
old_line_num = 0
new_line_num = 0
for line in diff:
if line.startswith('---') or line.startswith('+++'):
diff_lines.append(DiffLine('header', line.rstrip()))
elif line.startswith('@@'):
diff_lines.append(DiffLine('header', line.rstrip()))
if line.startswith("---") or line.startswith("+++"):
diff_lines.append(DiffLine("header", line.rstrip()))
elif line.startswith("@@"):
diff_lines.append(DiffLine("header", line.rstrip()))
old_line_num, new_line_num = self._parse_hunk_header(line)
elif line.startswith('+'):
elif line.startswith("+"):
stats.insertions += 1
diff_lines.append(DiffLine('add', line[1:].rstrip(), None, new_line_num))
diff_lines.append(
DiffLine("add", line[1:].rstrip(), None, new_line_num)
)
new_line_num += 1
elif line.startswith('-'):
elif line.startswith("-"):
stats.deletions += 1
diff_lines.append(DiffLine('delete', line[1:].rstrip(), old_line_num, None))
diff_lines.append(
DiffLine("delete", line[1:].rstrip(), old_line_num, None)
)
old_line_num += 1
elif line.startswith(' '):
diff_lines.append(DiffLine('context', line[1:].rstrip(), old_line_num, new_line_num))
elif line.startswith(" "):
diff_lines.append(
DiffLine("context", line[1:].rstrip(), old_line_num, new_line_num)
)
old_line_num += 1
new_line_num += 1
@@ -101,15 +115,20 @@ class DiffDisplay:
def _parse_hunk_header(self, header: str) -> Tuple[int, int]:
try:
parts = header.split('@@')[1].strip().split()
old_start = int(parts[0].split(',')[0].replace('-', ''))
new_start = int(parts[1].split(',')[0].replace('+', ''))
parts = header.split("@@")[1].strip().split()
old_start = int(parts[0].split(",")[0].replace("-", ""))
new_start = int(parts[1].split(",")[0].replace("+", ""))
return old_start, new_start
except (IndexError, ValueError):
return 0, 0
def render_diff(self, diff_lines: List[DiffLine], stats: DiffStats,
show_line_nums: bool = True, show_stats: bool = True) -> str:
def render_diff(
self,
diff_lines: List[DiffLine],
stats: DiffStats,
show_line_nums: bool = True,
show_stats: bool = True,
) -> str:
output = []
if show_stats:
@@ -124,10 +143,15 @@ class DiffDisplay:
if show_stats:
output.append(f"\n{Colors.BOLD}{Colors.BLUE}{'=' * 60}{Colors.RESET}\n")
return '\n'.join(output)
return "\n".join(output)
def display_file_diff(self, old_content: str, new_content: str,
filename: str = "file", show_line_nums: bool = True) -> str:
def display_file_diff(
self,
old_content: str,
new_content: str,
filename: str = "file",
show_line_nums: bool = True,
) -> str:
diff_lines, stats = self.create_diff(old_content, new_content, filename)
if not diff_lines:
@@ -135,8 +159,13 @@ class DiffDisplay:
return self.render_diff(diff_lines, stats, show_line_nums)
def display_side_by_side(self, old_content: str, new_content: str,
filename: str = "file", width: int = 80) -> str:
def display_side_by_side(
self,
old_content: str,
new_content: str,
filename: str = "file",
width: int = 80,
) -> str:
old_lines = old_content.splitlines()
new_lines = new_content.splitlines()
@@ -144,40 +173,57 @@ class DiffDisplay:
output = []
output.append(f"\n{Colors.BOLD}{Colors.BLUE}{'=' * width}{Colors.RESET}")
output.append(f"{Colors.BOLD}{Colors.BLUE}SIDE-BY-SIDE COMPARISON: {filename}{Colors.RESET}")
output.append(
f"{Colors.BOLD}{Colors.BLUE}SIDE-BY-SIDE COMPARISON: {filename}{Colors.RESET}"
)
output.append(f"{Colors.BOLD}{Colors.BLUE}{'=' * width}{Colors.RESET}\n")
half_width = (width - 5) // 2
for tag, i1, i2, j1, j2 in matcher.get_opcodes():
if tag == 'equal':
for i, (old_line, new_line) in enumerate(zip(old_lines[i1:i2], new_lines[j1:j2])):
if tag == "equal":
for i, (old_line, new_line) in enumerate(
zip(old_lines[i1:i2], new_lines[j1:j2])
):
old_display = old_line[:half_width].ljust(half_width)
new_display = new_line[:half_width].ljust(half_width)
output.append(f"{Colors.GRAY}{old_display} | {new_display}{Colors.RESET}")
elif tag == 'replace':
output.append(
f"{Colors.GRAY}{old_display} | {new_display}{Colors.RESET}"
)
elif tag == "replace":
max_lines = max(i2 - i1, j2 - j1)
for i in range(max_lines):
old_line = old_lines[i1 + i] if i1 + i < i2 else ""
new_line = new_lines[j1 + i] if j1 + i < j2 else ""
old_display = old_line[:half_width].ljust(half_width)
new_display = new_line[:half_width].ljust(half_width)
output.append(f"{Colors.RED}{old_display}{Colors.RESET} | {Colors.GREEN}{new_display}{Colors.RESET}")
elif tag == 'delete':
output.append(
f"{Colors.RED}{old_display}{Colors.RESET} | {Colors.GREEN}{new_display}{Colors.RESET}"
)
elif tag == "delete":
for old_line in old_lines[i1:i2]:
old_display = old_line[:half_width].ljust(half_width)
output.append(f"{Colors.RED}{old_display} | {' ' * half_width}{Colors.RESET}")
elif tag == 'insert':
output.append(
f"{Colors.RED}{old_display} | {' ' * half_width}{Colors.RESET}"
)
elif tag == "insert":
for new_line in new_lines[j1:j2]:
new_display = new_line[:half_width].ljust(half_width)
output.append(f"{' ' * half_width} | {Colors.GREEN}{new_display}{Colors.RESET}")
output.append(
f"{' ' * half_width} | {Colors.GREEN}{new_display}{Colors.RESET}"
)
output.append(f"\n{Colors.BOLD}{Colors.BLUE}{'=' * width}{Colors.RESET}\n")
return '\n'.join(output)
return "\n".join(output)
def display_diff(old_content: str, new_content: str, filename: str = "file",
format_type: str = "unified", context_lines: int = 3) -> str:
def display_diff(
old_content: str,
new_content: str,
filename: str = "file",
format_type: str = "unified",
context_lines: int = 3,
) -> str:
displayer = DiffDisplay(context_lines)
if format_type == "side-by-side":
@@ -191,9 +237,9 @@ def get_diff_stats(old_content: str, new_content: str) -> Dict[str, int]:
_, stats = displayer.create_diff(old_content, new_content)
return {
'insertions': stats.insertions,
'deletions': stats.deletions,
'modifications': stats.modifications,
'total_changes': stats.total_changes,
'files_changed': stats.files_changed
"insertions": stats.insertions,
"deletions": stats.deletions,
"modifications": stats.modifications,
"total_changes": stats.total_changes,
"files_changed": stats.files_changed,
}
+5 -4
View File
@@ -1,8 +1,6 @@
import json
import time
from typing import Dict, Any
from pr.ui.colors import Colors
def display_tool_call(tool_name, arguments, status="running", result=None):
if status == "running":
return
@@ -15,8 +13,11 @@ def display_tool_call(tool_name, arguments, status="running", result=None):
print(f"{Colors.GRAY}{line}{Colors.RESET}")
def print_autonomous_header(task):
print(f"{Colors.BOLD}Task:{Colors.RESET} {task}")
print(f"{Colors.GRAY}r will work continuously until the task is complete.{Colors.RESET}")
print(
f"{Colors.GRAY}r will work continuously until the task is complete.{Colors.RESET}"
)
print(f"{Colors.GRAY}Press Ctrl+C twice to interrupt.{Colors.RESET}\n")
print(f"{Colors.BOLD}{'' * 80}{Colors.RESET}\n")
+60 -38
View File
@@ -1,12 +1,20 @@
from typing import List, Dict, Optional
from datetime import datetime
from typing import Dict, List, Optional
from .colors import Colors
from .progress import ProgressBar
class EditOperation:
def __init__(self, op_type: str, filepath: str, start_pos: int = 0,
end_pos: int = 0, content: str = "", old_content: str = ""):
def __init__(
self,
op_type: str,
filepath: str,
start_pos: int = 0,
end_pos: int = 0,
content: str = "",
old_content: str = "",
):
self.op_type = op_type
self.filepath = filepath
self.start_pos = start_pos
@@ -18,40 +26,46 @@ class EditOperation:
def format_operation(self) -> str:
op_colors = {
'INSERT': Colors.GREEN,
'REPLACE': Colors.YELLOW,
'DELETE': Colors.RED,
'WRITE': Colors.BLUE
"INSERT": Colors.GREEN,
"REPLACE": Colors.YELLOW,
"DELETE": Colors.RED,
"WRITE": Colors.BLUE,
}
color = op_colors.get(self.op_type, Colors.RESET)
status_icon = {
'pending': '',
'in_progress': '',
'completed': '',
'failed': ''
}.get(self.status, '')
"pending": "",
"in_progress": "",
"completed": "",
"failed": "",
}.get(self.status, "")
return f"{color}{status_icon} [{self.op_type}]{Colors.RESET} {self.filepath}"
def format_details(self, show_content: bool = True) -> str:
output = [self.format_operation()]
if self.op_type in ('INSERT', 'REPLACE'):
output.append(f" {Colors.GRAY}Position: {self.start_pos}-{self.end_pos}{Colors.RESET}")
if self.op_type in ("INSERT", "REPLACE"):
output.append(
f" {Colors.GRAY}Position: {self.start_pos}-{self.end_pos}{Colors.RESET}"
)
if show_content:
if self.old_content:
lines = self.old_content.split('\n')
preview = lines[0][:60] + ('...' if len(lines[0]) > 60 or len(lines) > 1 else '')
lines = self.old_content.split("\n")
preview = lines[0][:60] + (
"..." if len(lines[0]) > 60 or len(lines) > 1 else ""
)
output.append(f" {Colors.RED}- {preview}{Colors.RESET}")
if self.content:
lines = self.content.split('\n')
preview = lines[0][:60] + ('...' if len(lines[0]) > 60 or len(lines) > 1 else '')
lines = self.content.split("\n")
preview = lines[0][:60] + (
"..." if len(lines[0]) > 60 or len(lines) > 1 else ""
)
output.append(f" {Colors.GREEN}+ {preview}{Colors.RESET}")
return '\n'.join(output)
return "\n".join(output)
class EditTracker:
@@ -76,11 +90,13 @@ class EditTracker:
def get_stats(self) -> Dict[str, int]:
stats = {
'total': len(self.operations),
'completed': sum(1 for op in self.operations if op.status == 'completed'),
'pending': sum(1 for op in self.operations if op.status == 'pending'),
'in_progress': sum(1 for op in self.operations if op.status == 'in_progress'),
'failed': sum(1 for op in self.operations if op.status == 'failed')
"total": len(self.operations),
"completed": sum(1 for op in self.operations if op.status == "completed"),
"pending": sum(1 for op in self.operations if op.status == "pending"),
"in_progress": sum(
1 for op in self.operations if op.status == "in_progress"
),
"failed": sum(1 for op in self.operations if op.status == "failed"),
}
return stats
@@ -88,7 +104,7 @@ class EditTracker:
if not self.operations:
return 0.0
stats = self.get_stats()
return (stats['completed'] / stats['total']) * 100
return (stats["completed"] / stats["total"]) * 100
def display_progress(self) -> str:
if not self.operations:
@@ -96,26 +112,30 @@ class EditTracker:
output = []
output.append(f"\n{Colors.BOLD}{Colors.BLUE}{'=' * 60}{Colors.RESET}")
output.append(f"{Colors.BOLD}{Colors.BLUE}EDIT OPERATIONS PROGRESS{Colors.RESET}")
output.append(
f"{Colors.BOLD}{Colors.BLUE}EDIT OPERATIONS PROGRESS{Colors.RESET}"
)
output.append(f"{Colors.BOLD}{Colors.BLUE}{'=' * 60}{Colors.RESET}\n")
stats = self.get_stats()
completion = self.get_completion_percentage()
self.get_completion_percentage()
progress_bar = ProgressBar(total=stats['total'], width=40)
progress_bar.current = stats['completed']
progress_bar = ProgressBar(total=stats["total"], width=40)
progress_bar.current = stats["completed"]
bar_display = progress_bar._get_bar_display()
output.append(f"Progress: {bar_display}")
output.append(f"{Colors.BLUE}Total: {stats['total']}, Completed: {stats['completed']}, "
f"Pending: {stats['pending']}, Failed: {stats['failed']}{Colors.RESET}\n")
output.append(
f"{Colors.BLUE}Total: {stats['total']}, Completed: {stats['completed']}, "
f"Pending: {stats['pending']}, Failed: {stats['failed']}{Colors.RESET}\n"
)
output.append(f"{Colors.BOLD}Recent Operations:{Colors.RESET}")
for i, op in enumerate(self.operations[-5:], 1):
output.append(f"{i}. {op.format_operation()}")
output.append(f"\n{Colors.BOLD}{Colors.BLUE}{'=' * 60}{Colors.RESET}\n")
return '\n'.join(output)
return "\n".join(output)
def display_timeline(self, show_content: bool = False) -> str:
if not self.operations:
@@ -134,18 +154,20 @@ class EditTracker:
stats = self.get_stats()
output.append(f"{Colors.BOLD}Summary:{Colors.RESET}")
output.append(f"{Colors.BLUE}Total operations: {stats['total']}, "
f"Completed: {stats['completed']}, Failed: {stats['failed']}{Colors.RESET}")
output.append(
f"{Colors.BLUE}Total operations: {stats['total']}, "
f"Completed: {stats['completed']}, Failed: {stats['failed']}{Colors.RESET}"
)
output.append(f"\n{Colors.BOLD}{Colors.BLUE}{'=' * 60}{Colors.RESET}\n")
return '\n'.join(output)
return "\n".join(output)
def display_summary(self) -> str:
if not self.operations:
return f"{Colors.GRAY}No edits to summarize{Colors.RESET}"
stats = self.get_stats()
files_modified = len(set(op.filepath for op in self.operations))
files_modified = len({op.filepath for op in self.operations})
output = []
output.append(f"\n{Colors.BOLD}{Colors.GREEN}{'=' * 60}{Colors.RESET}")
@@ -156,7 +178,7 @@ class EditTracker:
output.append(f"{Colors.GREEN}Total Operations: {stats['total']}{Colors.RESET}")
output.append(f"{Colors.GREEN}Successful: {stats['completed']}{Colors.RESET}")
if stats['failed'] > 0:
if stats["failed"] > 0:
output.append(f"{Colors.RED}Failed: {stats['failed']}{Colors.RESET}")
output.append(f"\n{Colors.BOLD}Operations by Type:{Colors.RESET}")
@@ -168,7 +190,7 @@ class EditTracker:
output.append(f" {op_type}: {count}")
output.append(f"\n{Colors.BOLD}{Colors.GREEN}{'=' * 60}{Colors.RESET}\n")
return '\n'.join(output)
return "\n".join(output)
def clear(self):
self.operations.clear()
+16 -16
View File
@@ -1,31 +1,31 @@
import json
import sys
from typing import Any, Dict, List
from datetime import datetime
from typing import Any
class OutputFormatter:
def __init__(self, format_type: str = 'text', quiet: bool = False):
def __init__(self, format_type: str = "text", quiet: bool = False):
self.format_type = format_type
self.quiet = quiet
def output(self, data: Any, message_type: str = 'response'):
if self.quiet and message_type not in ['error', 'result']:
def output(self, data: Any, message_type: str = "response"):
if self.quiet and message_type not in ["error", "result"]:
return
if self.format_type == 'json':
if self.format_type == "json":
self._output_json(data, message_type)
elif self.format_type == 'structured':
elif self.format_type == "structured":
self._output_structured(data, message_type)
else:
self._output_text(data, message_type)
def _output_json(self, data: Any, message_type: str):
output = {
'type': message_type,
'timestamp': datetime.now().isoformat(),
'data': data
"type": message_type,
"timestamp": datetime.now().isoformat(),
"data": data,
}
print(json.dumps(output, indent=2))
@@ -46,24 +46,24 @@ class OutputFormatter:
print(data)
def error(self, message: str):
if self.format_type == 'json':
self._output_json({'error': message}, 'error')
if self.format_type == "json":
self._output_json({"error": message}, "error")
else:
print(f"Error: {message}", file=sys.stderr)
def success(self, message: str):
if not self.quiet:
if self.format_type == 'json':
self._output_json({'success': message}, 'success')
if self.format_type == "json":
self._output_json({"success": message}, "success")
else:
print(message)
def info(self, message: str):
if not self.quiet:
if self.format_type == 'json':
self._output_json({'info': message}, 'info')
if self.format_type == "json":
self._output_json({"info": message}, "info")
else:
print(message)
def result(self, data: Any):
self.output(data, 'result')
self.output(data, "result")
+14 -8
View File
@@ -1,6 +1,6 @@
import sys
import time
import threading
import time
class ProgressIndicator:
@@ -30,15 +30,15 @@ class ProgressIndicator:
self.running = False
if self.thread:
self.thread.join(timeout=1.0)
sys.stdout.write('\r' + ' ' * (len(self.message) + 10) + '\r')
sys.stdout.write("\r" + " " * (len(self.message) + 10) + "\r")
sys.stdout.flush()
def _animate(self):
spinner = ['', '', '', '', '', '', '', '', '', '']
spinner = ["", "", "", "", "", "", "", "", "", ""]
idx = 0
while self.running:
sys.stdout.write(f'\r{spinner[idx]} {self.message}...')
sys.stdout.write(f"\r{spinner[idx]} {self.message}...")
sys.stdout.flush()
idx = (idx + 1) % len(spinner)
time.sleep(0.1)
@@ -62,14 +62,20 @@ class ProgressBar:
else:
percent = int((self.current / self.total) * 100)
filled = int((self.current / self.total) * self.width) if self.total > 0 else self.width
bar = '' * filled + '' * (self.width - filled)
filled = (
int((self.current / self.total) * self.width)
if self.total > 0
else self.width
)
bar = "" * filled + "" * (self.width - filled)
sys.stdout.write(f'\r{self.description}: |{bar}| {percent}% ({self.current}/{self.total})')
sys.stdout.write(
f"\r{self.description}: |{bar}| {percent}% ({self.current}/{self.total})"
)
sys.stdout.flush()
if self.current >= self.total:
sys.stdout.write('\n')
sys.stdout.write("\n")
def finish(self):
self.current = self.total
+51 -38
View File
@@ -1,90 +1,103 @@
import re
from pr.ui.colors import Colors
from pr.config import LANGUAGE_KEYWORDS
from pr.ui.colors import Colors
def highlight_code(code, language=None, syntax_highlighting=True):
if not syntax_highlighting:
return code
if not language:
if 'def ' in code or 'import ' in code:
language = 'python'
elif 'function ' in code or 'const ' in code:
language = 'javascript'
elif 'public ' in code or 'class ' in code:
language = 'java'
if "def " in code or "import " in code:
language = "python"
elif "function " in code or "const " in code:
language = "javascript"
elif "public " in code or "class " in code:
language = "java"
if language and language in LANGUAGE_KEYWORDS:
keywords = LANGUAGE_KEYWORDS[language]
for keyword in keywords:
pattern = r'\b' + re.escape(keyword) + r'\b'
pattern = r"\b" + re.escape(keyword) + r"\b"
code = re.sub(pattern, f"{Colors.BLUE}{keyword}{Colors.RESET}", code)
code = re.sub(r'"([^"]*)"', f'{Colors.GREEN}"\\1"{Colors.RESET}', code)
code = re.sub(r"'([^']*)'", f"{Colors.GREEN}'\\1'{Colors.RESET}", code)
code = re.sub(r'#(.*)$', f'{Colors.GRAY}#\\1{Colors.RESET}', code, flags=re.MULTILINE)
code = re.sub(r'//(.*)$', f'{Colors.GRAY}//\\1{Colors.RESET}', code, flags=re.MULTILINE)
code = re.sub(
r"#(.*)$", f"{Colors.GRAY}#\\1{Colors.RESET}", code, flags=re.MULTILINE
)
code = re.sub(
r"//(.*)$", f"{Colors.GRAY}//\\1{Colors.RESET}", code, flags=re.MULTILINE
)
return code
def render_markdown(text, syntax_highlighting=True):
if not syntax_highlighting:
return text
code_blocks = []
def extract_code_block(match):
lang = match.group(1) or ''
lang = match.group(1) or ""
code = match.group(2)
highlighted_code = highlight_code(code.strip('\n'), lang, syntax_highlighting)
highlighted_code = highlight_code(code.strip("\n"), lang, syntax_highlighting)
placeholder = f"%%CODEBLOCK{len(code_blocks)}%%"
full_block = f'{Colors.GRAY}```{lang}{Colors.RESET}\n{highlighted_code}\n{Colors.GRAY}```{Colors.RESET}'
full_block = f"{Colors.GRAY}```{lang}{Colors.RESET}\n{highlighted_code}\n{Colors.GRAY}```{Colors.RESET}"
code_blocks.append(full_block)
return placeholder
text = re.sub(r'```(\w*)\n(.*?)\n?```', extract_code_block, text, flags=re.DOTALL)
text = re.sub(r"```(\w*)\n(.*?)\n?```", extract_code_block, text, flags=re.DOTALL)
inline_codes = []
def extract_inline_code(match):
code = match.group(1)
placeholder = f"%%INLINECODE{len(inline_codes)}%%"
inline_codes.append(f'{Colors.YELLOW}{code}{Colors.RESET}')
inline_codes.append(f"{Colors.YELLOW}{code}{Colors.RESET}")
return placeholder
text = re.sub(r'`([^`]+)`', extract_inline_code, text)
text = re.sub(r"`([^`]+)`", extract_inline_code, text)
lines = text.split('\n')
lines = text.split("\n")
processed_lines = []
for line in lines:
if line.startswith('### '):
line = f'{Colors.BOLD}{Colors.GREEN}{line[4:]}{Colors.RESET}'
elif line.startswith('## '):
line = f'{Colors.BOLD}{Colors.BLUE}{line[3:]}{Colors.RESET}'
elif line.startswith('# '):
line = f'{Colors.BOLD}{Colors.MAGENTA}{line[2:]}{Colors.RESET}'
elif line.startswith('> '):
line = f'{Colors.CYAN}> {line[2:]}{Colors.RESET}'
elif re.match(r'^\s*[\*\-\+]\s', line):
match = re.match(r'^(\s*)([\*\-\+])(\s+.*)', line)
if line.startswith("### "):
line = f"{Colors.BOLD}{Colors.GREEN}{line[4:]}{Colors.RESET}"
elif line.startswith("## "):
line = f"{Colors.BOLD}{Colors.BLUE}{line[3:]}{Colors.RESET}"
elif line.startswith("# "):
line = f"{Colors.BOLD}{Colors.MAGENTA}{line[2:]}{Colors.RESET}"
elif line.startswith("> "):
line = f"{Colors.CYAN}> {line[2:]}{Colors.RESET}"
elif re.match(r"^\s*[\*\-\+]\s", line):
match = re.match(r"^(\s*)([\*\-\+])(\s+.*)", line)
if match:
line = f"{match.group(1)}{Colors.YELLOW}{match.group(2)}{Colors.RESET}{match.group(3)}"
elif re.match(r'^\s*\d+\.\s', line):
match = re.match(r'^(\s*)(\d+\.)(\s+.*)', line)
elif re.match(r"^\s*\d+\.\s", line):
match = re.match(r"^(\s*)(\d+\.)(\s+.*)", line)
if match:
line = f"{match.group(1)}{Colors.YELLOW}{match.group(2)}{Colors.RESET}{match.group(3)}"
processed_lines.append(line)
text = '\n'.join(processed_lines)
text = "\n".join(processed_lines)
text = re.sub(r'\[(.*?)\]\((.*?)\)', f'{Colors.BLUE}\\1{Colors.RESET}{Colors.GRAY}(\\2){Colors.RESET}', text)
text = re.sub(r'~~(.*?)~~', f'{Colors.GRAY}\\1{Colors.RESET}', text)
text = re.sub(r'\*\*(.*?)\*\*', f'{Colors.BOLD}\\1{Colors.RESET}', text)
text = re.sub(r'__(.*?)__', f'{Colors.BOLD}\\1{Colors.RESET}', text)
text = re.sub(r'\*(.*?)\*', f'{Colors.CYAN}\\1{Colors.RESET}', text)
text = re.sub(r'_(.*?)_', f'{Colors.CYAN}\\1{Colors.RESET}', text)
text = re.sub(
r"\[(.*?)\]\((.*?)\)",
f"{Colors.BLUE}\\1{Colors.RESET}{Colors.GRAY}(\\2){Colors.RESET}",
text,
)
text = re.sub(r"~~(.*?)~~", f"{Colors.GRAY}\\1{Colors.RESET}", text)
text = re.sub(r"\*\*(.*?)\*\*", f"{Colors.BOLD}\\1{Colors.RESET}", text)
text = re.sub(r"__(.*?)__", f"{Colors.BOLD}\\1{Colors.RESET}", text)
text = re.sub(r"\*(.*?)\*", f"{Colors.CYAN}\\1{Colors.RESET}", text)
text = re.sub(r"_(.*?)_", f"{Colors.CYAN}\\1{Colors.RESET}", text)
for i, code in enumerate(inline_codes):
text = text.replace(f'%%INLINECODE{i}%%', code)
text = text.replace(f"%%INLINECODE{i}%%", code)
for i, block in enumerate(code_blocks):
text = text.replace(f'%%CODEBLOCK{i}%%', block)
text = text.replace(f"%%CODEBLOCK{i}%%", block)
return text