csquotes и beamer: цитата для blockquote смещена вправо на отдельную строку

csquotes и beamer: цитата для blockquote смещена вправо на отдельную строку

С csquotes, (необязательное) цитирование длинного текста \blockquoteпо умолчанию помещается сразу после самой цитаты. Если вы хотите, чтобы цитата была на следующей строке и выровнена по правому краю, вы можете сделать

\renewcommand{\mkblockquote}[4]{#1#2\par\hfill#4#3}

что отлично работает в стандартных классах:

\documentclass{article}
\usepackage{csquotes,lipsum}
\renewcommand{\mkblockquote}[4]{#1#2\par\hfill#4#3}
\begin{document}
\blockquote[Some Bloke][]{\lipsum*[2]}
\end{document}

введите описание изображения здесь

Однако, beamerэто не работает, переопределение \mkblockquoteне имеет никакого эффекта, насколько я могу судить. Есть ли какой-то способ заставить это работать beamerи в рамке?

MWE, обратите внимание на положение(Какой-то парень)по сравнению с примером articleвыше:

\documentclass{beamer}
\usepackage{csquotes,lipsum}
\renewcommand{\mkblockquote}[4]{#1#2\par\hfill#4#3}
\begin{document}
\begin{frame}
\blockquote[Some Bloke][]{\lipsum*[2]}
\end{frame}
\end{document}

введите описание изображения здесь

(Кстати, я, конечно, знаю, что мне не нужно csquotesприводить такую ​​цитату, поэтому ответ, который говорит что-то вроде"откажитесь от \blockquoteи используйте \lipsum*[2]\par\hfill(Some Bloke)"не так уж и интересно.)

решение1

Это произошло из-за ошибки, csquotesкоторая исправлена ​​вверсия 5.2а(дата выпуска 2017-02-03). Анализ и обходной путь для версии до 5.2a приведены ниже.


Применение \tracingallили размещение «маркера» внутри \mkblockquoteпокажет, что он никогда не выполняется в этом beamerслучае. Причина в том, что csquotesпроверяет, находится ли TeX в «соответствующем» режиме для создания отображаемого материала как части \blockquote. Если этот тест не пройден, цитата устанавливается как текстовая цитата.

Тест, используемый csquotesпримитивом \ifinner, является истинным внутри примитивных конструкций \hboxи (что особенно важно) в начале абзаца в \vboxили \vtop. (TeX находится в ограниченном горизонтальном режиме и ограниченном вертикальном режиме соответственно.) Фреймы создаются в beamerвиде вертикальных блоков, поэтому первый материал, помещенный во фрейм, имеет именно последнее условие. Это означает, что csquotesвидит контекст как «неподходящий» для отображения и переходит по текстовому маршруту.

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

\documentclass{beamer}
\usepackage{csquotes,lipsum}
\renewcommand{\mkblockquote}[4]{#1#2\par\hfill#4#3}
\begin{document}
\begin{frame}
\leavevmode
\blockquote[Some Bloke][]{\lipsum*[2]}
\end{frame}
\end{document}

В этом articleслучае TeX находится внеограниченныйвертикальный режим (основной вертикальный список), когда \blockquoteвстречается so, \ifinnerто это ложно и выбирается маршрут блочной цитаты.


Дефектный код был

\long\def\csq@bquote#1#2#3#4#5#6{%
  \csq@ifnested
    {\csq@err@nbquote}
    {\csq@getpunct{%
       \ifbool{inner}
         {\csq@bquote@ii}
     {\ifbool{csdisplay}
        {\csq@bquote@i}
        {\iftoggle{csq@parbox}\csq@bquote@ii\csq@bquote@i}}%
     {#1}{#2}{#3}{#4}{#5}{#6}}}}

где неисправная линия \ifbool{inner}. Как уже отмечалось, это будет справедливо как для горизонтального, так и для вертикального режима. Замена на

\ifboolexpr{ bool {inner} and bool {hmode} }

исправляет это, так как теперь это верно только внутри \hbox. Исправление делает задокументированное поведение внутри \parboxи подобных активным, поскольку они устанавливают csq@parbox, в то время как beamerиспользует 'raw' \vboxдля кадров, теперь это работает как для основного вертикального списка.

Можно использовать etoolboxдля исправления дефектного кода во время ожидания обновления:

\makeatletter
\patchcmd{\csq@bquote}{\ifbool{inner}}{\ifboolexpr{ bool {inner} and bool {hmode} }}
  {}{}
\makeatother

Связанный контент