% yafp.sty
% Copyright 2008 Олександр М. Барановський (Oleksandr M. Baranovskyi)
%
% This work may be distributed and/or modified under the
% conditions of the LaTeX Project Public License, either version 1.3
% of this license or (at your option) any later version.
% The latest version of this license is in
%   http://www.latex-project.org/lppl.txt
% and version 1.3 or later is part of all distributions of LaTeX
% version 2005/12/01 or later.
%
% This work has the LPPL maintenance status `author-maintained'.
%
% This work consists of the file yafp.sty.
%
%
% Цей пакет призначений для підтримки уривків,
% у яких збережена нумерація формул, теорем, плаваючих об'єктів тощо,
% як в основному документі.
% Короткий посібник користувача пакета yafp див. нижче, після \endinput.
%
% Це експериментальна версія.
% Інтерфейс і реалізація можуть змінитися у наступних версіях!
%
% Повідомлення про помилки, пропозиції нових функцій, зауваження,
% будь ласка, надсилайте автору:
%   Олександр Барановський
%   ombaranovskyi at gmail dot com
%
\NeedsTeXFormat{LaTeX2e}[2003/12/01]
\ProvidesPackage{yafp}
  [2008/06/03 v0.00 Yet Another Fine Package (OMB)]
% Start 2008/05/24

% Пакет xr потрібен лише, якщо уривки у іншому файлі,
% тому видається, що його підключення краще залишити користувачеві.
%\RequirePackage{xr}

% Заміна команди \the<лічильник> буде посиланням на мітку,
% що є аргументом \label.
% Але команда \label може з'являтися після \begin{<оточення>},
% тому заміна команди \label має теж писати в .aux-файл зв'язок між міткою,
% що згенерована заміною команди \refstepcounter, та своїм аргументом.
%
% Для оточень типу equation (коли виведення номера може бути після команди \label),
% напевно, можна обійтися без .aux-файла.
% Але у випадку теорем (коли виведення номера відбувається перед \label),
% переозначення неможливе без цього.
%
% Заміна для стандартної команди \label.
% Записуємо в .aux-файл не команду \newlabel, а фактично її <<внутрішність>>:
% тобто це майже мітка \@currentlabel, що посилається на значення мітки #1.
\def\yafea@label#1{%
  \@bsphack
  \protected@write\@auxout{}%
    {\string\global\string\@namedef{r@\@currentlabel}{\@nameuse{r@#1}}}%
  \@esphack
}
%
% Заміна для стандартної команди \refstepcounter.
% Означуємо \@currentlabel як унікальний ідентифікатор на основі лічильника #1.
% Означуємо \the#1 як посилання на той унікальний ідентифікатор.
\def\yafea@refstepcounter#1{%
  \stepcounter{#1}%
  \protected@edef\@currentlabel{excerpt:#1\the\value{#1}}%
  \@namedef{the#1}{\ref{\@currentlabel}}%
}
%
% Оточення eqnarray не використовує команду \refstepcounter,
% тому потребує окремої уваги.
\def\yafea@eqnarray{%
  \stepcounter{equation}%
% Означуємо, як вище, але тут конкретний лічильник.
  \def\@currentlabel{excerpt:equation\the\value{equation}}%
  \@namedef{theequation}{\ref{\@currentlabel}}%
%
  \global\@eqnswtrue
  \m@th
  \global\@eqcnt\z@
  \tabskip\@centering
  \let\\\@eqncr
  $$\everycr{}\halign to\displaywidth\bgroup
      \hskip\@centering$\displaystyle\tabskip\z@skip{##}$\@eqnsel
     &\global\@eqcnt\@ne\hskip \tw@\arraycolsep \hfil${##}$\hfil
     &\global\@eqcnt\tw@ \hskip \tw@\arraycolsep
        $\displaystyle{##}$\hfil\tabskip\@centering
     &\global\@eqcnt\thr@@ \hb@xt@\z@\bgroup\hss##\egroup
        \tabskip\z@skip
     \cr
}
%
% Тепер те саме, якщо клас викликає опцію fleqn.
\@ifl@aded{clo}{fleqn}{%
  \renewenvironment{yafea@eqnarray}{%
    \stepcounter{equation}%
% Тут так само, як вище.
    \def\@currentlabel{excerpt:equation\the\value{equation}}%
    \@namedef{theequation}{\ref{\@currentlabel}}%
%
    \global\@eqnswtrue\m@th
    \global\@eqcnt\z@
    \tabskip\mathindent
    \let\\=\@eqncr
    \setlength\abovedisplayskip{\topsep}%
    \ifvmode
      \addtolength\abovedisplayskip{\partopsep}%
    \fi
    \addtolength\abovedisplayskip{\parskip}%
    \setlength\belowdisplayskip{\abovedisplayskip}%
    \setlength\belowdisplayshortskip{\abovedisplayskip}%
    \setlength\abovedisplayshortskip{\abovedisplayskip}%
    $$\everycr{}\halign to\linewidth% $$
    \bgroup
      \hskip\@centering
      $\displaystyle\tabskip\z@skip{##}$\@eqnsel&%
      \global\@eqcnt\@ne \hskip \tw@\arraycolsep \hfil${##}$\hfil&%
      \global\@eqcnt\tw@ \hskip \tw@\arraycolsep
        $\displaystyle{##}$\hfil \tabskip\@centering&%
      \global\@eqcnt\thr@@
        \hb@xt@\z@\bgroup\hss##\egroup\tabskip\z@skip\cr}%
      {\@@eqncr
    \egroup
    \global\advance\c@equation\m@ne$$% $$
    \@ignoretrue
    }%
}{\relax}
%
% Нарешті, основне оточення.
% Замінюємо необхідні команди на вище означені нові варіанти.
% Команду \ltx@label означує пакет amsmath.
% Всі зміни є локальними і скасовуються після оточення,
% коли група закривається.
\newenvironment{yafea}{%
  \begingroup
  \let\label\yafea@label
  \let\ltx@label\yafea@label% для amsmath!
  \let\refstepcounter\yafea@refstepcounter
  \let\eqnarray\yafea@eqnarray
% Це була спроба імпортувати мітки тут,
% але \externaldocument можна використовувати лише в преамбулі.
%  \def\@tempa{#1}%
%  \ifx\@tempa\@empty\else\externaldocument{#1}\fi
}{%
  \endgroup
}

\endinput

% obsolete
% Це була перша спроба: переозначувати всі нумеровані оточення.
% У цьому випадку .aux-файл не потрібен,
% але теореми повинні <<виловлювати>> свої команди \label.
% Універсальний варіант, реалізований вище, наразі видається ліпшим.
\newenvironment{yafec}{%
  \begingroup
  \renewcommand{\label}[1]{\def\temp@{##1}}%
% standard equation
  \def\equation{$$}%
  \def\endequation{\eqno \hbox{\@eqnnum}$$\@ignoretrue}%
  \def\@eqnnum{{\normalfont \normalcolor (\ref{\temp@})}}%
% theorem
  \def\@thm##1##2{%
    \@ifnextchar[{\@ythm{##1}{##2}}{\@xthm{##1}{##2}}}
  \def\@xthm##1##2\label##3{%
    \@begintheorem{##2}{\ref{##3}}\ignorespaces}
  \def\@ythm##1##2[##3]\label##4{%
    \@opargbegintheorem{##2}{\ref{##4}}{##3}\ignorespaces}
}{%
  \endgroup
}

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

КОРОТКИЙ ПОСІБНИК КОРИСТУВАЧА ПАКЕТА YAFP

Вступ
=====

Нехай маємо документ з великою кількістю нумерованих об'єктів (формул,
теорем, плаваючих об'єктів тощо). Необхідно вибрати деякі частини цього
документа (серед них і нумеровані об'єкти) і вибраний текст помістити в
цьому ж документі або в іншому, причому
 - нумеровані об'єкти в уривках мають такі самі номери, як в основному
   тексті;
 - збереження нумерації досягається автоматично, без потреби якимось
   чином змінювати чи основний текст, чи вибрані уривки (хоча власне
   формула чи теорема може змінюватися).

Це не лише теоретична проблема. Потреба в цьому виникає, наприклад, при
підготовці автореферату дисертації на здобуття наукового ступеня в
Україні.

Я швидко проглянув TeX Catalogue та UK TeX FAQ і не знайшов на CTAN
пакета, що таке реалізує. Найближчою до розв'язання вказаної проблеми є
команда \tag з пакета amsmath, яка дозволяє значити формули довільними
мітками, а не лише послідовними номерами. Але природна спроба
переозначити
  \def\label#1{\tag{\ref{#1}}}
і потім писати в уривках просто
  \begin{equation}\label{eq:x}
    x^2
  \end{equation}
не дає бажаного результату. Напевно, складна схема управління мітками у
різних оточеннях для набору формул, що пропонує amsmath, не дозволяє це
так просто зробити. Крім того, команду \tag не можна використовувати
для маркування інших нумерованих об'єктів, скажімо, теорем.

Ще існують пакети deleq та thrmappendix. Перший, зокрема, дозволяє
повторно використовувати нумеровані формули, але має певні обмеження.
Другий призначений для повторного використання теорем, але користувач
повинен форматувати теореми нестандартним чином.

Отже, я не знайшов готового продукту для розв'язання вказаної проблеми.
Пакет yafp (який наразі не має доброї назви) означує спеціальне
оточення yafea (теж поки що без назви), всередині якого користувач
розміщує уривки з основного тексту, в яких хоче зберегти нумерацію.
Важливо, що зв'язок з нумерованими об'єктами в основному тексті
здійснюється за допомогою команди \label, тобто всі нумеровані об'єкти
в основному тексті повинні мати мітки (це не надто обмежуюче обмеження,
бо насправді потенційно посилання може бути на все, що має номер, і
немає потреби нумерувати те, на що автор не посилається). Уривок можна
розмістити як у цьому ж документі (наприклад, зміст роботи у вступі до
дисертації) або в іншому (наприклад, розділ у авторефераті дисертації).


Як використовувати
==================

Ця версія є експериментальною. Тому назви команд та їх аргументи можуть
змінитися у майбутньому, і я не буду турбуватися про забезпечення
сумісності майбутніх версій з цією.

Пакет підключається, як будь який інший пакет LaTeX:
  \usepackage{yafp}
У поточній версії опції відсутні.

Користувач з основного документа вибирає необхідні шматки тексту
(скажімо, використовуючи засоби свого улюбленого текстового редактора)
і розміщує їх всередині оточення yafea. Це оточення переозначує
відповідним чином команди \label та \refstecounter, щоб зберегти
нумерацію таку, як в основному тексті. Кожне нумероване оточення
всередині оточення yafea повинно містити команду \label, яка й пов'язує
його з відповідним оточенням в основному тексті.

Якщо уривки розміщуються в тому самому документі (скажімо, у вступі),
користувач не потребує ніяких інших дій.

Якщо уривки мають бути розміщені в окремому документі (скажімо, в
авторефераті), необхідно імпортувати мітки з основного документа за
допомогою пакета xr (стандартний пакет LaTeX, входить до набору пакетів
tools). А саме, в преамбулі нового документа необхідно вказати
  \usepackage{xr}
  \externaldocument{<ім'я основного файла, з якого імпортуються мітки>}
Неважливо, у якому порядку викликаються пакети yafp та xr.

Як уже зазначалося, всі нумеровані об'єкти повинні мати мітки. Разом з
тим, ненумеровані об'єкти строго рекомендується не значити мітками,
тобто конструкція вигляду
  \begin{align*}\label{eq:bad}
  ...
  \end{align*}
може викликати проблеми (слід сказати, що такі конструкції "--- погана
ідея у будь-якому разі, навіть без пакета yafp).

Необхідно кілька разів компілювати документ (щонайменше два, інколи
три), щоб отримати правильні посилання.

У наступному розділі наведено перелік того, що необхідно реалізувати,
виправити чи дослідити. Він є одночасно переліком можливих проблем.
Користувач має читати цей розділ, якщо у нього виникають проблеми.


TODO
====

! Узгодити з пакетом hyperref. Він переозначає команди для роботи з
мітками спеціальним чином, щоб досягти своєї мети. З теоремами наче
працює, а от з формулами "--- проблеми (equation в \@currentlabel
зникає).

! Перевірити, чи сумісний з пакетами для відображення міток (showkeys,
showlabels та ін.). Такі пакети теж мають переозначувати \label.

! Чи відновлювати значення лічильників у кінці оточення? Лічильники
відповідних нумерованих об'єктів використовуються для створення
унікальних ідентифікаторів нумерованих об'єктів всередині уривка. Тому,
якщо після оточення ще є нумеровані об'єкти, то вони будуть
нумеруватися неправильно (нумерація не буде продовжувати ту, що була
перед оточенням). В дисертації (в авторефераті) після короткого викладу
змісту роботи, як правило, розділ закінчується, тому ця проблема
непомітна.

Можливо, можна експортувати лічильники в окремий файл на початку, а
потім імпортувати в кінці оточення (за допомогою пакета export).

! Як варіант, можна використовувати окремий, спеціальний, лічильник для
всіх нумерованих об'єктів уривка. Тоді немає проблеми з продовженням
нумерації після оточення. Але, можливо, пакет hyperref потребує знати
тип об'єкта?

! Додати безпечну обробку виняткових ситуацій. LaTeX дає повідомлення
про неозначену команду (яка відповідає за мітку нумерованого об'єкта в
уривку) при першій компіляції. Також необхідно додати попередження про
перекомпіляцію, якщо в цьому є потреба.

! Пакет amsmath робить дуже складні маніпуляції з командами \label та
\tag. Здається, що достатньо переозначити команду \ltx@label, щоб схема
збереження нумерації працювала. Але потрібні додаткові дослідження, щоб
знати певно.

! Дослідити проблему з мітками в ненумерованих оточеннях. Інколи це
викликає проблеми. На деякі оточення (наприклад, gather*) це не
впливає.

! Перевірити, чи сумісний з командою \tag (пакет amsmath).

! В оточенні flalign (яке всередині уривка) формула накладається на
номер. Напевно, flalign обчислює ширину мітки (наприклад, для вступу
має бути (8)), а потім підставляється ширша мітка (як для розділу,
наприклад, (2.12)).

! Перевірити, чи сумісний з <<теоремними>> пакетами: theorem, ntheorem,
nccthm, shadethm, thmbox, thrmappendix (які ще?). З пакетом amsthm
сумісний.

! Перевірити, чи сумісний з оточеннями для таблиць: longtable,
ltxtable, ltablex, supertabular, xtab, stabular, booktabs, subfloat
(які ще?).

! Перевірити, чи сумісний зі стандартними класами LaTeX, AMS-LaTeX, а
також з альтернативними класами: memoir, koma-script, octavo (які ще?).
Я перевіряв з класом report і трохи з класами vaktesis+vakaref.

! Здається, що ця схема має працювати без проблем з вкладеними файлами.
Але додаткові перевірки не завадять (мітки записуються в .aux-файли
відповідних вкладених файлів, чи не може це викликати проблеми, якщо
якийсь клас змінює стандартну поведінку?). Перевірив вкладені файли з
класом report.

! Побічний ефект: оточення впливає також на нумерацію всередині
оточення enumerate. І тому, якщо позиції в enumerate не мають міток і
немає інших оточень enumerate за межами оточення yafea, то enumerate не
може бути занумеровано. Здається, не важко програмувати їх по-іншому,
але я ще не вирішив, як доцільно робити: чи ігнорувати лічильник enumi
всередині оточення yafea (тобто дозволити оточенню enumerate
нумеруватися як завжди), чи все-таки вимагати, щоб всі позиції в
enumerate мали мітки (що не видається таким природним, як для формул чи
теорем).

Можливо, нумерувати <<як звичайно>> всі об'єкти, що не мають \label?

! Побічний ефект: файл автореферату з оточенням yafea не є мобільним,
його не можна передати іншим людям без дисертації (файл неможливо
скомпілювати без дисертації).

Можливо, це можуть вирішити скрипти (мовами Perl, Python чи щось таке;
наразі я в цьому не розуміюся), які б <<заморожували>> лічильники.
Ідеально, якби це можна було робити лише засобами TeX. Можливо, пакет
extract (чи інший) може щось таке робити?

! Чи можна пакет extract (чи якийсь інший) використовувати для
автоматичного (напівавтоматичного) генерування файла уривків з
основного файла?

! Команду \externaldocument з пакета xr (точніше, команду \newlabel)
можна використовувати лише в преамбулі, тому не можуть бути уривки з
різних файлів? Але, можливо, використання двох команд \externaldocument
дає таку можливість? Хотілося б, якщо більше одного оточення yafea в
документі, які є уривками з різних файлів, то щоб кожне оточення
імпортувало мітки лише свого файла.

! Префікс (факультативний аргумент команди \externaldocument) не можна
використовувати, бо тоді доведеться змінювати вирізаний текст (хочеться
цього уникати). Тому основний документ і похідний (за межами оточення)
не повинні мати однакових міток.

! Чи треба заховати інтерфейс xr всередину пакета?

! Придумати красиву назву для пакета.

repeat, reprise реприза
(повторное исполнение какого-л. отрывка музыкального произведения)

уривок excerpt, ?excerpt

! Як цей пакет ще можна використовувати (крім підготовки автореферату
дисертації)?

! Ймовірно, на CTAN немає схожого пакета. Але може бути деінде в
Інтернеті. Я не пробував читати чи запитувати на comp.text.tex,
fido7.ru.tex, lib.mexmat.ru/forum та ін.

UK TeX FAQ: Запитання 234 Re-using an equation.

Знайти TeX Macro Index, що згадується в showkeys.dvi.
