@@ -166,12 +166,14 @@ def __init__(self) -> None:
166
166
self .FILE = "\033 [33m"
167
167
self .WWORD = "\033 [31m"
168
168
self .FWORD = "\033 [32m"
169
+ self .CARET = "\033 [1;36m"
169
170
self .DISABLE = "\033 [0m"
170
171
171
172
def disable (self ) -> None :
172
173
self .FILE = ""
173
174
self .WWORD = ""
174
175
self .FWORD = ""
176
+ self .CARET = ""
175
177
self .DISABLE = ""
176
178
177
179
@@ -540,6 +542,11 @@ def parse_options(
540
542
action = "store_true" ,
541
543
help = "output just a single line for each misspelling in stdin mode" ,
542
544
)
545
+ parser .add_argument (
546
+ "--caret-diagnostic" ,
547
+ action = "store_true" ,
548
+ help = "use the diagnostic message format of modern compilers" ,
549
+ )
543
550
parser .add_argument ("--config" , type = str , help = "path to config file." )
544
551
parser .add_argument ("--toml" , type = str , help = "path to a pyproject.toml file." )
545
552
parser .add_argument ("files" , nargs = "*" , help = "files or directories to check" )
@@ -919,6 +926,7 @@ def parse_file(
919
926
)
920
927
for match in check_matches :
921
928
word = match .group ()
929
+ column = match .start ()
922
930
lword = word .lower ()
923
931
if lword in misspellings :
924
932
# Sometimes we find a 'misspelling' which is actually a valid word
@@ -973,8 +981,10 @@ def parse_file(
973
981
974
982
cfilename = f"{ colors .FILE } { filename } { colors .DISABLE } "
975
983
cline = f"{ colors .FILE } { i + 1 } { colors .DISABLE } "
984
+ ccolumn = f"{ colors .FILE } { column + 1 } { colors .DISABLE } "
976
985
cwrongword = f"{ colors .WWORD } { word } { colors .DISABLE } "
977
986
crightword = f"{ colors .FWORD } { fixword } { colors .DISABLE } "
987
+ ccaret = f"{ colors .CARET } ^{ colors .DISABLE } "
978
988
979
989
reason = misspellings [lword ].reason
980
990
if reason :
@@ -993,10 +1003,22 @@ def parse_file(
993
1003
if (not context_shown ) and (context is not None ):
994
1004
print_context (lines , i , context )
995
1005
if filename != "-" :
996
- print (
997
- f"{ cfilename } :{ cline } : { cwrongword } "
998
- f"==> { crightword } { creason } "
999
- )
1006
+ if options .caret_diagnostic :
1007
+ ntabs = line [:column ].count ("\t " )
1008
+ if ntabs > 0 :
1009
+ line = line .replace ("\t " , " " )
1010
+ column = column + ntabs * 3
1011
+ print (
1012
+ f"{ cfilename } :{ cline } :{ ccolumn } : { cwrongword } "
1013
+ f"==> { crightword } { creason } "
1014
+ )
1015
+ print (f"{ line } " , end = "" )
1016
+ print ("{:>{width}}{}" .format ("" , ccaret , width = column ))
1017
+ else :
1018
+ print (
1019
+ f"{ cfilename } :{ cline } : { cwrongword } "
1020
+ f"==> { crightword } { creason } "
1021
+ )
1000
1022
elif options .stdin_single_line :
1001
1023
print (f"{ cline } : { cwrongword } ==> { crightword } { creason } " )
1002
1024
else :
@@ -1139,6 +1161,18 @@ def main(*args: str) -> int:
1139
1161
summary = None
1140
1162
1141
1163
context = None
1164
+ if options .caret_diagnostic and (
1165
+ (options .context is not None )
1166
+ or (options .before_context is not None )
1167
+ or (options .after_context is not None )
1168
+ ):
1169
+ print (
1170
+ "ERROR: --caret-diagnostic cannot be used together with "
1171
+ "--context/-C --context-before/-B or --context-after/-A" ,
1172
+ file = sys .stderr ,
1173
+ )
1174
+ parser .print_help ()
1175
+ return EX_USAGE
1142
1176
if options .context is not None :
1143
1177
if (options .before_context is not None ) or (options .after_context is not None ):
1144
1178
print (
0 commit comments