Repository navigation
[6226] LaTeX: round-trip \begin{proof}[Title] as a titled proof - #4753
Merged
Merged
Conversation
The importer parsed the optional argument (turning the environment into
"proof*") but finalize_layout never emitted a matching begin/end, so the
whole proof environment, its title and its markers, was lost and only the
body text remained. Emit render-proof with the title as its first argument
and close it at the matching \end{proof}.
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
render-proof (the tag a titled proof has in Mogan, and what the importer now
produces for \begin{proof}[Title]) was exported as a custom proof* environment
defined in the preamble, instead of the amsthm proof environment that the
untitled proof already uses. Emit \begin{proof}[Title] directly, and a plain
\begin{proof} when the title is empty. Tests extended with export and
import->export checks.
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Solves #4752
What happened
Importing a LaTeX proof with an optional title, such as
\begin{proof}[Proof of Theorem 1] ... \end{proof},silently destroyed the environment: the title and the
proofblock were gone and the body was left as aplain paragraph. A proof without a title imported correctly. Separately, a titled proof inside Mogan was
exported as a custom
proof*environment rather than\begin{proof}[Title], so even with the importrepaired the round trip would not have produced the original LaTeX.
Input used (
proof.tex):Output of conversion on unmodified
upstream/main(the titled proof isgone):
Output with this change (title and environment kept):
How the importer works here (background)
Importing is a pipeline:
parsetex.cppparses the LaTeX into a tuple tree;fromtex.cppconverts it; thenfromtex_post.cpppost-processes. In the parse tree an environment is a pair of markers,(tuple "\begin-NAME" ...args)and(tuple "\end-NAME"). When the parser consumes an optional argumentof an environment it appends
*to the begin marker's name and stores the option as an argument. So\begin{proof}[Title]becomes\begin-proof*with argumentTitle, but its\end{proof}stays\end-proof: the end marker never learns about the option. Post-processing then turns these markers intoMogan's
BEGIN/ENDnodes that become<\name> ... </name>blocks.Cause
In
finalize_layout(src/Plugins/Tex/fromtex_post.cpp), the branch that handles theorem-likeenvironments with an option is
It rewrites
theorem*+ option into<theorem>followed by<dueto|option>. It excludesproof*explicitly, and no other branch in
finalize_layoutnamesproof*. I did not trace exactly which laterstage discards the leftover
proof*begin marker (the generic branch for admissible environments wouldpass it on, but the final tree contains no trace of it); the observable result is that neither the begin
nor the end marker of a titled proof survives, and the fix below does not depend on that detail because
the marker is now replaced before it reaches those stages.
Change
1. Import (
src/Plugins/Tex/fromtex_post.cpp,finalize_layout)BEGIN "proof*"with one argument) is emitted asBEGIN "render-proof"with the titleas its argument, i.e.
<\render-proof|Title>.render-proof: it is the tag Mogan uses for a proof with its own title.text-edit.scmrewrites
proofinto(render-proof "" body)when the title is made editable, andtext-drd.scmputs itin the
titled-taggroup, so it is the editor's own form for this, not an internal helper. Itstitle replaces the word "Proof", as in LaTeX. The alternative
proof-ofprepends "Proof" and would show"Proof Proof of Theorem 1". The theorem-style
<dueto|...>appends a parenthesised name after thedefault heading and would also be wrong here.
finalize_layoutnow keeps a small stack (array<bool> titled_proofs) local tothe concatenation it is processing. Every begin marker of a proof pushes whether it was titled
(
proof*) or not (proof); every(END "proof")pops, and emitsEND "render-proof"for a titledone and leaves a plain one untouched. Nesting is therefore handled by stack discipline: a titled proof
that contains a plain proof, or the reverse, closes each with the right tag.
falseon thestack), so their output is unchanged.
2. Export (
TeXmacs/plugins/latex/progs/latex/convert-latex-tmtex.scm,tmtex-render-proof)render-proofwas exported as(!begin "proof*" title), i.e. a custom environmentproof*; thegenerated preamble then defined
\newenvironment{proof*}[1]{\begin{proof}[{#1}]}{\end{proof}}and thebody used
\begin{proof*}{Title}. It now produces(!begin "proof" (!option title)), i.e.\begin{proof}[Title]directly, the same shapelatex-define.scmalready uses for theproof*tag.\begin{proof}, so a proof whose title was never filled in does not get an empty[].amsthmpackage dependency is already declared forbegin-proof, so no preamble change is needed.proofandproof*as\begin{proof}, tests in[203_28] Add unit tests for LaTeX proof environment export #3052). Those changes target the
proofandproof*tags; they do not coverrender-proof, which iswhat a titled proof is, and they do not touch the importer.
3. Tests (
TeXmacs/tests/7003.scm, 17 checks)Import: titled proof gives
render-proof, keeps the title and body, and noproof; plain proof givesproofand norender-proof; titled proof containing a plain proof gives both. Export: titled proof gives\begin{proof}[Proof of Theorem 1],\end{proof}, and neitherproof*nornewenvironment; empty titlegives
\begin{proof}without[; plainproofstill gives\begin{proof}. Round trip: importing theLaTeX proof and exporting the result gives
\begin{proof}[Proof of Theorem 1]with noproof*.Verified (Windows, release build, headless)
TeXmacs/tests/7003.scmagainst unmodifiedupstream/main: the first 8 checks (import only) give5 correct, 3 failed; with the change all 17 checks pass (console output of the test run below).proof.texwith-headless -c: outputs shown above; the plain proof is identical in both.mainwith both commits:proof.tex->proof.tmu(as above) ->proof.texwith
-headless -cgivesNot checked
\begin{proof}[...]in styles other than the default article style, and proofs aliased by the importer(
pf,dem,preuve,IEEEproof) with an option; those aliases are renamed toproofbefore thiscode runs, so they should behave the same, but this was not tried.
Test output
Unmodified
upstream/main(import checks only, the first 8 of today's 17):With this change:
How this fix was made
Developed through human-aided debugging: I reported the problem and ran and checked the builds, and the
cause was worked out interactively with an AI assistant. The code was written using Claude Sonnet 5.5
(Anthropic); I reviewed and tested it before submitting. The commits carry a
Co-Authored-Bytrailer tothe same effect.