Criando um banco de dados contendo blocos numerados de código TeX

Criando um banco de dados contendo blocos numerados de código TeX

Quero criar um banco de dados que consiste em blocos numerados de código TeX. Em particular, quero fazer algo como \mycommand{counterName}{Some text}e salvar uma nova entrada em algum lugar, para usá-la Some Textposteriormente em outra parte do documento. É CounterNameum contador que posso consultar para inserir o texto no documento:

\newcounter{a}
\mycommand{a}{The first line}
\stepcounter{a}
\mycommand{a}{The second line}

.........

print{2}

E o TeX produzirá "A segunda linha".

Estou procurando algo como glossariespacote, mas com capacidade de produzir não todas as listas de uma vez, mas uma entrada específica para que pareça que o comando \print{n}foi simplesmente substituído pelo texto em command \mycommand{n}{TEXT}.

Pesquisando no TeX.SX encontrei algumas respostas sobre datatoolpacotes e Luacódigos, mas não encontrei uma solução que pudesse aplicar.

Eu realmente apreciaria uma breve explicação sobre como usar datatoolou glossariesalgo semelhante para essas coisas.

Responder1

Já que você mencionou datatoole glossaries, aqui estão algumas alternativas.

Com datatool, o método mais simples requer a definição de todas as entradas em ordem incremental (sem usar um contador). O número da linha fornece a indexação.

\documentclass{article}

\usepackage{datatool}

\DTLnewdb{data}

