
Estou tentando criar um novo ambiente e usá-lo como um array customizado (com muitas alterações no código fornecido). Então eu preciso ler o \BODY
e \NewEnviron
ler linha por linha. Não me importo se tenho que terminar as linhas com \\
ou com linha vazia ou algo assim. Mas tenho que lê-los um por um e não sei quantas linhas tem antes de usar o ambiente.
Eu tentei isso:
\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}
Mas usa tudo \BODY
e não linha por linha. Além disso, se eu adicionar uma quebra de linha, #1
of \StrLen
não será mais uma string (contém quebra de linha e apresenta erros).
Finalmente consegui pegar a primeira linha do meu novo ambiente usando o código do @Bruno Le Floch deaquimas eu realmente não entendo esse código e não sei o que ler para entendê-lo e alterá-lo para receber todos os argumentos. Além disso, ainda não consigo adicionar \ no final das linhas para mostrar onde termina a linha do array... Aqui está o que tenho agora:
\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}
Qualquer ajuda será apreciada. O resultado que desejo é tomar como argumentos as linhas do ambiente. (Não sei quantas linhas o array terá. Portanto, não forneça um número específico de argumentos no novo ambiente).
Responder1
Isso usa o listofitems
pacote poderoso para analisar o \BODY
, usando \\
separadores.
\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}
E isso mostra como subanalisar cada linha, palavra por palavra, usando um espaço como separador de segunda camada:
\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}
Responder2
Se você não se importa se as linhas terminam com \\
(o que é mais seguro do que brincar com \endlinechar
), é realmente simples com 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}
Usei uma ação fictícia para ser executada em cada linha, apenas a título de exemplo. A verificação de vazios mostra-se útil caso a última linha termine com \\
. Existem outras possibilidades: pode-se simplesmente verificar se o último item da sequência obtida \BODY
está vazio. Tudo depende do que você quer fazer com o conteúdo do ambiente.