2014 dxdy logo

Научный форум dxdy

Математика, Физика, Computer Science, Machine Learning, LaTeX, Механика и Техника, Химия,
Биология и Медицина, Экономика и Финансовая Математика, Гуманитарные науки




Начать новую тему Ответить на тему На страницу Пред.  1, 2, 3  След.
 
 Re: Как обойти \detokenize?
Сообщение28.06.2022, 15:40 
Заслуженный участник


14/10/14
1207
epros в сообщении #1558709 писал(а):
Думаю, если бы дело было только в гиперрсылке
Нет, не только, я пробовал просто убрать hyperref, и всё равно не работало. Надо изучать, как работает \cite.

 Профиль  
                  
 
 Re: Как обойти \detokenize?
Сообщение28.06.2022, 16:18 
Заслуженный участник
Аватара пользователя


28/09/06
10440
Slav-27 в сообщении #1558715 писал(а):
Надо изучать, как работает \cite

Небольшое исследование показало, что после первого прохода компилятора в файле *.aux появляется строчка:
\bibcite{leibniz_tom1}{1}
Если её из этого файла удалить, то при следующем проходе всё ещё пишет сообщение:
[BibTeX] finished with exit code 2
и в файле PDF там, где должна быть ссылка на библиографию, всё ещё печатается вопросительный знак в квадратных скобках.

Если же эту строчку в файле *.aux оставить, то при следующем проходе PDF формируется без ошибок.

Поскольку у меня также включены обратные ссылки из библиографии (параметр pagebackref=true пакета hyperref), при первом проходе компилятора создаётся файл *.brf, содержащий одну строку:
\backcite {leibniz_tom1}{{7}{1.1}{section.1.1}}
но сама обратная ссылка в файле PDF на странице библиографии не создаётся. Она там появляется при втором проходе компилятора, если не удалять файл *.brf.

Вывод: Нужно разбираться, как достать второй параметр, прописанный в команде \bibcite{*}{*} в файле *.aux.

 Профиль  
                  
 
 Re: Как обойти \detokenize?
Сообщение28.06.2022, 19:50 
Заслуженный участник
Аватара пользователя


28/09/06
10440
Экспериментальным путём установлено, что добавление в преамбулу (а она может быть только там) команды:

Используется синтаксис LaTeX
\bibcite{label}{foo}

приводит к тому, что становится определённой переменная \b@label, которая получает значение foo.
Это независимо от наличия файла *.aux, а по результатам выполнения этой команды в файл *.aux ничего нового тоже не вносится.

Вероятно, во время парсинга преамбулы выполняется \input(*.aux), поэтому при втором проходе компилятора в документ вносятся ссылки на библиографию, которые были записаны в файл *.aux (в виде таких команд) во время первого прохода.

Но раскрыть \b@label с помощью \edef мне всё равно не удалось.

 Профиль  
                  
 
 Re: Как обойти \detokenize?
Сообщение29.06.2022, 13:54 
Заслуженный участник


14/10/14
1207
"Изначально" \b@label раскрывается в номер соответствующего элемента списка литературы. Проблема в том, что подгружаемые пакеты меняют \b@label кто во что горазд. А контрольной последовательности, которая всегда содержит номер и ничего более, видимо, нет в штате. Может, и есть, надо поискать,.

У меня работает следующий грязный хак, но, вероятно, придётся всё переделывать, когда вы поменяете какие-нибудь опции или подгрузите ещё пакеты.
код: [ скачать ] [ спрятать ]
Используется синтаксис LaTeX
\documentclass[
    a4paper,% размеры листа
    11pt,% размеры нормального шрифта
    toc=bibliography% включить в оглавление литературу
    ]{book} % книга KOMAscript, см. scrguien.pdf (у меня нету такого документкласса)
\usepackage[T2A]{fontenc}% Выбор внутренней TeX−кодировки
\usepackage[utf8]{inputenc}% Выбор кодовой страницы документа.
\usepackage[english,russian]{babel}% Выбор языка документа.
\usepackage{indentfirst}% Начинать первый параграф с красной строки.
\usepackage{xcolor}% Для работы с цветами, включая гиперссылки
\usepackage{stringenc}% Конвертер кодировок, позволяет из utf8 делать utf16be
\usepackage[hyperfootnotes=false,pagebackref=true,pdftex]{hyperref}% Для гиперссылок, включая из оглавления, на библиографию и обратные
\hypersetup{
    colorlinks=true% ссылки будут выделяться цветом, а не рамкой
}



