Add validators, TUI, and file watcher modules
Some checks failed
CI / test (push) Has been cancelled
Some checks failed
CI / test (push) Has been cancelled
This commit is contained in:
159
src/tui/viewer.py
Normal file
159
src/tui/viewer.py
Normal file
@@ -0,0 +1,159 @@
|
||||
"""TUI viewer module for displaying data with syntax highlighting."""
|
||||
|
||||
from typing import Any
|
||||
from rich.console import Console
|
||||
from rich.syntax import Syntax
|
||||
from rich.theme import Theme
|
||||
from rich.panel import Panel
|
||||
from rich.text import Text
|
||||
from rich.box import ROUNDED
|
||||
|
||||
|
||||
class DataViewer:
|
||||
"""Viewer for displaying data with syntax highlighting."""
|
||||
|
||||
DEFAULT_THEMES = {
|
||||
'default': 'rich',
|
||||
'monokai': 'monokai',
|
||||
'github-dark': 'github-dark',
|
||||
'github-light': 'github-light',
|
||||
'dracula': 'dracula',
|
||||
'nord': 'nord',
|
||||
'one-dark': 'one-dark',
|
||||
}
|
||||
|
||||
def __init__(self, theme: str = 'default', console: Console = None):
|
||||
"""Initialize the data viewer.
|
||||
|
||||
Args:
|
||||
theme: Syntax highlighting theme name
|
||||
console: Rich Console instance
|
||||
"""
|
||||
self.theme_name = theme
|
||||
self.console = console or Console()
|
||||
self.theme = self._load_theme(theme)
|
||||
|
||||
def _load_theme(self, theme_name: str) -> Theme:
|
||||
"""Load a Rich theme.
|
||||
|
||||
Args:
|
||||
theme_name: Name of the theme
|
||||
|
||||
Returns:
|
||||
Rich Theme instance
|
||||
"""
|
||||
theme_map = {
|
||||
'default': None,
|
||||
'monokai': Theme({'syntax.string': 'green', 'syntax.keyword': 'orange3'}),
|
||||
'github-dark': Theme({'syntax.string': 'green', 'syntax.keyword': 'blue'}),
|
||||
'github-light': Theme({'syntax.string': 'green', 'syntax.keyword': 'blue'}),
|
||||
'dracula': Theme({'syntax.string': 'green', 'syntax.keyword': 'purple'}),
|
||||
'nord': Theme({'syntax.string': 'green', 'syntax.keyword': 'blue'}),
|
||||
'one-dark': Theme({'syntax.string': 'green', 'syntax.keyword': 'orange3'}),
|
||||
}
|
||||
return theme_map.get(theme_name)
|
||||
|
||||
def get_language_for_format(self, format_name: str) -> str:
|
||||
"""Get syntax highlighting language for format.
|
||||
|
||||
Args:
|
||||
format_name: Data format name
|
||||
|
||||
Returns:
|
||||
Language identifier for Syntax highlighter
|
||||
"""
|
||||
language_map = {
|
||||
'json': 'json',
|
||||
'yaml': 'yaml',
|
||||
'toml': 'toml',
|
||||
'csv': 'csv',
|
||||
}
|
||||
return language_map.get(format_name.lower(), 'text')
|
||||
|
||||
def view(self, content: str, format_name: str, title: str = None) -> None:
|
||||
"""Display data with syntax highlighting.
|
||||
|
||||
Args:
|
||||
content: Data content to display
|
||||
format_name: Format of the data
|
||||
title: Optional title for the panel
|
||||
"""
|
||||
language = self.get_language_for_format(format_name)
|
||||
|
||||
syntax = Syntax(
|
||||
content,
|
||||
language,
|
||||
theme=self.theme or 'default',
|
||||
line_numbers=True,
|
||||
word_wrap=True,
|
||||
indent_guides=True,
|
||||
)
|
||||
|
||||
panel = Panel(
|
||||
syntax,
|
||||
title=title or f"Data ({format_name.upper()})",
|
||||
box=ROUNDED,
|
||||
expand=True,
|
||||
)
|
||||
|
||||
self.console.print(panel)
|
||||
|
||||
def view_data(self, data: Any, format_name: str, title: str = None, indent: int = 2) -> None:
|
||||
"""Display data object with syntax highlighting.
|
||||
|
||||
Args:
|
||||
data: Data object to display
|
||||
format_name: Format of the data
|
||||
title: Optional title for the panel
|
||||
indent: Indentation level for serialization
|
||||
"""
|
||||
from src.converters import get_converter
|
||||
|
||||
converter = get_converter(format_name)
|
||||
content = converter.dumps(data, indent=indent)
|
||||
self.view(content, format_name, title)
|
||||
|
||||
def display_error(self, message: str, title: str = "Error") -> None:
|
||||
"""Display an error message.
|
||||
|
||||
Args:
|
||||
message: Error message to display
|
||||
title: Title for the error panel
|
||||
"""
|
||||
text = Text(message, style='red bold')
|
||||
panel = Panel(text, title=title, box=ROUNDED, style='red')
|
||||
self.console.print(panel)
|
||||
|
||||
def display_success(self, message: str, title: str = "Success") -> None:
|
||||
"""Display a success message.
|
||||
|
||||
Args:
|
||||
message: Success message to display
|
||||
title: Title for the success panel
|
||||
"""
|
||||
text = Text(message, style='green bold')
|
||||
panel = Panel(text, title=title, box=ROUNDED, style='green')
|
||||
self.console.print(panel)
|
||||
|
||||
def display_validation_result(self, result) -> None:
|
||||
"""Display validation result.
|
||||
|
||||
Args:
|
||||
result: ValidationResult object
|
||||
"""
|
||||
if result.valid:
|
||||
self.display_success(f"Valid {result.format_type.upper()} file", "Validation")
|
||||
else:
|
||||
error_text = Text()
|
||||
for error in result.errors:
|
||||
if error.line and error.column:
|
||||
error_text.append(f"Line {error.line}, Column {error.column}: ", style='yellow')
|
||||
error_text.append(f"{error.message}\n", style='red')
|
||||
|
||||
panel = Panel(
|
||||
error_text,
|
||||
title="Validation Errors",
|
||||
box=ROUNDED,
|
||||
style='red'
|
||||
)
|
||||
self.console.print(panel)
|
||||
Reference in New Issue
Block a user