@@ -66,6 +66,7 @@ pub struct Renderer {
6666 term_width : usize ,
6767 theme : OutputTheme ,
6868 stylesheet : Stylesheet ,
69+ short_message : bool ,
6970}
7071
7172impl Renderer {
@@ -76,6 +77,7 @@ impl Renderer {
7677 term_width : DEFAULT_TERM_WIDTH ,
7778 theme : OutputTheme :: Ascii ,
7879 stylesheet : Stylesheet :: plain ( ) ,
80+ short_message : false ,
7981 }
8082 }
8183
@@ -137,6 +139,11 @@ impl Renderer {
137139 self
138140 }
139141
142+ pub const fn short_message ( mut self , short_message : bool ) -> Self {
143+ self . short_message = short_message;
144+ self
145+ }
146+
140147 // Set the terminal width
141148 pub const fn term_width ( mut self , term_width : usize ) -> Self {
142149 self . term_width = term_width;
@@ -199,19 +206,23 @@ impl Renderer {
199206
200207impl Renderer {
201208 pub fn render ( & self , mut message : Message < ' _ > ) -> String {
202- let max_line_num_len = if self . anonymized_line_numbers {
203- ANONYMIZED_LINE_NUM . len ( )
209+ if self . short_message {
210+ self . render_short_message ( message ) . unwrap ( )
204211 } else {
205- let n = message. max_line_number ( ) ;
206- num_decimal_digits ( n)
207- } ;
208- let title = message. groups . remove ( 0 ) . elements . remove ( 0 ) ;
209- if let Some ( first) = message. groups . first_mut ( ) {
210- first. elements . insert ( 0 , title) ;
211- } else {
212- message. groups . push ( Group :: new ( ) . element ( title) ) ;
212+ let max_line_num_len = if self . anonymized_line_numbers {
213+ ANONYMIZED_LINE_NUM . len ( )
214+ } else {
215+ let n = message. max_line_number ( ) ;
216+ num_decimal_digits ( n)
217+ } ;
218+ let title = message. groups . remove ( 0 ) . elements . remove ( 0 ) ;
219+ if let Some ( first) = message. groups . first_mut ( ) {
220+ first. elements . insert ( 0 , title) ;
221+ } else {
222+ message. groups . push ( Group :: new ( ) . element ( title) ) ;
223+ }
224+ self . render_message ( message, max_line_num_len) . unwrap ( )
213225 }
214- self . render_message ( message, max_line_num_len) . unwrap ( )
215226 }
216227
217228 fn render_message (
@@ -320,6 +331,7 @@ impl Renderer {
320331 ( true , false ) => TitleStyle :: Header ,
321332 ( false , _) => TitleStyle :: Secondary ,
322333 } ;
334+ let buffer_msg_line_offset = buffer. num_lines ( ) ;
323335 self . render_title (
324336 & mut buffer,
325337 title,
@@ -333,6 +345,7 @@ impl Renderer {
333345 }
334346 } ) ,
335347 matches ! ( peek, Some ( Element :: Title ( _) ) ) ,
348+ buffer_msg_line_offset,
336349 ) ;
337350 last_was_suggestion = false ;
338351 }
@@ -390,7 +403,13 @@ impl Renderer {
390403 }
391404
392405 Element :: Origin ( origin) => {
393- self . render_origin ( & mut buffer, max_line_num_len, origin) ;
406+ let buffer_msg_line_offset = buffer. num_lines ( ) ;
407+ self . render_origin (
408+ & mut buffer,
409+ max_line_num_len,
410+ origin,
411+ buffer_msg_line_offset,
412+ ) ;
394413 last_was_suggestion = false ;
395414 }
396415 Element :: Padding ( _) => {
@@ -434,6 +453,91 @@ impl Renderer {
434453 Ok ( out_string)
435454 }
436455
456+ fn render_short_message ( & self , mut message : Message < ' _ > ) -> Result < String , fmt:: Error > {
457+ let mut buffer = StyledBuffer :: new ( ) ;
458+
459+ let Element :: Title ( title) = message. groups . remove ( 0 ) . elements . remove ( 0 ) else {
460+ panic ! (
461+ "Expected first element to be a Title, got: {:?}" ,
462+ message. groups
463+ ) ;
464+ } ;
465+
466+ let mut labels = None ;
467+
468+ if let Some ( Element :: Cause ( cause) ) = message. groups . first ( ) . and_then ( |group| {
469+ group
470+ . elements
471+ . iter ( )
472+ . find ( |e| matches ! ( e, Element :: Cause ( _) ) )
473+ } ) {
474+ let labels_inner = cause
475+ . markers
476+ . iter ( )
477+ . filter_map ( |ann| match ann. label {
478+ Some ( msg) if ann. kind . is_primary ( ) => {
479+ if !msg. trim ( ) . is_empty ( ) {
480+ Some ( msg. to_owned ( ) )
481+ } else {
482+ None
483+ }
484+ }
485+ _ => None ,
486+ } )
487+ . collect :: < Vec < _ > > ( )
488+ . join ( ", " ) ;
489+ if !labels_inner. is_empty ( ) {
490+ labels = Some ( labels_inner) ;
491+ }
492+
493+ if let Some ( origin) = cause. origin {
494+ let mut origin = Origin :: new ( origin) ;
495+ origin. primary = true ;
496+
497+ let source_map = SourceMap :: new ( cause. source , cause. line_start ) ;
498+ let ( _depth, annotated_lines) =
499+ source_map. annotated_lines ( cause. markers . clone ( ) , cause. fold ) ;
500+
501+ if let Some ( primary_line) = annotated_lines
502+ . iter ( )
503+ . find ( |l| l. annotations . iter ( ) . any ( LineAnnotation :: is_primary) )
504+ . or ( annotated_lines. iter ( ) . find ( |l| !l. annotations . is_empty ( ) ) )
505+ {
506+ origin. line = Some ( primary_line. line_index ) ;
507+ if let Some ( first_annotation) = primary_line
508+ . annotations
509+ . iter ( )
510+ . min_by_key ( |a| ( Reverse ( a. is_primary ( ) ) , a. start . char ) )
511+ {
512+ origin. char_column = Some ( first_annotation. start . char + 1 ) ;
513+ }
514+ }
515+
516+ self . render_origin ( & mut buffer, 0 , & origin, 0 ) ;
517+ buffer. append ( 0 , ": " , ElementStyle :: LineAndColumn ) ;
518+ }
519+ }
520+
521+ self . render_title (
522+ & mut buffer,
523+ & title,
524+ 0 , // No line numbers in short messages
525+ TitleStyle :: MainHeader ,
526+ message. id . as_ref ( ) ,
527+ false ,
528+ 0 ,
529+ ) ;
530+
531+ if let Some ( labels) = labels {
532+ buffer. append ( 0 , & format ! ( ": {labels}" ) , ElementStyle :: NoStyle ) ;
533+ }
534+
535+ let mut out_string = String :: new ( ) ;
536+ buffer. render ( title. level , & self . stylesheet , & mut out_string) ?;
537+
538+ Ok ( out_string)
539+ }
540+
437541 #[ allow( clippy:: too_many_arguments) ]
438542 fn render_title (
439543 & self ,
@@ -443,23 +547,27 @@ impl Renderer {
443547 title_style : TitleStyle ,
444548 id : Option < & & str > ,
445549 is_cont : bool ,
550+ buffer_msg_line_offset : usize ,
446551 ) {
447- let line_offset = buffer. num_lines ( ) ;
448-
449552 if title_style == TitleStyle :: Secondary {
450553 // This is a secondary message with no span info
451554 for _ in 0 ..max_line_num_len {
452- buffer. prepend ( line_offset , " " , ElementStyle :: NoStyle ) ;
555+ buffer. prepend ( buffer_msg_line_offset , " " , ElementStyle :: NoStyle ) ;
453556 }
454557
455558 if title. level . name != Some ( None ) {
456- self . draw_note_separator ( buffer, line_offset, max_line_num_len + 1 , is_cont) ;
559+ self . draw_note_separator (
560+ buffer,
561+ buffer_msg_line_offset,
562+ max_line_num_len + 1 ,
563+ is_cont,
564+ ) ;
457565 buffer. append (
458- line_offset ,
566+ buffer_msg_line_offset ,
459567 title. level . as_str ( ) ,
460568 ElementStyle :: MainHeaderMsg ,
461569 ) ;
462- buffer. append ( line_offset , ": " , ElementStyle :: NoStyle ) ;
570+ buffer. append ( buffer_msg_line_offset , ": " , ElementStyle :: NoStyle ) ;
463571 }
464572
465573 let printed_lines =
@@ -476,7 +584,7 @@ impl Renderer {
476584 // │ bar
477585 // ╰ note: foo
478586 // bar
479- for i in line_offset + 1 ..=printed_lines {
587+ for i in buffer_msg_line_offset + 1 ..=printed_lines {
480588 self . draw_col_separator_no_space ( buffer, i, max_line_num_len + 1 ) ;
481589 }
482590 }
@@ -485,31 +593,49 @@ impl Renderer {
485593
486594 if title. level . name != Some ( None ) {
487595 buffer. append (
488- line_offset ,
596+ buffer_msg_line_offset ,
489597 title. level . as_str ( ) ,
490598 ElementStyle :: Level ( title. level . level ) ,
491599 ) ;
492600 }
493601 label_width += title. level . as_str ( ) . len ( ) ;
494602 if let Some ( id) = id {
495- buffer. append ( line_offset, "[" , ElementStyle :: Level ( title. level . level ) ) ;
496- buffer. append ( line_offset, id, ElementStyle :: Level ( title. level . level ) ) ;
497- buffer. append ( line_offset, "]" , ElementStyle :: Level ( title. level . level ) ) ;
603+ buffer. append (
604+ buffer_msg_line_offset,
605+ "[" ,
606+ ElementStyle :: Level ( title. level . level ) ,
607+ ) ;
608+ buffer. append (
609+ buffer_msg_line_offset,
610+ id,
611+ ElementStyle :: Level ( title. level . level ) ,
612+ ) ;
613+ buffer. append (
614+ buffer_msg_line_offset,
615+ "]" ,
616+ ElementStyle :: Level ( title. level . level ) ,
617+ ) ;
498618 label_width += 2 + id. len ( ) ;
499619 }
500620 let header_style = match title_style {
501- TitleStyle :: MainHeader => ElementStyle :: MainHeaderMsg ,
621+ TitleStyle :: MainHeader => {
622+ if self . short_message {
623+ ElementStyle :: NoStyle
624+ } else {
625+ ElementStyle :: MainHeaderMsg
626+ }
627+ }
502628 TitleStyle :: Header => ElementStyle :: HeaderMsg ,
503629 TitleStyle :: Secondary => unreachable ! ( ) ,
504630 } ;
505631 if title. level . name != Some ( None ) {
506- buffer. append ( line_offset , ": " , header_style) ;
632+ buffer. append ( buffer_msg_line_offset , ": " , header_style) ;
507633 label_width += 2 ;
508634 }
509635 if !title. title . is_empty ( ) {
510636 for ( line, text) in normalize_whitespace ( title. title ) . lines ( ) . enumerate ( ) {
511637 buffer. append (
512- line_offset + line,
638+ buffer_msg_line_offset + line,
513639 & format ! (
514640 "{}{}" ,
515641 if line == 0 {
@@ -600,15 +726,15 @@ impl Renderer {
600726 buffer : & mut StyledBuffer ,
601727 max_line_num_len : usize ,
602728 origin : & Origin < ' _ > ,
729+ buffer_msg_line_offset : usize ,
603730 ) {
604- let buffer_msg_line_offset = buffer. num_lines ( ) ;
605- if origin. primary {
731+ if origin. primary && !self . short_message {
606732 buffer. prepend (
607733 buffer_msg_line_offset,
608734 self . file_start ( ) ,
609735 ElementStyle :: LineNumber ,
610736 ) ;
611- } else {
737+ } else if ! self . short_message {
612738 // if !origin.standalone {
613739 // // Add spacing line, as shown:
614740 // // --> $DIR/file:54:15
@@ -643,9 +769,12 @@ impl Renderer {
643769 ( Some ( line) , None ) => format ! ( "{}:{}" , origin. origin, line) ,
644770 _ => origin. origin . to_owned ( ) ,
645771 } ;
772+
646773 buffer. append ( buffer_msg_line_offset, & str, ElementStyle :: LineAndColumn ) ;
647- for _ in 0 ..max_line_num_len {
648- buffer. prepend ( buffer_msg_line_offset, " " , ElementStyle :: NoStyle ) ;
774+ if !self . short_message {
775+ for _ in 0 ..max_line_num_len {
776+ buffer. prepend ( buffer_msg_line_offset, " " , ElementStyle :: NoStyle ) ;
777+ }
649778 }
650779 }
651780
@@ -707,7 +836,8 @@ impl Renderer {
707836 }
708837 }
709838 }
710- self . render_origin ( buffer, max_line_num_len, & origin) ;
839+ let buffer_msg_line_offset = buffer. num_lines ( ) ;
840+ self . render_origin ( buffer, max_line_num_len, & origin, buffer_msg_line_offset) ;
711841 }
712842
713843 // Put in the spacer between the location and annotated source
0 commit comments