From 559c00160fd4da0a889251215af971eadeceb1fe Mon Sep 17 00:00:00 2001 From: Jeremy Harris Date: Tue, 18 Feb 2025 13:49:45 -0600 Subject: [PATCH 01/21] Use `line-ending` crate at v1.0.1 --- Cargo.lock | 12 ++++++++++- Cargo.toml | 3 ++- README.md | 6 +++--- src/lib.rs | 51 +++++++++++++++++++--------------------------- src/line_ending.rs | 46 ----------------------------------------- 5 files changed, 37 insertions(+), 81 deletions(-) delete mode 100644 src/line_ending.rs diff --git a/Cargo.lock b/Cargo.lock index 2ff6893..f15e2a8 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -8,9 +8,19 @@ version = "0.3.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "fea41bba32d969b513997752735605054bc0dfa92b4c56bf1189f2e174be7a10" +[[package]] +name = "line-ending" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "553d09af164e35635188a438ce8e81ed8adc7d3e436d2a17f0c7dbcf3fb1f82e" +dependencies = [ + "doc-comment", +] + [[package]] name = "string-auto-indent" -version = "0.1.0-alpha1" +version = "0.1.0-alpha2" dependencies = [ "doc-comment", + "line-ending", ] diff --git a/Cargo.toml b/Cargo.toml index 0d88688..9222574 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "string-auto-indent" -version = "0.1.0-alpha1" +version = "0.1.0-alpha2" authors = ["Jeremy Harris "] edition = "2021" description = "Normalizes multi-line string indentation while preserving platform-specific line endings." @@ -9,3 +9,4 @@ license = "MIT" [dependencies] doc-comment = "0.3.3" +line-ending = "1.0.1" diff --git a/README.md b/README.md index b7da419..c237cf5 100644 --- a/README.md +++ b/README.md @@ -41,20 +41,20 @@ let text = r#" "#; // For cross-platform testing -let line_ending = LineEnding::detect(text); +let line_ending = LineEnding::from(text); // With auto-indent assert_eq!( auto_indent(text), // For cross-platform testing: Restore platform-specific line endings - line_ending.restore("String Auto Indent\n\nLevel 1\n Level 2\n Level 3\n") + line_ending.denormalize("String Auto Indent\n\nLevel 1\n Level 2\n Level 3\n") ); // Without auto-indent assert_eq!( text, // For cross-platform testing: Restore platform-specific line endings - line_ending.restore("\n String Auto Indent\n\n Level 1\n Level 2\n Level 3\n"), + line_ending.denormalize("\n String Auto Indent\n\n Level 1\n Level 2\n Level 3\n"), ); ``` diff --git a/src/lib.rs b/src/lib.rs index 9dfc67c..9fd1b71 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -1,7 +1,6 @@ #[cfg(doctest)] doc_comment::doctest!("../README.md"); -pub mod line_ending; pub use line_ending::LineEnding; /// Struct that encapsulates auto-indentation logic. @@ -13,7 +12,7 @@ impl AutoIndent { /// Creates a new instance by detecting the line ending from the input. fn new(input: &str) -> Self { Self { - line_ending: LineEnding::detect(input), + line_ending: LineEnding::from(input), } } @@ -25,10 +24,7 @@ impl AutoIndent { // Normalize to `\n` for consistent processing let input = LineEnding::normalize(input); - let mut lines: Vec<&str> = input.lines().collect(); - - // Track whether the original input ended with a newline - let ends_with_newline = input.ends_with('\n'); + let mut lines: Vec = LineEnding::split_into_lines(input.as_str()); // Remove the first line if it's empty let first_line = if lines.first().map(|s| s.trim()).unwrap_or("").is_empty() { @@ -67,12 +63,7 @@ impl AutoIndent { } // Preserve the original trailing newline behavior - let mut output = self.line_ending.restore_from_lines(result); - if ends_with_newline { - output.push_str(self.line_ending.as_str()); - } - - output + self.line_ending.apply_to_lines(result) } } @@ -94,20 +85,20 @@ mod tests { 3 "#; - let line_ending = LineEnding::detect(input); + let line_ending = LineEnding::from(input); // With auto-indent assert_eq!( auto_indent(input), // string_replace_all("Basic Test\n1\n 2\n 3\n", "\n", e.as_str()) - line_ending.restore("Basic Test\n1\n 2\n 3\n") + line_ending.denormalize("Basic Test\n1\n 2\n 3\n") ); // Without auto-indent assert_eq!( input, line_ending - .restore("Basic Test\n 1\n 2\n 3\n ") + .denormalize("Basic Test\n 1\n 2\n 3\n ") ); } @@ -119,18 +110,18 @@ mod tests { 3 "#; - let line_ending = LineEnding::detect(input); + let line_ending = LineEnding::from(input); // With auto-indent assert_eq!( auto_indent(input), - line_ending.restore("1\n 2\n 3\n") + line_ending.denormalize("1\n 2\n 3\n") ); // Without auto-indent assert_eq!( input, - line_ending.restore("\n 1\n 2\n 3\n "), + line_ending.denormalize("\n 1\n 2\n 3\n "), ); } @@ -140,18 +131,18 @@ mod tests { Second Line "#; - let line_ending = LineEnding::detect(input); + let line_ending = LineEnding::from(input); // With auto-indent assert_eq!( auto_indent(input), - line_ending.restore(" <- First Line\nSecond Line\n") + line_ending.denormalize(" <- First Line\nSecond Line\n") ); // Without auto-indent assert_eq!( input, - line_ending.restore(" <- First Line\n Second Line\n "), + line_ending.denormalize(" <- First Line\n Second Line\n "), ); } @@ -162,18 +153,18 @@ mod tests { Third Line "#; - let line_ending = LineEnding::detect(input); + let line_ending = LineEnding::from(input); // With auto-indent assert_eq!( auto_indent(input), - line_ending.restore("First Line\n Second Line\nThird Line\n",) + line_ending.denormalize("First Line\n Second Line\nThird Line\n",) ); // Without auto-indent assert_eq!( input, - line_ending.restore("First Line\n Second Line\nThird Line\n "), + line_ending.denormalize("First Line\n Second Line\nThird Line\n "), ); } @@ -181,16 +172,16 @@ Third Line fn test_single_line_no_change() { let input = "Single line no change"; - let line_ending = LineEnding::detect(input); + let line_ending = LineEnding::from(input); // With auto-indent assert_eq!( auto_indent(input), - line_ending.restore("Single line no change") + line_ending.denormalize("Single line no change") ); // Without auto-indent - assert_eq!(input, line_ending.restore("Single line no change")); + assert_eq!(input, line_ending.denormalize("Single line no change")); } #[test] @@ -208,18 +199,18 @@ Third Line E "#; - let line_ending = LineEnding::detect(input); + let line_ending = LineEnding::from(input); // With auto-indent assert_eq!( auto_indent(input), - line_ending.restore("First Line\n\n A\n\n B\n\n C\n\n D\n\nE\n") + line_ending.denormalize("First Line\n\n A\n\n B\n\n C\n\n D\n\nE\n") ); // Without auto-indent assert_eq!( input, - line_ending.restore( + line_ending.denormalize( "First Line\n \n A\n\n B\n\n C\n\n D\n\n E\n " ), ); diff --git a/src/line_ending.rs b/src/line_ending.rs deleted file mode 100644 index 1c6ada8..0000000 --- a/src/line_ending.rs +++ /dev/null @@ -1,46 +0,0 @@ -/// Enum representing the detected line ending style. -#[derive(Debug, Clone, Copy, PartialEq, Eq)] -#[allow(clippy::upper_case_acronyms)] -pub enum LineEnding { - LF, // "\n" (Unix, Linux, macOS) - CRLF, // "\r\n" (Windows) - CR, // "\r" (old macOS) -} - -impl LineEnding { - /// Detects the line ending style used in the input string. - pub fn detect(s: &str) -> Self { - if s.contains("\r\n") { - Self::CRLF - } else if s.contains("\r") { - Self::CR - } else { - Self::LF - } - } - - /// Returns the string representation of the line ending. - pub fn as_str(&self) -> &'static str { - match self { - Self::LF => "\n", - Self::CRLF => "\r\n", - Self::CR => "\r", - } - } - - /// Normalize to `\n` for consistent processing. - pub fn normalize(s: &str) -> String { - s.replace("\r\n", "\n").replace("\r", "\n") - } - - /// Restores line endings back to their original value. - #[allow(dead_code)] - pub fn restore(&self, s: &str) -> String { - s.replace("\n", self.as_str()) - } - - /// Applies the line endiing to the given lines. - pub fn restore_from_lines(&self, lines: Vec) -> String { - lines.join(self.as_str()) - } -} From e05a29e078895adaa48b5b3d302a3d08d75aa1df Mon Sep 17 00:00:00 2001 From: Jeremy Harris Date: Tue, 18 Feb 2025 14:00:12 -0600 Subject: [PATCH 02/21] Add additional test to validate format preservation --- src/lib.rs | 34 ++++++++++++++++++++++++++++++++++ 1 file changed, 34 insertions(+) diff --git a/src/lib.rs b/src/lib.rs index 9fd1b71..8dbe50c 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -77,6 +77,40 @@ mod tests { use super::*; use line_ending::LineEnding; + fn get_readme_contents() -> String { + use std::fs::File; + use std::io::Read; + + let readme_file = "README.md"; + + // Read file contents + let mut read_content = String::new(); + File::open(readme_file) + .expect(&format!("Failed to open {}", readme_file)) + .read_to_string(&mut read_content) + .expect(&format!("Failed to read {}", readme_file)); + + read_content + } + + #[test] + fn test_preserves_formatting() { + let readme_contents = get_readme_contents(); + + assert_eq!(auto_indent(&readme_contents), readme_contents); + + // Validate the content was actually read + let lines = LineEnding::split_into_lines(&readme_contents); + assert_eq!(lines.first().unwrap(), "# Multi-line String Auto Indent"); + + // Ensure the README has more than 5 lines + assert!( + lines.len() > 5, + "Expected README to have more than 5 lines, but got {}", + lines.len() + ); + } + #[test] fn test_basic_implementation() { let input = r#"Basic Test From 361b71def064116073d8e422ca8c395e48f412f1 Mon Sep 17 00:00:00 2001 From: Jeremy Harris Date: Tue, 18 Feb 2025 14:05:18 -0600 Subject: [PATCH 03/21] Apply Clippy fixes --- examples/basic.rs | 4 ++-- src/lib.rs | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/examples/basic.rs b/examples/basic.rs index c1df09b..6925779 100644 --- a/examples/basic.rs +++ b/examples/basic.rs @@ -1,7 +1,7 @@ use string_auto_indent::auto_indent; fn main() { - println!(""); + println!(); let text = r#"Example: A B @@ -15,5 +15,5 @@ fn main() { println!("Without auto-indent:"); print!("{}", text); - println!(""); + println!(); } diff --git a/src/lib.rs b/src/lib.rs index 8dbe50c..ac0e7ab 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -86,9 +86,9 @@ mod tests { // Read file contents let mut read_content = String::new(); File::open(readme_file) - .expect(&format!("Failed to open {}", readme_file)) + .unwrap_or_else(|_| panic!("Failed to open {}", readme_file)) .read_to_string(&mut read_content) - .expect(&format!("Failed to read {}", readme_file)); + .unwrap_or_else(|_| panic!("Failed to read {}", readme_file)); read_content } From 648aa97adb741a12835da832e03d39cbb89393db Mon Sep 17 00:00:00 2001 From: Jeremy Harris Date: Tue, 18 Feb 2025 14:06:16 -0600 Subject: [PATCH 04/21] Add lint workflow --- .github/workflows/rust-lint.yml | 13 +++++++++++++ 1 file changed, 13 insertions(+) create mode 100644 .github/workflows/rust-lint.yml diff --git a/.github/workflows/rust-lint.yml b/.github/workflows/rust-lint.yml new file mode 100644 index 0000000..d792db9 --- /dev/null +++ b/.github/workflows/rust-lint.yml @@ -0,0 +1,13 @@ +name: Rust Lint +on: [push, pull_request] + +jobs: + lint: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v3 + - uses: dtolnay/rust-toolchain@stable + - run: cargo fmt --all -- --check + - run: cargo clippy --all-targets --all-features -- -D warnings + - run: cargo deny check + - run: cargo audit From 03848f800f521111bc0071866dada01c3b274080 Mon Sep 17 00:00:00 2001 From: Jeremy Harris Date: Tue, 18 Feb 2025 14:13:00 -0600 Subject: [PATCH 05/21] Patch workflow error --- .github/workflows/rust-lint.yml | 3 +++ 1 file changed, 3 insertions(+) diff --git a/.github/workflows/rust-lint.yml b/.github/workflows/rust-lint.yml index d792db9..793d9d1 100644 --- a/.github/workflows/rust-lint.yml +++ b/.github/workflows/rust-lint.yml @@ -9,5 +9,8 @@ jobs: - uses: dtolnay/rust-toolchain@stable - run: cargo fmt --all -- --check - run: cargo clippy --all-targets --all-features -- -D warnings + - name: Install cargo-deny + run: cargo install cargo-deny - run: cargo deny check + - run: cargo install cargo-audit - run: cargo audit From 1d2e67366094cde55d54e83295ef9b24d1921828 Mon Sep 17 00:00:00 2001 From: Jeremy Harris Date: Tue, 18 Feb 2025 14:23:51 -0600 Subject: [PATCH 06/21] Allow OSI-approved licenses --- .cargo/deny.toml | 2 ++ 1 file changed, 2 insertions(+) create mode 100644 .cargo/deny.toml diff --git a/.cargo/deny.toml b/.cargo/deny.toml new file mode 100644 index 0000000..5736f65 --- /dev/null +++ b/.cargo/deny.toml @@ -0,0 +1,2 @@ +[licenses] +allow = ["OSI-approved"] From e6cae1ff706e011a2a9782ce9a1974202706ae1d Mon Sep 17 00:00:00 2001 From: Jeremy Harris Date: Tue, 18 Feb 2025 14:31:49 -0600 Subject: [PATCH 07/21] Fix deny.toml --- .cargo/deny.toml | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/.cargo/deny.toml b/.cargo/deny.toml index 5736f65..04dad67 100644 --- a/.cargo/deny.toml +++ b/.cargo/deny.toml @@ -1,2 +1,4 @@ [licenses] -allow = ["OSI-approved"] +allow = [ + "MIT", +] From d425303949509a9274d129f879c187b03fd5b04c Mon Sep 17 00:00:00 2001 From: Jeremy Harris Date: Tue, 18 Feb 2025 14:47:36 -0600 Subject: [PATCH 08/21] Bump `line-ending` to v1.1.0 --- Cargo.lock | 4 ++-- Cargo.toml | 2 +- src/lib.rs | 6 +++--- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index f15e2a8..20147b7 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -10,9 +10,9 @@ checksum = "fea41bba32d969b513997752735605054bc0dfa92b4c56bf1189f2e174be7a10" [[package]] name = "line-ending" -version = "1.0.1" +version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "553d09af164e35635188a438ce8e81ed8adc7d3e436d2a17f0c7dbcf3fb1f82e" +checksum = "fa08c1e9c1ec43bffc12a0a0ec0fe7e263e975862450a4d91d15e90e421a4463" dependencies = [ "doc-comment", ] diff --git a/Cargo.toml b/Cargo.toml index 9222574..38d59bf 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -9,4 +9,4 @@ license = "MIT" [dependencies] doc-comment = "0.3.3" -line-ending = "1.0.1" +line-ending = "1.1.0" diff --git a/src/lib.rs b/src/lib.rs index ac0e7ab..81a4f43 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -24,7 +24,7 @@ impl AutoIndent { // Normalize to `\n` for consistent processing let input = LineEnding::normalize(input); - let mut lines: Vec = LineEnding::split_into_lines(input.as_str()); + let mut lines: Vec = LineEnding::split(input.as_str()); // Remove the first line if it's empty let first_line = if lines.first().map(|s| s.trim()).unwrap_or("").is_empty() { @@ -63,7 +63,7 @@ impl AutoIndent { } // Preserve the original trailing newline behavior - self.line_ending.apply_to_lines(result) + self.line_ending.join(result) } } @@ -100,7 +100,7 @@ mod tests { assert_eq!(auto_indent(&readme_contents), readme_contents); // Validate the content was actually read - let lines = LineEnding::split_into_lines(&readme_contents); + let lines = LineEnding::split(&readme_contents); assert_eq!(lines.first().unwrap(), "# Multi-line String Auto Indent"); // Ensure the README has more than 5 lines From e679e30c974fc5d726cdb02f7c01df7129fccb26 Mon Sep 17 00:00:00 2001 From: Jeremy Harris Date: Tue, 18 Feb 2025 17:19:46 -0600 Subject: [PATCH 09/21] Run doc checks --- .github/workflows/rust-lint.yml | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/.github/workflows/rust-lint.yml b/.github/workflows/rust-lint.yml index 793d9d1..4d83ebf 100644 --- a/.github/workflows/rust-lint.yml +++ b/.github/workflows/rust-lint.yml @@ -7,10 +7,21 @@ jobs: steps: - uses: actions/checkout@v3 - uses: dtolnay/rust-toolchain@stable + + # Check formatting - run: cargo fmt --all -- --check + + # Run Clippy with warnings treated as errors - run: cargo clippy --all-targets --all-features -- -D warnings + + # Fail on documentation warnings + - run: cargo doc --no-deps --document-private-items -D warnings + + # Install cargo-deny and check for security issues - name: Install cargo-deny run: cargo install cargo-deny - run: cargo deny check + + # Install and run cargo-audit for security vulnerabilities - run: cargo install cargo-audit - run: cargo audit From cc2d7414798b8b7488bee5777db26e83803ccbd3 Mon Sep 17 00:00:00 2001 From: Jeremy Harris Date: Tue, 18 Feb 2025 17:25:11 -0600 Subject: [PATCH 10/21] Debug fail on doc warnings --- .github/workflows/rust-lint.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/rust-lint.yml b/.github/workflows/rust-lint.yml index 4d83ebf..1d6f4a8 100644 --- a/.github/workflows/rust-lint.yml +++ b/.github/workflows/rust-lint.yml @@ -15,7 +15,7 @@ jobs: - run: cargo clippy --all-targets --all-features -- -D warnings # Fail on documentation warnings - - run: cargo doc --no-deps --document-private-items -D warnings + - run: RUSTDOCFLAGS="-Dwarnings" cargo doc --no-deps --document-private-items # Install cargo-deny and check for security issues - name: Install cargo-deny From f7b8f783e5417b81933e5257a9ec88b939f86687 Mon Sep 17 00:00:00 2001 From: Jeremy Harris Date: Tue, 18 Feb 2025 18:35:49 -0600 Subject: [PATCH 11/21] Bump `line-ending` to v1.2.0 --- Cargo.lock | 4 ++-- Cargo.toml | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 20147b7..321a2fa 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -10,9 +10,9 @@ checksum = "fea41bba32d969b513997752735605054bc0dfa92b4c56bf1189f2e174be7a10" [[package]] name = "line-ending" -version = "1.1.0" +version = "1.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fa08c1e9c1ec43bffc12a0a0ec0fe7e263e975862450a4d91d15e90e421a4463" +checksum = "510949e2bbe320b6e4db39883314e170fde67ecda62d8844bea64e3cb1be11d8" dependencies = [ "doc-comment", ] diff --git a/Cargo.toml b/Cargo.toml index 38d59bf..22870c0 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -9,4 +9,4 @@ license = "MIT" [dependencies] doc-comment = "0.3.3" -line-ending = "1.1.0" +line-ending = "1.2.0" From ade165287dd7c911fe10b822327ff95490fde1b9 Mon Sep 17 00:00:00 2001 From: Jeremy Harris Date: Tue, 18 Feb 2025 18:41:50 -0600 Subject: [PATCH 12/21] Remove duplicate normalization --- src/lib.rs | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/lib.rs b/src/lib.rs index 81a4f43..28a0c0a 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -23,8 +23,7 @@ impl AutoIndent { } // Normalize to `\n` for consistent processing - let input = LineEnding::normalize(input); - let mut lines: Vec = LineEnding::split(input.as_str()); + let mut lines: Vec = LineEnding::split(input); // Remove the first line if it's empty let first_line = if lines.first().map(|s| s.trim()).unwrap_or("").is_empty() { From 9f11bfac6fe6369c8bb0b560017f7d192d3058c5 Mon Sep 17 00:00:00 2001 From: Jeremy Harris Date: Tue, 18 Feb 2025 18:42:15 -0600 Subject: [PATCH 13/21] Remove comments --- src/lib.rs | 1 - 1 file changed, 1 deletion(-) diff --git a/src/lib.rs b/src/lib.rs index 28a0c0a..80a1b60 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -22,7 +22,6 @@ impl AutoIndent { return String::new(); } - // Normalize to `\n` for consistent processing let mut lines: Vec = LineEnding::split(input); // Remove the first line if it's empty From b01769725ea3155268f4384d9697d8a75791c95f Mon Sep 17 00:00:00 2001 From: Jeremy Harris Date: Tue, 18 Feb 2025 19:22:37 -0600 Subject: [PATCH 14/21] Bump to v0.1.0 --- Cargo.lock | 2 +- Cargo.toml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 321a2fa..46072bb 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -19,7 +19,7 @@ dependencies = [ [[package]] name = "string-auto-indent" -version = "0.1.0-alpha2" +version = "0.1.0" dependencies = [ "doc-comment", "line-ending", diff --git a/Cargo.toml b/Cargo.toml index 22870c0..362fa90 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "string-auto-indent" -version = "0.1.0-alpha2" +version = "0.1.0" authors = ["Jeremy Harris "] edition = "2021" description = "Normalizes multi-line string indentation while preserving platform-specific line endings." From 0854ac1fe0810f077e61f32db2c377dbccd2c132 Mon Sep 17 00:00:00 2001 From: Jeremy Harris Date: Tue, 18 Feb 2025 19:35:34 -0600 Subject: [PATCH 15/21] Don't remove first line --- src/lib.rs | 11 +++-------- 1 file changed, 3 insertions(+), 8 deletions(-) diff --git a/src/lib.rs b/src/lib.rs index 80a1b60..1393333 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -24,13 +24,8 @@ impl AutoIndent { let mut lines: Vec = LineEnding::split(input); - // Remove the first line if it's empty - let first_line = if lines.first().map(|s| s.trim()).unwrap_or("").is_empty() { - lines.remove(0); - None - } else { - Some(lines.remove(0)) // Take first line exactly as is - }; + // Take first line exactly as is + let first_line = Some(lines.remove(0)); // Find the minimum indentation for all remaining lines let min_indent = lines @@ -147,7 +142,7 @@ mod tests { // With auto-indent assert_eq!( auto_indent(input), - line_ending.denormalize("1\n 2\n 3\n") + line_ending.denormalize("\n1\n 2\n 3\n") ); // Without auto-indent From 87a92a75c70e8bdd4def37fa5025e4e7b4597b68 Mon Sep 17 00:00:00 2001 From: Jeremy Harris Date: Tue, 18 Feb 2025 19:35:44 -0600 Subject: [PATCH 16/21] Simplify example --- README.md | 25 +++++++++++-------------- 1 file changed, 11 insertions(+), 14 deletions(-) diff --git a/README.md b/README.md index c237cf5..a9b0436 100644 --- a/README.md +++ b/README.md @@ -38,29 +38,26 @@ let text = r#" Level 1 Level 2 Level 3 -"#; + "#; + +let expected = r#" +String Auto Indent -// For cross-platform testing -let line_ending = LineEnding::from(text); +Level 1 + Level 2 + Level 3 +"#; // With auto-indent assert_eq!( auto_indent(text), - // For cross-platform testing: Restore platform-specific line endings - line_ending.denormalize("String Auto Indent\n\nLevel 1\n Level 2\n Level 3\n") -); - -// Without auto-indent -assert_eq!( - text, - // For cross-platform testing: Restore platform-specific line endings - line_ending.denormalize("\n String Auto Indent\n\n Level 1\n Level 2\n Level 3\n"), + expected, ); ``` ### Example Output -**With `auto-indent` enabled.** +#### With `auto-indent` ```text String Auto Indent @@ -70,7 +67,7 @@ Level 1 Level 3 ``` -**With `auto-intent` disabled.** +#### Without `auto-intent` ```text String Auto Indent From 1f48710b8e8aef399dfdb29859b81846f9605a5f Mon Sep 17 00:00:00 2001 From: Jeremy Harris Date: Tue, 18 Feb 2025 19:38:23 -0600 Subject: [PATCH 17/21] Add additional doc test --- README.md | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index a9b0436..e3ddd5a 100644 --- a/README.md +++ b/README.md @@ -48,11 +48,16 @@ Level 1 Level 3 "#; -// With auto-indent assert_eq!( auto_indent(text), expected, ); + +// Assert the strings are not the same +assert_ne!( + text, + expected +) ``` ### Example Output From 8b0505183af86e91ac6c54e3bfc9f860cfbc6c4c Mon Sep 17 00:00:00 2001 From: Jeremy Harris Date: Tue, 18 Feb 2025 19:49:03 -0600 Subject: [PATCH 18/21] Add additional example --- README.md | 63 ++++++++++++++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 60 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index e3ddd5a..7c63150 100644 --- a/README.md +++ b/README.md @@ -29,6 +29,10 @@ cargo add string-auto-indent ## Usage +## Example 1: Basic Indentation + +This example removes unnecessary leading spaces while preserving the relative indentation of nested lines. + ```rust use string_auto_indent::{auto_indent, LineEnding}; @@ -40,6 +44,7 @@ let text = r#" Level 3 "#; +// Expected output after applying auto indentation let expected = r#" String Auto Indent @@ -48,16 +53,20 @@ Level 1 Level 3 "#; +// Verify that `auto_indent` correctly normalizes indentation assert_eq!( auto_indent(text), expected, + "The auto_indent function should normalize leading whitespace." ); -// Assert the strings are not the same +// Ensure the original text is not identical to the expected output +// This confirms that `auto_indent` actually modifies the string. assert_ne!( text, - expected -) + expected, + "The original text should *not* be identical to the expected output before normalization." +); ``` ### Example Output @@ -82,6 +91,54 @@ Level 1 Level 3 ``` +## Example 2: Mixed Indentation + +This example demonstrates how `auto_indent` normalizes inconsistent indentation while preserving the relative structure of nested content. + +```rust +use string_auto_indent::{auto_indent, LineEnding}; + +let text = r#" + String Auto Indent + + 1. Point 1 + a. Sub point a + b. Sub point b + 2. Point 2 + a. Sub point a + b. Sub piont b + 1b. Sub piont 1b + "#; + +// Expected output after applying auto indentation +let expected = r#" +String Auto Indent + + 1. Point 1 + a. Sub point a + b. Sub point b + 2. Point 2 + a. Sub point a + b. Sub piont b + 1b. Sub piont 1b +"#; + +// Verify that `auto_indent` correctly normalizes indentation +assert_eq!( + auto_indent(text), + expected, + "The auto_indent function should normalize leading whitespace." +); + +// Ensure the original text is not identical to the expected output +// This confirms that `auto_indent` actually modifies the string. +assert_ne!( + text, + expected, + "The original text should *not* be identical to the expected output before normalization." +); +``` + ## How It Works 1. Detects the platform’s line endings (`\n`, `\r\n`, `\r`) and normalizes input for processing. From ed06eb40430f5510c8f56dd10e9476f407d6711a Mon Sep 17 00:00:00 2001 From: Jeremy Harris Date: Tue, 18 Feb 2025 19:50:11 -0600 Subject: [PATCH 19/21] Add hypen in main heading --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 7c63150..b8fdfab 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,4 @@ -# Multi-line String Auto Indent +# Multi-line String Auto-Indent [![made-with-rust][rust-logo]][rust-src-page] [![crates.io][crates-badge]][crates-page] From ba7d0fb3087ab5f9001240e2a52207e495eb8808 Mon Sep 17 00:00:00 2001 From: Jeremy Harris Date: Tue, 18 Feb 2025 19:53:35 -0600 Subject: [PATCH 20/21] Update 'When to Use" --- README.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/README.md b/README.md index b8fdfab..9d536e0 100644 --- a/README.md +++ b/README.md @@ -152,6 +152,8 @@ assert_ne!( - Formatting log messages or CLI output while ensuring alignment. - Cleaning up documentation strings or multi-line literals in indented Rust code. - Processing structured text while ensuring consistent indentation. +- Declaring multi-line variables in code where the indentation should match the codebase for readability, but the actual string content should not retain unnecessary leading spaces. +- Ensuring consistent formatting in generated strings for use in templates, serialization, or output rendering. ## License Licensed under **MIT**. See [`LICENSE`][license-page] for details. From b29b4891cfb45227a0fb1827b295603b4279a3f4 Mon Sep 17 00:00:00 2001 From: Jeremy Harris Date: Tue, 18 Feb 2025 19:54:18 -0600 Subject: [PATCH 21/21] Fix failing test --- src/lib.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/lib.rs b/src/lib.rs index 1393333..3817325 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -94,7 +94,7 @@ mod tests { // Validate the content was actually read let lines = LineEnding::split(&readme_contents); - assert_eq!(lines.first().unwrap(), "# Multi-line String Auto Indent"); + assert_eq!(lines.first().unwrap(), "# Multi-line String Auto-Indent"); // Ensure the README has more than 5 lines assert!(