Skip to content

Commit ae7f2cd

Browse files
committed
Implement ParseOption::indented_multiline_values
1 parent 5748ae5 commit ae7f2cd

File tree

1 file changed

+68
-1
lines changed

1 file changed

+68
-1
lines changed

src/lib.rs

+68-1
Original file line numberDiff line numberDiff line change
@@ -214,13 +214,21 @@ pub struct ParseOption {
214214
///
215215
/// If `enabled_escape` is true, then the value of `Key` will become `C:Windows` (`\W` equals to `W`).
216216
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,
217224
}
218225

219226
impl Default for ParseOption {
220227
fn default() -> ParseOption {
221228
ParseOption {
222229
enabled_quote: true,
223230
enabled_escape: true,
231+
indented_multiline_values: false,
224232
}
225233
}
226234
}
@@ -1537,7 +1545,7 @@ impl<'a> Parser<'a> {
15371545
// Issue #35: Allow empty value
15381546
self.parse_whitespace_except_line_break();
15391547

1540-
match self.ch {
1548+
let mut val = match self.ch {
15411549
None => Ok(String::new()),
15421550
Some('"') if self.opt.enabled_quote => {
15431551
self.bump();
@@ -1558,7 +1566,27 @@ impl<'a> Parser<'a> {
15581566
})
15591567
}
15601568
_ => 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+
}
15611588
}
1589+
Ok(val)
15621590
}
15631591

15641592
#[inline]
@@ -2728,4 +2756,43 @@ x3 = nb
27282756
assert!(section_setter.get("b").is_none());
27292757
assert!(section_setter.get("c").is_none());
27302758
}
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\nv");
2791+
if cfg!(feature = "inline-comment") {
2792+
assert_eq!(baz, "w\nx\ny\n\nz");
2793+
} else {
2794+
assert_eq!(baz, "w\nx # intentional trailing whitespace below\ny\n\nz #2");
2795+
}
2796+
assert_eq!(bla, "a");
2797+
}
27312798
}

0 commit comments

Comments
 (0)