diff options
| author | A Farzat <a@farzat.xyz> | 2026-06-19 14:24:08 +0300 |
|---|---|---|
| committer | A Farzat <a@farzat.xyz> | 2026-06-19 14:28:16 +0300 |
| commit | bab2e079e37d75777ebf2849db69bdcf94c0a615 (patch) | |
| tree | 9f76541cffb781bcdc9921409931f3117dadb1f7 | |
| parent | 82b2555d858cc94c4c9b5655ee820d80540ea509 (diff) | |
| download | repo2markdown-bab2e079e37d75777ebf2849db69bdcf94c0a615.tar.gz repo2markdown-bab2e079e37d75777ebf2849db69bdcf94c0a615.zip | |
Add functions to edit stdin path list
These would be used to create binaries that manipulate the input before
piping it back into repo2markdown.
| -rw-r--r-- | src/lib.rs | 1 | ||||
| -rw-r--r-- | src/path_list_editor.rs | 210 |
2 files changed, 211 insertions, 0 deletions
@@ -3,5 +3,6 @@ pub mod fenced_md_generator; pub mod logger; pub mod md_generator; pub mod normalizer; +pub mod path_list_editor; pub mod renderer; mod util; diff --git a/src/path_list_editor.rs b/src/path_list_editor.rs new file mode 100644 index 0000000..e25b0db --- /dev/null +++ b/src/path_list_editor.rs @@ -0,0 +1,210 @@ +use std::{ + collections::HashSet, + ffi::{OsStr, OsString}, + io::{Read, Write}, + os::unix::ffi::OsStrExt, +}; + +pub fn append_paths<R: Read, W: Write>( + mut input: R, + mut output: W, + new_paths: &[OsString], +) -> std::io::Result<()> { + std::io::copy(&mut input, &mut output)?; + for path in new_paths { + output.write_all(path.as_bytes())?; + output.write_all(b"\0")?; + } + Ok(()) +} + +pub fn prepend_paths<R: Read, W: Write>( + mut input: R, + mut output: W, + new_paths: &[OsString], +) -> std::io::Result<()> { + for path in new_paths { + output.write_all(path.as_bytes())?; + output.write_all(b"\0")?; + } + std::io::copy(&mut input, &mut output)?; + Ok(()) +} + +pub fn remove_paths<R: Read, W: Write>( + mut input: R, + mut output: W, + unwanted_paths: &[OsString], +) -> std::io::Result<()> { + let mut buf = Vec::new(); + input.read_to_end(&mut buf)?; + let unwanted_paths = HashSet::<&OsString>::from_iter(unwanted_paths); + for segment in buf.split(|b| *b == 0) { + if segment.is_empty() { + continue; + } + let os_string_segment = OsStr::from_bytes(segment).to_os_string(); + if !unwanted_paths.contains(&os_string_segment) { + output.write_all(segment)?; + output.write_all(b"\0")?; + } + } + Ok(()) +} + +#[cfg(test)] +mod tests { + use std::ffi::OsString; + + use super::{append_paths, prepend_paths, remove_paths}; + + #[test] + fn append_paths_works_with_empty_stdin_and_args() { + let input = b""; + let mut output = Vec::new(); + + append_paths(&input[..], &mut output, &[]).unwrap(); + + assert_eq!(output, b""); + } + + #[test] + fn append_paths_works_with_empty_args() { + let input = b"README.md\0"; + let mut output = Vec::new(); + + append_paths(&input[..], &mut output, &[]).unwrap(); + + assert_eq!(output, b"README.md\0"); + } + + #[test] + fn append_paths_works_with_empty_stdin() { + let input = b""; + let mut output = Vec::new(); + + append_paths(&input[..], &mut output, &[OsString::from("README.md")]).unwrap(); + + assert_eq!(output, b"README.md\0"); + } + + #[test] + fn append_paths_works_with_unique_stdin_and_args() { + let input = b"a.rs\0b.rs\0"; + let mut output = Vec::new(); + + append_paths(&input[..], &mut output, &[OsString::from("c.rs")]).unwrap(); + + assert_eq!(output, b"a.rs\0b.rs\0c.rs\0"); + } + + #[test] + fn append_paths_keeps_duplicate_entries() { + let input = b"a.rs\0b.rs\0"; + let mut output = Vec::new(); + + append_paths(&input[..], &mut output, &[OsString::from("a.rs")]).unwrap(); + + assert_eq!(output, b"a.rs\0b.rs\0a.rs\0"); + } + + #[test] + fn prepend_paths_works_with_empty_stdin_and_args() { + let input = b""; + let mut output = Vec::new(); + + prepend_paths(&input[..], &mut output, &[]).unwrap(); + + assert_eq!(output, b""); + } + + #[test] + fn prepend_paths_works_with_empty_args() { + let input = b"README.md\0"; + let mut output = Vec::new(); + + prepend_paths(&input[..], &mut output, &[]).unwrap(); + + assert_eq!(output, b"README.md\0"); + } + + #[test] + fn prepend_paths_works_with_empty_stdin() { + let input = b""; + let mut output = Vec::new(); + + prepend_paths(&input[..], &mut output, &[OsString::from("README.md")]).unwrap(); + + assert_eq!(output, b"README.md\0"); + } + + #[test] + fn prepend_paths_works_with_unique_stdin_and_args() { + let input = b"a.rs\0b.rs\0"; + let mut output = Vec::new(); + + prepend_paths(&input[..], &mut output, &[OsString::from("c.rs")]).unwrap(); + + assert_eq!(output, b"c.rs\0a.rs\0b.rs\0"); + } + + #[test] + fn prepend_paths_keeps_duplicate_entries() { + let input = b"a.rs\0b.rs\0"; + let mut output = Vec::new(); + + prepend_paths(&input[..], &mut output, &[OsString::from("a.rs")]).unwrap(); + + assert_eq!(output, b"a.rs\0a.rs\0b.rs\0"); + } + + #[test] + fn remove_paths_works_with_empty_stdin_and_args() { + let input = b""; + let mut output = Vec::new(); + + remove_paths(&input[..], &mut output, &[]).unwrap(); + + assert_eq!(output, b""); + } + + #[test] + fn remove_paths_works_with_empty_args() { + let input = b"README.md\0"; + let mut output = Vec::new(); + + remove_paths(&input[..], &mut output, &[]).unwrap(); + + assert_eq!(output, b"README.md\0"); + } + + #[test] + fn remove_paths_works_with_empty_stdin() { + let input = b""; + let mut output = Vec::new(); + + remove_paths(&input[..], &mut output, &[OsString::from("README.md")]).unwrap(); + + assert_eq!(output, b""); + } + + #[test] + fn remove_paths_filters_matching_entries() { + let input = b"a.rs\0b.rs\0c.rs\0"; + let mut output = Vec::new(); + + remove_paths(&input[..], &mut output, &[OsString::from("b.rs")]).unwrap(); + + assert_eq!(output, b"a.rs\0c.rs\0"); + } + + #[test] + fn remove_paths_removes_all_matching_entries() { + let input = b"a.rs\0b.rs\0b.rs\0c.rs\0"; + let mut output = Vec::new(); + + remove_paths(&input[..], &mut output, &[OsString::from("b.rs")]).unwrap(); + + assert_eq!(output, b"a.rs\0c.rs\0"); + } +} |
