2014 dxdy logo

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

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




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


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

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


28/09/06
11353
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
11353
Экспериментальным путём установлено, что добавление в преамбулу (а она может быть только там) команды:

Используется синтаксис 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
1220
"Изначально" \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
1220
(\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
11353
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
1220
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
11353
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
1220
epros в сообщении #1558834 писал(а):
Получается, что все остальные хитрости - это результат переопределения \b@... какими-то пакетами?
Именно так, они переопределяют и \cite, и \b@... . Этим занимаются как минимум babel и hyperref.

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


28/09/06
11353
Полазил сейчас в 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
1220
epros в сообщении #1558841 писал(а):
Или это породит бесконечную рекурсию определений?
Наверно, вместо \def где-то надо \let.
Советую спросить на tex.stackexchange.com.

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


28/09/06
11353
Оу, с \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
1220
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
11353
Вот такой получился рабочий код:
код: [ скачать ] [ спрятать ]
Используется синтаксис 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
1220
Не знаю, что такое \@extra@binfo, но, насколько я понимаю, вы его то используете, то не используете как часть имени переменной; работает, наверно, из-за того, что сейчас оно пустое.

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

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

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

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



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

Сейчас этот форум просматривают: Taus


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

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