Skip to content

Commit

Permalink
Implement ParseOption::indented_multiline_values (#139)
Browse files Browse the repository at this point in the history
  • Loading branch information
davidhalter authored Nov 5, 2024
1 parent 5748ae5 commit b2a09b9
Showing 1 changed file with 68 additions and 1 deletion.
69 changes: 68 additions & 1 deletion src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -214,13 +214,21 @@ pub struct ParseOption {
///
/// If `enabled_escape` is true, then the value of `Key` will become `C:Windows` (`\W` equals to `W`).
pub enabled_escape: bool,

/// Enables values that span lines
/// ```ini
/// [Section]
/// Key1=C:\Windows
/// ```
pub indented_multiline_values: bool,
}

impl Default for ParseOption {
fn default() -> ParseOption {
ParseOption {
enabled_quote: true,
enabled_escape: true,
indented_multiline_values: false,
}
}
}
Expand Down Expand Up @@ -1537,7 +1545,7 @@ impl<'a> Parser<'a> {
// Issue #35: Allow empty value
self.parse_whitespace_except_line_break();

match self.ch {
let mut val = match self.ch {
None => Ok(String::new()),
Some('"') if self.opt.enabled_quote => {
self.bump();
Expand All @@ -1558,7 +1566,27 @@ impl<'a> Parser<'a> {
})
}
_ => self.parse_str_until_eol(cfg!(feature = "inline-comment")),
}?;
if self.opt.indented_multiline_values {
loop {
self.bump();
match self.ch {
Some(' ' | '\t') => {
self.parse_whitespace_except_line_break();
val.push('\n');
let mut new = self.parse_str_until_eol(cfg!(feature = "inline-comment"))?;
new.trim_in_place();
val.push_str(&new)
}
Some('\n') => {
val.push('\n');
continue
}
_ => break,
}
}
}
Ok(val)
}

#[inline]
Expand Down Expand Up @@ -2728,4 +2756,43 @@ x3 = nb
assert!(section_setter.get("b").is_none());
assert!(section_setter.get("c").is_none());
}

#[test]
fn parse_indented_multiline_values() {
let input = "
[Foo]
bar =
u
v
baz = w
x # intentional trailing whitespace below
y
z #2
bla = a
";

let opt = Ini::load_from_str_opt(
input,
ParseOption {
indented_multiline_values: true,
..ParseOption::default()
},
)
.unwrap();
let sec = opt.section(Some("Foo")).unwrap();
let mut iterator = sec.iter();
let bar = iterator.next().unwrap().1;
let baz = iterator.next().unwrap().1;
let bla = iterator.next().unwrap().1;
assert!(iterator.next().is_none());
assert_eq!(bar, "u\nv");
if cfg!(feature = "inline-comment") {
assert_eq!(baz, "w\nx\ny\n\nz");
} else {
assert_eq!(baz, "w\nx # intentional trailing whitespace below\ny\n\nz #2");
}
assert_eq!(bla, "a");
}
}

0 comments on commit b2a09b9

Please sign in to comment.