@@ -60,6 +60,19 @@ def bold(text: str) -> str:
6060 return f"\033 [1m{ text } \033 [0m"
6161
6262
63+ def red (text : str ) -> str :
64+ """
65+ Returns the given text formatted in red.
66+
67+ Args:
68+ text: The text to format.
69+
70+ Returns:
71+ The formatted text.
72+ """
73+ return f"\033 [31m{ text } \033 [0m"
74+
75+
6376USAGE = f"""
6477{ bold ('dotcat' )}
6578Read values, including nested values, from structured data files (JSON, YAML, TOML, INI)
@@ -115,7 +128,9 @@ def parse_yaml(file: StringIO) -> ParsedData:
115128 try :
116129 return yaml .safe_load (file )
117130 except yaml .YAMLError as e :
118- raise ParseError (f"[ERROR] { file .name } : Unable to parse YAML file: { str (e )} " )
131+ raise ParseError (
132+ f"{ red ('[ERROR]' )} { file .name } : Unable to parse YAML file: { str (e )} "
133+ )
119134
120135
121136def parse_json (file : StringIO ) -> ParsedData :
@@ -133,7 +148,9 @@ def parse_json(file: StringIO) -> ParsedData:
133148 try :
134149 return json .load (file )
135150 except json .JSONDecodeError as e :
136- raise ParseError (f"[ERROR] { file .name } : Unable to parse JSON file: { str (e )} " )
151+ raise ParseError (
152+ f"{ red ('[ERROR]' )} { file .name } : Unable to parse JSON file: { str (e )} "
153+ )
137154
138155
139156def parse_toml (file : StringIO ) -> ParsedData :
@@ -151,7 +168,9 @@ def parse_toml(file: StringIO) -> ParsedData:
151168 try :
152169 return toml .load (file )
153170 except toml .TomlDecodeError as e :
154- raise ParseError (f"[ERROR] { file .name } : Unable to parse TOML file: { str (e )} " )
171+ raise ParseError (
172+ f"{ red ('[ERROR]' )} { file .name } : Unable to parse TOML file: { str (e )} "
173+ )
155174
156175
157176FORMATS = [
@@ -179,18 +198,18 @@ def parse_file(filename: str) -> ParsedData:
179198 with open (filename , "r" ) as file :
180199 content = file .read ().strip ()
181200 if not content :
182- raise ValueError (f"[ERROR] { filename } : File is empty" )
201+ raise ValueError (f"{ red ( ' [ERROR]' ) } { filename } : File is empty" )
183202 for parser in parsers :
184203 try :
185204 return parser (StringIO (content ))
186205 except ParseError :
187206 continue
188207 msg = "Unsupported file format. Supported formats: JSON, YAML, TOML, INI"
189- raise ValueError (f"[ERROR] { filename } :{ msg } " )
208+ raise ValueError (f"{ red ( ' [ERROR]' ) } { filename } : { msg } " )
190209 except FileNotFoundError :
191- raise FileNotFoundError (f"[ERROR] { filename } : File not found" )
210+ raise FileNotFoundError (f"{ red ( ' [ERROR]' ) } { filename } : File not found" )
192211 except Exception as e :
193- raise ValueError (f"[ERROR] { filename } : Unable to parse file: { str (e )} " )
212+ raise ValueError (f"{ red ( ' [ERROR]' ) } { filename } : Unable to parse file: { str (e )} " )
194213
195214
196215######################################################################
@@ -288,7 +307,7 @@ def from_attr_chain(data: Dict[str, Any], lookup_chain: str) -> Any:
288307 """
289308 if data is None :
290309 chain = lookup_chain .split ("." )[0 ]
291- raise KeyError (f"[ERROR] key '{ bold ({ chain }) } ' not found in { italics ('' )} " )
310+ raise KeyError (f"{ red ( ' [ERROR] k' ) } ey '{ chain } ' not found in { italics ('' )} " )
292311 found_keys = []
293312 for key in lookup_chain .split ("." ):
294313 if LIST_ACCESS_SYMBOL in key :
@@ -298,7 +317,7 @@ def from_attr_chain(data: Dict[str, Any], lookup_chain: str) -> Any:
298317 data = data .get (key )
299318 if data is None :
300319 keys = "." .join (found_keys )
301- raise KeyError (f"[ERROR] key '{ key } ' not found in { keys } " )
320+ raise KeyError (f"{ red ( ' [ERROR]' ) } key '{ red ( key ) } ' not found in { keys } " )
302321 found_keys .append (key )
303322 return data
304323
@@ -399,9 +418,9 @@ def run(args: List[str] = None) -> None:
399418 if os .path .exists (filename ):
400419 # File exists, but dot pattern is missing
401420 print (
402- f"Dot path required. Which value do you want me to look up in { filename } ?"
421+ f"{ red ( ' Dot' ) } path required. { red ( ' Which' ) } value do you want me to look up in { filename } ?"
403422 )
404- print (f"\n $dotcat { filename } <pattern>" )
423+ print (f"\n $dotcat { filename } { red ( ' <pattern>' ) } " )
405424 sys .exit (2 ) # Invalid usage
406425 except Exception :
407426 # If there's any error checking the file, fall back to general usage message
@@ -412,9 +431,9 @@ def run(args: List[str] = None) -> None:
412431 if "." in lookup_chain :
413432 # It looks like a dot path, so assume the file is missing
414433 print (
415- f"File path required. Which file contains the value at { lookup_chain } ?"
434+ f"{ red ( ' File' ) } path required. { red ( ' Which' ) } file contains the value at { lookup_chain } ?"
416435 )
417- print (f"\n $dotcat <file> { lookup_chain } " )
436+ print (f"\n $dotcat { red ( ' <file>' ) } { lookup_chain } " )
418437 sys .exit (2 ) # Invalid usage
419438 # Otherwise, it might be a file without an extension or something else,
420439 # so fall back to the general usage message
@@ -427,18 +446,18 @@ def run(args: List[str] = None) -> None:
427446 try :
428447 data = parse_file (filename )
429448 except FileNotFoundError as e :
430- print (e )
449+ print (red ( str ( e )) )
431450 sys .exit (3 ) # File not found
432451 except ValueError as e :
433- print (e )
452+ print (red ( str ( e )) )
434453 sys .exit (4 ) # Parsing error
435454
436455 # get the value at the specified key
437456 try :
438457 value = from_attr_chain (data , lookup_chain )
439458 print (format_output (value , output_format ))
440459 except KeyError as e :
441- print (f"[ERROR] { filename } : " + e .args [0 ].strip ('"' ))
460+ print (f"{ red ( ' [ERROR]' ) } { filename } : " + e .args [0 ].strip ('"' ))
442461 sys .exit (5 ) # Key not found
443462
444463
0 commit comments