I use boldface math a lot, so to avoid typing \mathbf every time, I define macros like the following:
\newcommand{\x}{{\mathbf{x}}}
The issue is that macros such as \a, \c, \o exist already. Instead of overwriting these with \renewcommand, which is clearly suboptimal, I followed this answer and define my bold macros for the math mode only:
\usepackage{xparse}
\DeclareDocumentCommand{\newmathcommand}{mO{0}m}{%
\expandafter\let\csname old\string#1\endcsname=#1
\expandafter\newcommand\csname new\string#1\endcsname[#2]{#3}
\DeclareRobustCommand#1{%
\ifmmode
\expandafter\let\expandafter\next\csname new\string#1\endcsname
\else
\expandafter\let\expandafter\next\csname old\string#1\endcsname
\fi
\next
}%
}
\newmathcommand{\a}{{\mathbf{a}}}
\newmathcommand{\c}{{\mathbf{c}}}
This seems to work for most of the cases, except for \S. When I have \S in text mode, the code doesn't compile (it takes an infinite time). The complete source code is appended below for your convenience.
My question is obviously how to fix this. Thank you very much in advance for your help!
\documentclass{article}
\usepackage{amsmath}
\usepackage{amssymb}
\usepackage{amsthm}
\usepackage{xparse}
\DeclareDocumentCommand{\newmathcommand}{mO{0}m}{%
\expandafter\let\csname old\string#1\endcsname=#1
\expandafter\newcommand\csname new\string#1\endcsname[#2]{#3}
\DeclareRobustCommand#1{%
\ifmmode
\expandafter\let\expandafter\next\csname new\string#1\endcsname
\else
\expandafter\let\expandafter\next\csname old\string#1\endcsname
\fi
\next
}%
}
\newmathcommand{\S}{{\mathbf{S}}}
\newmathcommand{\o}{{\mathbf{o}}}
\begin{document}
Test S: $\S$, \S.
Test o: $\o$, \o.
\end{document}
Update:
Same behavior with:
\ifdefined\S
\let\svS\S
\DeclareRobustCommand\S{\ifmmode\mathbf{S}\else\expandafter\svS\fi}
\else
\newcommand{\S}{{\mathbf{S}}}
\fi
or with
\let\svS\S
\DeclareRobustCommand\S{\ifmmode\mathbf{S}\else\expandafter\svS\fi}
(the compilation ended up with "TeX capacity exceeded")
Update 2:
Following @Davislor's suggestion in the comments:
\let\oldS\S
\renewcommand\S{\ifmmode\mathbf{S}\else\oldS\fi}
I tried the following macro:
\newcommand{\newmathcommand}[2]{
\ifdefined#1
\let#1old#1
\renewcommand#1{\ifmmode#2\else#1old\fi}
\else
\newcommand{#1}{#2}
\fi
}
\newmathcommand{\S}{{\mathbf{S}}}
but I obtained: "Missing \begin{document}".
Update 3:
I received three excellent answers below from @Werner, @cgnieder, and @egreg (please upvote all of them!). Unfortunately it is not possible to accept more than one of them, so let me accept the first one (@Werner's), which is also the only one that can work on old LaTeX kernels (such as provided by TeXlive 2018, the one I am currently using).
To the future reader: It is not recommended to change the behavior of the default commands (see the experts' opinions below), so you should consider instead defining new commands, such as \bx, \bS, etc.

\bSor\setS. – Davislor Jan 07 '21 at 23:20\a,\b,...,\z,\A,\B,...,\Zin many documents. – f10w Jan 07 '21 at 23:31\renewcommand, not\newcommand. Or\DeclareRobustCommandworks in either case. – Davislor Jan 07 '21 at 23:41\renewcommandit works. Let me try building a similar\newmathcommand(cf. the question) with this solution. Could you please tell me what you meant by "with better formatting" in your first comment? – f10w Jan 07 '21 at 23:49\oldSand\oldo, and check ifold#1had already been defined. But his approach is clearly better. – Davislor Jan 08 '21 at 01:06\bSand\bcinstead of changing the behavior of the existing commands\Sand\c. – f10w Jan 08 '21 at 19:28\vectorsym{v}, it’s easy to tell what I intended, and easy to change to someone else’s house style. – Davislor Jan 08 '21 at 20:042\norm{\x}^2 + 2\norm{\y}^2 = \norm{\x + \y}^2 + \norm{\x - \y}^2in my code, rather than2\left\| \vectorsym{x} \right\|^2 + 2\left\| \vectorsym{y} \right\|^2 = \left\| \vectorsym{x} + \vectorsym{y} \right\|^2 + \left\| \vectorsym{x} - \vectorsym{y} \right\|^2(especially when I have hundreds of such formulas). – f10w Jan 08 '21 at 20:50