![Дополнительное место из-за \patchcmd](https://rvso.com/image/281608/%D0%94%D0%BE%D0%BF%D0%BE%D0%BB%D0%BD%D0%B8%D1%82%D0%B5%D0%BB%D1%8C%D0%BD%D0%BE%D0%B5%20%D0%BC%D0%B5%D1%81%D1%82%D0%BE%20%D0%B8%D0%B7-%D0%B7%D0%B0%20%5Cpatchcmd.png)
Похоже, что \patchcmd
from etoolbox
добавляет три нежелательных пробела, как показано ниже:
\documentclass{minimal}
\usepackage{etoolbox}
\begin{document}
\tracingall% 3 spaces in log file
\def\test{1}]\patchcmd\test{1}{2}{}{}[% 3 spaces between brackets in output
\end{document}
Как я могу это исправить?
решение1
Два пробела возникают из-за вызовов \scantokens
, третий — из-за незащищенного конца строки в коде.
\documentclass{minimal}
\usepackage{etoolbox}
\makeatletter
% Add \ifhmode\unskip\fi
\protected\def\etb@ifscanable#1{%
\begingroup
\edef\etb@resrvda{%
\def\noexpand\etb@resrvda####1\detokenize{macro}:####2->####3&{%
####1\def\string\etb@resrvda####2{####3}}%
\edef\noexpand\etb@resrvda{\noexpand\etb@resrvda\meaning#1&}}%
\etb@resrvda
\makeatletter
\scantokens\expandafter{\etb@resrvda}%
%%% ADDITION
\ifhmode\unskip\fi
%%% END ADDITION
\expandafter\endgroup\ifx#1\etb@resrvda
\expandafter\@firstoftwo
\else
\expandafter\@secondoftwo
\fi}
\def\etb@patchcmd@scantoks#1{%
\edef\etb@resrvda{\endgroup
\unexpanded{\makeatletter\scantokens}{#1}%
\catcode\number`\@=\the\catcode`\@\relax}%
\etb@resrvda
%%% ADDITION
\ifhmode\unskip\fi
%%% END ADDITION
}
% Fix a missing `%'
\protected\long\def\etb@ifpattern#1#2{%
\begingroup
\edef\etb@resrvda{%
\def\noexpand\etb@resrvda####1\detokenize{#2}####2&{%
\endgroup\noexpand\noexpand\noexpand\ifblank{####2}}%
\edef\noexpand\etb@resrvda{\noexpand\etb@resrvda
\expandafter\strip@prefix\meaning#1\detokenize{#2}&}%
\noexpand\etb@resrvda}% <---------- MISSING IN etoolbox.sty
\etb@resrvda\@secondoftwo\@firstoftwo}
\makeatother
\begin{document}
\def\test{1}]\patchcmd\test{1}{2}{}{}[% brackets for checking
][% for check
\end{document}
Однако лучшей стратегией будет никогда не использовать его \patchcmd
в горизонтальном режиме.
Соответствующая команда \xpatchcmd
от regexpatch
этой проблемы свободна.
Другой патч мог бы добавить \@empty
в конец двух `\scantokens:
\protected\def\etb@ifscanable#1{%
\begingroup
\edef\etb@resrvda{%
\def\noexpand\etb@resrvda####1\detokenize{macro}:####2->####3&{%
####1\def\string\etb@resrvda####2{####3}}%
\edef\noexpand\etb@resrvda{\noexpand\etb@resrvda\meaning#1&}}%
\etb@resrvda
\makeatletter
\scantokens\expandafter{\etb@resrvda\@empty}% <---- ADDED
\expandafter\endgroup\ifx#1\etb@resrvda
\expandafter\@firstoftwo
\else
\expandafter\@secondoftwo
\fi}
\def\etb@patchcmd@scantoks#1{%
\edef\etb@resrvda{\endgroup
\unexpanded{\makeatletter\scantokens}{#1\noexpand\@empty}% <---- ADDED
\catcode\number`\@=\the\catcode`\@\relax}%
\etb@resrvda}
Во втором случае \noexpand\@empty
необходимо, поскольку мы находимся внутри \edef
. Однако это требует большего количества тестов, чем я склонен делать.
Мне бы хотелось объединить эти две команды с \patchcmd
самим собой, но они сопротивляются этому.