% Берёт последовательность токенов-символов, заканчивающуюся токеном "контрольная последовательность relax" (буква кириллицы -- 2 токена-символа), и меняет для таких символов правило назначения каткодов: им будет назначаться other.
\def\makeother#1#2\relax{\ifx\relax#1\else\catcode`#1=12\makeother#2\relax\relax\fi}
\def\azbuka{АБВГДЕЁЖЗИЙКЛМНОПРСТУФХЦЧШЩЪЫЬЭЮЯабвгдеёжзийклмнопрстуфхцчшщъыьэюя}


% Макрос создаёт сноску с всплывающей подсказкой (ВТОРОЙ аргумент); ПЕРВЫЙ агрумент - содержимое нормальной сноски внизу страницы.
% Каждая буква кириллицы в UTF-8 кодируется 2 байтами. TeX читает каждый из этих 2 байтов как отдельный токен-символ с каткодом 13 (active). Я меняю каткоды символов, встречающихся в буквах кириллицы, на 12 (other), чтобы они не раскрывались (expand), когда мы будем раскрывать всё остальное.
% Каткоды замораживаются при передаче в качестве аргумента макроса (потому что каткод назначается при токенизации, которая происходит только один раз и до передачи аргумента макросу). Поэтому я вместо 1 макроса пишу 2, первый берёт в качестве аргумента текст нормальной сноски и далее меняет правила назначения каткодов, а второй потом забирает оставшийся аргумент -- текст всплывающей подсказки.
\def\myfootnote#1{%
\begingroup\expandafter\makeother\azbuka\relax\myfootnoteaux{#1}}

\def\myfootnoteaux#1#2{%
\edef\myfootipUTFeight{#2}% здесь происходит раскрытие контрольных последовательностей, содержащихся в тексте всплывающей подсказки
\StringEncodingConvert\myfootip{\myfootipUTFeight}{utf8}{utf16be}%
%
\def\myauthorUTFeight{Пушкин}%
\StringEncodingConvert\myauthor{\expandafter\detokenize\expandafter{\myauthorUTFeight}}{utf8}{utf16be}%
%
\pdfstartlink user{%
  /Subtype /Text% создаётся аннотация типа Text
  /T (\string\376\string\377\myauthor)% автор аннотации
  /Contents (\string\376\string\377\myfootip)% текст аннотации; префикс перед \myfootip согласно формату pdf идентифициует строку unicode
  /AP <<
   /N \emptyicon\space 0 R% ссылка на создаваемый в начале документа объект pdf - основной вид значка аннотации
   /R \emptyicon\space 0 R% вид значка при наведённом указателе мыши
   /D \emptyicon\space 0 R% вид значка при нажатой кнопке мыши
  >>
}%
\footnote{#1}%
\pdfendlink%
\endgroup% изменённые правила назначения каткодов действуют досюда
}


% Цитирование для всплывающей подсказки
\def\extractnumberfromhyperlink#1[#2]#3#4#5#6\relax{#5}
\def\bibitemsnumber#1{\expandafter\expandafter\expandafter\extractnumberfromhyperlink\csname b@#1\endcsname[]{}{}?\relax}
\def\mycite#1{[\bibitemsnumber{#1}]}


\title{Пробный заголовок}
%\subtitle{пробной книги}
\author{epros}
\date{\today}


\begin{document}
   
   \maketitle
   
   \tableofcontents
   
   % Этот код создаёт объект pdf - пустой бокс для использования вместо стандартного значка текстовой аннотации
   \newbox\tempboxa
   \setbox\tempboxa=\hbox{}
   \immediate\pdfxform\tempboxa
   \edef\emptyicon{\the\pdflastxform}% сохраняем номер объекта для использования при вызове макроса \myfootnote
 
   \part{Пробная часть}
   \chapter{Пробная глава}
   \section{Пробный раздел}


    Что же позволяет говорить не просто об эквивалентности, а о равенстве объектов? Для этого они должны быть ещё и неразличимы\myfootnote{Смотри \cite{kalevala}.}{Смотри \mycite{kalevala}.}. Принцип, отождествляющий неразличимость и равенство объектов, известен как <<закон Лейбница>>\myfootnote{См. переписку Лейбница с Кларком в \cite{leibniz_tom1}.}{См. переписку Лейбница с Кларком в \mycite{leibniz_tom1}.}.


{\raggedright
\begin{thebibliography}{99}

   \bibitem{kalevala}Лёнрот. Калевала.
   
   \bibitem{leibniz_tom1}Г.\,В.~Лейбниц. Сочинения в четырёх томах (под редакцией В.\,В.~Соколова, 1982). Том 1. Упоминается на с.%\!\!

\end{thebibliography}
}


\end{document}

 Профиль  
                  
 
 Re: Как обойти \detokenize?
Сообщение29.06.2022, 15:35 
Заслуженный участник


14/10/14
1207
(\makeatletter там даже не надо на самом деле.)
Получилось это так: я написал
Используется синтаксис LaTeX
\makeatletter
\meaning\b@kalevala
\makeatother
(ещё можно \show, однако в неинтерактивном режиме оно хотя и сработает, но потом выкинет ошибку) и узнал
Используется синтаксис LaTeX
\hyper@@link [cite]{}{cite.kalevala\@extra@b@citeb }{1}


-- 29.06.2022, 17:06 --

epros в сообщении #1558735 писал(а):
Экспериментальным путём
В принципе-то всё можно прочитать в texmf-dist/tex/latex/base/latex.ltx и в окрестных файлах.

 Профиль  
                  
 
 Re: Как обойти \detokenize?
Сообщение29.06.2022, 18:01 
Заслуженный участник
Аватара пользователя


28/09/06
10440
Slav-27 в сообщении #1558795 писал(а):
код: [ скачать ] [ спрятать ]
Используется синтаксис LaTeX
\documentclass[
    a4paper,% размеры листа
    11pt,% размеры нормального шрифта
    toc=bibliography% включить в оглавление литературу
    ]{book} % книга KOMAscript, см. scrguien.pdf (у меня нету такого документкласса)
\usepackage[T2A]{fontenc}% Выбор внутренней TeX−кодировки
\usepackage[utf8]{inputenc}% Выбор кодовой страницы документа.
\usepackage[english,russian]{babel}% Выбор языка документа.
\usepackage{indentfirst}% Начинать первый параграф с красной строки.
\usepackage{xcolor}% Для работы с цветами, включая гиперссылки
\usepackage{stringenc}% Конвертер кодировок, позволяет из utf8 делать utf16be
\usepackage[hyperfootnotes=false,pagebackref=true,pdftex]{hyperref}% Для гиперссылок, включая из оглавления, на библиографию и обратные
\hypersetup{
    colorlinks=true% ссылки будут выделяться цветом, а не рамкой
}



% Берёт последовательность токенов-символов, заканчивающуюся токеном "контрольная последовательность relax" (буква кириллицы -- 2 токена-символа), и меняет для таких символов правило назначения каткодов: им будет назначаться other.
\def\makeother#1#2\relax{\ifx\relax#1\else\catcode`#1=12\makeother#2\relax\relax\fi}
\def\azbuka{АБВГДЕЁЖЗИЙКЛМНОПРСТУФХЦЧШЩЪЫЬЭЮЯабвгдеёжзийклмнопрстуфхцчшщъыьэюя}


% Макрос создаёт сноску с всплывающей подсказкой (ВТОРОЙ аргумент); ПЕРВЫЙ агрумент - содержимое нормальной сноски внизу страницы.
% Каждая буква кириллицы в UTF-8 кодируется 2 байтами. TeX читает каждый из этих 2 байтов как отдельный токен-символ с каткодом 13 (active). Я меняю каткоды символов, встречающихся в буквах кириллицы, на 12 (other), чтобы они не раскрывались (expand), когда мы будем раскрывать всё остальное.
% Каткоды замораживаются при передаче в качестве аргумента макроса (потому что каткод назначается при токенизации, которая происходит только один раз и до передачи аргумента макросу). Поэтому я вместо 1 макроса пишу 2, первый берёт в качестве аргумента текст нормальной сноски и далее меняет правила назначения каткодов, а второй потом забирает оставшийся аргумент -- текст всплывающей подсказки.
\def\myfootnote#1{%
\begingroup\expandafter\makeother\azbuka\relax\myfootnoteaux{#1}}

\def\myfootnoteaux#1#2{%
\edef\myfootipUTFeight{#2}% здесь происходит раскрытие контрольных последовательностей, содержащихся в тексте всплывающей подсказки
\StringEncodingConvert\myfootip{\myfootipUTFeight}{utf8}{utf16be}%
%
\def\myauthorUTFeight{Пушкин}%
\StringEncodingConvert\myauthor{\expandafter\detokenize\expandafter{\myauthorUTFeight}}{utf8}{utf16be}%
%
\pdfstartlink user{%
  /Subtype /Text% создаётся аннотация типа Text
  /T (\string\376\string\377\myauthor)% автор аннотации
  /Contents (\string\376\string\377\myfootip)% текст аннотации; префикс перед \myfootip согласно формату pdf идентифициует строку unicode
  /AP <<
   /N \emptyicon\space 0 R% ссылка на создаваемый в начале документа объект pdf - основной вид значка аннотации
   /R \emptyicon\space 0 R% вид значка при наведённом указателе мыши
   /D \emptyicon\space 0 R% вид значка при нажатой кнопке мыши
  >>
}%
\footnote{#1}%
\pdfendlink%
\endgroup% изменённые правила назначения каткодов действуют досюда
}


% Цитирование для всплывающей подсказки
\def\extractnumberfromhyperlink#1[#2]#3#4#5#6\relax{#5}
\def\bibitemsnumber#1{\expandafter\expandafter\expandafter\extractnumberfromhyperlink\csname b@#1\endcsname[]{}{}?\relax}
\def\mycite#1{[\bibitemsnumber{#1}]}


\title{Пробный заголовок}
%\subtitle{пробной книги}
\author{epros}
\date{\today}


\begin{document}
   
   \maketitle
   
   \tableofcontents
   
   % Этот код создаёт объект pdf - пустой бокс для использования вместо стандартного значка текстовой аннотации
   \newbox\tempboxa
   \setbox\tempboxa=\hbox{}
   \immediate\pdfxform\tempboxa
   \edef\emptyicon{\the\pdflastxform}% сохраняем номер объекта для использования при вызове макроса \myfootnote
 
   \part{Пробная часть}
   \chapter{Пробная глава}
   \section{Пробный раздел}


    Что же позволяет говорить не просто об эквивалентности, а о равенстве объектов? Для этого они должны быть ещё и неразличимы\myfootnote{Смотри \cite{kalevala}.}{Смотри \mycite{kalevala}.}. Принцип, отождествляющий неразличимость и равенство объектов, известен как <<закон Лейбница>>\myfootnote{См. переписку Лейбница с Кларком в \cite{leibniz_tom1}.}{См. переписку Лейбница с Кларком в \mycite{leibniz_tom1}.}.


{\raggedright
\begin{thebibliography}{99}

   \bibitem{kalevala}Лёнрот. Калевала.
   
   \bibitem{leibniz_tom1}Г.\,В.~Лейбниц. Сочинения в четырёх томах (под редакцией В.\,В.~Соколова, 1982). Том 1. Упоминается на с.%\!\!

\end{thebibliography}
}


\end{document}

К сожалению, я не смог разобраться, как срабатывает этот \extractnumberfromhyperlink (и из чего он, собственно, делает extract). Мне не нравится идея выделять номер из чего-то, зависимого от пакета hyperref. В конце концов, создание гиперссылок можно локально отключить с помощью окружения NoHyper. Правда повторить Ваш результат для случая отключенного hyperref мне не удалось.

Я ведь правильно понимаю, что три \expandafter внутри определения \bibitemsnumber нужны для того, чтобы сначала раскрыть \csname, потом раскрыть \b@..., и только потом применить \extractnumberfromhyperlink к тому, что получилось от раскрытия \b@...? Поскольку я не очень понимаю, во что именно раскрывается \b@... (если вставить его в текст, то печатается номер источника с гиперссылкой, а если внутри окружения NoHyper - то без гиперссылки), то я решил посмотреть. Поэтому я тупо в Вашем примере заменил \extractnumberfromhyperlink на \relax:

Используется синтаксис LaTeX
\def\myct{\makeatletter\expandafter\expandafter\expandafter\relax\csname b@leibniz_tom1\endcsname\makeatother}
\begin{NoHyper}
 \myct
\end{NoHyper}

В итоге печатается номер источника (без гиперссылки). Но это ведь не означает, что в переменной \b@... не содержится ничего другого? Попытка замены \def на \edef сразу же приводит к ошибкам (почему?). Попытка вывести содержимое \myct в файл вот так:

Используется синтаксис LaTeX
\def\myct{\makeatletter\expandafter\expandafter\expandafter\relax\csname b@leibniz_tom1\endcsname\makeatother}
\newwrite\tempf
\immediate\openout\tempf=test.txt
\begin{NoHyper}
 \immediate\write\tempf{\myct}
\end{NoHyper}
 

тоже сразу приводит к ошибкам. Почему? Разве в файл не должен выводиться любой бред, включая нечитаемые последовательности байтов?

 Профиль  
                  
 
 Re: Как обойти \detokenize?
Сообщение29.06.2022, 20:35 
Заслуженный участник


14/10/14
1207
epros в сообщении #1558808 писал(а):
Мне не нравится идея выделять номер из чего-то, зависимого от пакета hyperref.
Мне тоже. Повторяюсь: пакеты портят \b@label, в котором хранится номер. Так что надо либо поискать, откуда ещё его можно выцепить, либо на каком-то этапе спасти его в \old@b@label, либо придётся для каждого набора пакетов и опций использовать отдельный макрос...
epros в сообщении #1558808 писал(а):
В конце концов, создание гиперссылок можно локально отключить с помощью окружения NoHyper.
Насколько я понимаю, при NoHyper макросы hyperref'а вызываются как и раньше, они просто перестают что-либо содержательное делать; но \b@label всё равно остаётся испорченным.
epros в сообщении #1558808 писал(а):
Поскольку я не очень понимаю, во что именно раскрывается \b@...
А я же выше написал, во что оно раскрывается: в \hyper@@link [cite]{}{cite.kalevala\@extra@b@citeb }{1}, смотреть можно с помощью \meaning.

-- 29.06.2022, 21:36 --

epros в сообщении #1558808 писал(а):
Я ведь правильно понимаю, что три \expandafter внутри определения \bibitemsnumber нужны для того, чтобы сначала раскрыть \csname, потом раскрыть \b@..., и только потом применить \extractnumberfromhyperlink к тому, что получилось от раскрытия \b@...?
Да.

 Профиль  
                  
 
 Re: Как обойти \detokenize?
Сообщение29.06.2022, 20:55 
Заслуженный участник
Аватара пользователя


28/09/06
10440
Slav-27 в сообщении #1558804 писал(а):
В принципе-то всё можно прочитать в texmf-dist/tex/latex/base/latex.ltx и в окрестных файлах.

У меня latex.ltx находится в /usr/local/texlive/2022/texmf-dist/tex/latex/base/. Но там я не нашёл ничего криминального.

Ищу \cite, нахожу команду:

Используется синтаксис LaTeX
\DeclareRobustCommand\cite{%
  \@ifnextchar [{\@tempswatrue\@citex}{\@tempswafalse\@citex[]}}

Далее:

Используется синтаксис LaTeX
\def\@citex[#1]#2{\leavevmode
  \let\@citea\@empty
  \@cite{\@for\@citeb:=#2\do
    {\@citea\def\@citea{,\penalty\@m\ }%
     \edef\@citeb{\expandafter\@firstofone\@citeb\@empty}%
     \if@filesw\immediate\write\@auxout{\string\citation{\@citeb}}\fi
     \@ifundefined{b@\@citeb}{\hbox{\reset@font\bfseries ?}%
       \G@refundefinedtrue
       \@latex@warning
         {Citation `\@citeb' on page \thepage \space undefined}}%
       {\@cite@ofmt{\csname b@\@citeb\endcsname}}}}{#1}}

Далее смотрю \@cite@ofmt - это просто \let\@cite@ofmt\hbox. Т.е. \cite просто печатает в боксе то, на что раскрывается \b@..., где вместо троеточия нужно нужно поставить обязательный аргумент \cite. Как и предполагалось.

Чтобы понять, откуда берётся \b@..., ищу \bibcite. Нахожу вот это:

Используется синтаксис LaTeX
\def\bibcite{\@newl@bel b}

Далее вот это:

Используется синтаксис LaTeX
\def\@newl@bel#1#2#3{{%
  \@ifundefined{#1@#2}%
    \relax
    {\gdef \@multiplelabels {%
       \@latex@warning@no@line{There were multiply-defined labels}}%
     \@latex@warning@no@line{Label `#2' multiply defined}}%
  \global\@namedef{#1@#2}{#3}}}

\@namedef в последней строчке - это просто такой вариант \def:

Используется синтаксис LaTeX
\def\@namedef#1{\expandafter\def\csname #1\endcsname}


Отсюда видно, что \bibcite определяет значение \b@... значением своего второго аргумента, только и всего. Никаких подводных камней не видно, в \b@... должен лежать просто текстовой (цифровой) индекс источника. Получается, что все остальные хитрости - это результат переопределения \b@... какими-то пакетами?

 Профиль  
                  
 
 Re: Как обойти \detokenize?
Сообщение29.06.2022, 21:02 
Заслуженный участник


14/10/14
1207
epros в сообщении #1558834 писал(а):
Получается, что все остальные хитрости - это результат переопределения \b@... какими-то пакетами?
Именно так, они переопределяют и \cite, и \b@... . Этим занимаются как минимум babel и hyperref.

 Профиль  
                  
 
 Re: Как обойти \detokenize?
Сообщение29.06.2022, 21:25 
Заслуженный участник
Аватара пользователя


28/09/06
10440
Полазил сейчас в hyperref.sty, вот, что нашёл:

Используется синтаксис LaTeX
  \def\bibcite#1#2{%
    \@newl@bel{b}{#1\@extra@binfo}{%
      \hyper@@link[cite]{}{cite.#1\@extra@b@citeb}{#2}%
    }%
  }%

Только непонятно, почему это определение находится внутри большого блока \ltx@IfUndefined{NAT@parse}{...}.

Зато теперь понятно, откуда берётся этот \hyper@@link[cite]{}{cite.#1\@extra@b@citeb}{#2}. И видно, что старого, не обременённого гиперссылками, значения hyperref даже не пытается где-то сохранить.

Я так предполагаю, что корректным способом решения проблемы должен быть не парсинг "испорченного" пакетами кода, а определение собственного окружения, в рамках которого восстанавливается "неиспорченные" значения переменных (возможно, под другими именами).

-- Ср июн 29, 2022 22:44:11 --

Может быть как-то так:

Используется синтаксис LaTeX
  \def\oldbibcite{\bibcite}
  \def\bibcite#1#2{%
    \oldbibcite{#1}{#2}%
    \@newl@bel{B}{#1\@extra@binfo}{#2}%
  }%

И в своих макросах пользоваться переменной \B@...? Или это породит бесконечную рекурсию определений?

 Профиль  
                  
 
 Re: Как обойти \detokenize?
Сообщение29.06.2022, 22:18 
Заслуженный участник


14/10/14
1207
epros в сообщении #1558841 писал(а):
Или это породит бесконечную рекурсию определений?
Наверно, вместо \def где-то надо \let.
Советую спросить на tex.stackexchange.com.

 Профиль  
                  
 
 Re: Как обойти \detokenize?
Сообщение29.06.2022, 23:08 
Заслуженный участник
Аватара пользователя


28/09/06
10440
Оу, с \let сработало. Вот этот код в преамбуле:

Используется синтаксис LaTeX
\makeatletter
\let\oldbibcite=\bibcite
\def\bibcite#1#2{%
    \oldbibcite{#1}{#2}
    \@newl@bel{B}{#1\@extra@binfo}{#2}%
}%
\makeatother
\bibcite{leibniz}{2}

Создаёт и переменную \b@leibniz, содержащую двойку с гиперссылкой, и переменную \B@leibniz, содержащую двойку без гиперссылки:

Используется синтаксис LaTeX
macro:->\hyper@@link [cite]{}{cite.leibniz\@extra@b@citeb }{2}
macro:->2

Только почему-то \meaning для обеих команд теперь выдаёт одно и то же, т.е. для переопределённой команды \bibcite показывает старый код.

Теперь нужно попробовать докрутить макросы, чтобы они использовали переменную \B@...

 Профиль  
                  
 
 Re: Как обойти \detokenize?
Сообщение30.06.2022, 09:44 
Заслуженный участник


14/10/14
1207
epros в сообщении #1558856 писал(а):
Вот этот код в преамбуле
Здорово! Теперь можно
Используется синтаксис LaTeX
\def\mycite#1{[\expandafter\ifx\csname B@#1\endcsname\relax?\else\csname B@#1\endcsname\fi]}

Остаётся только понять, как сделать, чтобы 2 раза сноску не писать. Я что-то видел на эту тему на tex.SE, надо то ли записать аргумент в файл и сделать \input, то ли даже без записи в файл как-то можно обойтись.

 Профиль  
                  
 
 Re: Как обойти \detokenize?
Сообщение30.06.2022, 15:13 
Заслуженный участник
Аватара пользователя


28/09/06
10440
Вот такой получился рабочий код:
код: [ скачать ] [ спрятать ]
Используется синтаксис LaTeX
\documentclass[
    a4paper,% размеры листа
    11pt,% размеры нормального шрифта
    toc=bibliography% включить в содержание литературу
    ]{scrbook} % книга KOMAscript, см. scrguien.pdf

\usepackage[T2A]{fontenc}% Выбор внутренней TeX−кодировки
\usepackage[utf8]{inputenc}% Выбор кодовой страницы документа.
\usepackage[english,russian]{babel}% Выбор языка документа.
\usepackage{indentfirst}% Начинать первый параграф с красной строки.
\usepackage{xcolor}% Для работы с цветами, включая гиперссылки
\usepackage{stringenc}% Конвертер кодировок, позволяет из utf8 делать utf16le
\usepackage[hyperfootnotes=false,pagebackref=true,pdftex]{hyperref}% Для гиперссылок, включая из оглавления, на библиографию и обратные
\hypersetup{
    colorlinks=true% ссылки будут выделяться цветом, а не рамкой
}

\title{Пробный заголовок}
\subtitle{пробной книги}
\author{епрос}
\date{\today}

\def\setcatcodes#1#2#3{% байтам в диапазоне #1-#2 устанавливает каткод #3
\ifnum #1<\numexpr 1+#2\relax\catcode#1=#3\expandafter
  \setcatcodes\expandafter{\the\numexpr 1+#1\relax}{#2}{#3}\fi}

\makeatletter
\StringEncodingConvert\reauthor{\expandafter\detokenize\expandafter{\@author}}{utf8}{utf16le}% перекодируем имя автора в utf-16le
\let\oldbibcite=\bibcite% сохраняем старую версию макроса, записывающего номера источников для ссылок на литературу
\def\bibcite#1#2{% новая версия макроса
    \oldbibcite{#1}{#2}% выполяет всё то же, что и старая, чтобы где нужно ссылки на литературу были с гиперссылками
    \@newl@bel{B}{#1\@extra@binfo}{#2}% и определяет новую переменную, в которую записывается номер источника без гиперссылок
}%
\makeatother
\def\mycite#1{[\expandafter\ifx\csname B@#1\endcsname\relax?\else\csname B@#1\endcsname\fi]}% ссылки на литературу без гиперссылок

% Макрос создаёт сноску с всплывающей подсказкой (второй аргумент); первый агрумент - содержимое нормальной сноски внизу страницы
\def\myfootnote#1{%
\begingroup\setcatcodes{128}{255}{12}\myfootnoteaux{#1}}
\def\myfootnoteaux#1#2{%
\edef\myfootipUTFeight{#2}%
\StringEncodingConvert\myfootip{\myfootipUTFeight}{utf8}{utf16le}%
\pdfstartlink user{%
  /Subtype /Text% создаётся аннотация типа Text
  /T (\detokenize{^^ff^^fe}\reauthor)% автор аннотации; префикс перед \reauthor согласно формату pdf идентифицирует строку UTF-16LE
  /Contents (\detokenize{^^ff^^fe}\myfootip)% текст аннотации
  /AP <<
   /N \emptyicon\space 0 R% ссылка на создаваемый в начале документа объект pdf - основной вид значка аннотации
   /R \emptyicon\space 0 R% вид значка при наведённом указателе мыши
   /D \emptyicon\space 0 R% вид значка при нажатой кнопке мыши
  >>
}%
\footnote{#1}%
\pdfendlink%
\endgroup% изменённые каткоды байтов 128-255 действуют досюда
}%

\begin{document}
   
    \maketitle
   
        \tableofcontents
       
        % Этот код создаёт объект pdf - пустой бокс для использования вместо стандартного значка текстовой аннотации
        \newbox\tempboxa
        \setbox\tempboxa=\hbox{}
        \immediate\pdfxform\tempboxa
        \edef\emptyicon{\the\pdflastxform}% сохраняем номер объекта для использования при вызове макроса \myfootnote

        \part{Пробная часть}
        \chapter{Пробная глава}
        \section{Пробный раздел}
    Что же позволяет говорить не просто об эквивалентности, а о равенстве объектов? Для этого они должны быть ещё и неразличимы. Принцип, отождествляющий неразличимость и равенство объектов, известен как <<закон Лейбница>>\myfootnote{См. переписку Лейбница с Кларком в~\cite{leibniz_tom1}.}{См. переписку Лейбница с Кларком в \mycite{leibniz_tom1}.}.
   
{\raggedright
\begin{thebibliography}{99}
       
        \bibitem{leibniz_tom1}Г.\,В.~Лейбниц. Сочинения в четырёх томах (под редакцией В.\,В.~Соколова, 1982). Том 1. Упоминается на с.\!\!

\end{thebibliography}
}

\end{document}

Я решил перекодировать каткоды не русским буквам, а всем байтам в диапазоне кодов 128-255. Всё равно там ничего, кроме "активных символов" нет. Для русских букв перекодировка срабатывает для байтов с кодами 128-191,208,209. С учётом того, что у меня в комментариях попадаются и греческие буквы с матсимволами и т.п., думаю, что так будет правильнее.

Огромное спасибо за неоценимую помощь!

Slav-27 в сообщении #1558893 писал(а):
Остаётся только понять, как сделать, чтобы 2 раза сноску не писать. Я что-то видел на эту тему на tex.SE, надо то ли записать аргумент в файл и сделать \input, то ли даже без записи в файл как-то можно обойтись.
Это уже не столь критично, поскольку второй аргумент заполняется один раз копипастом из сгенерированного pdf-файла. Таким образом нормально отображаются даже большинство матформул (не считая "многоэтажных" - типа дробей, индексов и форматирований). Так что это не напрягает так сильно, как номера источников в ссылках на библиографию, которые могут в любой момент съехать и их придётся везде перепроверять.

Наверное, в принципе можно было бы что-то придумать. Но проблема в том, что скомпилированный текст в pdf вносится отнюдь не в форме строк символов unicode. Конечно, для целей копипаста предусмотрена такая вещь, как "коды unicode выделенных символов", которые нормальные pdf-ридеры способны прочитать из соответствующих объектов файла pdf, а потом, при нажатии пользователем Ctrl-C, сформировать из них строку в буфере обмена. Но как их выцепить на этапе компиляции исходного кода pdfTeX я пока не знаю.

 Профиль  
                  
 
 Re: Как обойти \detokenize?
Сообщение30.06.2022, 17:14 
Заслуженный участник


14/10/14
1207
Не знаю, что такое \@extra@binfo, но, насколько я понимаю, вы его то используете, то не используете как часть имени переменной; работает, наверно, из-за того, что сейчас оно пустое.

Как вариант, можно попробовать раскрывать не всё на свете, а только \mycite (вполне возможно, что тогда удастся обойтись без этих дурацких изменений каткодов).
Результат при желании можно скармливать какому-нибудь конвертеру LaTeX в Юникод.

Пожалуйста, мне в общем самому было интересно поразбираться, как что работает.

 Профиль  
                  
Показать сообщения за:  Поле сортировки  
Начать новую тему Ответить на тему  [ Сообщений: 37 ]  На страницу Пред.  1, 2, 3  След.

Модераторы: Karan, Toucan, PAV, maxal, Супермодераторы



Кто сейчас на конференции

Сейчас этот форум просматривают: нет зарегистрированных пользователей


Вы не можете начинать темы
Вы не можете отвечать на сообщения
Вы не можете редактировать свои сообщения
Вы не можете удалять свои сообщения
Вы не можете добавлять вложения

Найти:
Powered by phpBB © 2000, 2002, 2005, 2007 phpBB Group