Coverage for src/prosemark/adapters/console_pretty.py: 100%
28 statements
« prev ^ index » next coverage.py v7.8.0, created at 2025-09-24 18:08 +0000
« prev ^ index » next coverage.py v7.8.0, created at 2025-09-24 18:08 +0000
1# Copyright (c) 2024 Prosemark Contributors
2# This software is licensed under the MIT License
4"""Pretty console output implementation with colors and formatting."""
6import os
7import sys
8from typing import TYPE_CHECKING, TextIO
10from prosemark.ports.console_port import ConsolePort
12if TYPE_CHECKING: # pragma: no cover
13 from prosemark.domain.models import Binder, BinderItem
16class ConsolePretty(ConsolePort):
17 """Production console implementation with rich formatting and colors.
19 This implementation provides enhanced console output with:
20 - Color support with automatic terminal detection
21 - Pretty tree rendering with Unicode box-drawing characters
22 - Proper stdout/stderr stream handling
23 - Graceful fallback for non-color terminals
25 The adapter handles all presentation concerns while keeping the
26 business logic focused on content generation.
27 """
29 def __init__(self, output_stream: TextIO = sys.stdout) -> None:
30 """Initialize console with specified output stream.
32 Args:
33 output_stream: Target stream for output (default: sys.stdout)
35 """
36 self.output_stream = output_stream
37 self._supports_color = self._detect_color_support()
39 def print(self, msg: str) -> None:
40 """Display formatted message to the console.
42 Args:
43 msg: The message content to display
45 """
46 print(msg, file=self.output_stream)
48 def print_tree(self, binder: 'Binder') -> None:
49 """Display formatted tree representation of binder structure.
51 Args:
52 binder: The Binder object containing the hierarchical structure
54 """
55 # For now, implement a simple tree representation
56 # This can be enhanced later with proper tree formatting
57 self.print('Binder structure:')
58 for item in binder.roots:
59 self._print_tree_item(item, indent=0)
61 def _print_tree_item(self, item: 'BinderItem', indent: int = 0) -> None:
62 """Print a single tree item with proper indentation.
64 Args:
65 item: The BinderItem to print
66 indent: Current indentation level
68 """
69 prefix = ' ' * indent + '- '
70 display = item.display_title or str(item.id)
71 self.print(f'{prefix}{display}')
73 for child in item.children:
74 self._print_tree_item(child, indent + 1)
76 def _detect_color_support(self) -> bool:
77 """Detect if the terminal supports color output.
79 Returns:
80 True if terminal supports colors, False otherwise
82 """
83 # Simple color detection - check if stdout is a TTY
84 # and not explicitly disabled
85 if not hasattr(self.output_stream, 'isatty'):
86 return False
88 if not self.output_stream.isatty():
89 return False
91 # Check common environment variables that disable color
92 if os.environ.get('NO_COLOR'):
93 return False
95 return os.environ.get('TERM') != 'dumb'