11use ratatui:: {
22 layout:: { Constraint , Rect } ,
33 style:: { Color , Modifier , Style , Stylize } ,
4- text:: Text ,
4+ text:: { Line , Span , Text } ,
55 widgets:: { Block , Borders , Cell , Row , StatefulWidget , Table , TableState } ,
66} ;
77
@@ -44,8 +44,8 @@ impl<'b> TaskTable<'b> {
4444 . max ( )
4545 . unwrap_or_default ( )
4646 . clamp ( min_width, 40 ) as u16 ;
47- // Add space for column divider and status emoji
48- task_name_width + 1
47+ // Add space for status emoji and space
48+ task_name_width + 2
4949 }
5050
5151 /// Update the current time of the table
@@ -72,69 +72,67 @@ impl<'b> TaskTable<'b> {
7272 }
7373 }
7474
75- /// Get styled status icon for a finished task
76- fn status_icon ( & self , task_name : & str , result : TaskResult ) -> Cell < ' static > {
77- let should_dim = self . should_dim_task ( task_name) ;
78- match result {
79- // matches Next.js (and many other CLI tools) https://github.com/vercel/next.js/blob/1a04d94aaec943d3cce93487fea3b8c8f8898f31/packages/next/src/build/output/log.ts
80- TaskResult :: Success => {
81- let style = if should_dim {
82- Style :: default ( ) . green ( ) . add_modifier ( Modifier :: DIM )
83- } else {
84- Style :: default ( ) . green ( ) . bold ( )
85- } ;
86- Cell :: new ( Text :: styled ( "✓" , style) )
87- }
88- TaskResult :: CacheHit => {
89- let style = if should_dim {
90- Style :: default ( ) . magenta ( ) . add_modifier ( Modifier :: DIM )
91- } else {
92- Style :: default ( ) . magenta ( )
93- } ;
94- Cell :: new ( Text :: styled ( "⊙" , style) )
95- }
96- TaskResult :: Failure => {
97- let style = if should_dim {
98- Style :: default ( ) . red ( ) . add_modifier ( Modifier :: DIM )
99- } else {
100- Style :: default ( ) . red ( ) . bold ( )
101- } ;
102- Cell :: new ( Text :: styled ( "⨯" , style) )
103- }
104- }
105- }
106-
10775 fn finished_rows ( & self ) -> impl Iterator < Item = Row < ' _ > > + ' _ {
10876 self . tasks_by_type . finished . iter ( ) . map ( move |task| {
10977 let base_style = self . task_style ( task. name ( ) ) ;
110- let name = if matches ! ( task. result( ) , TaskResult :: CacheHit ) {
111- Cell :: new ( Text :: styled ( task. name ( ) , base_style. italic ( ) ) )
78+ let icon = match task. result ( ) {
79+ // matches Next.js (and many other CLI tools) https://github.com/vercel/next.js/blob/1a04d94aaec943d3cce93487fea3b8c8f8898f31/packages/next/src/build/output/log.ts
80+ TaskResult :: Success => {
81+ let style = if self . should_dim_task ( task. name ( ) ) {
82+ Style :: default ( ) . green ( ) . add_modifier ( Modifier :: DIM )
83+ } else {
84+ Style :: default ( ) . green ( ) . bold ( )
85+ } ;
86+ Span :: styled ( "✓ " , style)
87+ }
88+ TaskResult :: CacheHit => {
89+ let style = if self . should_dim_task ( task. name ( ) ) {
90+ Style :: default ( ) . magenta ( ) . add_modifier ( Modifier :: DIM )
91+ } else {
92+ Style :: default ( ) . magenta ( )
93+ } ;
94+ Span :: styled ( "⊙ " , style)
95+ }
96+ TaskResult :: Failure => {
97+ let style = if self . should_dim_task ( task. name ( ) ) {
98+ Style :: default ( ) . red ( ) . add_modifier ( Modifier :: DIM )
99+ } else {
100+ Style :: default ( ) . red ( ) . bold ( )
101+ } ;
102+ Span :: styled ( "⨯ " , style)
103+ }
104+ } ;
105+
106+ let name_style = if matches ! ( task. result( ) , TaskResult :: CacheHit ) {
107+ base_style. italic ( )
112108 } else {
113- Cell :: new ( Text :: styled ( task . name ( ) , base_style) )
109+ base_style
114110 } ;
115111
116- Row :: new ( vec ! [ name, self . status_icon( task. name( ) , task. result( ) ) ] )
112+ let mut content = vec ! [ icon] ;
113+ content. push ( Span :: styled ( task. name ( ) , name_style) ) ;
114+
115+ Row :: new ( vec ! [ Cell :: new( Line :: from( content) ) ] )
117116 } )
118117 }
119118
120119 fn running_rows ( & self ) -> impl Iterator < Item = Row < ' _ > > + ' _ {
121120 let spinner = self . spinner . current ( ) ;
122121 self . tasks_by_type . running . iter ( ) . map ( move |task| {
123122 let style = self . task_style ( task. name ( ) ) ;
124- Row :: new ( vec ! [
125- Cell :: new( Text :: styled( task. name( ) , style) ) ,
126- Cell :: new( Text :: styled( spinner, style) ) ,
127- ] )
123+ let content = vec ! [
124+ Span :: styled( format!( "{} " , spinner) , style) ,
125+ Span :: styled( task. name( ) , style) ,
126+ ] ;
127+ Row :: new ( vec ! [ Cell :: new( Line :: from( content) ) ] )
128128 } )
129129 }
130130
131131 fn planned_rows ( & self ) -> impl Iterator < Item = Row < ' _ > > + ' _ {
132132 self . tasks_by_type . planned . iter ( ) . map ( move |task| {
133133 let style = self . task_style ( task. name ( ) ) ;
134- Row :: new ( vec ! [
135- Cell :: new( Text :: styled( task. name( ) , style) ) ,
136- Cell :: new( " " ) ,
137- ] )
134+ let content = vec ! [ Span :: raw( " " ) , Span :: styled( task. name( ) , style) ] ;
135+ Row :: new ( vec ! [ Cell :: new( Line :: from( content) ) ] )
138136 } )
139137 }
140138}
@@ -147,17 +145,13 @@ impl<'a> StatefulWidget for &'a TaskTable<'a> {
147145 self . running_rows ( )
148146 . chain ( self . planned_rows ( ) )
149147 . chain ( self . finished_rows ( ) ) ,
150- [
151- Constraint :: Min ( 15 ) ,
152- // Status takes one cell to render
153- Constraint :: Length ( 1 ) ,
154- ] ,
148+ [ Constraint :: Min ( 15 ) ] ,
155149 )
156150 . highlight_style ( Style :: default ( ) . fg ( Color :: Yellow ) )
157151 . column_spacing ( 0 )
158152 . block ( Block :: new ( ) . borders ( Borders :: RIGHT ) )
159153 . header (
160- vec ! [ Text :: styled(
154+ Row :: new ( vec ! [ Cell :: from ( Text :: styled(
161155 match self . section {
162156 LayoutSections :: Search { results, .. }
163157 | LayoutSections :: SearchLocked { results, .. } => {
@@ -166,20 +160,14 @@ impl<'a> StatefulWidget for &'a TaskTable<'a> {
166160 _ => TASK_HEADER . to_string( ) ,
167161 } ,
168162 Style :: default ( ) . add_modifier( Modifier :: DIM ) ,
169- ) ]
170- . into_iter ( )
171- . map ( Cell :: from)
172- . collect :: < Row > ( )
163+ ) ) ] )
173164 . height ( 1 ) ,
174165 )
175166 . footer (
176- vec ! [ Text :: styled(
167+ Row :: new ( vec ! [ Cell :: from ( Text :: styled(
177168 format!( "{TASK_NAVIGATE_INSTRUCTIONS}\n {MORE_BINDS_INSTRUCTIONS}" ) ,
178169 Style :: default ( ) . add_modifier( Modifier :: DIM ) ,
179- ) ]
180- . into_iter ( )
181- . map ( Cell :: from)
182- . collect :: < Row > ( )
170+ ) ) ] )
183171 . height ( 2 ) ,
184172 ) ;
185173 StatefulWidget :: render ( table, area, buf, state) ;
0 commit comments