Skip to content

Commit cf05593

Browse files
committed
Preserve blank lines within multiline values
1 parent 5544794 commit cf05593

File tree

3 files changed

+51
-26
lines changed

3 files changed

+51
-26
lines changed

src/ini.rs

+46-24
Original file line numberDiff line numberDiff line change
@@ -674,8 +674,10 @@ impl Ini {
674674

675675
for line in lines {
676676
out.push_str(LINE_ENDING);
677-
out.push_str(" ".repeat(indent).as_ref());
678-
out.push_str(line);
677+
if !line.is_empty() {
678+
out.push_str(" ".repeat(indent).as_ref());
679+
out.push_str(line);
680+
}
679681
}
680682
} else {
681683
out.push_str(value);
@@ -734,6 +736,9 @@ impl Ini {
734736
}
735737
};
736738

739+
// Track blank lines to preserve them in multiline values.
740+
let mut blank_lines = 0usize;
741+
737742
for (num, raw_line) in input.lines().enumerate() {
738743
let line = match raw_line.find(|c: char| self.comment_symbols.contains(&c)) {
739744
Some(idx) => &raw_line[..idx],
@@ -742,7 +747,13 @@ impl Ini {
742747

743748
let trimmed = line.trim();
744749

750+
// Skip empty lines, but keep track of them for multiline values.
745751
if trimmed.is_empty() {
752+
// If a line is _just_ a comment (regardless of whether it's preceded by
753+
// whitespace), ignore it.
754+
if line == raw_line {
755+
blank_lines += 1;
756+
}
746757
continue;
747758
}
748759

@@ -779,41 +790,52 @@ impl Ini {
779790
.or_insert_with(|| Some(String::new()));
780791

781792
match val {
782-
Some(x) => {
783-
x.push_str(LINE_ENDING);
784-
x.push_str(trimmed);
793+
Some(s) => {
794+
for _ in 0..blank_lines {
795+
s.push_str(LINE_ENDING);
796+
}
797+
s.push_str(LINE_ENDING);
798+
s.push_str(trimmed);
785799
}
786800
None => {
787-
*val = Some(format!("{}{}", LINE_ENDING, trimmed));
801+
let mut s = String::with_capacity(
802+
(blank_lines + 1) * LINE_ENDING.len() + trimmed.len(),
803+
);
804+
for _ in 0..blank_lines {
805+
s.push_str(LINE_ENDING);
806+
}
807+
s.push_str(LINE_ENDING);
808+
s.push_str(trimmed);
809+
*val = Some(s);
788810
}
789811
}
812+
} else {
813+
let valmap = map.entry(section.clone()).or_default();
790814

791-
continue;
792-
}
815+
match trimmed.find(&self.delimiters[..]) {
816+
Some(delimiter) => {
817+
let key = caser(trimmed[..delimiter].trim());
793818

794-
let valmap = map.entry(section.clone()).or_default();
819+
if key.is_empty() {
820+
return Err(format!("line {}:{}: Key cannot be empty", num, delimiter));
821+
} else {
822+
current_key = Some(key.clone());
795823

796-
match trimmed.find(&self.delimiters[..]) {
797-
Some(delimiter) => {
798-
let key = caser(trimmed[..delimiter].trim());
824+
let value = trimmed[delimiter + 1..].trim().to_owned();
799825

800-
if key.is_empty() {
801-
return Err(format!("line {}:{}: Key cannot be empty", num, delimiter));
802-
} else {
826+
valmap.insert(key, Some(value));
827+
}
828+
}
829+
None => {
830+
let key = caser(trimmed);
803831
current_key = Some(key.clone());
804832

805-
let value = trimmed[delimiter + 1..].trim().to_owned();
806-
807-
valmap.insert(key, Some(value));
833+
valmap.insert(key, None);
808834
}
809835
}
810-
None => {
811-
let key = caser(trimmed);
812-
current_key = Some(key.clone());
813-
814-
valmap.insert(key, None);
815-
}
816836
}
837+
838+
blank_lines = 0;
817839
}
818840

819841
Ok(map)

tests/test.rs

+2-1
Original file line numberDiff line numberDiff line change
@@ -534,7 +534,7 @@ fn multiline_on() -> Result<(), Box<dyn Error>> {
534534
assert_eq!(config.get("Section", "Key2").unwrap(), "Value Two");
535535
assert_eq!(
536536
config.get("Section", "Key3").unwrap(),
537-
"this is a haiku\nspread across separate lines\na single value"
537+
"this is a haiku\nspread across separate lines\n\na single value"
538538
);
539539
assert_eq!(config.get("Section", "Key4").unwrap(), "Four");
540540

@@ -545,6 +545,7 @@ Key1=Value1
545545
Key2=Value Two
546546
Key3=this is a haiku
547547
spread across separate lines
548+
548549
a single value
549550
Key4=Four
550551
"

tests/test_multiline.ini

+3-1
Original file line numberDiff line numberDiff line change
@@ -3,5 +3,7 @@ Key1: Value1
33
Key2: Value Two
44
Key3: this is a haiku
55
spread across separate lines
6+
# This is a comment
7+
68
a single value
7-
Key4: Four
9+
Key4: Four

0 commit comments

Comments
 (0)