@@ -16,69 +16,69 @@ Examples from my pains of the past two days
1616 defined
1717
1818 ❯ ~/bin/show-paths -f full-lines -e 'name="relatedIdentifier"' metadata.xsd
19- 16 <xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://datacite.org/schema/kernel-4" targetNamespace="http://datacite.org/schema/kernel-4" elementFormDefault="qualified" xml:lang="EN">
20- 28 <xs:element name="resource">
21- 35 <xs:complexType>
22- 36 <xs:all>
23- 236 : <xs:element name="relatedIdentifiers" minOccurs="0">
24- 237 <xs:complexType>
25- 238 <xs:sequence>
26- 239 : <xs:element name="relatedIdentifier" minOccurs="0" maxOccurs="unbounded">
19+ \x1b [2m16 <xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://datacite.org/schema/kernel-4" targetNamespace="http://datacite.org/schema/kernel-4" elementFormDefault="qualified" xml:lang="EN">\x1b [0m
20+ \x1b [2m28 <xs:element name="resource">\x1b [0m
21+ \x1b [2m35 <xs:complexType>\x1b [0m
22+ \x1b [2m36 <xs:all>\x1b [0m
23+ \x1b [31m236 : <xs:element name="relatedIdentifiers" minOccurs="0">\x1b [0m
24+ \x1b [2m237 <xs:complexType>\x1b [0m
25+ \x1b [2m238 <xs:sequence>\x1b [0m
26+ \x1b [31m239 : <xs:element name="relatedIdentifier" minOccurs="0" maxOccurs="unbounded">\x1b [0m
2727
2828 ❯ ~/bin/show-paths -f full-lines -e '\b relatedIdentifier\b ' ~/proj/datacite/inveniosoftware-datacite/datacite/schemas/datacite-v4.5.json
29- 304 "properties": {
30- 419 "relatedIdentifiers": {
31- 421 "items": {
32- 425 "properties": {
33- 426 : "relatedIdentifier": {"type": "string"},
34- 429 : "required": ["relatedIdentifier", "relatedIdentifierType", "relationType"],
29+ \x1b [2m304 "properties": {\x1b [0m
30+ \x1b [2m419 "relatedIdentifiers": {\x1b [0m
31+ \x1b [2m421 "items": {\x1b [0m
32+ \x1b [2m425 "properties": {\x1b [0m
33+ \x1b [31m426 : "relatedIdentifier": {"type": "string"},\x1b [0m
34+ \x1b [31m429 : "required": ["relatedIdentifier", "relatedIdentifierType", "relationType"],\x1b [0m
3535
3636- Dig out where enhanced DICOM contains RepetitionTime in contrast to regular
3737 or interoperable one (this was the drop which overfilled the cup and
3838 needed to trigger coding!)
3939
4040
4141 ❯ dcmdump dcm_qa_xa30i/In/7001_func-bold_task-fa_run-1/7001001_1.3.12.2.1107.5.2.43.67093.30000023011319484937100000688.dcm | show-paths -e RepetitionTime
42- 77 : (0018,0080) DS [1000] # 4, 1 RepetitionTime
42+ \x1b [31m77 : (0018,0080) DS [1000] # 4, 1 RepetitionTime\x1b [0m
4343
4444 ❯ dcmdump dcm_qa_xa30/In/7_func-bold_task-fa_run-1/0001_1.3.12.2.1107.5.2.43.67093.2022071112090640678703211.dcm | show-paths -e RepetitionTime
45- 467 : (5200,9229).(fffe,e000).(0018,9112).(fffe,e000) (0018,0080) DS [1000] # 4, 1 RepetitionTime
45+ \x1b [2m467 : (5200,9229).(fffe,e000).(0018,9112).(fffe,e000)\x1b [0m \x1b [31m (0018,0080) DS [1000] # 4, 1 RepetitionTime\x1b [0m
4646
4747 ❯ dcmdump dcm_qa_xa30/In/7_func-bold_task-fa_run-1/0001_1.3.12.2.1107.5.2.43.67093.2022071112090640678703211.dcm | show-paths -f full-lines -e RepetitionTime
48- 221 (5200,9229) SQ (Sequence with undefined length #=1) # u/l, 1 SharedFunctionalGroupsSequence
49- 222 (fffe,e000) na (Item with undefined length #=11) # u/l, 1 Item
50- 465 (0018,9112) SQ (Sequence with undefined length #=1) # u/l, 1 MRTimingAndRelatedParametersSequence
51- 466 (fffe,e000) na (Item with undefined length #=9) # u/l, 1 Item
52- 467 : (0018,0080) DS [1000] # 4, 1 RepetitionTime
48+ \x1b [2m221 (5200,9229) SQ (Sequence with undefined length #=1) # u/l, 1 SharedFunctionalGroupsSequence\x1b [0m
49+ \x1b [2m222 (fffe,e000) na (Item with undefined length #=11) # u/l, 1 Item\x1b [0m
50+ \x1b [2m465 (0018,9112) SQ (Sequence with undefined length #=1) # u/l, 1 MRTimingAndRelatedParametersSequence\x1b [0m
51+ \x1b [2m466 (fffe,e000) na (Item with undefined length #=9) # u/l, 1 Item\x1b [0m
52+ \x1b [31m467 : (0018,0080) DS [1000] # 4, 1 RepetitionTime\x1b [0m
5353
5454 - In Python code (better visible in terminal with colors), e.g.
5555
5656 ❯ show-paths -f full-lines -e '\b colored\b ' $(which show-paths)
57- 57 : 29: from termcolor import colored
58- 59 : 31: colored = None
59- 63 : 63: path_str = colored(path_str, attrs=["dark"])
60- 64 : 64: line = colored(line, "red")
61- 68 : 74: line_colored = colored(lines[i], attrs=["dark"]) if use_color else lines[i]
62- 69 : 78: line_colored = colored(lines[line_num], "red") if use_color else lines[line_num]
63- 71 : 111: (args.color == "auto" and sys.stdout.isatty() and colored)
64- 72 : 113: if use_color and not colored:
65- 81 try:
66- 82 : from termcolor import colored
67- 83 except ImportError as exc:
68- 84 : colored = None
69- 110 def print_inline(paths, lines, use_color):
70- 112 for line_num, path in paths:
71- 115 if use_color:
72- 116 : path_str = colored(path_str, attrs=["dark"])
73- 117 : line = colored(line, "red")
74- 120 def print_full_lines(paths, lines, use_color):
75- 124 for line_num, path in paths:
76- 126 for key, indent, i in path[:-1]:
77- 127 : line_colored = colored(lines[i], attrs=["dark"]) if use_color else lines[i]
78- 131 : line_colored = colored(lines[line_num], "red") if use_color else lines[line_num]
79- 162 use_color = (
80- 164 : (args.color == "auto" and sys.stdout.isatty() and colored)
81- 166 : if use_color and not colored:
57+ \x1b [31m57 : 29: from termcolor import colored\x1b [0m
58+ \x1b [31m59 : 31: colored = None\x1b [0m
59+ \x1b [31m63 : 63: path_str = colored(path_str, attrs=["dark"])\x1b [0m
60+ \x1b [31m64 : 64: line = colored(line, "red")\x1b [0m
61+ \x1b [31m68 : 74: line_colored = colored(lines[i], attrs=["dark"]) if use_color else lines[i]\x1b [0m
62+ \x1b [31m69 : 78: line_colored = colored(lines[line_num], "red") if use_color else lines[line_num]\x1b [0m
63+ \x1b [31m71 : 111: (args.color == "auto" and sys.stdout.isatty() and colored)\x1b [0m
64+ \x1b [31m72 : 113: if use_color and not colored:\x1b [0m
65+ \x1b [2m81 try:\x1b [0m
66+ \x1b [31m82 : from termcolor import colored\x1b [0m
67+ \x1b [2m83 except ImportError as exc:\x1b [0m
68+ \x1b [31m84 : colored = None\x1b [0m
69+ \x1b [2m110 def print_inline(paths, lines, use_color):\x1b [0m
70+ \x1b [2m112 for line_num, path in paths:\x1b [0m
71+ \x1b [2m115 if use_color:\x1b [0m
72+ \x1b [31m116 : path_str = colored(path_str, attrs=["dark"])\x1b [0m
73+ \x1b [31m117 : line = colored(line, "red")\x1b [0m
74+ \x1b [2m120 def print_full_lines(paths, lines, use_color):\x1b [0m
75+ \x1b [2m124 for line_num, path in paths:\x1b [0m
76+ \x1b [2m126 for key, indent, i in path[:-1]:\x1b [0m
77+ \x1b [31m127 : line_colored = colored(lines[i], attrs=["dark"]) if use_color else lines[i]\x1b [0m
78+ \x1b [31m131 : line_colored = colored(lines[line_num], "red") if use_color else lines[line_num]\x1b [0m
79+ \x1b [2m162 use_color = (\x1b [0m
80+ \x1b [31m164 : (args.color == "auto" and sys.stdout.isatty() and colored)\x1b [0m
81+ \x1b [31m166 : if use_color and not colored:\x1b [0m
8282
8383
8484""" # noqa: E501
@@ -93,6 +93,24 @@ except ImportError:
9393 colored = None
9494
9595
96+ class ColoredHelpFormatter (argparse .RawDescriptionHelpFormatter ):
97+ """Formatter that strips ANSI color codes from help text if terminal doesn't support colors."""
98+
99+ def _strip_ansi (self , text ):
100+ """Strip ANSI escape codes from text."""
101+ # Match ANSI escape sequences
102+ ansi_escape = re .compile (r"\x1b\[[0-9;]*m" )
103+ return ansi_escape .sub ("" , text )
104+
105+ def format_help (self ):
106+ """Format help, stripping colors if stdout is not a TTY."""
107+ help_text = super ().format_help ()
108+ # Strip colors if not outputting to a TTY
109+ if not sys .stdout .isatty ():
110+ help_text = self ._strip_ansi (help_text )
111+ return help_text
112+
113+
96114def get_paths (lines ):
97115 """Generate indentation-based paths for given lines."""
98116 paths = []
@@ -146,7 +164,7 @@ def print_full_lines(paths, lines, use_color):
146164
147165def main ():
148166 parser = argparse .ArgumentParser (
149- description = __doc__ , formatter_class = argparse . RawDescriptionHelpFormatter
167+ description = __doc__ , formatter_class = ColoredHelpFormatter
150168 )
151169 parser .add_argument (
152170 "file" ,
0 commit comments