@@ -245,6 +245,113 @@ impl FileChecker for DiffTypos {
245
245
}
246
246
}
247
247
248
+ #[ derive( Debug , Clone , Copy ) ]
249
+ pub struct HighlightIdentifiers ;
250
+
251
+ impl FileChecker for HighlightIdentifiers {
252
+ fn check_file (
253
+ & self ,
254
+ path : & std:: path:: Path ,
255
+ explicit : bool ,
256
+ policy : & crate :: policy:: Policy < ' _ , ' _ , ' _ > ,
257
+ reporter : & dyn report:: Report ,
258
+ ) -> Result < ( ) , std:: io:: Error > {
259
+ use std:: fmt:: Write as _;
260
+
261
+ let stdout = std:: io:: stdout ( ) ;
262
+ let mut handle = stdout. lock ( ) ;
263
+
264
+ let mut ignores: Option < Ignores > = None ;
265
+ if policy. check_filenames {
266
+ if let Some ( file_name) = path. file_name ( ) . and_then ( |s| s. to_str ( ) ) {
267
+ let mut styled = String :: new ( ) ;
268
+ let mut prev_end = 0 ;
269
+ for ( word, highlight) in policy
270
+ . tokenizer
271
+ . parse_str ( file_name)
272
+ . filter ( |word| {
273
+ !ignores
274
+ . get_or_insert_with ( || {
275
+ Ignores :: new ( file_name. as_bytes ( ) , policy. ignore )
276
+ } )
277
+ . is_ignored ( word. span ( ) )
278
+ } )
279
+ . zip ( HIGHLIGHTS . iter ( ) . cycle ( ) )
280
+ {
281
+ let start = word. offset ( ) ;
282
+ let end = word. offset ( ) + word. token ( ) . len ( ) ;
283
+ if prev_end != start {
284
+ let _ = write ! (
285
+ & mut styled,
286
+ "{UNMATCHED}{}{UNMATCHED:#}" ,
287
+ & file_name[ prev_end..start]
288
+ ) ;
289
+ }
290
+ let _ = write ! ( & mut styled, "{highlight}{}{highlight:#}" , word. token( ) ) ;
291
+ prev_end = end;
292
+ }
293
+ let _ = write ! (
294
+ & mut styled,
295
+ "{UNMATCHED}{}{UNMATCHED:#}" ,
296
+ & file_name[ prev_end..file_name. len( ) ]
297
+ ) ;
298
+
299
+ let parent_dir = path. parent ( ) . unwrap ( ) ;
300
+ if !parent_dir. as_os_str ( ) . is_empty ( ) {
301
+ let parent_dir = parent_dir. display ( ) ;
302
+ write ! ( handle, "{UNMATCHED}{parent_dir}/" ) ?;
303
+ }
304
+ writeln ! ( handle, "{styled}{UNMATCHED}:{UNMATCHED:#}" ) ?;
305
+ } else {
306
+ writeln ! ( handle, "{UNMATCHED}{}:{UNMATCHED:#}" , path. display( ) ) ?;
307
+ }
308
+ } else {
309
+ writeln ! ( handle, "{UNMATCHED}{}:{UNMATCHED:#}" , path. display( ) ) ?;
310
+ }
311
+
312
+ if policy. check_files {
313
+ let ( buffer, content_type) = read_file ( path, reporter) ?;
314
+ if !explicit && !policy. binary && content_type. is_binary ( ) {
315
+ // nop
316
+ } else if let Ok ( buffer) = buffer. to_str ( ) {
317
+ let mut styled = String :: new ( ) ;
318
+ let mut prev_end = 0 ;
319
+ for ( word, highlight) in policy
320
+ . tokenizer
321
+ . parse_bytes ( buffer. as_bytes ( ) )
322
+ . filter ( |word| {
323
+ !ignores
324
+ . get_or_insert_with ( || Ignores :: new ( buffer. as_bytes ( ) , policy. ignore ) )
325
+ . is_ignored ( word. span ( ) )
326
+ } )
327
+ . zip ( HIGHLIGHTS . iter ( ) . cycle ( ) )
328
+ {
329
+ let start = word. offset ( ) ;
330
+ let end = word. offset ( ) + word. token ( ) . len ( ) ;
331
+ if prev_end != start {
332
+ let _ = write ! (
333
+ & mut styled,
334
+ "{UNMATCHED}{}{UNMATCHED:#}" ,
335
+ & buffer[ prev_end..start]
336
+ ) ;
337
+ }
338
+ let _ = write ! ( & mut styled, "{highlight}{}{highlight:#}" , word. token( ) ) ;
339
+ prev_end = end;
340
+ }
341
+ let _ = write ! (
342
+ & mut styled,
343
+ "{UNMATCHED}{}{UNMATCHED:#}" ,
344
+ & buffer[ prev_end..buffer. len( ) ]
345
+ ) ;
346
+
347
+ write ! ( handle, "{styled}" ) ?;
348
+ }
349
+ }
350
+
351
+ Ok ( ( ) )
352
+ }
353
+ }
354
+
248
355
#[ derive( Debug , Clone , Copy ) ]
249
356
pub struct Identifiers ;
250
357
@@ -307,6 +414,124 @@ impl FileChecker for Identifiers {
307
414
}
308
415
}
309
416
417
+ #[ derive( Debug , Clone , Copy ) ]
418
+ pub struct HighlightWords ;
419
+
420
+ impl FileChecker for HighlightWords {
421
+ fn check_file (
422
+ & self ,
423
+ path : & std:: path:: Path ,
424
+ explicit : bool ,
425
+ policy : & crate :: policy:: Policy < ' _ , ' _ , ' _ > ,
426
+ reporter : & dyn report:: Report ,
427
+ ) -> Result < ( ) , std:: io:: Error > {
428
+ use std:: fmt:: Write as _;
429
+
430
+ let stdout = std:: io:: stdout ( ) ;
431
+ let mut handle = stdout. lock ( ) ;
432
+
433
+ let mut ignores: Option < Ignores > = None ;
434
+ if policy. check_filenames {
435
+ if let Some ( file_name) = path. file_name ( ) . and_then ( |s| s. to_str ( ) ) {
436
+ let mut styled = String :: new ( ) ;
437
+ let mut prev_end = 0 ;
438
+ for ( word, highlight) in policy
439
+ . tokenizer
440
+ . parse_str ( file_name)
441
+ . flat_map ( |i| i. split ( ) )
442
+ . filter ( |word| {
443
+ !ignores
444
+ . get_or_insert_with ( || {
445
+ Ignores :: new ( file_name. as_bytes ( ) , policy. ignore )
446
+ } )
447
+ . is_ignored ( word. span ( ) )
448
+ } )
449
+ . zip ( HIGHLIGHTS . iter ( ) . cycle ( ) )
450
+ {
451
+ let start = word. offset ( ) ;
452
+ let end = word. offset ( ) + word. token ( ) . len ( ) ;
453
+ if prev_end != start {
454
+ let _ = write ! (
455
+ & mut styled,
456
+ "{UNMATCHED}{}{UNMATCHED:#}" ,
457
+ & file_name[ prev_end..start]
458
+ ) ;
459
+ }
460
+ let _ = write ! ( & mut styled, "{highlight}{}{highlight:#}" , word. token( ) ) ;
461
+ prev_end = end;
462
+ }
463
+ let _ = write ! (
464
+ & mut styled,
465
+ "{UNMATCHED}{}{UNMATCHED:#}" ,
466
+ & file_name[ prev_end..file_name. len( ) ]
467
+ ) ;
468
+
469
+ let parent_dir = path. parent ( ) . unwrap ( ) ;
470
+ if !parent_dir. as_os_str ( ) . is_empty ( ) {
471
+ let parent_dir = parent_dir. display ( ) ;
472
+ write ! ( handle, "{UNMATCHED}{parent_dir}/" ) ?;
473
+ }
474
+ writeln ! ( handle, "{styled}{UNMATCHED}:{UNMATCHED:#}" ) ?;
475
+ } else {
476
+ writeln ! ( handle, "{UNMATCHED}{}:{UNMATCHED:#}" , path. display( ) ) ?;
477
+ }
478
+ } else {
479
+ writeln ! ( handle, "{UNMATCHED}{}:{UNMATCHED:#}" , path. display( ) ) ?;
480
+ }
481
+
482
+ if policy. check_files {
483
+ let ( buffer, content_type) = read_file ( path, reporter) ?;
484
+ if !explicit && !policy. binary && content_type. is_binary ( ) {
485
+ // nop
486
+ } else if let Ok ( buffer) = buffer. to_str ( ) {
487
+ let mut styled = String :: new ( ) ;
488
+ let mut prev_end = 0 ;
489
+ for ( word, highlight) in policy
490
+ . tokenizer
491
+ . parse_bytes ( buffer. as_bytes ( ) )
492
+ . flat_map ( |i| i. split ( ) )
493
+ . filter ( |word| {
494
+ !ignores
495
+ . get_or_insert_with ( || Ignores :: new ( buffer. as_bytes ( ) , policy. ignore ) )
496
+ . is_ignored ( word. span ( ) )
497
+ } )
498
+ . zip ( HIGHLIGHTS . iter ( ) . cycle ( ) )
499
+ {
500
+ let start = word. offset ( ) ;
501
+ let end = word. offset ( ) + word. token ( ) . len ( ) ;
502
+ if prev_end != start {
503
+ let _ = write ! (
504
+ & mut styled,
505
+ "{UNMATCHED}{}{UNMATCHED:#}" ,
506
+ & buffer[ prev_end..start]
507
+ ) ;
508
+ }
509
+ let _ = write ! ( & mut styled, "{highlight}{}{highlight:#}" , word. token( ) ) ;
510
+ prev_end = end;
511
+ }
512
+ let _ = write ! (
513
+ & mut styled,
514
+ "{UNMATCHED}{}{UNMATCHED:#}" ,
515
+ & buffer[ prev_end..buffer. len( ) ]
516
+ ) ;
517
+
518
+ write ! ( handle, "{styled}" ) ?;
519
+ }
520
+ }
521
+
522
+ Ok ( ( ) )
523
+ }
524
+ }
525
+
526
+ static HIGHLIGHTS : & [ anstyle:: Style ] = & [
527
+ anstyle:: AnsiColor :: Cyan . on_default ( ) ,
528
+ anstyle:: AnsiColor :: Cyan
529
+ . on_default ( )
530
+ . effects ( anstyle:: Effects :: BOLD ) ,
531
+ ] ;
532
+
533
+ static UNMATCHED : anstyle:: Style = anstyle:: Style :: new ( ) . effects ( anstyle:: Effects :: DIMMED ) ;
534
+
310
535
#[ derive( Debug , Clone , Copy ) ]
311
536
pub struct Words ;
312
537
0 commit comments