@@ -214,13 +214,21 @@ pub struct ParseOption {
214
214
///
215
215
/// If `enabled_escape` is true, then the value of `Key` will become `C:Windows` (`\W` equals to `W`).
216
216
pub enabled_escape : bool ,
217
+
218
+ /// Enables values that span lines
219
+ /// ```ini
220
+ /// [Section]
221
+ /// Key1=C:\Windows
222
+ /// ```
223
+ pub indented_multiline_values : bool ,
217
224
}
218
225
219
226
impl Default for ParseOption {
220
227
fn default ( ) -> ParseOption {
221
228
ParseOption {
222
229
enabled_quote : true ,
223
230
enabled_escape : true ,
231
+ indented_multiline_values : false ,
224
232
}
225
233
}
226
234
}
@@ -1537,7 +1545,7 @@ impl<'a> Parser<'a> {
1537
1545
// Issue #35: Allow empty value
1538
1546
self . parse_whitespace_except_line_break ( ) ;
1539
1547
1540
- match self . ch {
1548
+ let mut val = match self . ch {
1541
1549
None => Ok ( String :: new ( ) ) ,
1542
1550
Some ( '"' ) if self . opt . enabled_quote => {
1543
1551
self . bump ( ) ;
@@ -1558,7 +1566,27 @@ impl<'a> Parser<'a> {
1558
1566
} )
1559
1567
}
1560
1568
_ => self . parse_str_until_eol ( cfg ! ( feature = "inline-comment" ) ) ,
1569
+ } ?;
1570
+ if self . opt . indented_multiline_values {
1571
+ loop {
1572
+ self . bump ( ) ;
1573
+ match self . ch {
1574
+ Some ( ' ' | '\t' ) => {
1575
+ self . parse_whitespace_except_line_break ( ) ;
1576
+ val. push ( '\n' ) ;
1577
+ let mut new = self . parse_str_until_eol ( cfg ! ( feature = "inline-comment" ) ) ?;
1578
+ new. trim_in_place ( ) ;
1579
+ val. push_str ( & new)
1580
+ }
1581
+ Some ( '\n' ) => {
1582
+ val. push ( '\n' ) ;
1583
+ continue
1584
+ }
1585
+ _ => break ,
1586
+ }
1587
+ }
1561
1588
}
1589
+ Ok ( val)
1562
1590
}
1563
1591
1564
1592
#[ inline]
@@ -2728,4 +2756,43 @@ x3 = nb
2728
2756
assert ! ( section_setter. get( "b" ) . is_none( ) ) ;
2729
2757
assert ! ( section_setter. get( "c" ) . is_none( ) ) ;
2730
2758
}
2759
+
2760
+ #[ test]
2761
+ fn parse_indented_multiline_values ( ) {
2762
+ let input = "
2763
+ [Foo]
2764
+ bar =
2765
+ u
2766
+ v
2767
+
2768
+ baz = w
2769
+ x # intentional trailing whitespace below
2770
+ y
2771
+
2772
+ z #2
2773
+ bla = a
2774
+ " ;
2775
+
2776
+ let opt = Ini :: load_from_str_opt (
2777
+ input,
2778
+ ParseOption {
2779
+ indented_multiline_values : true ,
2780
+ ..ParseOption :: default ( )
2781
+ } ,
2782
+ )
2783
+ . unwrap ( ) ;
2784
+ let sec = opt. section ( Some ( "Foo" ) ) . unwrap ( ) ;
2785
+ let mut iterator = sec. iter ( ) ;
2786
+ let bar = iterator. next ( ) . unwrap ( ) . 1 ;
2787
+ let baz = iterator. next ( ) . unwrap ( ) . 1 ;
2788
+ let bla = iterator. next ( ) . unwrap ( ) . 1 ;
2789
+ assert ! ( iterator. next( ) . is_none( ) ) ;
2790
+ assert_eq ! ( bar, "u\n v" ) ;
2791
+ if cfg ! ( feature = "inline-comment" ) {
2792
+ assert_eq ! ( baz, "w\n x\n y\n \n z" ) ;
2793
+ } else {
2794
+ assert_eq ! ( baz, "w\n x # intentional trailing whitespace below\n y\n \n z #2" ) ;
2795
+ }
2796
+ assert_eq ! ( bla, "a" ) ;
2797
+ }
2731
2798
}
0 commit comments