From ed61a47a941e728af8287dd15f044bcd935f3598 Mon Sep 17 00:00:00 2001 From: Vlad Zagvozdkin Date: Sun, 21 Dec 2025 22:01:41 +0500 Subject: [PATCH 1/2] fix: Last line swallowing - fix last line swallow when it doesn't end with newline - fix last char being newline swallow --- .pre-commit-config.yaml | 5 +++-- README.md | 2 +- src/lib.rs | 7 ++++++- src/main.rs | 16 ++++------------ src/parser.rs | 19 ++++++++++--------- 5 files changed, 24 insertions(+), 25 deletions(-) diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 6cf508a..828b3cc 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -12,7 +12,8 @@ repos: - id: mdsh name: mdsh description: README.md shell pre-processor. - entry: cargo run -- --inputs + entry: cargo run -- --inputs README.md language: system - files: README.md + files: ^README.md$ always_run: true + pass_filenames: false diff --git a/README.md b/README.md index 8f2ed8b..e2a3340 100644 --- a/README.md +++ b/README.md @@ -268,4 +268,4 @@ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - \ No newline at end of file + diff --git a/src/lib.rs b/src/lib.rs index 5df275a..5d6d6b6 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -2,6 +2,8 @@ pub mod cli; pub mod executor; mod nom_ext; pub mod parser; +#[cfg(test)] +mod tests; use std::io::Write; @@ -26,12 +28,15 @@ pub trait Processor<'a> { .context("processing markdown piece")?; } - let (_input, _) = iter + let (remaining_input, _) = iter .finish() .finish() .map_err(fmt_nom_error(input, &format!("{input_pipe:?}"))) .context("parsing markdown")?; + self.process_piece(MdPiece::RawLine(remaining_input)) + .context("processing remaining unparsed input")?; + Ok(()) } } diff --git a/src/main.rs b/src/main.rs index c14ccdb..9210c70 100644 --- a/src/main.rs +++ b/src/main.rs @@ -4,16 +4,6 @@ use std::{ }; use anyhow::Context; - -/// Trims trailing ASCII whitespace from a byte slice. -/// Stable alternative to the unstable `trim_ascii_end()` method. -fn trim_ascii_end(bytes: &[u8]) -> &[u8] { - let mut end = bytes.len(); - while end > 0 && bytes[end - 1].is_ascii_whitespace() { - end -= 1; - } - &bytes[..end] -} use clap::Parser; use mdsh::{ cli::{FileArg, Opt, Parent}, @@ -81,8 +71,10 @@ fn process_file( } let file_unmodified_check = !frozen || input_content.as_bytes() == buffer; - std::fs::write(outf, trim_ascii_end(&buffer)) - .with_context(|| format!("failed to write file {outf:?}"))?; + let mut out = + File::create(outf).with_context(|| format!("failed to write file {outf:?}"))?; + out.write(buffer.trim_ascii_end())?; + out.write(b"\n")?; file_unmodified_check .then_some(()) diff --git a/src/parser.rs b/src/parser.rs index 2213fcc..99f8c72 100644 --- a/src/parser.rs +++ b/src/parser.rs @@ -80,10 +80,7 @@ impl<'a> nom::Parser<&'a str> for FencedBlockParser { many0_count(not(tag(BEGIN_MDSH).or(tag(END_MDSH))).and(anychar)) .and(alt((peek(tag(END_MDSH)), recognize(Self)))), ), - cut(tag(END_MDSH) - .and(space0) - .and(recognize(newline).or(eof)) - .and(multispace0)), + cut(tag(END_MDSH).and(space0).and(eolf()).and(multispace0)), ), ) .map(|_| ()) @@ -104,7 +101,7 @@ fn link<'a>() -> impl Parser<'a, Action<'a>> { not(char('[')), cut((take_until("]"), tag("]("))), cut(filepath()), - cut((char(')'), newline)), + cut((char(')'), eolf())), ), ) .map(|(_, command, _, _, filepath, _)| Action { @@ -166,7 +163,7 @@ fn actionable_comment<'a>() -> impl Parser<'a, Action<'a>> { delimited( tag(""), - tag("-->").and(space0).and(newline), + tag("-->").and(space0).and(eolf()), ) .and_then( ( @@ -197,7 +194,7 @@ fn inline_code<'a>() -> impl Parser<'a, Action<'a>> { context( "inline code", recognize(take_while_m_n(1, 2, |x| x == '`').and(not(char('`')))) - .flat_map(|q1| terminated(take_until1(q1), tag(q1).and(newline))) + .flat_map(|q1| terminated(take_until1(q1), tag(q1).and(eolf()))) .and_then((command(), space0, rest)) .map(|(command, _, rest)| Action { command, @@ -221,7 +218,7 @@ fn actionable_code_block<'a>() -> impl Parser<'a, Action<'a>> { command(), space0, opt(take_until1("\n")), - newline, + eolf(), ) .map(|(_srclang, command, _, data_line, _)| (command, data_line)) } @@ -252,7 +249,7 @@ fn code_block<'a, X>( peek(tag(q)).map(|_| "\n"), // covers the edge case with empty code block recognize(many0_count(not(newline.and(tag(q))).and(anychar)).and(newline)), ))), - cut(tag(q).and(newline)), + cut(tag(q).and(eolf())), ) }), ) @@ -288,6 +285,10 @@ pub fn env_var_line<'a>() -> impl Parser<'a, Option<(&'a str, &'a str)>> { )) } +fn eolf<'a>() -> impl Parser<'a, &'a str> { + recognize(newline).or(eof) +} + pub fn fmt_nom_error<'a>( input: &'a str, src_name: &'a str, From cd7d2374b551fbe5bf02367398cf6d6b140fca38 Mon Sep 17 00:00:00 2001 From: Vlad Zagvozdkin Date: Sun, 21 Dec 2025 22:25:14 +0500 Subject: [PATCH 2/2] ci: update nixos --- ci.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ci.sh b/ci.sh index 4a15fcc..e7e3fcc 100755 --- a/ci.sh +++ b/ci.sh @@ -1,5 +1,5 @@ #!/usr/bin/env nix-shell -#!nix-shell -i bash -I nixpkgs=channel:nixos-22.05 +#!nix-shell -i bash -I nixpkgs=channel:nixos-25.11 # shellcheck shell=bash # # Travis CI specific build script