命令周围有空格,输出为空(用于段落内的注释)

命令周围有空格,输出为空(用于段落内的注释)

我定义了一个简单的命令来注释段落内的文本:

\newcommand{\comm}[1]{}

This is a␣\comm{commented text}␣paragraph containing a comment.

问题是我在注释的位置放了两个空格:

“这是一个包含评论的段落。”

我显然可以写

This is a\comm{commented text}␣paragraph containing a comment.

但我的文本中已经有一些评论,这也会使可读性变差。

是否有任何简单的方法(即不需要比上面的简单解决方案付出更多努力)来仅显示一个空格来代替注释,而与注释之前和之后的空格无关\comm

谢谢你!

答案1

另一个选择是使用\@bsphack\@esphack,如下所示:

\documentclass{article}

\makeatletter %% <- make @ usable in macro names
\newcommand{\comm}[1]{\@bsphack\@esphack}
\makeatother %% <- change @ back

\begin{document}

A Test. \comm{test} This works.

A Test.\comm{test} This works.

A Test. \comm{test}This works.

A Test\comm{test}. This works.

\end{document}

这会产生一个正确长度的空间,并且\comm实际上会执行某些操作。例如,这就是\label(创建可以交叉引用的标签)、\index(创建索引条目)和(将文本放在边距中)的工作方式。通常使用和的\marginpar方式如下:\@bsphack\@esphack

\newcommand{\comm}[1]{\@bsphack<do things here>\@esphack}

稍微解释一下:

\@bsphack\@esphack执行以下操作(或多或少):

  • \@bsphack\lastskip存储和的值\spacefactor。第一个是前一个空格的长度(如果适用,否则为 0),第二个是影响此处空格长度的数字。(例如,句号后面的空格稍长,如果需要,可以拉伸到更长。)
  • \@esphack如果调用时结果为正,则恢复\spacefactor并插入\ignorespaces(按其说明进行操作) 。\lastskip\@bsphack

至少存在两个限制:多个连续的\@bsphack/\@sphack不起作用,并且在段落末尾使用它有时会导致本段落的最后一个单词移动到下一行。


实际上,我自己使用了一个稍微修改过的版本,它确实允许您在一行中使用多个这样的符号,并且不会出现段落结尾的问题。它会删除前面的空格,然后在之后重新插入。

\documentclass{article}

\newcommand{\comm}[1]{\mybsphack\myesphack}
%% This also works if \comm does do something:
% \newcommand{\comm}[1]{\mybsphack{\marginpar{#1}}\myesphack}

\makeatletter              %% <- make @ usable in macro names
\newskip\my@savsk          %% <- holds a skip
\newcount\my@savsf         %% <- holds space factor
\newcount\my@savpn         %% <- holds penalty (for line breaking)
\newcommand*{\mybsphack}{% %% <- this % is relevant, see the comments
  \relax\ifhmode           %% <- if in horizontal mode
    \my@savsk\lastskip     %% <- store \lastskip
    \@savsf\spacefactor    %% <- store \spacefactor
    \my@savpn\lastpenalty  %% <- store \lastpenalty
    \unskip                %% <- remove the last skip
  \fi
}
\newcommand*{\myesphack}{% %% <- this % is relevant, see the comments
  \relax\ifhmode           %% <- if in horizontal mode
    \penalty\my@savpn      %% <- restore the penalty
    \spacefactor\@savsf    %% <- restore the space factor
    \ifdim\my@savsk>\z@    %% <- if the removed skip was positive
      \hskip\my@savsk      %% <- then reinsert it
      \ignorespaces        %% <- and ignore subsequent spaces
    \fi
  \fi
}
\makeatother               %% <- change @ back

\begin{document}

A Test. \comm{test}\comm{test}This works.

A Test.\comm{test}\comm{test} This works.

A Test. \comm{test}\comm{test} This works.

A Test. \comm{test} \comm{test}This works.

A Test.\comm{test} \comm{test} This works.

A Test. \comm{test} \comm{test} This works.

A Test\comm{test}\comm{test}. This works.

\end{document}

在此处输入图片描述

编辑: 如果\comm真的什么都不做,那么以下内容就足够了:

\newcommand{\comm}[1]{\ifdim\lastskip>0pt\ignorespaces\fi}

编辑: 改进了我的代码:它现在考虑了惩罚并存储\lastskip在跳过寄存器而不是默认维度寄存器(oops)。

答案2

您可以使用\ignorespaces

\documentclass[]{article}

\newcommand\comm[1]{\ignorespaces}

\begin{document}
Foo \comm{bar} baz
\end{document}

这会占用后面的空格\comm,但不占用前面的空格。因此,只有在前面有一个空格的情况下,此方法才能正常工作。

如果您只\comm在句中和两个单词之间使用(因此应该出现空格),则可以使用:

\newcommand\comm[1]{\ifhmode\unskip\fi\space\ignorespaces}

这将导致一个空格,忽略任何尾随空格并吃掉前导空格。我会选择第一个选项并正确使用它,这样你就不会得到任何意外的行为,如果你\unskip在错误的地方使用,可能会发生这种情况。

相关内容