Smart subscript indexing macro I need to go and rework a bunch of notation in a large body of work. But I might change my mind later, so I want to move to defining the notation a bit more semantically (e.g. writing \v x to represent a vector, so I can later decide to format vectors in different ways).

On thing that is currently wrong with it is that I write A_i to represent that \$i^{\text {th}}\$ column vector. After looking at other similar works, I have concluded that A_{:,i} would be clearer. So I have defined a macro to smartly determine if a : should be added.

I called it \i to be concise since I will be writing it often.



\documentclass{article}

\usepackage{xparse,xstring,etoolbox}

\renewcommand{\v}[1]{\tilde{#1}} % a vector 

\newcommand{\ind}[2]{#1_{#2}} % indexed

%% Smart indexing and naming code

\newcommand{\ifupper}[3]{
    \normalexpandarg
    \exploregroups
    \StrCount{ABCDEFGHIJKLMNOPQRSTUVWXYZ}{#1}[\uppercount]
    \ifnumgreater{\uppercount}{0}{#2}{#3}
}

%smart index
\DeclareDocumentCommand{\i}{u{_} m}{
    \ifupper{#1}%
    {% just a single uppercase character, i.e. a matrix
        %make sure the index is the right length
        \StrCount{#2}{,}[\indcount]
        \ifnumgreater{\indcount}{0}
        { % Got multiple indexes so all good
            \ind{#1}{#2}
        }
        { % Only 1 index so grab the column
            \ind{#1}{{:,#2}}
        }
    }%
    {% Not just a single upper case character
        \ind{#1}{#2}
    }
}

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% Example document
\begin{document}

        \begin{tabular}{r l}
  $\i {\v x}_i$ &amp; the $i$th element of the vector $\v x$\\
  $\i{X}_{i,j}$ &amp; the row $i$ and column $j$ element of the matrix $X$\\
  $\i{X}_i$ &amp; the $i$th column vector of the matrix $X$\\
  $\i{X}_{i,:}$ &amp; the $i$th row vector of the matrix $X$\\
 \end{tabular}

\end{document}


Example document output



Crossref
Redefining \v and \i is a bad thing. Don't, you'll regret it as soon as you want to need to cite a paper by Eduard Čech or by Erdal Arıkan.

You also have quite an inefficient usage of xstring and no error checking if a _ is forgotten.

Here's a complete implementation with xparse:

\documentclass{article}

\usepackage{xparse}

\NewDocumentCommand{\ind}{me{_}}{%
  \IfNoValueTF{#2}{\doind{#1}{???}}{\doind{#1}{#2}}
}

\ExplSyntaxOn
\NewDocumentCommand{\doind}{mm}
 {
  \tl_if_single:nTF { #1 }
   {% a single character
    \str_if_eq_x:nnTF { #1 } { \str_upper_case:n { #1 } }
     {% upper case, assume matrix
      \lyndon_index_matrix:nn { #1 } { #2 }
     }
     {
      \lyndon_index_do:nn { #1 } { #2 }
     }
   }
   {% not a single character
    \lyndon_index_do:nn { #1 } { #2 }
   }
 }

\cs_new_protected:Nn \lyndon_index_matrix:nn
 {
  \int_compare:nTF { \clist_count:n { #2 } &gt; 1 }
   {% Got multiple indexes so all good
    \lyndon_index_do:nn { #1 } { #2 }
   }
   {% Only one index so grab the column
    \lyndon_index_do:nn { #1 } { {:},#2 }
   }
 }
\cs_new_protected:Nn \lyndon_index_do:nn
 {
  #1\sb{#2}
 }
\ExplSyntaxOff

% Example document
\begin{document}

\begin{tabular}{r l}
$\ind{A}$           &amp; missing subscript\\
$\ind{\tilde{x}}_i$ &amp; the $i$th element of the vector $\tilde{x}$\\
$\ind{X}_{i,j}$     &amp; the row $i$ and column $j$ element of the matrix $X$\\
$\ind{X}_i$         &amp; the $i$th column vector of the matrix $X$\\
$\ind{X}_{i,:}$     &amp; the $i$th row vector of the matrix $X$\\
\end{tabular}

\end{document}




On the other hand, I see no much gain in using _ and also in doing checks for uppercase letters, which is quite limiting. I'd prefer a * version for vectors.

\documentclass{article}

\usepackage{xparse}

\ExplSyntaxOn

\NewDocumentCommand{\ind}{smm}
 {
  \IfBooleanTF{#1}
   {% *, a vector
    \lyndon_index_do:nn { #2 } { #3 }
   }
   {% normal, a matrix
    \lyndon_index_matrix:nn { #2 } { #3 }
   }
 }
\cs_new_protected:Nn \lyndon_index_matrix:nn
 {
  \int_compare:nTF { \clist_count:n { #2 } &gt; 1 }
   {% Got multiple indexes so all good
    \lyndon_index_do:nn { #1 } { #2 }
   }
   {% Only one index so grab the column
    \lyndon_index_do:nn { #1 } { {:},#2 }
   }
 }
\cs_new_protected:Nn \lyndon_index_do:nn
 {
  #1\sb{#2}
 }

\ExplSyntaxOff

% Example document
\begin{document}

\begin{tabular}{r l}
$\ind*{\tilde{x}}{i}$ &amp; the $i$th element of the vector $\tilde{x}$\\
$\ind{X}{i,j}$        &amp; the row $i$ and column $j$ element of the matrix $X$\\
$\ind{X}{i}$          &amp; the $i$th column vector of the matrix $X$\\
$\ind{X}{i,:}$        &amp; the $i$th row vector of the matrix $X$\\
$\ind{\Gamma}{j}$     &amp; Greek matrix
\end{tabular}

\end{document}