2222//! 
2323
2424use  crate :: * ; 
25- use  md_math:: MdOffset ; 
2625use  print:: 
2726{ 
2827  InputExtract , 
2928  Context , 
3029} ; 
30+ use  std:: borrow:: Cow ; 
3131use  core:: 
3232{ 
3333  fmt, 
@@ -59,6 +59,8 @@ pub struct Records
5959   pub  cell_postfix  :  String , 
6060  /// Separator used between table columns. 
6161   pub  cell_separator  :  String , 
62+   /// Limit table width. If the value is zero, then no limitation. 
63+    pub  max_width :  usize , 
6264  // /// Horizontal line character. 
6365  // pub h : char, 
6466  // /// Vertical line character. 
@@ -91,6 +93,25 @@ impl Records
9193    static  INSTANCE  :  OnceLock <  Records  >  = OnceLock :: new ( ) ; 
9294    INSTANCE . get_or_init (  || Records :: default ( )  ) 
9395  } 
96+ 
97+   /// Calculate how much space is minimally needed in order to generate an output with this output formatter. 
98+    /// It will be impossible to render tables smaller than the result of `min_width()`. 
99+    /// 
100+    /// This function is similar to `output_format::Table::min_width`, but it does not contain a 
101+    /// `column_count` as it always equal to 2, and it aslo uses the `output_format::Records`  
102+    /// style parameters. 
103+    pub  fn  min_width 
104+   ( 
105+     & self , 
106+   )  -> usize 
107+   { 
108+     // 2 is used here, because `Records` displays 2 columns: keys and values. 
109+     self . row_prefix . chars ( ) . count ( ) 
110+     + self . row_postfix . chars ( ) . count ( ) 
111+     + 2  *  (  self . cell_postfix . chars ( ) . count ( )  + self . cell_prefix . chars ( ) . count ( )  ) 
112+     + self . cell_separator . chars ( ) . count ( ) 
113+     + 2 
114+   } 
94115} 
95116
96117impl  Default  for  Records 
@@ -108,6 +129,8 @@ impl Default for Records
108129    let  table_postfix = "" . to_string ( ) ; 
109130    let  table_separator = "\n " . to_string ( ) ; 
110131
132+     let  max_width = 0 ; 
133+ 
111134    // let h = '─'; 
112135    // let v = '|'; 
113136    // let t_l = '├'; 
@@ -131,6 +154,7 @@ impl Default for Records
131154      cell_prefix, 
132155      cell_postfix, 
133156      cell_separator, 
157+       max_width, 
134158      // h, 
135159      // v, 
136160      // t_l, 
@@ -155,70 +179,88 @@ impl TableOutputFormat for Records
155179    c  :  &  mut  Context <  ' buf  > , 
156180  )  -> fmt:: Result 
157181  { 
182+     use  format:: text_wrap:: {  text_wrap,  width_calculate } ; 
183+ 
184+     if  self . max_width  != 0  && self . max_width  < self . min_width ( ) 
185+     { 
186+       return  Err (  fmt:: Error  ) ; 
187+     } 
188+ 
189+     // 2 because there are only 2 columns: key and value. 
190+     let  columns_max_width = if  self . max_width  == 0  {  0  }  else  {  self . max_width  - self . min_width ( )  + 2  } ; 
158191
159-     let  label_width = x. header ( ) . fold (  0 ,  | acc,  cell | acc. max (  cell. 1 [  0  ]  )  ) ; 
192+     let  keys :  Vec <  (  Cow <  ' data ,  str  > ,  [  usize ;  2  ]  )  >  = x. header ( ) . collect ( ) ; 
193+     let  keys_width = width_calculate (  & keys ) ; 
160194
161195    write ! (  c. buf,  "{}" ,  self . table_prefix ) ?; 
162196
163-     let  mut  first = true ; 
164-     // Write each record 
165-     for  (  irow,  row )  in  x. rows ( ) 
166-     { 
197+     let  mut  printed_tables_count = 0 ; 
167198
168-       if  !row. vis 
199+     for  (  itable_descriptor,  table_descriptor )  in  x. row_descriptors . iter ( ) . enumerate ( ) 
200+     { 
201+       if  !table_descriptor. vis  || (  x. has_header  && itable_descriptor == 0  ) 
169202      { 
170203        continue ; 
171204      } 
172205
173-       if  first
174-       { 
175-         first = false ; 
176-       } 
177-       else 
206+       if  printed_tables_count > 0 
178207      { 
179208        write ! (  c. buf,  "{}" ,  self . table_separator ) ?; 
180209      } 
181210
182-       let  slice_width = x. data [  irow ] . iter ( ) . fold (  0 ,  | acc,  cell | acc. max (  cell. 1 [  0  ]  )  ) ; 
211+       printed_tables_count += 1 ; 
212+ 
213+       writeln ! (  c. buf,  " = {}" ,  table_descriptor. irow ) ?; 
183214
184-       writeln ! (  c. buf,  " = {}" ,  irow ) ?; 
215+       let  values = & x. data [  itable_descriptor ] ; 
216+       let  values_width = width_calculate (  & values ) ; 
185217
186-       for  (  icol,  _col )  in  x. col_descriptors . iter ( ) . enumerate ( ) 
218+       let  table_for_wrapping :  Vec <  Vec <  (  Cow <  ' data ,  str  > ,  [  usize ;  2 ]  )  >  >  =
219+       keys. iter ( ) . enumerate ( ) . map (  | (  ikey,  key )  |
187220      { 
188-         let  cell =  & x . data [  irow  ] [  icol  ] ; 
189-          let  height = cell . 1 [   1   ] ; 
221+         vec ! [  key . clone ( ) ,  values [  ikey  ] . clone ( )   ] 
222+       } ) . collect ( ) ; 
190223
191-         for  islice in  0 ..height
224+       let  wrapped_text = text_wrap 
225+       ( 
226+         table_for_wrapping. iter ( ) , 
227+         & [  keys_width,  values_width ] , 
228+         columns_max_width, 
229+         keys_width + values_width, 
230+       ) ; 
231+ 
232+       for  (  irow,  cols )  in  wrapped_text. data . into_iter ( ) . enumerate ( ) 
233+       { 
234+         if  irow != 0 
192235        { 
193-           let  label = x. header_slice (  islice,  icol ) ; 
194-           let  md_index = [  islice,  icol,  irow ] ; 
195-           let  slice = x. slices [  x. slices_dim . md_offset (  md_index )  ] ; 
196- 
197-           if  icol > 0  || islice > 0 
198-           { 
199-             write ! (  c. buf,  "{}" ,  self . row_separator ) ?; 
200-           } 
201- 
202-           write ! (  c. buf,  "{}" ,  self . row_prefix ) ?; 
203- 
204-           write ! (  c. buf,  "{}" ,  self . cell_prefix ) ?; 
205-           write ! (  c. buf,  "{:<label_width$}" ,  label ) ?; 
206-           write ! (  c. buf,  "{}" ,  self . cell_postfix ) ?; 
207-           write ! (  c. buf,  "{}" ,  self . cell_separator ) ?; 
208-           write ! (  c. buf,  "{}" ,  self . cell_prefix ) ?; 
209-           write ! (  c. buf,  "{:<slice_width$}" ,  slice ) ?; 
210-           write ! (  c. buf,  "{}" ,  self . cell_postfix ) ?; 
211- 
212-           write ! (  c. buf,  "{}" ,  self . row_postfix ) ?; 
236+           write ! (  c. buf,  "{}" ,  self . row_separator ) ?; 
213237        } 
214238
215-       } 
239+         let  key = & cols[  0  ] ; 
240+         let  value = & cols[  1  ] ; 
241+ 
242+         let  key_width = wrapped_text. column_widthes [  0  ] ; 
243+         let  value_width = wrapped_text. column_widthes [  1  ] ; 
244+ 
245+         write ! (  c. buf,  "{}" ,  self . row_prefix ) ?; 
216246
247+         write ! (  c. buf,  "{}" ,  self . cell_prefix ) ?; 
248+         write ! (  c. buf,  "{:<key_width$}" ,  key. content ) ?; 
249+         write ! (  c. buf,  "{}" ,  self . cell_postfix ) ?; 
250+         write ! (  c. buf,  "{}" ,  self . cell_separator ) ?; 
251+         write ! (  c. buf,  "{}" ,  self . cell_prefix ) ?; 
252+         // No need to use `wrap_width` of `WrappedCell`, as `output_format::Records` 
253+         // does not center values in cells (they are always left aligned). 
254+         write ! (  c. buf,  "{:<value_width$}" ,  value. content ) ?; 
255+         write ! (  c. buf,  "{}" ,  self . cell_postfix ) ?; 
256+ 
257+         write ! (  c. buf,  "{}" ,  self . row_postfix ) ?; 
258+       } 
217259    } 
218260
219261    write ! (  c. buf,  "{}" ,  self . table_postfix ) ?; 
220262
221-     Ok ( ( ) ) 
263+     Ok (   ( )   ) 
222264  } 
223265
224266} 
0 commit comments