@@ -161,80 +161,89 @@ impl KdlEntry {
161161 self . len ( ) == 0
162162 }
163163
164+ /// Keeps the general entry formatting, though v1 entries will still be
165+ /// updated to v2 while preserving as much as possible.
166+ pub fn keep_format ( & mut self ) {
167+ if let Some ( fmt) = self . format_mut ( ) {
168+ fmt. autoformat_keep = true ;
169+ }
170+ }
171+
164172 /// Auto-formats this entry.
165173 pub fn autoformat ( & mut self ) {
166174 // TODO once MSRV allows:
167175 //self.format.take_if(|f| !f.autoformat_keep);
168- let value_repr = self . format . as_ref ( ) . map ( |x| {
169- match & self . value {
170- KdlValue :: String ( val) => {
171- // cleanup. I don't _think_ this should have any whitespace,
172- // but just in case.
173- let s = x. value_repr . trim ( ) ;
174- // convert raw strings to new format
175- let s = s. strip_prefix ( 'r' ) . unwrap_or ( s) ;
176- let s = if crate :: value:: is_plain_ident ( val) {
177- val. to_string ( )
178- } else if s
179- . find ( |c| v2_parser:: NEWLINES . iter ( ) . any ( |nl| nl. contains ( c) ) )
180- . is_some ( )
181- {
182- // Multiline string. Need triple quotes if they're not there already.
183- if s. contains ( "\" \" \" " ) {
184- // We're probably good. This could be more precise, but close enough.
185- s. to_string ( )
186- } else {
187- // `"` -> `"""` but also extra newlines need to be
188- // added because v2 strips the first and last ones.
189- let s = s. replacen ( '\"' , "\" \" \" \n " , 1 ) ;
190- s. chars ( )
191- . rev ( )
192- . collect :: < String > ( )
193- . replacen ( '\"' , "\" \" \" \n " , 1 )
194- . chars ( )
195- . rev ( )
196- . collect :: < String > ( )
197- }
198- } else if !s. starts_with ( '#' ) {
199- // `/` is no longer an escaped char in v2.
200- s. replace ( "\\ /" , "/" )
201- } else {
202- // We're all good! Let's move on.
203- s. to_string ( )
204- } ;
205- s
206- }
207- // These have `#` prefixes now. The regular Display impl will
208- // take care of that.
209- KdlValue :: Bool ( _) | KdlValue :: Null => format ! ( "{}" , self . value) ,
210- // These should be fine as-is?
211- KdlValue :: Integer ( _) | KdlValue :: Float ( _) => x. value_repr . clone ( ) ,
212- }
213- } ) ;
214-
176+ let old_fmt = self . format . clone ( ) ;
215177 if !self
216178 . format
217179 . as_ref ( )
218180 . map ( |f| f. autoformat_keep )
219181 . unwrap_or ( false )
220182 {
221183 self . format = None ;
222- }
223-
224- if let Some ( value_repr) = value_repr. as_ref ( ) {
225- self . format = Some (
226- self . format
227- . clone ( )
228- . map ( |mut x| {
229- x. value_repr = value_repr. into ( ) ;
230- x
231- } )
232- . unwrap_or_else ( || KdlEntryFormat {
233- value_repr : value_repr. into ( ) ,
234- leading : " " . into ( ) ,
235- ..Default :: default ( )
236- } ) ,
237- )
184+ } else {
185+ let value_repr = old_fmt. map ( |x| {
186+ match & self . value {
187+ KdlValue :: String ( val) => {
188+ // cleanup. I don't _think_ this should have any whitespace,
189+ // but just in case.
190+ let s = x. value_repr . trim ( ) ;
191+ // convert raw strings to new format
192+ let s = s. strip_prefix ( 'r' ) . unwrap_or ( s) ;
193+ let s = if crate :: value:: is_plain_ident ( val) {
194+ val. to_string ( )
195+ } else if s
196+ . find ( |c| v2_parser:: NEWLINES . iter ( ) . any ( |nl| nl. contains ( c) ) )
197+ . is_some ( )
198+ {
199+ // Multiline string. Need triple quotes if they're not there already.
200+ if s. contains ( "\" \" \" " ) {
201+ // We're probably good. This could be more precise, but close enough.
202+ s. to_string ( )
203+ } else {
204+ // `"` -> `"""` but also extra newlines need to be
205+ // added because v2 strips the first and last ones.
206+ let s = s. replacen ( '\"' , "\" \" \" \n " , 1 ) ;
207+ s. chars ( )
208+ . rev ( )
209+ . collect :: < String > ( )
210+ . replacen ( '\"' , "\" \" \" \n " , 1 )
211+ . chars ( )
212+ . rev ( )
213+ . collect :: < String > ( )
214+ }
215+ } else if !s. starts_with ( '#' ) {
216+ // `/` is no longer an escaped char in v2.
217+ s. replace ( "\\ /" , "/" )
218+ } else {
219+ // We're all good! Let's move on.
220+ s. to_string ( )
221+ } ;
222+ s
223+ }
224+ // These have `#` prefixes now. The regular Display impl will
225+ // take care of that.
226+ KdlValue :: Bool ( _) | KdlValue :: Null => format ! ( "{}" , self . value) ,
227+ // These should be fine as-is?
228+ KdlValue :: Integer ( _) | KdlValue :: Float ( _) => x. value_repr . clone ( ) ,
229+ }
230+ } ) ;
231+
232+ if let Some ( value_repr) = value_repr. as_ref ( ) {
233+ self . format = Some (
234+ self . format
235+ . clone ( )
236+ . map ( |mut x| {
237+ x. value_repr = value_repr. into ( ) ;
238+ x
239+ } )
240+ . unwrap_or_else ( || KdlEntryFormat {
241+ value_repr : value_repr. into ( ) ,
242+ leading : " " . into ( ) ,
243+ ..Default :: default ( )
244+ } ) ,
245+ )
246+ }
238247 }
239248
240249 if let Some ( name) = & mut self . name {
@@ -523,42 +532,52 @@ mod test {
523532 #[ test]
524533 fn v1_to_v2_format ( ) -> miette:: Result < ( ) > {
525534 let mut entry = KdlEntry :: parse_v1 ( r##"r#"hello, world!"#"## ) ?;
535+ entry. keep_format ( ) ;
526536 entry. autoformat ( ) ;
527537 assert_eq ! ( format!( "{}" , entry) , r##" #"hello, world!"#"## ) ;
528538
529539 let mut entry = KdlEntry :: parse_v1 ( r#""hello, \" world!""# ) ?;
540+ entry. keep_format ( ) ;
530541 entry. autoformat ( ) ;
531542 assert_eq ! ( format!( "{}" , entry) , r#" "hello, \" world!""# ) ;
532543
533544 let mut entry = KdlEntry :: parse_v1 ( "\" foo!`~.,<>\" " ) ?;
545+ entry. keep_format ( ) ;
534546 entry. autoformat ( ) ;
535547 assert_eq ! ( format!( "{}" , entry) , " foo!`~.,<>" ) ;
536548
537549 let mut entry = KdlEntry :: parse_v1 ( "\" \n hello, world!\" " ) ?;
550+ entry. keep_format ( ) ;
538551 entry. autoformat ( ) ;
539552 assert_eq ! ( format!( "{}" , entry) , " \" \" \" \n \n hello, world!\n \" \" \" " ) ;
540553
541554 let mut entry = KdlEntry :: parse_v1 ( "r#\" \n hello, world!\" #" ) ?;
555+ entry. keep_format ( ) ;
542556 entry. autoformat ( ) ;
543557 assert_eq ! ( format!( "{}" , entry) , " #\" \" \" \n \n hello, world!\n \" \" \" #" ) ;
544558
545559 let mut entry = KdlEntry :: parse_v1 ( "true" ) ?;
560+ entry. keep_format ( ) ;
546561 entry. autoformat ( ) ;
547562 assert_eq ! ( format!( "{}" , entry) , " #true" ) ;
548563
549564 let mut entry = KdlEntry :: parse_v1 ( "false" ) ?;
565+ entry. keep_format ( ) ;
550566 entry. autoformat ( ) ;
551567 assert_eq ! ( format!( "{}" , entry) , " #false" ) ;
552568
553569 let mut entry = KdlEntry :: parse_v1 ( "null" ) ?;
570+ entry. keep_format ( ) ;
554571 entry. autoformat ( ) ;
555572 assert_eq ! ( format!( "{}" , entry) , " #null" ) ;
556573
557574 let mut entry = KdlEntry :: parse_v1 ( "1_234_567" ) ?;
575+ entry. keep_format ( ) ;
558576 entry. autoformat ( ) ;
559577 assert_eq ! ( format!( "{}" , entry) , " 1_234_567" ) ;
560578
561579 let mut entry = KdlEntry :: parse_v1 ( "1_234_567E-10" ) ?;
580+ entry. keep_format ( ) ;
562581 entry. autoformat ( ) ;
563582 assert_eq ! ( format!( "{}" , entry) , " 1_234_567E-10" ) ;
564583 Ok ( ( ) )
0 commit comments