From dee2151f5929e4675b1630d084e0752da46e7037 Mon Sep 17 00:00:00 2001 From: Rohit Goswami Date: Sat, 26 Sep 2026 05:24:16 -0500 Subject: [PATCH 1/2] fix(latex): keep letter-delimited verb and url spans whole A space after \verb, \verb*, \Verb, or \spverb is not the delimiter. \url, \path, and \nolinkurl keep a non-brace delimiter as one span. Braced arguments stay on the generic command path, and a following sentence still splits. --- docs/orgmode/reference/formats.org | 3 +- src/parser/latex.rs | 111 +++++++++++++++++++------ src/sentence/unicode.rs | 125 +++++++++++++++++++++++++++-- 3 files changed, 207 insertions(+), 32 deletions(-) diff --git a/docs/orgmode/reference/formats.org b/docs/orgmode/reference/formats.org index 454d0adc..30531ed9 100644 --- a/docs/orgmode/reference/formats.org +++ b/docs/orgmode/reference/formats.org @@ -143,7 +143,8 @@ These tokens within prose are not split across lines: - Extra names from =[latex].verbatim_envs= are code regions too - Body follows the same comment-reflow and optional =--format-code= rules as other formats when language is known (=minted= / =minted*= language arg, =lstlisting= / =lstlisting*= =language== option) - Inline leftover =\verb= / =\verb*= / leftover =\lstinline= / leftover =\spverb= / leftover =\mintinline= / leftover =\mint= / leftover fancyvrb =\Verb= / =\Verb*= / leftover =\SaveVerb= / leftover =\UseVerb= / leftover =\UseVerbatim= / leftover =\LUseVerbatim= / leftover =\BUseVerbatim= / leftover =\DefineShortVerb= / =\UndefineShortVerb= / leftover fvextra =\EscVerb= / leftover fvextra =\VerbatimInsertBuffer= / =\VerbatimClearBuffer= / =\InsertBuffer= / =\IterateBuffer= / =\VerbatimInput= / =\BVerbatimInput= / =\LVerbatimInput= / piton.sty leftover =\piton= / =\PitonInputFile= / =\PitonInputFileT= / =\PitonInputFileF= / =\PitonInputFileTF= / listings.sty =\lstinputlisting= / minted.sty =\inputminted= / tools/verbatim.sty =\verbatiminput= / tcolorbox =\tcbinputlisting= / pythontex.sty =\inputpy= / =\inputpycon= / leftover inline =\py= / =\pyc= / =\pys= / =\pyb= / =\pyv= / =\pycon= and twins / =\sympy= / =\pylab= and twins / leftover usefamily =\ruby= / =\rb= / =\julia= / =\jl= / =\matlab= / =\octave= / =\bash= / =\sage= / =\rust= / =\rs= / =\R= / =\perl= / =\pl= / =\perlsix= / =\psix= / =\javascript= / =\js= and twins / =\inputpygments= / =\pygment= / leftover =\pythontexcustomc= / pythonhighlight.sty =\inputpython= / =\inputpythonfile= / leftover =\pyth= / catchfilebetweentags.sty =\CatchFileBetweenTags= / =\CatchFileBetweenDelims= / =\ExecuteMetaData= / catchfile.sty leftover =\CatchFileDef= / =\CatchFileEdef= / moreverb =\listinginput= / leftover =\verbatimtabinput= / =\verbatimtabinput*= / leftover =\verbatimwrite= / =\verbatimwrite*= / leftover =\listingcont= / sagetex =\sageinput= / leftover inline =\sageplot= / =\sagestr= / scontents leftover =\Scontents= / =\Scontents*= / =\typestored= / =\getstored= / =\mergesc= / =\meaningsc= / =\foreachsc= (and extra =[latex].verbatim_commands=) stay atomic; inner =.!?%= do not split or comment. - leftover =\verb= / =\verb*= / =\lstinline= / =\spverb= take a delimiter or, for =\lstinline=, optional =[...]= then a delimiter or ={...}=; a flush following sentence stays on its own line. + leftover =\verb= / =\verb*= / =\lstinline= / =\spverb= take a delimiter or, for =\lstinline=, optional =[...]= then a delimiter or ={...}=; spaces after the control word are not the delimiter, so =\verb x...x= closes on =x=; a flush following sentence stays on its own line. + url.sty =\url= / =\path= and hyperref =\nolinkurl= take a non-brace delimiter the same way (=\url|...|=); a braced argument stays on the generic command path; a flush following sentence stays on its own line. A width wrap keeps a space inside that delimiter on the same line leftover =\mintinline= / =\mint= take optional =[...]=, ={lang}=, then a delimiter or ={...}= body; a flush following sentence stays on its own line leftover =\SaveVerb= takes optional =[...]=, a ={name}=, then the same delimiter body as =\Verb=; a flush following sentence stays on its own line diff --git a/src/parser/latex.rs b/src/parser/latex.rs index fb8a9916..9e3b3e78 100644 --- a/src/parser/latex.rs +++ b/src/parser/latex.rs @@ -2,7 +2,7 @@ use regex::Regex; use std::sync::LazyLock; use crate::parser::{ - ByteSpan, FormatParser, Line, SpannedRegion, flush_prose_spanned, iter_lines, join_prose_gap, + flush_prose_spanned, iter_lines, join_prose_gap, ByteSpan, FormatParser, Line, SpannedRegion, }; use crate::sentence::unicode::{ catchfile_leftover_cs_name, fancyvrb_leftover_cs_name, fancyvrb_shortverb_leftover_cs_name, @@ -2754,7 +2754,7 @@ mod tests { #[test] fn multi_sentence_section_title_stays_one_line() { use crate::format::Format; - use crate::{FormatConfig, format_text}; + use crate::{format_text, FormatConfig}; let input = "\\begin{document}\n\\section{A long title. With two sentences.}\nBody text here. More body.\n\\end{document}\n"; let cfg = FormatConfig { @@ -2811,7 +2811,7 @@ mod tests { fn section_optional_short_title_stays_one_line() { use crate::format::Format; use crate::oracle; - use crate::{FormatConfig, format_text}; + use crate::{format_text, FormatConfig}; let input = "\\section[Short. Title.]{A long title. With two sentences.}\nBody. More body.\n"; @@ -2843,7 +2843,7 @@ mod tests { #[test] fn koma_addsec_addchap_addpart_optional_short_title_is_structure() { use crate::format::Format; - use crate::{FormatConfig, format_text}; + use crate::{format_text, FormatConfig}; let cfg = FormatConfig { format: Format::Latex, @@ -2887,7 +2887,7 @@ mod tests { #[test] fn fragment_without_begin_document_is_prose() { use crate::format::Format; - use crate::{FormatConfig, format_text}; + use crate::{format_text, FormatConfig}; let input = "This sentence is a test. This sentence is also a test.\n"; let cfg = FormatConfig { @@ -2905,7 +2905,7 @@ mod tests { #[test] fn no_preamble_pragma_formats_body() { use crate::format::Format; - use crate::{FormatConfig, format_text}; + use crate::{format_text, FormatConfig}; let input = "% snapper:no-preamble\nThis sentence is a test. This sentence is also a test.\n"; @@ -2928,7 +2928,7 @@ mod tests { #[test] fn documentclass_without_begin_stays_preamble() { use crate::format::Format; - use crate::{FormatConfig, format_text}; + use crate::{format_text, FormatConfig}; let input = "\\documentclass{article}\nThis sentence is a test. This sentence is also a test.\n"; @@ -3411,7 +3411,7 @@ Some text. #[test] fn trailing_percent_is_nospace_join() { use crate::format::Format; - use crate::{FormatConfig, format_text}; + use crate::{format_text, FormatConfig}; let input = "\\begin{document}\nfoo%\nbar. Next sentence.\n\\end{document}\n"; let cfg = FormatConfig { @@ -3435,7 +3435,7 @@ Some text. #[test] fn escaped_percent_is_not_a_comment() { use crate::format::Format; - use crate::{FormatConfig, format_text}; + use crate::{format_text, FormatConfig}; let input = "\\begin{document}\n50\\% of cases. More text.\n\\end{document}\n"; let cfg = FormatConfig { @@ -3454,7 +3454,7 @@ Some text. #[test] fn mid_line_percent_comment_is_structure() { use crate::format::Format; - use crate::{FormatConfig, format_text}; + use crate::{format_text, FormatConfig}; let input = "\\begin{document}\nSee Fig. 1. % TODO cite\nNext sentence.\n\\end{document}\n"; let cfg = FormatConfig { @@ -3552,6 +3552,65 @@ Some text. assert_eq!(format_text(&out, &latex_cfg()).unwrap(), out); } + #[test] + fn verb_letter_delimiter_round_trips() { + use crate::format_text; + + for cmd in [r"\verb", r"\verb*", r"\Verb", r"\spverb"] { + let input = format!( + "\\begin{{document}}\nSee {cmd} zCode. Next. Morez here. Done.\n\\end{{document}}\n" + ); + let out = format_text(&input, &latex_cfg()).unwrap(); + let span = format!("{cmd} zCode. Next. Morez"); + assert!( + out.contains(&span), + "{cmd} letter body must stay intact, got:\n{out}" + ); + assert!( + !out.contains("Next.\nMore"), + "{cmd} must not split after Next., got:\n{out}" + ); + assert!( + out.contains(&format!("See {span} here.\nDone.")), + "prose after {cmd} must still split, got:\n{out}" + ); + assert_eq!(format_text(&out, &latex_cfg()).unwrap(), out); + } + } + + #[test] + fn url_char_delimiter_round_trips() { + use crate::format_text; + + for (cmd, body) in [ + (r"\url", r"http://example.com/A. B"), + (r"\path", r"Foo. Bar"), + (r"\nolinkurl", r"http://example.com/A. B"), + ] { + let span = format!("{cmd}|{body}|"); + let input = format!("\\begin{{document}}\nSee {span} here. Done.\n\\end{{document}}\n"); + let out = format_text(&input, &latex_cfg()).unwrap(); + assert!( + out.contains(&span), + "{cmd} character body must stay intact, got:\n{out}" + ); + assert!( + out.contains(&format!("See {span} here.\nDone.")), + "prose after {cmd} must still split, got:\n{out}" + ); + let braced = format!(r"{cmd}{{{body}}}"); + let braced_in = + format!("\\begin{{document}}\nSee {braced} here. Done.\n\\end{{document}}\n"); + let braced_out = format_text(&braced_in, &latex_cfg()).unwrap(); + assert!( + braced_out.contains(&format!("See {braced} here.\nDone.")), + "braced {cmd} must stay one span and the next sentence must split, got:\n{braced_out}" + ); + assert_eq!(format_text(&out, &latex_cfg()).unwrap(), out); + assert_eq!(format_text(&braced_out, &latex_cfg()).unwrap(), braced_out); + } + } + #[test] fn fancyvrb_verb_with_inner_punct_round_trips() { use crate::format_text; @@ -4122,7 +4181,7 @@ Some text. /// form as Delim. #[test] fn pythontexcustomc_does_not_join_following_prose() { - use crate::{FormatConfig, format_text}; + use crate::{format_text, FormatConfig}; let cmd = r"\pythontexcustomc{python}{import numpy}"; let input = format!("Before. Next.\n{cmd}\nAfter. Next.\n"); @@ -4255,7 +4314,7 @@ Some text. /// no-brace form as Delim. #[test] fn pyth_does_not_join_following_prose() { - use crate::{FormatConfig, format_text}; + use crate::{format_text, FormatConfig}; let cmd = r"\pyth{print(1)}"; let input = format!("Before. Next.\n{cmd}\nAfter. Next.\n"); @@ -4397,7 +4456,7 @@ Some text. /// configured extra does not re-tokenize the no-brace form as Delim. #[test] fn scontents_leftover_cmds_do_not_join_following_prose() { - use crate::{FormatConfig, format_text}; + use crate::{format_text, FormatConfig}; for cmd in [ r"\Scontents*{foo bar}", @@ -4550,7 +4609,7 @@ Some text. /// re-tokenize the no-brace mintinline form as Delim. #[test] fn verb_span_leftover_cmds_do_not_join_following_prose() { - use crate::{FormatConfig, format_text}; + use crate::{format_text, FormatConfig}; for cmd in [ r"\lstinline|print(1)|", @@ -4705,7 +4764,7 @@ Some text. /// no-brace form as Delim. #[test] fn fancyvrb_leftover_cmds_do_not_join_following_prose() { - use crate::{FormatConfig, format_text}; + use crate::{format_text, FormatConfig}; for cmd in [ r"\UseVerb{foo}", @@ -5021,7 +5080,7 @@ Some text. /// the no-brace form as Delim. #[test] fn catchfile_leftover_cmds_do_not_join_following_prose() { - use crate::{FormatConfig, format_text}; + use crate::{format_text, FormatConfig}; for cmd in [ r"\CatchFileDef{\foo}{foo.py}{}", @@ -5130,7 +5189,7 @@ Some text. /// a configured extra does not re-tokenize the no-brace form as Delim. #[test] fn inputpython_does_not_join_following_prose() { - use crate::{FormatConfig, format_text}; + use crate::{format_text, FormatConfig}; let input = concat!( "Before. Next.\n", @@ -5254,7 +5313,7 @@ Some text. /// not re-tokenize the no-brace form as Delim. #[test] fn sagetex_inline_cmds_do_not_join_following_prose() { - use crate::{FormatConfig, format_text}; + use crate::{format_text, FormatConfig}; for (cmd, name) in [ (r"\sageplot{plot(sin(x))}", "sageplot"), @@ -5403,7 +5462,7 @@ Some text. /// `\inputpygments` / `\pygment` unchanged. #[test] fn pytx_inline_cmds_do_not_join_following_prose() { - use crate::{FormatConfig, format_text}; + use crate::{format_text, FormatConfig}; for name in [ "py", "pyc", "pys", "pyb", "pyv", "pycon", "pyconc", "pycons", "pyconv", "sympy", @@ -5536,7 +5595,7 @@ Some text. /// mint envs, not these inlines. #[test] fn pytx_usefamily_inline_cmds_do_not_join_following_prose() { - use crate::{FormatConfig, format_text}; + use crate::{format_text, FormatConfig}; const FAMILIES: &[&str] = &[ "ruby", @@ -9198,7 +9257,7 @@ Some text. fn enumerate_item_hangs_next_sentence() { use crate::format::Format; use crate::oracle; - use crate::{FormatConfig, format_text}; + use crate::{format_text, FormatConfig}; let cfg = FormatConfig { format: Format::Latex, @@ -11424,7 +11483,7 @@ Some text. /// does not re-tokenize the no-brace form as Delim. #[test] fn verbatimtabinput_does_not_join_following_prose() { - use crate::{FormatConfig, format_text}; + use crate::{format_text, FormatConfig}; for cmd in [ r"\verbatimtabinput{foo.py}", @@ -11541,7 +11600,7 @@ Some text. /// configured extra does not re-tokenize the no-brace form as Delim. #[test] fn verbatimwrite_does_not_join_following_prose() { - use crate::{FormatConfig, format_text}; + use crate::{format_text, FormatConfig}; for cmd in [r"\verbatimwrite{foo.py}", r"\verbatimwrite*{foo.py}"] { let input = format!("Before. Next.\n{cmd}\nAfter. Next.\n"); @@ -11651,7 +11710,7 @@ Some text. /// no-brace form as Delim. #[test] fn listingcont_does_not_join_following_prose() { - use crate::{FormatConfig, format_text}; + use crate::{format_text, FormatConfig}; let cmd = r"\listingcont"; let input = format!("Before. Next.\n{cmd}\nAfter. Next.\n"); @@ -11743,7 +11802,7 @@ Some text. /// form as Delim. #[test] fn defineshortverb_does_not_join_following_prose() { - use crate::{FormatConfig, format_text}; + use crate::{format_text, FormatConfig}; for cmd in [r"\DefineShortVerb{\|}", r"\UndefineShortVerb{\|}"] { let input = format!("Before. Next.\n{cmd}\nAfter. Next.\n"); @@ -11849,7 +11908,7 @@ Some text. /// form as Delim. #[test] fn fvextra_buffer_leftover_cmds_do_not_join_following_prose() { - use crate::{FormatConfig, format_text}; + use crate::{format_text, FormatConfig}; for cmd in [ r"\VerbatimInsertBuffer[foo]", diff --git a/src/sentence/unicode.rs b/src/sentence/unicode.rs index 35823ceb..ff35c168 100644 --- a/src/sentence/unicode.rs +++ b/src/sentence/unicode.rs @@ -313,9 +313,13 @@ fn protect_latex_verbatim( /// `\InsertBuffer` / `\IterateBuffer` / extra-name span /// starting at `at`. /// -/// `\verb` / `\verb*` / `\spverb` / `\spverb*` / `\Verb` / `\Verb*`: next -/// character is the -/// delimiter; content runs to the same character. Leftover walker +/// `\verb` / `\verb*` / `\spverb` / `\spverb*` / `\Verb` / `\Verb*`: the +/// delimiter is the next character after spaces TeX drops following the +/// control word (and after `*` for the star form). A letter there is +/// the delimiter (`\verb x...x`), not the space. Content runs to the +/// same character. url.sty `\url` / `\path` and hyperref `\nolinkurl` +/// use that non-brace delimiter; a `{` stays on the generic `\cmd{arg}` +/// path. Leftover walker /// (GitHub #452) classifies `\verb` / `\verb*` / `\lstinline` / /// `\mintinline` / `\mint` / `\SaveVerb` / `\spverb` / `\piton` as /// Structure so following flush prose does not join. `\lstinline` / @@ -765,6 +769,12 @@ pub(crate) fn latex_verb_span_end_with( return None; } (after_bs + "SaveVerb".len(), VerbKind::SaveVerb) + } else if let Some(name) = url_delim_cs_name(tail) { + // url.sty `\url` / `\path` and hyperref `\nolinkurl`. Longer + // name first is unnecessary (`url` is not a prefix of + // `nolinkurl`). Alphabetic leftover rejects a longer name. + // A `{` body stays on the generic `\cmd{arg}` path. + (after_bs + name.len(), VerbKind::UrlDelim) } else if let Some(stripped) = tail.strip_prefix("verb") { if stripped.starts_with(|c: char| c.is_ascii_alphabetic()) { return None; @@ -775,7 +785,14 @@ pub(crate) fn latex_verb_span_end_with( (after_bs + name.len(), VerbKind::Delim) }; - if text.get(i..)?.starts_with('*') { + // `\url` / `\path` / `\nolinkurl` have no star form. A following + // `*` is not this span, so the generic command path can still see + // `\url*{...}`. + if kind == VerbKind::UrlDelim { + if text.get(i..).is_some_and(|s| s.starts_with('*')) { + return None; + } + } else if text.get(i..)?.starts_with('*') { i += 1; } @@ -1095,10 +1112,22 @@ pub(crate) fn latex_verb_span_end_with( } } + // TeX drops spaces after a control word, and the undelimited + // delimiter argument drops spaces too. The character after that + // space is the delimiter. + if matches!(kind, VerbKind::Delim | VerbKind::UrlDelim) { + i = skip_ascii_ws(text, i); + } + let delim = text.get(i..).and_then(|s| s.chars().next())?; if delim == '\n' { return None; } + // Braced `\url{...}` / `\path{...}` / `\nolinkurl{...}` stay on the + // generic `\cmd{arg}` path. Do not retokenize them here. + if kind == VerbKind::UrlDelim && delim == '{' { + return None; + } // pythontex `\py After.` is leftover prose, not `A` as a delimiter. // Same for `\pythontexcustomc{python} After.` after the type brace // and for `\pyth After.`. @@ -1145,8 +1174,12 @@ pub(crate) fn latex_verb_span_end_with( /// Built-in verb-like command shape (GitHub #245 minted `{lang}` body). #[derive(Clone, Copy, PartialEq, Eq)] enum VerbKind { - /// `\verb` / `\spverb` / extras: next character is the delimiter. + /// `\verb` / `\spverb` / `\Verb` / extras: next character after + /// dropped spaces is the delimiter. Delim, + /// url.sty `\url` / `\path` and hyperref `\nolinkurl`: non-brace + /// delimiter. `{` is not this span. + UrlDelim, /// `\lstinline`: optional `[...]` then delimiter or `{...}`. Lstinline, /// `\lstinputlisting` / fancyvrb `\VerbatimInput` family / @@ -1358,6 +1391,22 @@ pub(crate) fn fancyvrb_shortverb_leftover_cs_name(tail: &str) -> Option<&'static None } +/// url.sty `\url` / `\path` and hyperref `\nolinkurl`. Alphabetic +/// leftover rejects a longer name (`\urlfoo`, `\pathological`). No +/// `*` form. A `{` body is not this span. +fn url_delim_cs_name(tail: &str) -> Option<&'static str> { + for name in ["nolinkurl", "path", "url"] { + let Some(after) = tail.strip_prefix(name) else { + continue; + }; + if after.starts_with(|c: char| c.is_ascii_alphabetic()) { + return None; + } + return Some(name); + } + None +} + /// Leftover inline verb-span cmds (GitHub #452). Longer names first so /// `\mintinline` is not `\mint` + leftover. `\verbatiminput` / /// `\lstinputlisting` / `\inputminted` stay their own leftovers @@ -3905,6 +3954,72 @@ mod tests { ); } + #[test] + fn latex_verb_letter_delimiter_stays_atomic() { + for cmd in [r"\verb", r"\verb*", r"\Verb", r"\spverb"] { + // `z` is the delimiter. `Next` contains `x`, so an `x` + // delimiter closes inside that word. + let text = format!("See {cmd} zCode. Next. Morez here. Done."); + let span = format!("{cmd} zCode. Next. Morez"); + assert_eq!( + latex_verb_span_end_with(&span, 0, &[]), + Some(span.len()), + "{cmd} letter delimiter must close on the letter" + ); + assert_eq!( + split(&text), + vec![format!("See {span} here."), "Done.".to_string()], + "{cmd} letter body must stay one span and the next sentence must split" + ); + } + let symbol = r"See \verb|Code. Next| here. Done."; + assert_eq!( + split(symbol), + vec![ + r"See \verb|Code. Next| here.".to_string(), + "Done.".to_string() + ] + ); + } + + #[test] + fn latex_url_char_delimiter_stays_atomic() { + for (cmd, body) in [ + (r"\url", r"http://example.com/A. B"), + (r"\path", r"Foo. Bar"), + (r"\nolinkurl", r"http://example.com/A. B"), + ] { + let span = format!("{cmd}|{body}|"); + let text = format!("See {span} here. Done."); + assert_eq!( + latex_verb_span_end_with(&span, 0, &[]), + Some(span.len()), + "{cmd} character delimiter must close on the delimiter" + ); + assert_eq!( + split(&text), + vec![format!("See {span} here."), "Done.".to_string()], + "{cmd} character body must stay one span and the next sentence must split" + ); + let braced = format!(r"See {cmd}{{{body}}} here. Done."); + assert_eq!( + latex_verb_span_end_with(&format!(r"{cmd}{{{body}}}"), 0, &[]), + None, + "{cmd} braced form must stay off the delimiter scanner" + ); + assert_eq!( + split(&braced), + vec![format!(r"See {cmd}{{{body}}} here."), "Done.".to_string(),], + "{cmd} braced form must stay one span and the next sentence must split" + ); + } + assert_eq!(latex_verb_span_end_with(r"\urlfoo|a.b|", 0, &[]), None); + assert_eq!( + latex_verb_span_end_with(r"\pathological|a.b|", 0, &[]), + None + ); + } + #[test] fn latex_spverb_inner_percent_stays_atomic() { let text = r"See \spverb|a.b%| please. Next."; From b5de4caf76510f88533a75ebda9973ac0e704e7e Mon Sep 17 00:00:00 2001 From: Rohit Goswami Date: Sat, 26 Sep 2026 05:48:08 -0500 Subject: [PATCH 2/2] style(latex): sort imports with the edition 2024 formatter The CI formatter reorders use groups. The local edition 2021 invocation did not. --- src/parser/latex.rs | 52 ++++++++++++++++++++++----------------------- 1 file changed, 26 insertions(+), 26 deletions(-) diff --git a/src/parser/latex.rs b/src/parser/latex.rs index 9e3b3e78..d1c88469 100644 --- a/src/parser/latex.rs +++ b/src/parser/latex.rs @@ -2,7 +2,7 @@ use regex::Regex; use std::sync::LazyLock; use crate::parser::{ - flush_prose_spanned, iter_lines, join_prose_gap, ByteSpan, FormatParser, Line, SpannedRegion, + ByteSpan, FormatParser, Line, SpannedRegion, flush_prose_spanned, iter_lines, join_prose_gap, }; use crate::sentence::unicode::{ catchfile_leftover_cs_name, fancyvrb_leftover_cs_name, fancyvrb_shortverb_leftover_cs_name, @@ -2754,7 +2754,7 @@ mod tests { #[test] fn multi_sentence_section_title_stays_one_line() { use crate::format::Format; - use crate::{format_text, FormatConfig}; + use crate::{FormatConfig, format_text}; let input = "\\begin{document}\n\\section{A long title. With two sentences.}\nBody text here. More body.\n\\end{document}\n"; let cfg = FormatConfig { @@ -2811,7 +2811,7 @@ mod tests { fn section_optional_short_title_stays_one_line() { use crate::format::Format; use crate::oracle; - use crate::{format_text, FormatConfig}; + use crate::{FormatConfig, format_text}; let input = "\\section[Short. Title.]{A long title. With two sentences.}\nBody. More body.\n"; @@ -2843,7 +2843,7 @@ mod tests { #[test] fn koma_addsec_addchap_addpart_optional_short_title_is_structure() { use crate::format::Format; - use crate::{format_text, FormatConfig}; + use crate::{FormatConfig, format_text}; let cfg = FormatConfig { format: Format::Latex, @@ -2887,7 +2887,7 @@ mod tests { #[test] fn fragment_without_begin_document_is_prose() { use crate::format::Format; - use crate::{format_text, FormatConfig}; + use crate::{FormatConfig, format_text}; let input = "This sentence is a test. This sentence is also a test.\n"; let cfg = FormatConfig { @@ -2905,7 +2905,7 @@ mod tests { #[test] fn no_preamble_pragma_formats_body() { use crate::format::Format; - use crate::{format_text, FormatConfig}; + use crate::{FormatConfig, format_text}; let input = "% snapper:no-preamble\nThis sentence is a test. This sentence is also a test.\n"; @@ -2928,7 +2928,7 @@ mod tests { #[test] fn documentclass_without_begin_stays_preamble() { use crate::format::Format; - use crate::{format_text, FormatConfig}; + use crate::{FormatConfig, format_text}; let input = "\\documentclass{article}\nThis sentence is a test. This sentence is also a test.\n"; @@ -3411,7 +3411,7 @@ Some text. #[test] fn trailing_percent_is_nospace_join() { use crate::format::Format; - use crate::{format_text, FormatConfig}; + use crate::{FormatConfig, format_text}; let input = "\\begin{document}\nfoo%\nbar. Next sentence.\n\\end{document}\n"; let cfg = FormatConfig { @@ -3435,7 +3435,7 @@ Some text. #[test] fn escaped_percent_is_not_a_comment() { use crate::format::Format; - use crate::{format_text, FormatConfig}; + use crate::{FormatConfig, format_text}; let input = "\\begin{document}\n50\\% of cases. More text.\n\\end{document}\n"; let cfg = FormatConfig { @@ -3454,7 +3454,7 @@ Some text. #[test] fn mid_line_percent_comment_is_structure() { use crate::format::Format; - use crate::{format_text, FormatConfig}; + use crate::{FormatConfig, format_text}; let input = "\\begin{document}\nSee Fig. 1. % TODO cite\nNext sentence.\n\\end{document}\n"; let cfg = FormatConfig { @@ -4181,7 +4181,7 @@ Some text. /// form as Delim. #[test] fn pythontexcustomc_does_not_join_following_prose() { - use crate::{format_text, FormatConfig}; + use crate::{FormatConfig, format_text}; let cmd = r"\pythontexcustomc{python}{import numpy}"; let input = format!("Before. Next.\n{cmd}\nAfter. Next.\n"); @@ -4314,7 +4314,7 @@ Some text. /// no-brace form as Delim. #[test] fn pyth_does_not_join_following_prose() { - use crate::{format_text, FormatConfig}; + use crate::{FormatConfig, format_text}; let cmd = r"\pyth{print(1)}"; let input = format!("Before. Next.\n{cmd}\nAfter. Next.\n"); @@ -4456,7 +4456,7 @@ Some text. /// configured extra does not re-tokenize the no-brace form as Delim. #[test] fn scontents_leftover_cmds_do_not_join_following_prose() { - use crate::{format_text, FormatConfig}; + use crate::{FormatConfig, format_text}; for cmd in [ r"\Scontents*{foo bar}", @@ -4609,7 +4609,7 @@ Some text. /// re-tokenize the no-brace mintinline form as Delim. #[test] fn verb_span_leftover_cmds_do_not_join_following_prose() { - use crate::{format_text, FormatConfig}; + use crate::{FormatConfig, format_text}; for cmd in [ r"\lstinline|print(1)|", @@ -4764,7 +4764,7 @@ Some text. /// no-brace form as Delim. #[test] fn fancyvrb_leftover_cmds_do_not_join_following_prose() { - use crate::{format_text, FormatConfig}; + use crate::{FormatConfig, format_text}; for cmd in [ r"\UseVerb{foo}", @@ -5080,7 +5080,7 @@ Some text. /// the no-brace form as Delim. #[test] fn catchfile_leftover_cmds_do_not_join_following_prose() { - use crate::{format_text, FormatConfig}; + use crate::{FormatConfig, format_text}; for cmd in [ r"\CatchFileDef{\foo}{foo.py}{}", @@ -5189,7 +5189,7 @@ Some text. /// a configured extra does not re-tokenize the no-brace form as Delim. #[test] fn inputpython_does_not_join_following_prose() { - use crate::{format_text, FormatConfig}; + use crate::{FormatConfig, format_text}; let input = concat!( "Before. Next.\n", @@ -5313,7 +5313,7 @@ Some text. /// not re-tokenize the no-brace form as Delim. #[test] fn sagetex_inline_cmds_do_not_join_following_prose() { - use crate::{format_text, FormatConfig}; + use crate::{FormatConfig, format_text}; for (cmd, name) in [ (r"\sageplot{plot(sin(x))}", "sageplot"), @@ -5462,7 +5462,7 @@ Some text. /// `\inputpygments` / `\pygment` unchanged. #[test] fn pytx_inline_cmds_do_not_join_following_prose() { - use crate::{format_text, FormatConfig}; + use crate::{FormatConfig, format_text}; for name in [ "py", "pyc", "pys", "pyb", "pyv", "pycon", "pyconc", "pycons", "pyconv", "sympy", @@ -5595,7 +5595,7 @@ Some text. /// mint envs, not these inlines. #[test] fn pytx_usefamily_inline_cmds_do_not_join_following_prose() { - use crate::{format_text, FormatConfig}; + use crate::{FormatConfig, format_text}; const FAMILIES: &[&str] = &[ "ruby", @@ -9257,7 +9257,7 @@ Some text. fn enumerate_item_hangs_next_sentence() { use crate::format::Format; use crate::oracle; - use crate::{format_text, FormatConfig}; + use crate::{FormatConfig, format_text}; let cfg = FormatConfig { format: Format::Latex, @@ -11483,7 +11483,7 @@ Some text. /// does not re-tokenize the no-brace form as Delim. #[test] fn verbatimtabinput_does_not_join_following_prose() { - use crate::{format_text, FormatConfig}; + use crate::{FormatConfig, format_text}; for cmd in [ r"\verbatimtabinput{foo.py}", @@ -11600,7 +11600,7 @@ Some text. /// configured extra does not re-tokenize the no-brace form as Delim. #[test] fn verbatimwrite_does_not_join_following_prose() { - use crate::{format_text, FormatConfig}; + use crate::{FormatConfig, format_text}; for cmd in [r"\verbatimwrite{foo.py}", r"\verbatimwrite*{foo.py}"] { let input = format!("Before. Next.\n{cmd}\nAfter. Next.\n"); @@ -11710,7 +11710,7 @@ Some text. /// no-brace form as Delim. #[test] fn listingcont_does_not_join_following_prose() { - use crate::{format_text, FormatConfig}; + use crate::{FormatConfig, format_text}; let cmd = r"\listingcont"; let input = format!("Before. Next.\n{cmd}\nAfter. Next.\n"); @@ -11802,7 +11802,7 @@ Some text. /// form as Delim. #[test] fn defineshortverb_does_not_join_following_prose() { - use crate::{format_text, FormatConfig}; + use crate::{FormatConfig, format_text}; for cmd in [r"\DefineShortVerb{\|}", r"\UndefineShortVerb{\|}"] { let input = format!("Before. Next.\n{cmd}\nAfter. Next.\n"); @@ -11908,7 +11908,7 @@ Some text. /// form as Delim. #[test] fn fvextra_buffer_leftover_cmds_do_not_join_following_prose() { - use crate::{format_text, FormatConfig}; + use crate::{FormatConfig, format_text}; for cmd in [ r"\VerbatimInsertBuffer[foo]",