I'm working on an environment in which each sentence is supposed to end with a line break. This should happen automatically and with minimal intrusion into the text because in the actual use case the contents of the environment (which will be \included from another file) will be reused in other documents where this behavior is undesirable. In another question it was proposed that this could be accomplished by making the full stops active so that they functioned as a command which would not only print the full stop normally but also insert the desired line break. When combined with a command to protect non-full stop uses of the character (which is intrusive, but not too bad), this works reasonably well for cases where the full stop ends the sentence but runs afoul when closing delimiters (quotation marks, parentheses, braces, and brackets) come into play.
Such closing delimiters could, in theory, be added to the list of active characters within the environment, but doing so would make for a much longer list of active characters and require a much more intrusive use of the protection function.
Is there a way to adapt the answer (a version of which is shown below) which would take closing delimiters into account while not requiring a huge amount of intrusion into the text?
\documentclass{article}
\begingroup
\catcode`\.=\active
\catcode`\?=\active
\catcode`\!=\active
\gdef.{\normalperiod\formattingcommand}%
\gdef?{\normalqmark\formattingcommand}%
\gdef!{\normalexclam\formattingcommand}%
\endgroup
\newcommand\formattingcommand{\newline\makebox[0pt][r]{$\rightarrow$}\ignorespaces}
\newenvironment{speech}
{ \vspace{2ex}\par
\let\normalperiod=.
\let\normalqmark=?
\let\normalexclam=!
\catcode`\.=\active
\catcode`\?=\active
\catcode`\!=\active
\sffamily\small
}{\vspace{2ex}\par}
\chardef\periodcatcode=\catcode`\.
\chardef\qmarkcatcode=\catcode`\?
\chardef\exclamcatcode=\catcode`\!
\newcommand\aeprotect[1]{%%
\begingroup
\catcode`\.=\periodcatcode
\catcode`\?=\qmarkcatcode
\catcode`\!=\exclamcatcode
\scantokens{#1\ignorespaces}%%
\endgroup
}
\begin{document}
GALLIA est omnis divisa in partes tres, quarum unam incolunt Belgae, aliam Aquitani, tertiam qui ipsorum lingua Celtae, nostra Galli appellantur. Hi omnes lingua,
institutis, legibus inter se differunt. Gallos ab Aquitanis Garumna flumen, a Belgis Matrona et Sequana dividit. Horum omnium fortissimi sunt Belgae, propterea quod a
cultu atque humanitate provinciae longissime absunt, minimeque ad eos mercatores saepe commeant atque ea quae ad effeminandos animos pertinent important, proximique sunt
\begin{speech}
\providecommand{\aeprotect}{\relax}
This is the beginning of paragraph 1.
Lorem ipsum dolor sit amet, consectetur adipiscing elit?
\aeprotect{S.P.Q.R.} Sed faucibus, sem vel suscipit eleifend, ipsum dolor tempus nunc, ut iaculis nibh arcu vitae tortor.
Pellentesque a efficitur lectus, eget sagittis lorem.
Fusce vestibulum feugiat nibh, pulvinar convallis eros sagittis ac.
Pellentesque aliquam arcu a augue malesuada, sit amet eleifend orci vulputate!
Sed nibh dolor, commodo vel risus quis, elementum consequat dui.
This is the beginning of paragraph 2.
Pellentesque eu neque eleifend, tincidunt mauris id, ultricies odio.
Aenean ac nisi congue, mollis leo a, cursus dolor!
Aenean non justo felis.
Cras interdum quam eu metus imperdiet ultricies.
Fusce finibus pellentesque volutpat?
“Praesent id lacus eget dui ullamcorper finibus nec nec urna?”
“Quisque vel vestibulum quam.”
(Lorem ipsum dolor sit amet, consectetur adipiscing elit.)
Mauris vel nisl eros.
\end{speech}
Germanis, qui trans Rhenum incolunt, quibuscum continenter bellum gerunt. Qua de causa Helvetii quoque reliquos Gallos virtute praecedunt, quod fere cotidianis proeliis
cum Germanis contendunt, cum aut suis finibus eos prohibent aut ipsi in eorum finibus bellum gerunt.
\end{document}
Oh, and in case it is useful, I use LuaLaTeX as my default engine, so feel free to employ features of that engine, if needed.
