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

1# Copyright (c) 2024 Prosemark Contributors 

2# This software is licensed under the MIT License 

3 

4"""Pretty console output implementation with colors and formatting.""" 

5 

6import os 

7import sys 

8from typing import TYPE_CHECKING, TextIO 

9 

10from prosemark.ports.console_port import ConsolePort 

11 

12if TYPE_CHECKING: # pragma: no cover 

13 from prosemark.domain.models import Binder, BinderItem 

14 

15 

16class ConsolePretty(ConsolePort): 

17 """Production console implementation with rich formatting and colors. 

18 

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 

24 

25 The adapter handles all presentation concerns while keeping the 

26 business logic focused on content generation. 

27 """ 

28 

29 def __init__(self, output_stream: TextIO = sys.stdout) -> None: 

30 """Initialize console with specified output stream. 

31 

32 Args: 

33 output_stream: Target stream for output (default: sys.stdout) 

34 

35 """ 

36 self.output_stream = output_stream 

37 self._supports_color = self._detect_color_support() 

38 

39 def print(self, msg: str) -> None: 

40 """Display formatted message to the console. 

41 

42 Args: 

43 msg: The message content to display 

44 

45 """ 

46 print(msg, file=self.output_stream) 

47 

48 def print_tree(self, binder: 'Binder') -> None: 

49 """Display formatted tree representation of binder structure. 

50 

51 Args: 

52 binder: The Binder object containing the hierarchical structure 

53 

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) 

60 

61 def _print_tree_item(self, item: 'BinderItem', indent: int = 0) -> None: 

62 """Print a single tree item with proper indentation. 

63 

64 Args: 

65 item: The BinderItem to print 

66 indent: Current indentation level 

67 

68 """ 

69 prefix = ' ' * indent + '- ' 

70 display = item.display_title or str(item.id) 

71 self.print(f'{prefix}{display}') 

72 

73 for child in item.children: 

74 self._print_tree_item(child, indent + 1) 

75 

76 def _detect_color_support(self) -> bool: 

77 """Detect if the terminal supports color output. 

78 

79 Returns: 

80 True if terminal supports colors, False otherwise 

81 

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 

87 

88 if not self.output_stream.isatty(): 

89 return False 

90 

91 # Check common environment variables that disable color 

92 if os.environ.get('NO_COLOR'): 

93 return False 

94 

95 return os.environ.get('TERM') != 'dumb'