我定义了一个新命令\openintro
,在工作的每个章节中都会调用它。这个命令基本上构造了一个字母句子,如下图所示(不用考虑文本样式):
\openintro{This is a working test}
我使用包中的一些命令来剪切/分割文本,以达到 lettrine 所需的效果。但是,在命令中xstring
使用时出现一些错误。\ref{label}
\openintro{This is a NOT working test due to~\ref{mylabel}}
问题与启用了链接的包有关。当字符串中有链接时,hyperref
命令会出现一些错误。如果我禁用,使用时不会有问题。但我需要使用。你有什么建议来解决这个问题吗?谢谢。\StrBefore
hyperref
\ref
hyperref
梅威瑟:
\documentclass[12pt]{book}
\usepackage{xstring,lettrine}
\usepackage[pagebackref]{hyperref}
\hypersetup{
linktoc=all,
colorlinks=true,
allcolors=red
}%
\newcommand{\openintro}[1]{%
\def\firsttwowords{}%
\def\firstword{}%
\def\firstwordsplit{}%
\def\secondword{}%
\def\firstletter{}%
\def\remainingtext{}%
\def\charcount{}%
\StrBefore[2]{#1}{ }[\firsttwowords]% get the first two words
\StrBefore[1]{\firsttwowords}{ }[\firstword]% get the first word
\StrGobbleLeft{\firstword}{1}[\firstwordsplit]% del the first letter of first word
\StrBehind[1]{\firsttwowords}{ }[\secondword]% get only the second word
\StrLeft{#1}{1}[\firstletter]% get the first letter of first word
\StrLen{\firsttwowords}[\charcount]% count the number of characters of first two words
\StrGobbleLeft{#1}{\charcount}[\remainingtext]% del the number of characters on the left of the whole sentence
\lettrine{\firstletter}{\firstwordsplit~\secondword}~\textit{\remainingtext}\\[1PC]%
}%
\begin{document}
\chapter{test}
\openintro{This is a NOT working test due to~\ref{mylabel}}
\section{Hi there}\label{mylabel}
\end{document}
错误如下:
! Use of \@xs@StrBefore@@ doesn't match its definition.
\@ifnextchar ... \reserved@d =#1\def \reserved@a {
#2}\def \reserved@b {#3}\f...
l.36 ...s a NOT working test due to~\ref{mylabel}}
! Argument of \@firstoftwo has an extra }.
<inserted text>
\par
l.36 ...s a NOT working test due to~\ref{mylabel}}
Runaway argument?
! Paragraph ended before \@firstoftwo was complete.
答案1
的扩展\ref...
会导致错误。但是,xstring
知道\noexpandarg
宏,阻止将主输入字符串的参数扩展为xstring
宏,但在第一次操作之后必须再次启用扩展,使用\expandarg
。
\documentclass[12pt]{book}
\usepackage{xstring,lettrine}
\usepackage[pagebackref]{hyperref}
\hypersetup{
linktoc=all,
colorlinks=true,
allcolors=red
}%
\newcommand{\openintro}[1]{%
\def\firsttwowords{}%
\def\firstword{}%
\def\firstwordsplit{}%
\def\secondword{}%
\def\firstletter{}%
\def\remainingtext{}%
\def\charcount{}%
\noexpandarg%
\StrBefore[2]{#1}{ }[\firsttwowords]% get the first two words
\expandarg% Now expand again
\StrBefore[1]{\firsttwowords}{ }[\firstword]% get the first word
\StrGobbleLeft{\firstword}{1}[\firstwordsplit]% del the first letter of first word
\StrBehind[1]{\firsttwowords}{ }[\secondword]% get only the second word
\StrLeft{#1}{1}[\firstletter]% get the first letter of first word
\StrLen{\firsttwowords}[\charcount]% count the number of characters of first two words
\StrGobbleLeft{#1}{\charcount}[\remainingtext]% del the number of characters on the left of the whole sentence
\lettrine{\firstletter}{\firstwordsplit~\secondword}~\textit{\remainingtext}\\[1PC]%
}%
\begin{document}
\chapter{test}
\openintro{This is a NOT working test due to~\ref{mylabel}}
\section{Hi there}\label{mylabel}
\end{document}
答案2
我觉得这太复杂了。为什么会有\StrBefore
等等的处理?为什么需要letrine
包?你可以这样做:
\documentclass[12pt]{book}
\usepackage[pagebackref]{hyperref}
\hypersetup{
linktoc=all,
colorlinks=true,
allcolors=red
}%
\def\openintro#1{\openintroA #1 \end}
\def\openintroA#1#2 #3 #4\end{\par
\setbox0=\hbox{\fontsize{27}{27}\selectfont#1\/}%
\hangindent=\wd0 \advance\hangindent by0pt \hangafter=-2
\noindent \hskip-\hangindent\vbox to0pt{\kern-6pt\box0\vss}%
{\uppercase{#2 #3} \it#4\unskip}%
\medskip
}
\begin{document}
\chapter{test}
\openintro{This is a working test due to~\ref{mylabel}}
\section{Hi there}\label{mylabel}
\end{document}
许多问题的出现是因为人们不知道事情可以做得更简单。
编辑:由于 David 的评论,我修改了\openitroA
定义,以便对于具有更多行的文本,行为将类似于 letrine 的使用。
答案3
我正在回答我自己的问题,使用 @wipet 和 lettrine 提供的部分代码(因为它更容易操作文本样式)。我没有使用第一个问题的整个字符串操作,而是使用以下代码(替换整个\newcommand{\openintro}
):
\def\openintro#1{\openintroA #1 \end}
\def\openintroA#1#2 #3 #4\end{%
\lettrine{#1}{#2~#3}~\textit{#4}%
}
我要再次感谢@ChristianHupfer、@wipet 和@DavidCarlisle 的帮助。