[Tex/LaTex] Customizing style of formal block quote in csquotes

csquotesquoting

The MWE below:

% pdflatex test.tex; biber test; pdflatex test.tex; pdflatex test.tex
\documentclass{article}

\usepackage[autostyle=tryonce,autopunct=true]{csquotes}
\usepackage[%
  style=ieee,
  isbn=true,
  doi=false,
  url=true,
  defernumbers=true,
  sorting=nyt,
  %sorting=none, % "Do not sort at all. All entries are processed in citation order." (order of appearance)
  firstinits=false, % shows full first name
  backend=biber
]{biblatex}
\usepackage[UKenglish,USenglish]{babel}

\addbibresource{biblatex-examples.bib}
% @book{knuth:ct:a,
%   author       = {Knuth, Donald E.},
%   title        = {The \TeX book},
%   date         = 1984,

\usepackage{xcolor}
\pagecolor{yellow!10}

% [http://www.latex-community.org/forum/viewtopic.php?f=44&t=5444 csquotes package question • Text Formatting • LaTeX Community]
% \renewenvironment{quoteblock}{\openautoquote}{\closeautoquote} % quoteblock has been removed from csquotes!
% \renewcommand{\mkblockquote}[4]{\openautoquote{\itshape#1#2}#4#3\closeautoquote} % <--! works, but changes all

% http://tex.stackexchange.com/questions/39285/whats-the-advantage-of-using-csquotes-over-using-an-editors-auto-replacement-f
\begin{document}

\hyphenquote{UKenglish}{quote with UK English hyphenation}

\textcquote[1]{knuth:ct:a}{formal quote}

\hyphentextcquote{UKenglish}[1]{knuth:ct:a}{formal quote with UK English hyphenation}

\hyphenblockcquote{UKenglish}[1]{knuth:ct:a}{A long formal quote with UK English hyphenation which happens to be longer than three lines and, thus, is typeset as a block quote. This text is just to make it long enough. This text is just to make it long enough. This text is just to make it long enough.}

\printbibliography[sorting=none]

\end{document}

… currently produces this output:

test.png

What I'd like to get, is a block quotation that starts and ends with the right quotation marks, the text inside is styled italic, and the italic stops before the bibliography citation; that is:

testb.png

… which I can get by uncommenting the line marked with <--!, that is, \renewcommand{\mkblockquote}[4]{\openautoquote{\itshape#1#2}#4#3\closeautoquote}. This command, however, changes a relatively low-level \mkblockquote command.

So what I'd like to do now, is to have the default behavior of \hyphenblockcquote unchanged, and have a sort of a customized formal block quote environment instead. Ideally, I'd like to have a sort of a style option that I could use with \hyphenblockcquote – but if that is impossible, then I'd settle for a custom command (with a similar syntax like \hyphenblockcquote).

What would be the csquotes recommended way to achieve this?

Best Answer

Well, apparently what I wanted was a feature not yet implemented. I think I managed to solve it somewhat:

test1.png

... the MWE is below, and it required definitions and use of new user commands, \DeclareQuoteBlockStyle and \setquoteblockstyle. However, some discussion may be in order.

  • All this business with inner and outer quoting is only possible if you use \enquote{...} inside your e.g. \hyphentextcquote; I thought it was doable also by defining characters via \MakeOuterQuote/\MakeAutoQuote - but it seems not.
  • When you make a style in \DeclareQuoteStyle, it is by default not "applied" anywhere - unless you happen to alias it with the same name as a currently chosen language.
  • In order to "apply"/"activate" such a quote style, you cannot use \ExecuteQuoteOptions or \setkeys, as they run only in preamble; there is actually a command for that, and it is \setquotestyle
  • When you use csquotes' \DeclareQuoteAlias[variant]{style}{alias}, note that you can use the alias only in \setquotestyle{alias}; you can not use the alias in \hyphentextcquote{alias}... (wasted so much time on this). \hyphentextcquote and the like are multilingual commands, and the first argument for them is supposed to be an actual language (as seen by e.g. babel). If it happens that the language chosen for \hyphentextcquote etc. also has a quote style alias with the same name, then the quote style will be applied.
  • When you call \setquotestyle[italic]{english} (originating from \DeclareQuoteStyle[italic]{english}...) you force csquotes to exit "multilingual mode"; and then the language settings in \hyphentextcquote{language}... don't matter; the quote style from \setquotestyle takes priority. To go back to multilingual mode, use the starred \setquotestyle* (no arguments).

Some complication was encountered when looking for the customization of the block quote style; I tried \unravel{} around the \hyphentextcquote - that resulted with ~14000 steps, and \mkblockquote (which obviously has an influence, given the OP), didn't even show! What did show, however, was \csq@bquote@iii, the only command that calls it. From its definition, it's clear that there's no other way to edit the block quote style but to redefine \mkblockquote.

So that's what the new commands do:

  • \DeclareQuoteBlockStyle is the same as \DeclareQuoteStyle, but it has an extra first optional argument, where we can specify a definition for a \mkblockquote as a "style"; this gets saved under a name derived from the [variant]{style} names (so it should be able to handle multiple styles); and
  • \setquoteblockstyle is the same as \setquotestyle, but it also sets the saved "block style" definition as per [variant]{style} to \mkblockquote so its active; \setquoteblockstyle* also restores \mkblockquote to its original definition.

Note that once \setquote(block)style has properly set the quote style, then the style will also be applied via \openautoquote, if it is present in \mkblockquote, to block quotes! So, any additional formatting in \mkblockquote for block quotes will be added in addition to set style via \openautoquote; that is why I used \bfseries in there, so it can be seen on the MWE which covers what.

Well, hope I didn't misunderstood the manual, and I didn't code all this in vain :) Anyways, here - csquotes_test.tex @gist.github.com - is a previous test file with some comments; and the final MWE is:

% pdflatex test.tex; biber test; pdflatex test.tex; pdflatex test.tex
\documentclass{article}

\usepackage[utf8]{inputenc}
\usepackage[T1]{fontenc}
% \usepackage{unravel}

\usepackage[autostyle=tryonce,autopunct=true]{csquotes}
\usepackage[style=ieee, isbn=true, doi=false, url=true, defernumbers=true, sorting=nyt, firstinits=false, backend=biber]{biblatex}
\usepackage[UKenglish,USenglish]{babel}
\addbibresource{biblatex-examples.bib}

\usepackage{xcolor}
\pagecolor{yellow!10}

% start hacks:
\makeatletter
  % prepare vars
  \let\csq@oldblockstyle\mkblockquote
  \def\csq@newblockstyle{}
  % cmd to declare a quote and block style
  \newrobustcmd*{\DeclareQuoteBlockStyle}[2][]{%
    \let\if@safe@actives\iftrue
    \ifblank{#1}
      {\typeout{DQBS: 1 is blank}}
      {%\def\csq@newblockstyle{#1}% new variable; but cannot handle `#1` in '#1', which \mkblockquote below needs
       % save for \mkblockquote
       \renewcommand{\csq@newblockstyle}[4]{#1}
       \typeout{DQBS: 1 is \meaning\csq@newblockstyle} %#1}%
      }
    \DeclareQuoteBlockStyleI#2%
  }
  % helper to extract the names
  \newrobustcmd*{\DeclareQuoteBlockStyleI}[2][]{%
    \begingroup
    \let\if@safe@actives\iftrue
    \ifblank{#1}
      {\typeout{DQBSI: 1 is blank, 2 is '#2'}%
      % \DeclareQuoteStyle#2 % cannot, args are gobbled, must use low-level now:
      \edef\csq@tempa{#2}
      }%
      {\typeout{DQBSI: 1 is '#1', 2 is '#2'}%
      %\DeclareQuoteStyle[1]#2\expandafter % cannot...
      \edef\csq@tempa{#2/#1}
      }
    % \let assigned vars should survive renewcommand of @newblockstyle;
    % but must be global, else other code can't see it:
    \global\cslet{csq@blkstyle@\csq@tempa}{\csq@newblockstyle}
    \typeout{Command: csq@blkstyle@\csq@tempa -> \expandafter\meaning\csname csq@blkstyle@\csq@tempa \endcsname}
    \@ifnextchar[%] % continue w/ low-level
      {\csq@declareqstyle@i}
      {\csq@declareqstyle@i[]}%
  }
  % cmd to set also block style when changing quote style
  \newrobustcmd*{\setquoteblockstyle}{%
    \@ifstar
      {\typeout{setquoteblockstyle has to restore}%}
      \let\mkblockquote\csq@oldblockstyle % restore block quote style
      \setquotestyle*} % here the star is gobbled, so must re-add it manually!
      {\@ifnextchar[%]
         {\typeout{setquoteblockstyle has two} %'#1' and '#2'}} "! Illegal parameter number in definition"
         \setquoteblockstyleI}
         {\typeout{setquoteblockstyle has only one} %'#1'}}%
         \setquoteblockstyleI}
      }%
      %\setquotestyle% proceed with original; here will also claim the * correctly and will work - but makes the \@ifstar/\@ifnextchar switch above incorrect, so must include it everywhere separately
  }
  % helper - so we can capture the args
  \def\setquoteblockstyleI[#1]#2{%
    \ifblank{#1}
      { \edef\csq@tempa{#2}%
        \csletcs{mkblockquote}{csq@blkstyle@\csq@tempa}%
        \setquotestyle{#2}%
      }
      { \edef\csq@tempa{#2/#1}%
        \typeout{mkblockquote was \meaning\mkblockquote}%
        \csletcs{mkblockquote}{csq@blkstyle@\csq@tempa}%
        \typeout{mkblockquote csq@blkstyle@\csq@tempa, is now \meaning\mkblockquote}% undefined
        \setquotestyle[#1]{#2}%
      }%
  }
\makeatother
% end hacks

% the original use: (now as first opt arg in \DeclareQuoteBlockStyle)
% \renewcommand{\mkblockquote}[4]{\openautoquote{\itshape##1##2}##4##3\closeautoquote}

% \DeclareQuoteBlockStyle[]% leave like this for #1 blank...
\DeclareQuoteBlockStyle[%
  \openautoquote{\bfseries#1#2}#4#3\closeautoquote% \mkblockquote contents (block style)
]%
[italics]{english}%
[\itshape]
[\normalfont]
  {>\textquoteleft}
  {\textquoteright<}
  [0.05em]
  {>{>}\textquotedblleft}
  {\textquotedblright<{<}}
\DeclareQuoteAlias[italics]{english}{ITenglish}


\begin{document}

\hyphenquote{UKenglish}{quote with UK English hyphenation}

% \ExecuteQuoteOptions{english=italics} % only in preamble!
% \setkeys{csq}{english=italics} % only in preamble!
% \setquotestyle{debug} % ok
% \setquotestyle[italics]{english}
\setquoteblockstyle[italics]{english}

\textcquote[1]{knuth:ct:a}{formal quote}

\hyphentextcquote{UKenglish}[1]{knuth:ct:a}{formal quote \enquote{with UK} English hyphenation}

\MakeOuterQuote{"}
\hyphentextcquote{UKenglish}[1]{knuth:ct:a}{formal quote "with UK" English hyphenation}

\MakeAutoQuote{«}{»}
\hyphentextcquote{UKenglish}[1]{knuth:ct:a}{formal quote «with UK» English hyphenation}

\hyphenblockcquote{UKenglish}[1]{knuth:ct:a}{A long formal quote with UK English hyphenation which \enquote{happens to be longer than three lines}, thus, is typeset as a block quote. This text is just to make it long enough. This text is just to make it long enough. This text is just to make it long enough.}


% \setquotestyle*
\setquoteblockstyle*

\hyphenblockcquote{english}[1]{knuth:ct:a}{ A long formal quote with UK English hyphenation which \enquote{happens to be longer than three lines} and, thus, is typeset as a block quote. This text is just to make it long enough. This text is just to make it long enough. This text is just to make it long enough.}
\printbibliography[sorting=none]

\end{document}