Skip to content
Merged
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
52 changes: 52 additions & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ anyhow = "1"
clap = { version = "4", features = ["derive"] }
regex = "1"
once_cell = "1"
rayon = "^1.0"
html5ever = "0.27"
markup5ever_rcdom = "0.3"
unicode-width = ">=0.1, <0.2"
Expand Down
10 changes: 5 additions & 5 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,6 @@ cargo install --path .

## Command-line usage


```bash
mdtablefix [--wrap] [--renumber] [--breaks] [--ellipsis] [--fences] [--footnotes] [--in-place] [FILE...]
```
Expand Down Expand Up @@ -111,8 +110,8 @@ A brief intermission for pizza.

## Library usage

The crate exposes helper functions for embedding the table-reflow logic in
Rust projects:
The crate exposes helper functions for embedding the table-reflow logic in Rust
projects:

```rust
use mdtablefix::{process_stream_opts, rewrite, Options};
Expand Down Expand Up @@ -159,8 +158,9 @@ For an overview of how the crate's internal modules relate to each other, see

## Testing

The test suite is structured using the `rstest` crate. See [Rust testing with
rstest fixtures](docs/rust-testing-with-rstest-fixtures.md) for details.
The test suite is structured using the `rstest` crate. See
[Rust testing with rstest fixtures](docs/rust-testing-with-rstest-fixtures.md)
for details.

## License

Expand Down
10 changes: 5 additions & 5 deletions docs/parallel-processing-roadmap.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,15 +4,15 @@ The command-line tool currently processes input files sequentially. The steps
below outline the work required to allow concurrent processing while preserving
serial output order.

- [ ] **Adopt `rayon` for concurrency**
- [x] **Adopt `rayon` for concurrency**
- Use `rayon` thread pools to spawn work for each file path.
- Ensure the approach integrates cleanly with existing modules.
- [ ] **Add chosen crate to `Cargo.toml`**
- [x] **Add chosen crate to `Cargo.toml`**
- Pin an explicit version and document the decision in `docs/`.
- [ ] **Refactor `main.rs` to launch parallel tasks**
- [x] **Refactor `main.rs` to launch parallel tasks**
- Spawn a worker for each file path using the concurrency crate.
- Maintain a list of handles so outputs can be gathered in order.
- [ ] **Collect results sequentially**
- Maintain a list of handles, so outputs can be gathered in order.
- [x] **Collect results sequentially**
- Await or join handles in the same order the files were supplied.
- Print each processed file or error message before moving to the next.
- [ ] **Extend tests for parallel execution**
Expand Down
7 changes: 7 additions & 0 deletions docs/rayon-concurrency.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
# Concurrency with `rayon`

`mdtablefix` uses the `rayon` crate to process multiple files concurrently.
`rayon` provides a work-stealing thread pool and simple parallel iterators. The
tool relies on Rayon’s global thread pool so that no manual setup is required.
The dependency is specified as `^1.0` in `Cargo.toml` to track stable API
changes within the same major release.
Comment thread
coderabbitai[bot] marked this conversation as resolved.
43 changes: 32 additions & 11 deletions src/main.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,9 @@
//! Command-line interface for the mdtablefix tool.
//!
//! This module provides the main entry point and CLI parsing for fixing
//! markdown table formatting. It supports concurrent processing of multiple
//! files using Rayon for improved performance.

use std::{
borrow::Cow,
fs,
Expand All @@ -7,6 +13,7 @@ use std::{

use clap::Parser;
use mdtablefix::{Options, format_breaks, process_stream_opts, renumber_lists};
use rayon::prelude::*;

#[derive(Parser)]
#[command(about = "Reflow broken markdown tables")]
Expand Down Expand Up @@ -67,11 +74,17 @@ fn process_lines(lines: &[String], opts: FormatOpts) -> Vec<String> {
out
}

fn rewrite_path(path: &Path, opts: FormatOpts) -> std::io::Result<()> {
fn handle_file(path: &Path, in_place: bool, opts: FormatOpts) -> anyhow::Result<Option<String>> {
let content = fs::read_to_string(path)?;
let lines: Vec<String> = content.lines().map(str::to_string).collect();
let fixed = process_lines(&lines, opts);
fs::write(path, fixed.join("\n") + "\n")
let fixed = process_lines(&lines, opts).join("\n");

if in_place {
fs::write(path, format!("{fixed}\n"))?;
Ok(None)
} else {
Ok(Some(fixed))
}
}
Comment thread
coderabbitai[bot] marked this conversation as resolved.

/// Entry point for the command-line tool that reflows broken markdown tables.
Expand Down Expand Up @@ -109,14 +122,22 @@ fn main() -> anyhow::Result<()> {
return Ok(());
}

for path in cli.files {
if cli.in_place {
rewrite_path(&path, cli.opts)?;
} else {
let content = fs::read_to_string(&path)?;
let lines: Vec<String> = content.lines().map(str::to_string).collect();
let fixed = process_lines(&lines, cli.opts);
println!("{}", fixed.join("\n"));
if cli.in_place {
cli.files
.par_iter()
.try_for_each(|p| handle_file(p, true, cli.opts).map(|_| ()))?;
} else {
let outputs: Vec<String> = cli
.files
.par_iter()
.map(|p| handle_file(p, false, cli.opts))
.collect::<anyhow::Result<Vec<_>>>()?
.into_iter()
.flatten()
.collect();

for out in outputs {
println!("{out}");
}
}

Expand Down