如何定义宏的可选的第二个参数?

如何定义宏的可选的第二个参数?

我定义了一个命令,可以让我同时快速引用编号(图形或表格)和页面:

命令

 \newcommand{\kplref}[2]{~\ref{#1}, S.~\pageref{#1}{#2}\xspace}

第二个参数用于添加类似“第 6f 页”或“第 6ff 页”的内容,但我希望它是可选的,并且不想每次都强制输入空的 {}。

但是,像这样定义,命令将后面单词的首字母作为其第二个参数(参见示例)。

  • 我该如何更改命令定义以避免这种情况?
  • 或者是否已经有一个现成的命令可以完全满足我的要求?

结果

在此处输入图片描述

示例文档

\documentclass[11pt, parskip=half]{scrbook}


\usepackage{xspace}
\newcommand{\kplref}[2]{~\ref{#1}, S.~\pageref{#1}{#2}\xspace}

\begin{document}

%\tableofcontents

\section{Section1}
\label{sec1}

This is a nonsense paragraph. This is a nonsense paragraph. This is a nonsense paragraph. This is a nonsense paragraph. This is a nonsense paragraph. This is a nonsense paragraph.

This is a nonsense paragraph. This is a nonsense paragraph. This is a nonsense paragraph. This is a nonsense paragraph. This is a nonsense paragraph. This is a nonsense paragraph.

\section{Section2}

Now lets refer to section~\kplref{sec1}.

It fails if other text is following and there is no second argument like here:\newline 
\kplref{sec1} shows the nonsense of this document.

\end{document}

答案1

您应该将命令定义为

\newcommand{\kplref}[2][]{\ref{#2}, S.~\pageref{#2}#1\xspace}

并使用可选参数,如

\kplref[f]{sec1}

梅威瑟:

\documentclass[11pt, parskip=half]{scrbook}


\usepackage{xspace}
\newcommand{\kplref}[2][]{\ref{#2}, S.~\pageref{#2}#1\xspace}

\begin{document}

%\tableofcontents

\section{Section1}
\label{sec1}

This is a nonsense paragraph. This is a nonsense paragraph. This is a nonsense paragraph. This is a nonsense paragraph. This is a nonsense paragraph. This is a nonsense paragraph.

This is a nonsense paragraph. This is a nonsense paragraph. This is a nonsense paragraph. This is a nonsense paragraph. This is a nonsense paragraph. This is a nonsense paragraph.

\section{Section2}

Now lets refer to section~\kplref{sec1}.

It doesn't fail if other text is following and there is no optional argument like here:\newline
\kplref{sec1} shows the nonsense of this document.

This is how to use the optional argument: \kplref[f]{sec1} which shows again the nonsense of this document.

\end{document} 

在此处输入图片描述

答案2

这并不是对您关于如何设置带有可选参数的宏的问题的直接回答。相反,这是一个建议,希望它能更好地解决您要解决的问题。

如果我理解您的设置正确,您希望有一种方法来引用某些项目(在您的示例中是部分,但其他类型的项目也应该允许)——如果标注与项目本身位于同一页,则仅通过编号引用,如果项目位于其他位置,则通过编号加上某种形式的页码引用。如果这种解释是正确的,您应该研究瓦里雷夫包及其\vref宏,它自动处理这些任务。

运行下面的示例代码,第一个页面如下所示

在此处输入图片描述

而第二页看起来像这样——请注意由宏提供的附加字符串“在上一页” \vref

在此处输入图片描述

\documentclass[11pt, parskip=half]{scrbook}
\usepackage{varioref} % for \vref macro
\begin{document}
\setcounter{chapter}{1} % just for this example

\section{Thoughts} \label{sec1}
This is a nonsense paragraph. 

\section{More thoughts}
Now let's refer to Section~\vref{sec1}.

\newpage % force a page break
Now let's again refer to Section~\vref{sec1}.
\end{document}

附录:如果您另外加载聪明人包(之后varioref),你可以写Now let's again refer to~\vref{sec1}.(注意:没有“Section”字符串),你会得到

现在我们再次参考第 1 页的第 1.1 节。

即,您将获得数字页面引用(“在第 1 页”),而不是字符串“在前一页”。

答案3

您可以使用 xargs 包

\documentclass[11pt, parskip=half]{scrbook}


\usepackage{xspace,xargs}

\newcommandx{\kplref}[2][2]{\ref{#1}, S.~\pageref{#1}#2\xspace}% removed ~ from OP


\begin{document}

\section{Section1}
\label{sec1}

This is a nonsense paragraph. This is a nonsense paragraph. This is a
nonsense paragraph. This is a nonsense paragraph. This is a nonsense
paragraph. This is a nonsense paragraph.

This is a nonsense paragraph. This is a nonsense paragraph. This is a
nonsense paragraph. This is a nonsense paragraph. This is a nonsense
paragraph. This is a nonsense paragraph.

\section{Section2}

Now lets refer to section~\kplref{sec1}, or even to
section~\kplref{sec1}[ff] to check also that the following space is not gobbled.

It does not fail if other text is following and there is no second
argument like here:\newline \kplref{sec1} shows the true sense of this
document.

\end{document}

答案4

以下是一些可能性:

\documentclass{article}
\usepackage{xparse}

\NewDocumentCommand{\kplref}{m}{%
  \unskip~\ref{#1}, S.~\pageref{#1}%
}

\NewDocumentCommand{\kplrefA}{mo}{%
  \unskip~\ref{#1}, S.~\pageref{#1}
  \IfValueTF{#2}{#2}% <--- this adds the possibility of manipulating the argument
}

\NewDocumentCommand{\kplrefB}{mG{}}{%
  \unskip~\ref{#1}, S.~\pageref{#1}%
  \IfValueTF{#2}{#2}% <--- this adds the possibility of manipulating the argument
}

\begin{document}

\section{Title}\label{aaa}

Here are usage examples:
\begin{itemize}
\item Example of \verb|\kplref| for \kplref{aaa} and something
\item Example of \verb|\kplref| for \kplref{aaa}ff and something
\item Example of \verb|\kplrefA| for \kplrefA{aaa} and something
\item Example of \verb|\kplrefA| for \kplrefA{aaa}[ff] and something
\item Example of \verb|\kplrefB| for \kplrefB{aaa} and something
\item Example of \verb|\kplrefB| for \kplrefB{aaa}{ff} and something
\end{itemize}

\end{document}

注意,这很简单,只需ff在单个参数宏后添加即可。这个\unskip技巧可以让你忘记\kplref在前一个单词后面写东西。

在此处输入图片描述

然而,我倾向于采用不同的方法,即先给出可选参数,然后tie 被隐式地使用:

\NewDocumentCommand{\kplref}{om}{%
  \ref{#2}, S.~\pageref{#2}%
  \IfValueT{#1}{#1}% <--- this adds the possibility of manipulating the argument
}

\item Example of \verb|\kplref| for~\kplref{aaa} and something

\item Example of \verb|\kplref| for~\kplref[ff]{aaa} and something

我说的“操纵论点的可能性”是什么意思?假设你的缩写ff需要变成,ff.因为一些挑剔的文字编辑的要求。使用最后一种方法,但它与相同\kplrefA\kplrefB你只需要将定义更改为

\NewDocumentCommand{\kplref}{om}{%
  \ref{#2}, S.~\pageref{#2}%
  \IfValueT{#1}{#1.\@}%
}

重新处理文档后,就会出现句号。

相关内容