4

I've been trying to make a command that allows me to automatically retypeset any V̇ in a given string, as in the font I'm using it typests as .V which isn't ideal. Using XeLaTeX I compiled this source

\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}

And got the following errors:

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

What do these mean, and also why is this happening? Is it something to do with combining the stackengine and xstring? Thanks!!

3 Answers 3

1

You have to use \expandarg before \StrSubstitute in order to expand \Vdot. I also added \kern-1.5pt to adjust the space between V and a. (I am not sure if this is a good solution or if it is effective in general, even if it works in this case.)

enter image description here

\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}
1
  • Exactly what I was looking for! I'd actually been looking for something like \expandarg for awhile but hadn't been able to find it; I assume it just expands the argument immediately instead of waiting until later? Again thanks so much! Apr 2, 2021 at 19:18
3

Use a font with good anchors for the combining characters.

Alternatively, use a better method for substitutions.

\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}

You can define \dottedV as you please, also with stackengine if you prefer.

enter image description here

We can also reinsert the right kerning, by extending the code.

\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}

Note that the kerning is not respected in the Libertinus example. It would be a good feature of XeTeX if combining characters were ignored when deciding for kerning.

enter image description here

1

Here I devise a tokcycle environment named \dothing that can extend across multiple paragraphs, even to the extent of your whole document. Just terminate with \enddothing.

EDITED to remove \makeatletter code, which has now been incorporated into tokcycle[2021-05-27]. Also, eliminated one prior failure mode of \Vdotcheck as well as other potential failure modes (which included a space after V and/or a group after 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}

enter image description here

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .