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.
\bS
or\setS
. – Davislor Jan 7 at 23:20\a,\b,...,\z,\A,\B,...,\Z
in many documents. – Khue Jan 7 at 23:31\renewcommand
, not\newcommand
. Or\DeclareRobustCommand
works in either case. – Davislor Jan 7 at 23:41\renewcommand
it 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? – Khue Jan 7 at 23:49