217 lines
6.1 KiB
Python
217 lines
6.1 KiB
Python
"""
|
|
Markdown formatting utilities for terminal display.
|
|
"""
|
|
import re
|
|
import io
|
|
import sys
|
|
from termcolor import colored
|
|
from rich.console import Console
|
|
from rich.markdown import Markdown
|
|
from rich.syntax import Syntax
|
|
from rich.panel import Panel
|
|
|
|
def convert_markdown_to_terminal(text):
|
|
"""
|
|
Convert markdown formatting to terminal-friendly colored text.
|
|
|
|
Args:
|
|
text (str): Markdown text to convert
|
|
|
|
Returns:
|
|
str: Terminal-formatted text with ANSI color codes
|
|
"""
|
|
if not text:
|
|
return text
|
|
|
|
# Handle code blocks with triple backticks
|
|
text = re.sub(
|
|
r'```(?:\w+)?\n(.*?)\n```',
|
|
lambda m: '\n' + colored(m.group(1), 'white', attrs=['bold', 'dark']) + '\n',
|
|
text,
|
|
flags=re.DOTALL
|
|
)
|
|
|
|
# Handle inline code with single backticks
|
|
text = re.sub(
|
|
r'`([^`]+)`',
|
|
lambda m: colored(m.group(1), 'white', attrs=['bold']),
|
|
text
|
|
)
|
|
|
|
# Handle bold text with ** or __
|
|
text = re.sub(
|
|
r'\*\*([^*]+)\*\*|__([^_]+)__',
|
|
lambda m: colored(m.group(1) or m.group(2), attrs=['bold']),
|
|
text
|
|
)
|
|
|
|
# Handle italic text with * or _
|
|
text = re.sub(
|
|
r'\*([^*]+)\*|_([^_]+)_',
|
|
lambda m: colored(m.group(1) or m.group(2), attrs=['underline']),
|
|
text
|
|
)
|
|
|
|
# Handle headers
|
|
text = re.sub(
|
|
r'^#{1,6}\s+(.+)$',
|
|
lambda m: colored(m.group(1), 'cyan', attrs=['bold']),
|
|
text,
|
|
flags=re.MULTILINE
|
|
)
|
|
|
|
# Handle unordered lists
|
|
text = re.sub(
|
|
r'^(\s*[-*•]\s+)(.+)$',
|
|
lambda m: m.group(1) + colored(m.group(2), 'white'),
|
|
text,
|
|
flags=re.MULTILINE
|
|
)
|
|
|
|
# Handle ordered lists
|
|
text = re.sub(
|
|
r'^(\s*\d+\.\s+)(.+)$',
|
|
lambda m: m.group(1) + colored(m.group(2), 'white'),
|
|
text,
|
|
flags=re.MULTILINE
|
|
)
|
|
|
|
# Handle links [text](url) - keep only the text part
|
|
text = re.sub(
|
|
r'\[([^\]]+)\]\([^)]+\)',
|
|
lambda m: colored(m.group(1), 'blue', attrs=['underline']),
|
|
text
|
|
)
|
|
|
|
# Handle horizontal rules
|
|
text = re.sub(
|
|
r'^-{3,}$|^\*{3,}$|^_{3,}$',
|
|
lambda m: colored('-' * 50, 'white', attrs=['dark']),
|
|
text,
|
|
flags=re.MULTILINE
|
|
)
|
|
|
|
# Handle blockquotes
|
|
text = re.sub(
|
|
r'^>\s+(.+)$',
|
|
lambda m: colored('│ ', 'cyan') + colored(m.group(1), 'cyan'),
|
|
text,
|
|
flags=re.MULTILINE
|
|
)
|
|
|
|
return text
|
|
|
|
def format_command_explanation(explanation, use_rich=False):
|
|
"""
|
|
Format a command explanation with appropriate terminal styling.
|
|
|
|
Args:
|
|
explanation (str): The explanation text in markdown format
|
|
use_rich (bool): Whether to use rich formatting
|
|
|
|
Returns:
|
|
str: Formatted explanation with terminal-friendly styling
|
|
"""
|
|
if use_rich:
|
|
return format_command_explanation_rich(explanation)
|
|
|
|
# First convert markdown to terminal format
|
|
formatted_text = convert_markdown_to_terminal(explanation)
|
|
|
|
# Add additional formatting for common command explanation patterns
|
|
|
|
# Highlight command parts and common technical terms
|
|
formatted_text = re.sub(
|
|
r'\b(command|option|flag|argument|parameter|switch)\b',
|
|
lambda m: colored(m.group(0), 'yellow'),
|
|
formatted_text,
|
|
flags=re.IGNORECASE
|
|
)
|
|
|
|
# Highlight file paths and patterns
|
|
# More specific pattern to avoid matching things like "Unix/Linux"
|
|
formatted_text = re.sub(
|
|
r'(?:^|\s)(/(?:[\w.-]+/?)+)(?=\s|$|[,.;:])', # Path must start with / and have at least one directory component
|
|
lambda m: colored(m.group(1), 'green'),
|
|
formatted_text
|
|
)
|
|
|
|
# Highlight command names and utilities
|
|
# Common Unix/Linux commands
|
|
formatted_text = re.sub(
|
|
r'\b(ls|grep|find|awk|sed|cat|cp|mv|rm|mkdir|chmod|chown|ps|kill|top|df|du|tar|gzip|ssh|scp|curl|wget)\b',
|
|
lambda m: colored(m.group(0), 'green'),
|
|
formatted_text
|
|
)
|
|
|
|
# Highlight "This command" starts of sentences
|
|
formatted_text = re.sub(
|
|
r'(^|[.!?]\s+)(This command|The command)',
|
|
lambda m: m.group(1) + colored(m.group(2), 'cyan', attrs=['bold']),
|
|
formatted_text
|
|
)
|
|
|
|
return formatted_text
|
|
|
|
def format_command_explanation_rich(explanation):
|
|
"""
|
|
Format a command explanation with rich formatting.
|
|
|
|
Args:
|
|
explanation (str): The explanation text in markdown format
|
|
|
|
Returns:
|
|
str: Rich-formatted explanation as a string
|
|
"""
|
|
# Capture the rich output as a string
|
|
str_io = io.StringIO()
|
|
console = Console(file=str_io, width=80)
|
|
|
|
# Create a markdown object
|
|
md = Markdown(explanation)
|
|
|
|
# Render in a panel with a title
|
|
panel = Panel(md, title="Command Explanation", border_style="green")
|
|
console.print(panel)
|
|
|
|
return str_io.getvalue()
|
|
|
|
def format_command_rich(command, shell="bash", theme="monokai"):
|
|
"""
|
|
Format a command with syntax highlighting using Rich.
|
|
|
|
Args:
|
|
command (str): The command to format
|
|
shell (str): The shell language for syntax highlighting
|
|
theme (str): The color theme to use
|
|
|
|
Returns:
|
|
str: Rich-formatted command as a string
|
|
"""
|
|
# Capture the rich output as a string
|
|
str_io = io.StringIO()
|
|
console = Console(file=str_io, width=80)
|
|
|
|
# Create a syntax object
|
|
syntax = Syntax(command, shell, theme=theme, word_wrap=True)
|
|
|
|
# Render in a panel with a title
|
|
panel = Panel(syntax, title="Command", border_style="blue")
|
|
console.print(panel)
|
|
|
|
return str_io.getvalue()
|
|
|
|
def print_command_rich(command, shell="bash", theme="monokai"):
|
|
"""
|
|
Print a command with syntax highlighting using Rich.
|
|
|
|
Args:
|
|
command (str): The command to print
|
|
shell (str): The shell language for syntax highlighting
|
|
theme (str): The color theme to use
|
|
"""
|
|
console = Console()
|
|
syntax = Syntax(command, shell, theme=theme, word_wrap=True)
|
|
panel = Panel(syntax, title="Command", border_style="blue")
|
|
console.print(panel)
|