Skip to content

Commit

Permalink
Merge pull request #26 from corn-config/feat/multiline-string
Browse files Browse the repository at this point in the history
feat: trim whitespace from multi-line strings
  • Loading branch information
JakeStanger authored Nov 5, 2023
2 parents 233bf74 + 2273ce7 commit edd5540
Show file tree
Hide file tree
Showing 9 changed files with 64 additions and 6 deletions.
6 changes: 6 additions & 0 deletions assets/inputs/string_multiline.corn
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
{
foo = "
hello
world
"
}
2 changes: 1 addition & 1 deletion assets/outputs/json/string.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"foo": "bar",
"bar": "\"\\\n\r\t",
"bar": "\"\\\n",
"baz": "a",
"qux": ""
}
3 changes: 3 additions & 0 deletions assets/outputs/json/string_multiline.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
{
"foo": "hello\nworld\n"
}
6 changes: 3 additions & 3 deletions assets/outputs/toml/string.toml
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
foo = "bar"
bar = """
\"\\
\r\t"""
bar = '''
"\
'''
baz = "a"
qux = ""

5 changes: 5 additions & 0 deletions assets/outputs/toml/string_multiline.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
foo = """
hello
world
"""

3 changes: 2 additions & 1 deletion assets/outputs/yaml/string.yml
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
foo: bar
bar: "\"\\\n\r\t"
bar: |
"\
baz: a
qux: ''

4 changes: 4 additions & 0 deletions assets/outputs/yaml/string_multiline.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
foo: |
hello
world
40 changes: 40 additions & 0 deletions libcorn/src/parser.rs
Original file line number Diff line number Diff line change
Expand Up @@ -124,6 +124,12 @@ impl<'a> CornParser<'a> {
};
}

let full_string = if full_string.contains('\n') {
trim_multiline_string(&full_string)
} else {
full_string
};

Ok(Cow::Owned(full_string))
}

Expand Down Expand Up @@ -315,6 +321,40 @@ impl<'a> CornParser<'a> {
}
}

/// Takes a multiline string and trims the maximum amount of
/// whitespace at the start of each line
/// while preserving formatting.
///
/// Based on code from `indoc` crate:
/// <https://github.com/dtolnay/indoc/blob/60b5fa29ba4f98b479713621a1f4ec96155caaba/src/unindent.rs#L15-L51>

fn trim_multiline_string(string: &str) -> String {
let ignore_first_line = string.starts_with('\n') || string.starts_with("\r\n");

let spaces = string
.lines()
.skip(1)
.map(|line| line.chars().take_while(char::is_ascii_whitespace).count())
.min()
.unwrap_or_default();

let mut result = String::with_capacity(string.len());
for (i, line) in string.lines().enumerate() {
if i > 1 || (i == 1 && !ignore_first_line) {
result.push('\n');
}
if i == 0 {
// Do not un-indent anything on same line as opening quote
result.push_str(line);
} else if line.len() > spaces {
// Whitespace-only lines may have fewer than the number of spaces
// being removed
result.push_str(&line[spaces..]);
}
}
result
}

/// Parses the input string into a `Config`
/// containing the resolved inputs
/// and a map of values representing the top-level object.
Expand Down
1 change: 0 additions & 1 deletion libcorn/src/wasm.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,6 @@ use wasm_bindgen_test::*;
#[wasm_bindgen]
pub fn parse(corn: &str) -> Result<JsValue, JsValue> {
console_error_panic_hook::set_once();

let res = crate::parse(corn);

match res {
Expand Down

0 comments on commit edd5540

Please sign in to comment.