\newcommand{\addline}[1]{%
  \DTLnewrow{data}%
  \DTLnewdbentry{data}{Text}{#1}%
}

\newcommand{\print}[1]{%
  \DTLgetvalue{\thisval}{data}{#1}{1}%
  \thisval
}

\addline{The first line}
\addline{The second line}

\begin{document}

Line 2: \print{2}.

All lines:

\DTLforeach*{data}{\Text=Text}{\DTLcurrentindex. \Text.\par}

\end{document}

Isso produz:

imagem do documento

Linha 2: A segunda linha.
Todas as linhas:
1. A primeira linha.
2. A segunda linha.

Se você quiser definir suas entradas fora de ordem usando um contador, isso pode ser feito com uma coluna adicional:

\documentclass{article}

\usepackage{datatool}

\DTLnewdb{data}

\newcommand{\addline}[2]{%
  \DTLnewrow{data}%
  \dtlexpandnewvalue
  \DTLnewdbentry{data}{Index}{\the\value{#1}}%
  \dtlnoexpandnewvalue
  \DTLnewdbentry{data}{Text}{#2}%
}

\newcommand{\print}[1]{%
  \dtlgetrowindex{\thisrowidx}{data}{1}{#1}%
  \ifx\thisrowidx\dtlnovalue
    Not found!%
  \else
     \DTLgetvalue{\thisval}{data}{\thisrowidx}{2}%
     \thisval
  \fi
}

\newcounter{a}
\setcounter{a}{2}
\addline{a}{The second line}

\setcounter{a}{1}
\addline{a}{The first line}

\begin{document}

Line 2: \print{2}.

All lines:

\DTLforeach*{data}{\theIndex=Index,\Text=Text}{\theIndex. \Text.\par}

\end{document}

Isso produz:

imagem do documento

Linha 2: A segunda linha.
Todas as linhas:
2. A segunda linha.
1. A primeira linha.

A lista agora está fora de ordem numérica, mas corresponde à ordem em que os blocos foram definidos. Você pode classificá-los antes de exibir a lista:

\DTLsort{Index}{data}
\DTLforeach*{data}{\theIndex=Index,\Text=Text}{\theIndex. \Text.\par}

imagem do documento

Linha 2: A segunda linha.
Todas as linhas:
1. A primeira linha.
2. A segunda linha.

Aqui está uma glossariesabordagem:

\documentclass{article}

\usepackage{glossaries-extra}

\glssetexpandfield{name}

\newcommand{\addline}[2]{%
  \edef\thisidx{\the\value{#1}}%
  \newglossaryentry{\thisidx}{name={\thisidx},description={#2}}%
}

\newcommand{\print}[1]{%
  \glsentrydesc{#1}%
}

\newcounter{a}
\setcounter{a}{2}
\addline{a}{The second line}

\setcounter{a}{1}
\addline{a}{The first line}

\begin{document}

Line 2: \print{2}.

All lines:

\renewcommand{\glstreenamefmt}[1]{#1}
\renewcommand{\glossarysection}[2][]{}
\printunsrtglossary[style=index]

\end{document}

Isso produz:

imagem do documento

Novamente, isso lista em ordem de definição. Se quiser que a lista seja classificada, você pode usar o seguinte:

\documentclass{article}

\usepackage[automake,nopostdot]{glossaries}

\makeglossaries

\glssetexpandfield{name}

\newcommand{\addline}[2]{%
  \edef\thisidx{\the\value{#1}}%
  \newglossaryentry{\thisidx}{name={\thisidx},description={#2}}%
}

\newcommand{\print}[1]{%
  \glsentrydesc{#1}\glsadd{#1}%
}

\newcounter{a}
\setcounter{a}{2}
\addline{a}{The second line}

\setcounter{a}{1}
\addline{a}{The first line}

\begin{document}

Line 2: \print{2}.

All lines:

\renewcommand{\glstreenamefmt}[1]{#1}
\renewcommand{\glossarysection}[2][]{}
\printglossary[style=index,nonumberlist]

\end{document}

Isso produz:

imagem do documento

Linha 2: A segunda linha.
Todas as linhas:
2 A segunda linha

Isso lista apenas a entrada que foi indexada (com \glsadd). Se você quiser que todas as entradas sejam listadas, use \glsaddall(após todas as entradas terem sido definidas).

\documentclass{article}

\usepackage[automake,nopostdot]{glossaries}

\makeglossaries

\glssetexpandfield{name}

\newcommand{\addline}[2]{%
  \edef\thisidx{\the\value{#1}}%
  \newglossaryentry{\thisidx}{name={\thisidx},description={#2}}%
}

\newcommand{\print}[1]{%
  \glsentrydesc{#1}%
}

\newcounter{a}
\setcounter{a}{2}
\addline{a}{The second line}

\setcounter{a}{1}
\addline{a}{The first line}

\glsaddall

\begin{document}

Line 2: \print{2}.

All lines:

\renewcommand{\glstreenamefmt}[1]{#1}
\renewcommand{\glossarysection}[2][]{}
\printglossary[style=index,nonumberlist]

\end{document}

Isso produz:

imagem do documento

Linha 2: A segunda linha.
Todas as linhas:
1 A primeira linha
2 A segunda linha

Expansão

É importante que o valor da indexação \the\value{#1}seja totalmente expandido antes de ser armazenado, caso contrário ele continuará mudando conforme o contador muda de valor. Ambos datatooltêm glossariesuma maneira de ativar ou desativar a expansão ao adicionar/definir uma nova entrada.

No caso de datatool, a expansão é ativada usando \dtlexpandnewvalue. No caso de glossaries, a expansão é ativada para um campo específico usando\glssetexpandfield{Legenda do campo}.

O código que você deseja adicionar (no argumento final de \addline) pode conter comandos frágeis; nesse caso, é importante não expandir o valor. Com datatool, a expansão é desativada novamente usando \dtlnoexpandnewvalue. Com glossaries, o valor está sendo armazenado na descriptionchave e a expansão está desativada por padrão para esse campo.

Responder2

O seguinte é baseado na suposição que \printlistitemocorredepois \addlistitem:

insira a descrição da imagem aqui

\documentclass{article}

\usepackage{xparse}

\newcounter{listitem}
\NewDocumentCommand{\addlistitem}{o m}{%
  \IfValueTF{#1}
    {\expandafter\def\csname #1-list\endcsname{#2}}
    {\stepcounter{listitem}%
     \begingroup\edef\x{\endgroup\noexpand\expandafter
       \def\noexpand\csname \thelistitem-list\noexpand\endcsname}%
       \x{#2}}%
}

\newcommand{\printlistitem}[1]{%
  \ifcsname #1-list\endcsname
    \csname #1-list\endcsname
  \else
    Item~#1 does not exist.
  \fi
}

\begin{document}

\addlistitem{The first line}% 1
\addlistitem[B]{The second line}% C
\addlistitem{The third line}% 2

\printlistitem{2}

\printlistitem{1}

\printlistitem{3}

\printlistitem{B}

\end{document}

Mais modificações podem ser adicionadas, incluindo verificação/tratamento de erros e modificação para lidar com referência reversa (usando uma configuração \label- ).\ref


Você pode estar interessado em adicionar um \printallitemspara listar todos os itens adicionados na forma de um ToC. O exemplo a seguir imita isso definindo cada um \addlistitemcomo um arquivo \section. Você pode fazer ajustes na apresentação conforme necessário:

insira a descrição da imagem aqui

\documentclass{article}

\usepackage{xparse,tocloft}

\newcounter{listitem}
\NewDocumentCommand{\addlistitem}{o m}{%
  \IfValueTF{#1}
    {\expandafter\def\csname #1-list\endcsname{#2}%
     \addcontentsline{los}{listitem}{\protect\numberline{#1} #2}}
    {\stepcounter{listitem}%
     \begingroup\edef\x{\endgroup\noexpand\expandafter
       \def\noexpand\csname \thelistitem-list\noexpand\endcsname}%
       \x{#2}%
     \addcontentsline{los}{listitem}{\protect\numberline{\thelistitem} #2}}%
}

\newcommand{\printlistitem}[1]{%
  \ifcsname #1-list\endcsname
    \csname #1-list\endcsname
  \else
    Item~#1 does not exist.
  \fi
}

\makeatletter
\let\l@listitem\l@section
\newcommand{\printallitems}{{%
  \renewcommand{\cftsecfont}{\mdseries}% Add more ToC-related tuning here
  \@starttoc{los}}}
\makeatother

\begin{document}

\printallitems

\bigskip

\addlistitem{The first line}% 1
\addlistitem[B]{The second line}% C
\addlistitem{The third line}% 2

\printlistitem{2}

\printlistitem{1}

\printlistitem{3}

\printlistitem{B}

\end{document}

informação relacionada