Stackengine 无法与 xstring 一起使用

Stackengine 无法与 xstring 一起使用

我一直在尝试制作一个命令,允许我自动重新输入给定字符串中的任何 V̇,因为我使用的字体将其输入为 .V,这并不理想。XeLaTeX我使用这个源代码编译了

\documentclass{article}
\usepackage{xstring}
\usepackage{stackengine}
\newcommand{\Vh}{\stackon[1pt]{V}{.}}
\newcommand{\dothing}[1]{\StrSubstitute{#1}{V̇}{\Vh}}

\begin{document}
\dothing{V̇aglæja}
\end{document}

并收到以下错误:

Use of \\stackon doesn’t match its definition.
\kernel@ifnextchar ...d@d =#1\def\reserced@a{#2}
    \def\reserved@b{#3}\futu...
l.8\dothing{V̇aglæja}

Argument of \\stackon has an extra }.
<inserted text>
    \par
l.8\dothing{V̇aglæja}

Runaway argument?
! Paragraph ended before \\stackon was complete.
<to be read again>
    \par
l.8\dothing{V̇aglæja}

Undefined Control Sequence.
\xs_StrSubstitute__..._arg_iv{#4}\edef\xs_call
    {\noexpand\xs_testopt {\n...
l.8\dothing{V̇aglæja}

Undefined Control Sequence.
\xs_StrSubstitute__...d\xs_arg_iv}}{}}\xs_call

l.8\dothing{V̇aglæja}

Missing \endcsname inserted.
<to be read again>
    \protect
l.8\dothing{V̇aglæja}

Undefined Control Sequence.
\GenericError ...
    #4 \errhelp \@err@
l.9\end{document}

Undefined Control Sequence.
\GenericError ...
    \let \@err@     ...
l.9\end{document}

Undefined Control Sequence.
\GenericError ...
    \@empty \def\MessageBreak…
l.9\end{document}


Undefined Control Sequence.
\GenericError ...
    \endgroup
l.9\end{document}

Missing \endcsname inserted.
<to be read again>
    \let
l.8\dothing{V̇aglæja}

Incomplete \ifx; all text was ignored after line 9.
<inserted text>
    \fi
<*> main.tex

stackengine这些是什么意思?为什么会发生这种情况?这与结合和有关吗xstring?谢谢!

答案1

您必须使用\expandarg才能\StrSubstitute展开\Vdot。我还添加了\kern-1.5pt来调整 V 和 a 之间的空间。(我不确定这是否是一个好的解决方案,或者它是否通常有效,即使它在这种情况下有效。)

在此处输入图片描述

\documentclass{article}
\usepackage{xstring}
\usepackage{stackengine}

\newcommand{\Vdot}{\stackon[1pt]{V}{.}\kern-1.5pt}
\newcommand{\dothing}[1]{\expandarg\StrSubstitute{#1}{V̇}{\Vdot}}

\begin{document}
 
\dothing{V̇aglæja}

\end{document}

答案2

使用具有良好锚点的字体来组合字符。

或者,使用更好的方法进行替换。

\documentclass{article}
\usepackage{fontspec}

\newfontfamily{\libertinus}{Libertinus Serif}

\ExplSyntaxOn
\NewDocumentCommand{\dothing}{m}
 {
  \tl_set:Nn \l_dothing_text_tl { #1 }
  \regex_replace_all:nnN { V\x{0307} } { \c{dottedV} } \l_dothing_text_tl
  \tl_use:N \l_dothing_text_tl
 }

\tl_new:N \l_dothing_text_tl
\ExplSyntaxOff

\NewDocumentCommand{\dottedV}{}{%
  \leavevmode
  \vbox{%
    \offinterlineskip
    \ialign{%
      \hfil##\hfil\cr
      \.{}\cr
      \noalign{\kern-1.1ex}%
      V\cr
    }%
  }%
}

\begin{document}

V̇aglæja

\dothing{V̇aglæja}

\libertinus
V̇aglæja

\end{document}

您可以\dottedV按照自己喜欢的方式定义,也可以使用stackengine自己喜欢的方式定义。

在此处输入图片描述

我们还可以通过扩展代码来重新插入正确的字距。

\documentclass{article}
\usepackage{fontspec}

\newfontfamily{\libertinus}{Libertinus Serif}

\ExplSyntaxOn
\NewDocumentCommand{\dothing}{m}
 {
  \tl_set:Nn \l_dothing_text_tl { #1 }
  \regex_replace_all:nnN { V\x{0307} } { \c{dottedV} } \l_dothing_text_tl
  \tl_use:N \l_dothing_text_tl
 }

\tl_new:N \l_dothing_text_tl

\NewDocumentCommand{\checkkern}{m}
 {
  \peek_catcode:NT { #1 } { \addkern{#1} }
 }
\ExplSyntaxOff

\NewDocumentCommand{\dottedV}{}{%
  \leavevmode
  \vbox{%
    \offinterlineskip
    \ialign{%
      \hfil##\hfil\cr
      \.{}\cr
      \noalign{\kern-1.1ex}%
      V\cr
    }%
  }%
  \checkkern{V}%
}
\NewDocumentCommand{\addkern}{mm}{%
  \sbox0{#1#2}\sbox2{\hbox{#1}\hbox{#2}}%
  \kern\dimexpr\wd0-\wd2\relax #2%
}

\begin{document}

V̇aglæja

\dothing{V̇aglæja}

Vaglæja

\libertinus
V̇aglæja

Vaglæja

\end{document}

请注意,Libertinus 示例中没有考虑字距调整。如果在决定字距调整时忽略组合字符,这将是 XeTeX 的一个很好的功能。

在此处输入图片描述

答案3

这里我设计了一个 tokcycle名为的环境\dothing,它可以扩展到多个段落,甚至扩展到整个文档。只需以 终止即可\enddothing

已编辑以删除\makeatletter代码,该代码现已合并到 中tokcycle[2021-05-27]。此外,还消除了 的一个先前故障模式\Vdotcheck以及其他潜在故障模式(包括 之后的空格V和/或 之后的组V)。

\documentclass{article}
\usepackage{tokcycle}[2021-05-27]
\usepackage{stackengine}
\newcommand{\Vh}{\stackon[1pt]{V}{.}}
\def\zz#1#2{#2}
\edef\thedot{\zz V̇}
\newcommand\Vdotcheck{\tcpopliteral\z
  \ifx\thedot\z\addcytoks{\Vh}\else
  \addcytoks{V}\tcpush\z\fi}

\tokcycleenvironment\dothing
  {\ifx V##1\Vdotcheck\else\addcytoks{##1}\fi}%
  {\processtoks{##1}}
  {\addcytoks{##1}}
  {\addcytoks{##1}}
\begin{document}
\dothing
V̇aglæja 

V\today % MACRO AFTER V

V{\itshape a}bc% GROUP AFTER V

V bc% SPACE AFTER V

xV̇x VV̇% V̇  AFTER V
\enddothing
\end{document}

在此处输入图片描述

相关内容