Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions mdsf/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -100,9 +100,9 @@ pub fn format_file(
let is_go = language == "go" || language == "golang";

let (is_snippet, code_snippet, snippet_lines) = if is_go {
parse_go_codeblock(&mut lines)
parse_go_codeblock(&mut lines, &indentation)
} else {
parse_generic_codeblock(&mut lines)
parse_generic_codeblock(&mut lines, &indentation)
};

if is_snippet {
Expand Down
82 changes: 77 additions & 5 deletions mdsf/src/parser/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,10 @@ use regex::Regex;
const GO_TEMPORARY_PACKAGE_NAME: &str = "package mdsfformattertemporarynamespace\n";

#[inline]
pub fn parse_generic_codeblock(lines: &mut Enumerate<Lines>) -> (bool, String, usize) {
pub fn parse_generic_codeblock(
lines: &mut Enumerate<Lines>,
indentation: &str,
) -> (bool, String, usize) {
let mut code_snippet = String::new();

let mut is_snippet = false;
Expand All @@ -20,7 +23,7 @@ pub fn parse_generic_codeblock(lines: &mut Enumerate<Lines>) -> (bool, String, u
break;
}

code_snippet.push_str(subline);
code_snippet.push_str(dedent_line(subline, indentation));

code_snippet.push(crate::config::LF_NEWLINE_CHAR);
}
Expand All @@ -29,8 +32,11 @@ pub fn parse_generic_codeblock(lines: &mut Enumerate<Lines>) -> (bool, String, u
}

#[inline]
pub fn parse_go_codeblock(lines: &mut Enumerate<Lines>) -> (bool, String, usize) {
let (is_snippet, mut code_snippet, snippet_lines) = parse_generic_codeblock(lines);
pub fn parse_go_codeblock(
lines: &mut Enumerate<Lines>,
indentation: &str,
) -> (bool, String, usize) {
let (is_snippet, mut code_snippet, snippet_lines) = parse_generic_codeblock(lines, indentation);

if is_snippet && !GO_PACKAGE_RE.is_match(&code_snippet) {
code_snippet.insert_str(0, GO_TEMPORARY_PACKAGE_NAME);
Expand All @@ -52,19 +58,85 @@ pub fn remove_go_package(snippet: String) -> String {
}
}

#[inline]
fn dedent_line<'a>(line: &'a str, indentation: &str) -> &'a str {
if indentation.is_empty() {
line
} else {
line.strip_prefix(indentation)
.unwrap_or_else(|| line.trim_start())
}
}

#[inline]
pub fn indent_codeblock(indentation: &str, snippet: String) -> String {
if indentation.is_empty() {
snippet
} else {
snippet
.lines()
.map(|line| format!("{indentation}{line}"))
.map(|line| {
if line.is_empty() {
line.to_owned()
} else {
format!("{indentation}{line}")
}
})
.collect::<Vec<_>>()
.join(crate::config::Newline::Lf.as_str())
}
}

#[cfg(test)]
mod test_parse_generic_codeblock {
use crate::parser::parse_generic_codeblock;

#[test]
fn it_should_remove_the_codeblock_indentation() {
let input = " a = 1\n\n b = 2\n ```";

let (is_snippet, snippet, snippet_lines) =
parse_generic_codeblock(&mut input.lines().enumerate(), " ");

assert!(is_snippet);
assert_eq!("a = 1\n\nb = 2\n", snippet);
assert_eq!(4, snippet_lines);
}

#[test]
fn it_should_keep_lines_of_unindented_codeblocks() {
let input = "a = 1\n b = 2\n```";

let (is_snippet, snippet, snippet_lines) =
parse_generic_codeblock(&mut input.lines().enumerate(), "");

assert!(is_snippet);
assert_eq!("a = 1\n b = 2\n", snippet);
assert_eq!(3, snippet_lines);
}
}

#[cfg(test)]
mod test_indent_codeblock {
use crate::parser::indent_codeblock;

#[test]
fn it_should_indent_every_line() {
assert_eq!(
" a = 1\n b = 2",
indent_codeblock(" ", "a = 1\nb = 2".to_owned())
);
}

#[test]
fn it_should_not_indent_empty_lines() {
assert_eq!(
" a = 1\n\n b = 2",
indent_codeblock(" ", "a = 1\n\nb = 2".to_owned())
);
}
}

#[cfg(test)]
mod test_go_package_re {
use crate::parser::GO_PACKAGE_RE;
Expand Down