12

I want to define a command that behaves differently for single-character arguments than it does for longer arguments. How do I retrieve the number of characters in, e.g., #1?

The specific application that I have in mind is to set variable names in italic if they are single letters and otherwise to set them in Roman. Something like

\newcommand \mathvar [1] {
    \ifthenelse {\characters{#1} = 1}
    {\mathit{#1))
    {\mathrm{#1}}     
}

And, yes, I really mean the number of nonblank characters, not the size of the rendered text.

Note that I want to be able to submit to arXiv.org, and they do not support, e.g., LuaTeX, XeTeX. I'm currently using PDFlatex via MIKTeX, and don't know whether e-TeX is acceptable to arXiv; their current build is rather old.

I tried using xstring; since it doesn't support #, I had to resort to a hack:

\documentclass{article}
\usepackage{amsfonts}
\usepackage{amsmath}
\usepackage{amssymb}
\usepackage{ifthen}
\usepackage{xstring}

\newcommand {\funcname} [1]
   {
     \edef\Parameter1{#1}
     \StrDel[0]{\Parameter1}{ }[\stripped]
     \ifthenelse {\StrLen{\stripped} > 1}
       {\mathrm{#1}}
       {#1}
   }

\begin{document}

Test StrDel \{ foo \} \{ \} = /\StrDel { foo } { }/

\edef\Parameter1{ foo }
\StrDel {\Parameter1} { }[\stripped]
Test StrLen StrDel \{ foo \} \{ \} = \StrLen{\stripped}

Test funcname T funcname Table = $\funcname{T} \funcname{Table}$

\end{document}

and that gave me

! Argument of \@xs@StrDel has an extra }.
<inserted text>
                \par
l.25 ...funcname T funcname Table = $\funcname{T}
                                                   \funcname{Table}$
  • 1
    Do you really need the number of characters, or would the width of them be sufficient? – user36296 Aug 25 '16 at 15:45
  • 1
    Number of characters: tex.stackexchange.com/a/230911/36296 – user36296 Aug 25 '16 at 15:46
  • 2
    Maybe you could add a simple example of what you need. – egreg Aug 25 '16 at 16:26
  • 1
    Please always post complete minimal code we can compile as it makes it much easier for people to help. Especially if it isn't entirely clear what you are asking, complete code can really simplify things. – cfr Sep 1 '16 at 23:50
12

It's easy with expl3:

\documentclass{article}
\usepackage{xparse} % loads expl3

\ExplSyntaxOn

\NewDocumentCommand{\mathvar}{m}
 {
  \int_compare:nTF { \tl_count:n { #1 } > 1 }
   {
    \mathrm{#1}
   }
   {
    #1 % or \mathit{#1}, but I wouldn't do it
   }
 }

\ExplSyntaxOff

\begin{document}

$\mathvar{V}\ne\mathvar{Var}$

\end{document}

The code should be self-explaining: \tl_count:n counts the number of items in its argument (ignoring spaces, however).

I wouldn't use \mathit for single letter variables, as normal math italic is specially tailored for the purpose.

enter image description here

An implementation with xstring:

\documentclass{article}
\usepackage{xstring}

\newcommand{\mathvar}[1]{%
  \begingroup\noexpandarg
  \StrLen{#1}[\temp]%
  \ifnum\temp>1
    \mathrm{#1}%
  \else
    #1%
  \fi
  \endgroup
}

\begin{document}

$\mathvar{V}\ne\mathvar{Var}$

\end{document}
  • 1
    Definitely self-explaining :P – gigabytes Aug 25 '16 at 18:02
  • 1
    Do you know if arxiv.org accepts LaTeX3-based code? (The OP has edited his posting to note that he intends to submit his paper to arxiv.org.) – Mico Aug 25 '16 at 19:20
  • @Mico I hope so – egreg Aug 25 '16 at 19:39
  • Perfect if arXiv will accept manuscripts requiring xparse. They are already requiring that I include tikz-cd and pgf in my source file if I want to use them, so I wonder if I'll also need to include expl3 and xparse.\\I'd still like to know what's wong with my xstring code. – shmuel Sep 2 '16 at 21:12
  • @shmuel For instance, you can do \edef\Parameter1{...}, but you should be aware that this defines the macro \Parameter and \Parameter1 cannot be used in \StrDel. By the way, including tikz-cd and PGF in your submission is something I would be scared about. – egreg Sep 2 '16 at 21:22
9

Here's a LuaLaTeX-based solution. It defines a macro called \numchars, which returns the number of characters in its argument, and an implementation of \mathvar. Care is taken not to count whitespace characters in the argument of \mathvar.

enter image description here

% !TEX TS-program = lualatex
\documentclass{article}    
\usepackage{luacode} %  for "\luastring" macro and "luacode" environment
\begin{luacode}
function numchars ( s )  -- disregard any whitespace characters
   return tex.sprint ( unicode.utf8.len ( unicode.utf8.gsub ( s , "%s", "")))
end 
\end{luacode}
\newcommand\numchars[1]{\directlua{numchars(\luastring{#1})}}
\newcommand\mathvar[1]{%
   \ifnum\numchars{#1}<2\mathit{#1}\else\mathrm{#1}\fi}

\begin{document}
$\mathvar{ V }$, $\mathvar{VaR}$
\end{document}
  • Aside: I posted this answer before the OP edited his posting and provided a caveat that only pdfLaTeX-based answers would be useful to him (as he's planning to use the code in a document that's to be submitted to arxiv.org). – Mico Aug 25 '16 at 19:19
5

Plainer solution.

\documentclass{scrartcl}

\long\def\gobbleone#1{}
\newcommand*\var[1]{\if\relax\detokenize\expandafter{\gobbleone#1}\relax#1\else\mathrm{#1}\fi}

\begin{document}

$\var{A} = \var{B} = \var{Whatever}$

\end{document}
  • 1
    This code returns the incorrect answer if there is whitespace in the argument of \var. E.g., \var{A } (note the space after "A") will generate an upright "A" instead of an italic "A". Can you modify the code to disregard whitespace in the argument of \var? – Mico Aug 25 '16 at 18:57
  • @Mico It also does return an error if the argument is empty (or blank) \var{}, but I don't think it's necessary unless the OP asks for it. – Manuel Aug 25 '16 at 20:41
  • 1
    The OP did specify "the number of nonblank characters", so it seems likely that his document may feature whitespace characters in the argument of mathvar (or \var) directives. – Mico Aug 25 '16 at 21:12

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.