Here's a re-implementation of yannisl's answer which does not depend on Lua (so should work with any engine), avoids the need to start and end the environment for each paragraph and eliminates the need to explicitly capture the content of the paragraphs using the b
specifier. Instead, the code is automatically added to the start and end of paragraphs.
Which is all well and good, but it is not for free. Everything has its price. In this case, the price is dependence on multiple compilations. You need at least two and sometimes three compilations for the numbering to be correct. This is because the numbers are written at the start of the paragraph, when only the first sentence's number is known for this run. To get the number of the last sentence, we record its value at the end of the paragraph and read it back on the next run. So, initially, the final sentences of all paragraphs will be zero and you will see things like '9-0' in the output. That is expected.
An alternative would be to capture the paragraph, but there are some downsides to doing that, so I decided not to complicate things.
\documentclass{article}
% ateb: https://tex.stackexchange.com/a/719068/ addaswyd o ateb yannisl: https://tex.stackexchange.com/a/719024/
\ExplSyntaxOn
\int_new:N \g_gsl_sentences_int
\int_new:N \g_gsl_pars_int
\property_new:nnnn { sinpar }{ now }{ 0 }{ \int_use:N \g_gsl_sentences_int }
\cs_new_protected:Npn \sn #1 \n {
\int_gincr:N \g_gsl_sentences_int
#1 ~
}
\NewDocumentEnvironment{segmentation} {}
{
\hook_gput_code:nnn { para/begin } { gsl }
{
\int_gincr:N \g_gsl_pars_int
\hbox_gset:Nn \g_para_indent_box { [\int_to_arabic:n {\g_gsl_sentences_int} -- \property_ref:ee { gsl@para@\int_to_arabic:n {\g_gsl_pars_int} } {sinpar} ] ~ }
}
\hook_gput_code:nnn { para/end } { gsl }
{
\property_record:ee { gsl@para@\int_to_arabic:n {\g_gsl_pars_int} } { sinpar }
}
}{
\para_end:
\hook_gremove_code:nn { para / begin } { gsl }
\hook_gremove_code:nn { para / end } { gsl }
}
\ExplSyntaxOff
\begin{document}
\parindent0pt
\begin{segmentation}
\sn Myfirst sentence.\n
\sn My second sentence.\n
\sn My third sentence.\n
\sn My fourth sentence.\n
\sn My fifth sentence.\n
\sn His life is the life of desire.\n
\sn My fifth sentence.\n
\sn His life is the life of desire.\n
\sn This is the next in line!\n
\sn This is the next in line!\n
\end{segmentation}
Here's some regular text in sentences which aren't marked and in paragraphs which don't get the special treatment.
And here's another.
These sentences aren't marked or counted either.
That's because we finished the \texttt{segmentation} environment and haven't started another.
\begin{segmentation}
\sn Here we go again.\n
\sn Counting sentences one-by-one.\n
\sn However, we don't have to add the environment explicitly.\n
\sn So it is a bit more automatic.\n
\end{segmentation}
\thispagestyle{empty}
\end{document}
Note: the truth is, this was going to depend on Lua because I planned to just add the hooks wrapper around yannisl's code. But I know nothing about Lua and couldn't even figure out how to do that.
EDIT
This version offers ranges and/or sentence numbers on a per-environment or general basis and provides a key-value interface for customising the appearance of both.
\glsset{<list of key-values>}
or an optional argument to the segmentation
environment may be used for the customisation. All settings are local.
sentence numbers=<true|false>
determines whether numbers are printed.
- Default is true; initially false.
sentence ranges=<true|false>
determines whether ranges are printed.
- Default is true; initially true.
sentence number format={<code taking one argument>}
determines the format of sentence numbers, where #1
is the sentence number.
sentence range format={<code taking two arguments>}
determines the format of ranges, where #1
is the first sentence in the paragraph and #2
is the second.
Note that this will obviously be slightly slower than the less flexible code above.
\documentclass{article}
% ateb: https://tex.stackexchange.com/a/719068/ addaswyd o ateb yannisl: https://tex.stackexchange.com/a/719024/
\usepackage{xcolor}
\ExplSyntaxOn
\int_new:N \g_gsl_sentences_int
\int_new:N \g_gsl_pars_int
\property_new:nnnn { sinpar }{ now }{ 0 }{ \int_use:N \g_gsl_sentences_int }
\cs_new_protected_nopar:Nn \gsl_sentence_no_format:n
{
\textsubscript{ \textcolor{gray}{ #1 } }
}
\cs_set_protected_nopar:Nn \gsl_sentence_range_format:nn
{
[ #1 -- #2 ]
}
\keys_define:nn { gsl }
{
sentence ~ number ~ format .code:n = {
\cs_set_protected_nopar:Nn \gsl_sentence_no_format:n { #1 }
},
sentence ~ numbers .bool_set:N = \g_gsl_sentence_nos_bool,
sentence ~ numbers .initial:n = false,
sentence ~ numbers .default:n = true,
sentence ~ range ~ format .code:n = {
\cs_set_protected_nopar:Nn \gsl_sentence_range_format:nn { #1 }
},
sentence ~ ranges .bool_set:N = \g_gsl_sentence_ranges_bool,
sentence ~ ranges .initial:n = true,
sentence ~ ranges .default:n = true,
}
\cs_new_protected:Npn \sn #1 \n {
\int_gincr:N \g_gsl_sentences_int
#1 \bool_if:NT \g_gsl_sentence_nos_bool
{
\gsl_sentence_no_format:n { \int_to_arabic:n {\g_gsl_sentences_int} }
} ~
}
\NewDocumentEnvironment{segmentation} { o }
{
\IfValueT { #1 }
{
\keys_set:nn { gsl } { #1 }
}
\bool_if:NT \g_gsl_sentence_ranges_bool
{
\hook_gput_code:nnn { para/begin } { gsl }
{
\int_gincr:N \g_gsl_pars_int
% \hbox_gset:Nn \g_para_indent_box { [\int_to_arabic:n {\g_gsl_sentences_int} -- \property_ref:ee { gsl@para@\int_to_arabic:n {\g_gsl_pars_int} } {sinpar} ] ~ }
\hbox_gset:Nn \g_para_indent_box { \gsl_sentence_range_format:nn { \int_to_arabic:n {\g_gsl_sentences_int} } { \property_ref:ee { gsl@para@\int_to_arabic:n {\g_gsl_pars_int} } {sinpar} } ~ }
}
\hook_gput_code:nnn { para/end } { gsl }
{
\property_record:ee { gsl@para@\int_to_arabic:n {\g_gsl_pars_int} } { sinpar }
}
}
}{
\para_end:
\bool_if:NT \g_gsl_sentence_ranges_bool
{
\hook_gremove_code:nn { para / begin } { gsl }
\hook_gremove_code:nn { para / end } { gsl }
}
}
\NewDocumentCommand \gslset { m }
{
\keys_set:nn { gsl } { #1 }
}
\ExplSyntaxOff
\pagestyle{empty}
\begin{document}
\begin{segmentation}
\sn My first sentence.\n
\sn My second sentence.\n
\sn My third sentence.\n
\sn My fourth sentence.\n
\sn My fifth sentence.\n
\sn His life is the life of desire.\n
\sn My fifth sentence.\n
\sn His life is the life of desire.\n
\sn This is the next in line!\n
\sn This is the next in line!\n
\end{segmentation}
Here's some regular text in sentences which aren't marked and in paragraphs which don't get the special treatment.
And here's another.
These sentences aren't marked or counted either.
That's because we finished the \texttt{segmentation} environment and haven't started another.
\begin{segmentation}
\sn Here we go again.\n
\sn Counting sentences one-by-one.\n
\sn However, we don't have to add the environment explicitly.\n
\sn So it is a bit more automatic.\n
\end{segmentation}
\begin{segmentation}[sentence ranges=false]
\sn My first sentence.\n
\sn My second sentence.\n
\sn My third sentence.\n
\sn My fourth sentence.\n
\sn My fifth sentence.\n
\sn His life is the life of desire.\n
\sn My fifth sentence.\n
\sn His life is the life of desire.\n
\sn This is the next in line!\n
\sn This is the next in line!\n
\end{segmentation}
Here's some regular text in sentences which aren't marked and in paragraphs which don't get the special treatment.
And here's another.
These sentences aren't marked or counted either.
That's because we finished the \texttt{segmentation} environment and haven't started another.
\begin{segmentation}[sentence numbers]
\sn Here we go again.\n
\sn Counting sentences one-by-one.\n
\sn However, we don't have to add the environment explicitly.\n
\sn So it is a bit more automatic.\n
\end{segmentation}
\gslset{%
sentence ranges=true,
sentence numbers=true,
sentence range format={\textit{\textcolor{blue}{\small (#1--#2)}}},
sentence number format={\textsuperscript{\textcolor{red}{#1}}},
}%
\begin{segmentation}
\sn My first sentence.\n
\sn My second sentence.\n
\sn My third sentence.\n
\sn My fourth sentence.\n
\sn My fifth sentence.\n
\sn His life is the life of desire.\n
\sn My fifth sentence.\n
\sn His life is the life of desire.\n
\sn This is the next in line!\n
\sn This is the next in line!\n
\end{segmentation}
Here's some regular text in sentences which aren't marked and in paragraphs which don't get the special treatment.
And here's another.
These sentences aren't marked or counted either.
That's because we finished the \texttt{segmentation} environment and haven't started another.
\begin{segmentation}
\sn Here we go again.\n
\sn Counting sentences one-by-one.\n
\sn However, we don't have to add the environment explicitly.\n
\sn So it is a bit more automatic.\n
\end{segmentation}
\end{document}
The blue and red is hideous, but illustrates the idea.