2014 dxdy logo

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

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




Начать новую тему Ответить на тему На страницу Пред.  1, 2, 3
 
 Re: Как обойти \detokenize?
Сообщение30.06.2022, 20:08 
Заслуженный участник
Аватара пользователя


28/09/06
10981
Slav-27 в сообщении #1558936 писал(а):
Не знаю, что такое \@extra@binfo, но, насколько я понимаю, вы его то используете, то не используете как часть имени переменной; работает, наверно, из-за того, что сейчас оно пустое.

Я тоже не знаю, что это такое, взял из кода hyperref.sty как есть. Там эта переменная определяется пустой строкой и при каких условиях и чем она может заполняться - непонятно.

Вообще-то в коде есть ещё что поулучшать. Например, этот \mycite нормально работает только с одним аргументом, в отличие от фирменного \cite, который может принимать и корректно обрабатывать в аргументе список меток, разделённых запятыми. И, разумеется, он не принимает опциональный аргумент, который у фирменного \cite используется для дополнительных комментариев, печатаемых внутри квадратных скобок (типа указания раздела или страницы в источнике). Но с этим уже не хочется возиться. В конце концов, в тех редких случаях, когда у меня в сносках встретится такое, можно отредактировать руками.

Ещё одно направление для улучшения - это защитить текст аннотации от случайного появления всяческих специальных символов, типа слешей или несбалансированных скобок. Хотя я сомневаюсь, что мне понадобится писать в комментариях слеши или несбалансированные скобки, но потом как-нибудь это можно будет сделать. Для этого, вроде, есть специальная команда, \pdfescapestring, если не ошибаюсь.

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

Почему же дурацких? По-моему, очень логичное и красивое решение. И вряд ли оно может что-то испортить, поскольку изменения действуют только внутри макроса. Если я правильно понял, все эти назначения каткода 13 для байтов в диапазоне кодов 128-255 делает babel, причём исключительно для того, чтобы потом иметь возможность распознать и корректно транслировать в pdf символы utf-8.

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


14/10/14
1220
А может, можно спасти не только старый \b@... , но и старый \cite.

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


28/09/06
10981
Slav-27 в сообщении #1558951 писал(а):
А может, можно спасти не только старый \b@... , но и старый \cite.

Его ведь придётся не просто спасать, но и переделывать с использования \b@... на использование \B@... По-сути это означает, что нужно будет достать из latex.ltx и отредактировать определения \cite и связанных с ним вещей. Можно, конечно, заняться как-нибудь на досуге.

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


28/09/06
10981
Оказывается этот вариант кода зависим от наличия пакета hyperref, что совсем не есть хорошо. Отключив hyperref, я обнаружил странную вещь: Распознаваться стал только первый номер источника, для второго и последующих вызовов модифицированный макрос \bibcite уже не работает. Разбирательство показало следующее. В таком варианте (без hyperref) макрос \bibcite при первом проходе выполняет разнообразные проверки установленных пакетов, а также переопределяет вызов \bibcite на "базовый" вариант макроса, в котором, естественно, добавленной мной операции, определяющей переменную \B@..., нет.

Вот так выглядят расшифровки кодов макросов с помощью команды \meaning при первом вызове:

Используется синтаксис LaTeX
bibcite: macro:->\bbl@cite@choice \bibcite
bbl@cite@choice: macro:->\global \let \bibcite \bbl@bibcite \@ifpackageloaded {natbib}{\global \let \bibcite \org@bibcite }{}\@ifpackageloaded {cite}{\global \let \bibcite \org@bibcite }{}\global \let \bbl@cite@choice \relax
bbl@bibcite: macro:#1#2->\org@bibcite {#1}{\@safe@activesfalse #2}
@ifpackageloaded: macro:->\@ifl@aded \@pkgextension
org@bibcite: macro:->\@newl@bel b
@safe@activesfalse: macro:->\let \if@safe@actives \iffalse

А вот так при втором:

Используется синтаксис LaTeX
bibcite: macro:#1#2->\org@bibcite {#1}{\@safe@activesfalse #2}
bbl@cite@choice: \relax
bbl@bibcite: macro:#1#2->\org@bibcite {#1}{\@safe@activesfalse #2}
@ifpackageloaded: macro:->\@ifl@aded \@pkgextension
org@bibcite: macro:->\@newl@bel b
@safe@activesfalse: macro:->\let \if@safe@actives \iffalse

Т.е. при первом вызове \bibcite сначала вызывается \bbl@cite@choice, который первым делом переопределяет \bibcite на \bbl@bibcite. И мы видим, что при следующем вызове \bibcite уже такой же, как этот \bbl@bibcite.

Я не знаю, как корректно обойти такие трюки. Конечно, я могу в своём коде макроса \bibcite тупо заменить обращение к \oldbibcite на этот \bbl@bibcite, но это, в свою очередь, сделает код несовместимым с hyperref (и Бог знает с чем ещё). Городить в своём коде дополнительные проверки на наличие или отсутствие тех или иных пакетов тоже как-то не хочется. Неужели программирование на TeX всегда выглядит так криво?

