1

I am replacing a character. It works fine if I give that character as input directly. But when that character is extracted from a string, and then fed in to command for the reassignment it does not work. Here is MWC with the problem. Please run XeTeX.

\documentclass{article}
\usepackage{fontspec}
\usepackage{xstring}
\usepackage{xparse}
\RequirePackage{stackengine}
\setmainfont[Script=Devanagari,Mapping=devanagarinumerals]{Shobhika}

\def\kdh#1{\topinset{\rule{4pt}{0.7pt}}{#1}{8pt}{1pt}} %dh
\ExplSyntaxOn
\tl_new:N \l_swar_string_tl

\cs_new_protected:Npn \swar_replace_with:f #1
{
    \tl_set:Nn \l_swar_string_tl {#1}

    \tl_replace_all:Nnn \l_swar_string_tl {धं} {\kdh{ध}}


    \tl_use:N \l_swar_string_tl
}
\NewDocumentCommand \swar { m }
{
    \swar_replace_with:f { #1 }
}   
\ExplSyntaxOff
\begin{document}
Correct output is \swar{धं}\\
Incorrect output  is \StrBehind{प धं}{ }[\this] \swar{\this}, it should be \swar{धं}
\end{document}
7
  • \StrBehind is not expandable. – Ulrike Fischer May 12 '20 at 12:59
  • Also, you shouldn't define functions with signatures other than n and N (an sometimes w if you must). An f signature should only be generated by \cs_generate_variant:Nn. I think if you define \swar_replace_with:n instead and then do \cs_generate_variant:Nn \swar_replace_with:n { f } your code will work. – Phelype Oleinik May 12 '20 at 13:01
  • @UlrikeFischer sorry, edited the code. – Girish May 12 '20 at 13:01
  • you are now using brackets instead of braces. – Ulrike Fischer May 12 '20 at 13:03
  • @PhelypeOleinik Could you please elaborate? I am still learning expl3. I don't exactly understand these nomenclatures and how it works. – Girish May 12 '20 at 13:03
2

There are 21 base signatures for commands, n and N, both of which don't process the argument in any way. You should only define functions whose signature contains n or N, which is the “base” function and takes the argument as it should be.

In your case, the argument seems to be some text, so the n type (a braced group of tokens) is the correct choice, so you should do:

\cs_new_protected:Npn \swar_replace_with:n #1
  { ... }

and then, if you want a version of \swar_replace_with:n that f-expands the argument, you should use:

\cs_generate_variant:Nn \swar_replace_with:n { f }

then you can use \swar_replace_with:f, which will correctly process the argument.

Though it seems to me that an o (to expand the argument once) or x (to expand exhaustively) variant might be better than f.

Here's the code:

\documentclass{article}
\usepackage{fontspec}
\usepackage{xstring}
\usepackage{xparse}
\RequirePackage{stackengine}
% \setmainfont[Script=Devanagari,Mapping=devanagarinumerals]{Shobhika}

\def\kdh#1{\topinset{\rule{4pt}{0.7pt}}{#1}{8pt}{1pt}} %dh
\ExplSyntaxOn
\tl_new:N \l_swar_string_tl

\cs_new_protected:Npn \swar_replace_with:n #1
  {
    \tl_set:Nn \l_swar_string_tl {#1}
    \tl_replace_all:Nnn \l_swar_string_tl {धं} {\kdh{X}} % ध
    \tl_use:N \l_swar_string_tl
  }
\cs_generate_variant:Nn \swar_replace_with:n { f }

\NewDocumentCommand \swar { m }
  { \swar_replace_with:f {#1} }

\ExplSyntaxOff
\begin{document}
Correct output is \swar{धं}\\
Incorrect output  is \StrBehind{प धं}{ }[\this]\swar{\this}, it should be \swar{धं}
\end{document}

and the output (with X instead of because I don't have the proper font):

enter image description here


1 6, actually: n and N, which are “normal”; p which stands for “parameter specification”, like you see in \cs_new:Npn; T and F, which are the same as n, but they denote the true and false branches of conditionals; D, which stands for “Do not use”, and is used to name TeX primitives; and w, which should be used when the command doesn't follow one of the above. For starters, I suggest reading The expl3 package and LaTeX3 programming.

3
  • Thank you so much. This works perfectly, I tried to read the documentation but I haven't gained much. Are there any other sources that teach latex3 programming from basics? – Girish May 12 '20 at 13:57
  • @Girish We (LaTeX Team) are aware that the current documentation on expl3 is not the most beginner-friendly there is, and we plan on writing a beginner's manual (suggestions welcome). Speaking from my own experience with expl3: start by reading expl3.pdf (even if you don't understand some parts of it), and then move to interface3.pdf to see what functions the LaTeX3 kernel provides (both these files can be found at ctan.org/pkg/l3kernel), then go by using it. Any problem you find, you're welcome to ask here :-) – Phelype Oleinik May 12 '20 at 14:06
  • Thank you for the pointers I will go through it. – Girish May 12 '20 at 16:25

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.