Создание базы данных, содержащей пронумерованные блоки TeX-кода

Создание базы данных, содержащей пронумерованные блоки TeX-кода

Я хочу создать базу данных, состоящую из пронумерованных блоков TeX-кода. В частности, я хочу сделать что-то вроде \mycommand{counterName}{Some text}и сохранить новую запись где-то, чтобы использовать ее Some Textпозже в другой части документа. CounterNameЭто счетчик, на который я могу сослаться, чтобы получить текст, вставленный в документ:

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

.........

print{2}

А TeX создаст «Вторую линию».

Я ищу что-то вроде glossariesпакета, но с возможностью выдавать не весь список сразу, а конкретную запись, чтобы выглядело так, будто команда \print{n}просто заменяется текстом в команде \mycommand{n}{TEXT}.

Просматривая TeX.SX, я нашел некоторые ответы о datatoolпакетах и Lua​​кодах, но не нашел решения, которое я мог бы применить.

Я был бы очень признателен за краткое объяснение того, как использовать datatool, glossariesили что-то подобное для этого материала.

решение1

Поскольку вы упомянули datatoolи glossaries, вот несколько альтернатив.

С datatool, самый простой метод требует определения всех записей в порядке возрастания (без использования счетчика). Номер строки обеспечивает индексацию.

\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}

Это производит:

изображение документа

Строка 2: Вторая строка.
Все строки:
1. Первая строка.
2. Вторая строка.

Если вы хотите определить записи в неправильном порядке с помощью счетчика, это можно сделать с помощью дополнительного столбца:

\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}

Это производит:

изображение документа

Строка 2: Вторая строка.
Все строки:
2. Вторая строка.
1. Первая строка.

Список теперь не имеет числового порядка, но соответствует порядку, в котором были определены блоки. Вы можете отсортировать их перед отображением списка:

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

изображение документа

Строка 2: Вторая строка.
Все строки:
1. Первая строка.
2. Вторая строка.

Вот glossariesподход:

\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}

Это производит:

изображение документа

Опять же, это списки в порядке определения. Если вы хотите, чтобы список был отсортирован, вы можете использовать следующее:

\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}

Это производит:

изображение документа

Строка 2: Вторая строка.
Все строки:
2 Вторая строка

Это выводит только запись, которая была проиндексирована (с \glsadd). Если вы хотите, чтобы были перечислены все записи, используйте \glsaddall(после того, как все записи были определены).

\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}

Это производит:

изображение документа

Строка 2: Вторая строка.
Все строки:
1 Первая строка
2 Вторая строка

Расширение

Важно, чтобы значение индексации \the\value{#1}было полностью развернуто перед сохранением, в противном случае оно будет продолжать меняться по мере изменения значения счетчика. Оба datatoolи glossariesимеют возможность включать или выключать расширение при добавлении/определении новой записи.

В случае datatool, расширение включается с помощью \dtlexpandnewvalue. В случае glossaries, расширение включается для определенного поля с помощью\glssetexpandfield{метка поля}.

Код, который вы хотите добавить (в последнем аргументе \addline), может содержать хрупкие команды, в этом случае важно не расширять значение. С datatool, расширение снова отключается с помощью \dtlnoexpandnewvalue. С glossaries, значение сохраняется в descriptionключе, и расширение отключено по умолчанию для этого поля.

решение2

Следующее основано на предположении, что \printlistitemпроисходитпосле \addlistitem:

введите описание изображения здесь

\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}

Можно добавить больше модификаций, включая проверку/обработку ошибок и модификацию для обработки обратных ссылок (с использованием -setup \label) \ref.


Вам может быть интересно добавить , \printallitemsчтобы перечислить все добавленные вами элементы в форме ToC. Следующий пример имитирует это, устанавливая каждый \addlistitemкак \section. Вы можете вносить уточнения в представление по мере необходимости:

введите описание изображения здесь

\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}

Связанный контент