Попытка восстанавливать "испорченную" ссылку на мою процедуру \bibcite вот таким образом:

Используется синтаксис LaTeX
\let\oldbibcite\bibcite% сохраняем старую версию макроса, записывающего номера источников для ссылок на литературу
\def\newbibcite#1#2{% новая версия макроса
\oldbibcite{#1}{#2}% сначала вызывает старую,
\global\let\bibcite\newbibcite% а потом восстанавливает испорченную ссылку на себя
\@newl@bel{B}{#1}{#2}% и определяет новую переменную, в которую записывается номер источника без гиперссылок
}%
\let\bibcite\newbibcite

приводит к переполнению стека на втором вызове \bibcite.

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


14/10/14
1220
Нельзя ли сделать с \bbl@bibcite то же, что вы уже сделали с \bibcite, чтобы она тоже создавала 2 переменные, b@ и B@?
Из ваших объяснений я не понял, в чём принципиальное отличие hyperref от babel: почему ваш метод преодолевает переопределения, осуществляемые hyperref'ом, но не преодолевает осуществляемые babel'ем?

-- 02.07.2022, 14:55 --

epros в сообщении #1559096 писал(а):
Неужели программирование на TeX всегда выглядит так криво?
На то и собака, что лезть туда не положено, а мы ещё и не умеем.

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


28/09/06
10981
Slav-27 в сообщении #1559098 писал(а):
Нельзя ли сделать с \bbl@bibcite то же, что вы уже сделали с \bibcite, чтобы она тоже создавала 2 переменные, b@ и B@?

А смысл? hyperref переопределяет \bibcite вот так:

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

так что \bbl@bibcite с hyperref, похоже, вообще использоваться не будет. А если мы хотим работать только с babel без hyperref, то заменить в коде макроса \bibcite обращение к \oldbibcite на \bbl@bibcite - самое простое решение. Но при другой конфигурации пакетов оно уже не будет работать.

Slav-27 в сообщении #1559098 писал(а):
почему ваш метод преодолевает переопределения, осуществляемые hyperref'ом, но не преодолевает осуществляемые babel'ем?

Потому что babel определяет \bibcite таким образом, что при первом же обращении его код заменяется. Поэтому мой код тоже будет заменён. Последний приведённый мной код - это попытка тупо восстановить мой код. Но она почему-то не срабатывает.

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


28/09/06
10981
Дело ещё в том, что пакет hyperref вызывает у меня множество сомнений. С одной стороны, он делает массу полезного. Например, не хотелось бы самостоятельно на уровне создания объектов PDF программировать гиперссылки - как стандартные (на метки внутри документа), так и на пунктах оглавления, на литературу и т.п. С другой стороны он многие вещи делает очень уж криво.

Например, если определять метаданные (это заголовок, подзаголовок, имя автора и т.п., которые ридер PDF показывает, если выбрать в меню "свойства файла") с помощью hyperref-овской команды \hypersetup, то хотя они и отображаются ридерами корректно, но в коде PDF прописаны очень уж криво - без разбивки на строки, большей частью в виде 8-байтовых последовательностей на каждый символ (на каждый из двух байтов UTF-16BE отделенные слешем три восьмеричные цифры). С помощью команды \pdfinfo я могу записать метаданные в более приличной форме, например, так:

Код:
503 0 obj
<<
/Title <FFFE5400690074006C006500>
/Subject <FFFE5300750062007400690074006C006500>
/Author <FFFE41007500740068006F007200>
/Keywords <FFFE4B006500790077006F00720064007300>
/Producer <FFFE53006F006D00650020007400650078007400>
/Creator <>
/Trapped /False
>>
endobj

Но если я подключаю hyperref, то получаю вот это:

Код:
1702 0 obj
<<
/Title <FFFE5400690074006C006500>
/Subject <FFFE5300750062007400690074006C006500>
/Author <FFFE41007500740068006F007200>
/Keywords <FFFE4B006500790077006F00720064007300>
/Producer <FFFE53006F006D00650020007400650078007400>
/Creator <>
/Trapped /False/Author()/Title()/Subject()/Creator(LaTeX with hyperref)/Keywords()
>>
endobj

Как видите, hyperref сразу же дописал в объект пустые строки: /Author()/Title()/Subject()/Creator(LaTeX with hyperref)/Keywords(). И это только результат загрузки пакета, ни одной команды ему не подано. Отключить это тоже непонятно как. И не всякий ридер такое задвоение полей метаинформации переварит.

С помощью команд pdfTeX переписать это тоже уже невозможно, независимо от того, раньше или позже загрузки пакета hyperref они подаются. Получается, что я просто вынужден для записи метаинформации пользоваться функциями пакета hyperref, при всей их кривизне, отказавшись от нормального форматирования.

В общем, пакет наводит на мысли про кривые ручки разработчиков.

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

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



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

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


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

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