44import sys
55import tarfile
66import tempfile
7+ from dataclasses import dataclass
78from pathlib import Path
89
10+ from smartem_epuplayer import __version__
911from smartem_epuplayer .recorder import EPURecorder
1012from smartem_epuplayer .replayer import EPUReplayer
1113
1214
15+ @dataclass
16+ class OutputConfig :
17+ no_colors : bool = False
18+ plain : bool = False
19+ verbose : bool = False
20+ quiet : bool = False
21+
22+
23+ output_config = OutputConfig ()
24+
25+
26+ def print_msg (msg : str , verbose_only : bool = False ) -> None :
27+ if output_config .quiet :
28+ return
29+ if verbose_only and not output_config .verbose :
30+ return
31+ print (msg )
32+
33+
1334def main ():
1435 parser = argparse .ArgumentParser (description = "Filesystem Recording and Replay Tool" )
36+ parser .add_argument (
37+ "--version" ,
38+ "-V" ,
39+ action = "version" ,
40+ version = f"epuplayer { __version__ } " ,
41+ )
42+
43+ output_group = parser .add_argument_group ("output options" )
44+ output_group .add_argument ("--no-colors" , action = "store_true" , help = "Disable colored output" )
45+ output_group .add_argument ("--plain" , action = "store_true" , help = "Plain mode: no color, minimal output" )
46+
47+ verbosity = output_group .add_mutually_exclusive_group ()
48+ verbosity .add_argument ("-v" , "--verbose" , action = "store_true" , help = "Verbose output" )
49+ verbosity .add_argument ("-q" , "--quiet" , action = "store_true" , help = "Suppress non-essential output" )
50+
1551 subparsers = parser .add_subparsers (dest = "command" , help = "Available commands" )
1652
1753 # Record command
@@ -92,6 +128,11 @@ def main():
92128
93129 args = parser .parse_args ()
94130
131+ output_config .no_colors = getattr (args , "no_colors" , False )
132+ output_config .plain = getattr (args , "plain" , False )
133+ output_config .verbose = getattr (args , "verbose" , False )
134+ output_config .quiet = getattr (args , "quiet" , False )
135+
95136 if args .command == "record" :
96137 recorder = EPURecorder (
97138 args .directory ,
@@ -101,15 +142,14 @@ def main():
101142 args .force_binary_extensions ,
102143 )
103144
104- # Print binary content handling info
105145 if args .skip_binary_content :
106- print ("Binary content handling: Skip binary files (replace with placeholders)" )
146+ print_msg ("Binary content handling: Skip binary files (replace with placeholders)" )
107147 if args .force_text_extensions :
108- print (f"Force text extensions: { ', ' .join (args .force_text_extensions )} " )
148+ print_msg (f"Force text extensions: { ', ' .join (args .force_text_extensions )} " )
109149 if args .force_binary_extensions :
110- print (f"Force binary extensions: { ', ' .join (args .force_binary_extensions )} " )
150+ print_msg (f"Force binary extensions: { ', ' .join (args .force_binary_extensions )} " )
111151 else :
112- print ("Binary content handling: Store full content of all files" )
152+ print_msg ("Binary content handling: Store full content of all files" )
113153
114154 # Handle Ctrl+C gracefully
115155 def signal_handler (sig , frame ):
@@ -122,9 +162,8 @@ def signal_handler(sig, frame):
122162 elif args .command == "replay" :
123163 replayer = EPUReplayer (args .recording , args .target )
124164
125- # Handle preset modes
126165 if args .dev_mode :
127- print ("Development mode: maximum acceleration for fast testing" )
166+ print_msg ("Development mode: maximum acceleration for fast testing" )
128167 replayer .replay (
129168 speed_multiplier = 1000.0 ,
130169 verify_integrity = not args .no_verify ,
@@ -133,7 +172,7 @@ def signal_handler(sig, frame):
133172 skip_unreadable = args .skip_unreadable ,
134173 )
135174 elif args .fast :
136- print ("Fast mode: 100x speed with reasonable delays" )
175+ print_msg ("Fast mode: 100x speed with reasonable delays" )
137176 replayer .replay (
138177 speed_multiplier = 100.0 ,
139178 verify_integrity = not args .no_verify ,
@@ -142,7 +181,7 @@ def signal_handler(sig, frame):
142181 skip_unreadable = args .skip_unreadable ,
143182 )
144183 elif args .exact :
145- print ("Exact mode: preserving original timing" )
184+ print_msg ("Exact mode: preserving original timing" )
146185 replayer .replay (
147186 speed_multiplier = 1.0 ,
148187 verify_integrity = not args .no_verify ,
@@ -155,8 +194,7 @@ def signal_handler(sig, frame):
155194 has_custom_settings = args .speed != 1.0 or args .max_delay is not None or args .burst
156195
157196 if has_custom_settings :
158- # User specified custom settings - use them
159- print (f"Custom mode: { args .speed } x speed" )
197+ print_msg (f"Custom mode: { args .speed } x speed" )
160198 replayer .replay (
161199 speed_multiplier = args .speed ,
162200 verify_integrity = not args .no_verify ,
@@ -165,8 +203,7 @@ def signal_handler(sig, frame):
165203 skip_unreadable = args .skip_unreadable ,
166204 )
167205 else :
168- # No preset or custom settings specified - default to fast mode
169- print ("Fast mode (default): 100x speed with reasonable delays" )
206+ print_msg ("Fast mode (default): 100x speed with reasonable delays" )
170207 replayer .replay (
171208 speed_multiplier = 100.0 ,
172209 verify_integrity = not args .no_verify ,
@@ -177,7 +214,7 @@ def signal_handler(sig, frame):
177214
178215 elif args .command == "info" :
179216 if not Path (args .recording ).exists ():
180- print (f"Recording file not found: { args .recording } " )
217+ print (f"Recording file not found: { args .recording } " , file = sys . stderr )
181218 sys .exit (1 )
182219
183220 # Load recording data
@@ -192,7 +229,7 @@ def signal_handler(sig, frame):
192229
193230 recording_file = temp_path / "recording.json"
194231 if not recording_file .exists ():
195- print ("Invalid archive: missing recording.json" )
232+ print ("Invalid archive: missing recording.json" , file = sys . stderr )
196233 sys .exit (1 )
197234
198235 data = json .loads (recording_file .read_text ())
0 commit comments