
Я пытаюсь создать новую среду и использовать ее как настраиваемый массив (со многими изменениями в приведенном коде). Поэтому мне нужно прочитать из \BODY
и \NewEnviron
прочитать его построчно. Мне все равно, нужно ли мне заканчивать строки с помощью \\
или пустой строки или как-то еще. Но мне нужно прочитать их одну за другой, и я не знаю, сколько там строк, прежде чем использовать среду.
Я попробовал это:
\documentclass{article}
\usepackage{environ}
\usepackage{xstring}
\makeatletter
\long\def\findLength#1{\StrLen{#1}[\temp] The length of ``#1'' is \temp\\}
\NewEnviron{Graph}{\findLength{\BODY}}{}
\makeatother
\begin{document}
\begin{Graph}
test line 1
test line 2
\end{Graph}
\end{document}
Но использует все \BODY
и не построчно. Также если я добавляю перенос строки, то #1
из \StrLen
больше не является строкой (содержит перенос строки и выдает ошибки).
Мне наконец-то удалось занять первую строчку в моей новой среде, используя код @Bruno Le Floch изздесьно я не очень понимаю этот код и не знаю, что читать, чтобы понять его и изменить для принятия всех аргументов. Также я пока не могу добавить \ в конце строк, чтобы показать, где заканчивается строка массива... Вот что у меня сейчас:
\documentclass{article}
\usepackage{environ}% defines `NewEnviron`
\usepackage{xstring}
\makeatletter
\newcommand*{\newlinecommand}[2]{%
\newcommand*{#1}{%
\begingroup%
\escapechar=`\\%
\catcode\endlinechar=\active%
\csname\string#1\endcsname%
}%
\begingroup%
\escapechar=`\\%
\lccode`\~=\endlinechar%
\lowercase{%
\expandafter\endgroup
\expandafter\def\csname\string#1\endcsname##1~%
}{\endgroup#2\par\space}%
}
\makeatother
\makeatletter
\newlinecommand{\findLengthOfRow}{\StrLen{#1}[\temp] The length of ``#1'' is \temp}
\makeatother
\makeatletter
\long\def\findLength#1{\findLengthOfRow{#1}}
\newenvironment{Graph}{\findLength}{}
\makeatother
\begin{document}
\begin{Graph}
test line 1
test line 2
test line 3
\end{Graph}
\end{document}
Любая помощь будет оценена по достоинству. Результат, который я хочу получить, — это взять в качестве аргументов строки в среде. (Я не знаю, сколько строк будет в массиве. Поэтому не указывайте конкретное количество аргументов в новой среде).
решение1
Здесь используется мощный listofitems
пакет для анализа \BODY
с использованием \\
разделителей.
\documentclass[12pt]{article}
\usepackage{listofitems,environ}
\NewEnviron{linebyline}{%
\setsepchar{\\}%
\readlist*\mylines{\BODY}%
\foreachitem\x\in\mylines{Line \xcnt: \x\par}%
The total number of lines is \textbf{\listlen\mylines[]}.
}
\begin{document}
\begin{linebyline}
This is a test\\
of whether\\
I can identify line by line.
\end{linebyline}
\end{document}
А это показывает, как можно дополнительно разобрать каждую строку, слово за словом, используя пробел в качестве разделителя второго уровня:
\documentclass[12pt]{article}
\usepackage{listofitems,environ}
\NewEnviron{linebyline}{%
\setsepchar{\\/ }%
\readlist*\mylines{\BODY}%
\foreachitem\x\in\mylines{Line \xcnt: \x{} (has \listlen\mylines[\xcnt] words,
first/last: ``\mylines[\xcnt,1]/\mylines[\xcnt,-1]'')\par}%
The total number of lines is \textbf{\listlen\mylines[]}.
}
\begin{document}
\begin{linebyline}
This is a test\\
of whether\\
I can identify line by line.
\end{linebyline}
\end{document}
решение2
Если вас не волнует, заканчиваются ли строки символом \\
(что безопаснее, чем возиться с \endlinechar
), то с . все очень просто expl3
.
\documentclass{article}
\usepackage{xparse,environ}
\ExplSyntaxOn
\NewEnviron{Graph}
{
% split the environment's contents into items at the \\ separator
\seq_set_split:NnV \l_koleygr_graph_lines_seq { \\ } \BODY
\begin{enumerate}
% map over the sequence, passing each item to the internal function
\seq_map_function:NN \l_koleygr_graph_lines_seq \koleygr_graph_doline:n
\end{enumerate}
}
\cs_new_protected:Nn \koleygr_graph_doline:n
{
\tl_if_empty:nF { #1 }
{
\item #1
}
}
\ExplSyntaxOff
\begin{document}
Something at the top
\begin{Graph}
Line 1\\
Line 2\\
Line 3
\end{Graph}
Something in between
\begin{Graph}
Line 1\\
Line 2\\
Line 3\\
\end{Graph}
Something at the bottom
\end{document}
Я использовал фиктивное действие для выполнения в каждой строке, просто в качестве примера. Показано, что проверка на пустоту полезна в случае, если последняя строка заканчивается на \\
. Есть и другие возможности: можно просто проверить, является ли последний элемент в последовательности, полученной из , \BODY
пустым. Все зависит от того, что вы хотите сделать с содержимым среды.