6

Is it possible to create a command which takes the name of a command c as an argument and redefines c (e.g. via renewcommand) in terms of itself but adds some new functionality? In short, can we define a command x(c) whose effect is c := f (c) for some modification f such as \textcolor{blue}{...}.

Example use cases:

  • Add colors to existing symbols throughout the whole document, potentially with varying color themes:
    \setColor{neg}{blue}
    
    where \setColor is the command x I ask for with f = \textcolor{blue}{...}: Whenever \neg is used afterwards, it will be blue. Similarly, one could make symbols bold or italic.
  • Add a suffix or prefix:
    \newcommand{\hello}{hello}
    \addSuffix{hello}{ world}
    
    where \addSuffix is the searched command x and using \hello would write hello world.

The clean way to do this would probably be by just introducing custom commands to wrap each command of interest but that requires to adapt my whole (potentially) large document to replace all usages of the previous command with a new one (e.g., \neg -> \coloredneg).

This answer proposes a solution based on \NewCommandCopy, which works well when we have to do this a single time but becomes cumbersome when we want to redefine multiple commands:

\NewCommandCopy{\oldhello}{\hello}
\renewcommand{\hello}{\hello{} world}

I was not able to wrap this pattern inside a command that is parameterized in the name of the command to redefine (\hello here). All I got working was:

\newcommand{\setColor}[2]{%
  %%% Problem: Full inlining via \edef changes behavior. For example, it breaks ensuremath in #1.
  \expandafter\edef\csname old#1\endcsname{\csname #1 \endcsname}
  \expandafter\renewcommand\csname #1\endcsname{\textcolor{#2}{\csname old#1 \endcsname}}%
}

But this breaks for some commands (see comment).

Ideally, the command x in question would also be generic in the kind of modification f applied. Then x(f, c) would apply a given command f, which takes a single argument, to another command c to perform c := f(c). (Maybe we could even allow c to have parameters and do c(a, b, c, ...) := f(c(a, b, c, ...))?)

In a programming language sense, what I am looking for here might be some lightweight kind of aspects from aspect-oriented programming or features from feature-oriented programming, where some syntactical modification is applied to an existing implementation.

4
  • 1
    TeX/LaTeX is more flexible than this. This flexibility is provided with key-value lists. So new command set the old command with new values for the keys etc,etc.. Others like the color can be done even smpler! The hello world you showed is just a parameter. If you want to permanently redefine the old command (aspects) this can also be done through redefining the command within the factory command. But methinks you over complicating a simple problem. Better post your real use case. You will get better answers this way.
    – yannisl
    Commented Mar 21 at 8:38
  • 1
    @yannisl Interesting! I did not know of key-value lists. My real use case is actually the coloring. I wanted to try to add some syntax highlighting to my math equations consistently and with different color schemes. :) Commented Mar 21 at 8:48
  • 1
    Thanks. I see egreg already posted an answer. I had a similar problem, recently and I defined a palette macro holding all the color definitions. So calling a different palette can change the looks of a document. If you can it would be preferred and less typing to redefine an existing symbol like `rbrack` where \rbracc is the colored version. This way you can also mix and match.
    – yannisl
    Commented Mar 21 at 9:13
  • 1
    My suggestion is very similar to egreg's approach. Except the palette concept and the suggestion of the colored version of a command to be different. So one could do `\rbrackc\rbrack to color only the outer.
    – yannisl
    Commented Mar 21 at 9:17

2 Answers 2

11

You're asking several different questions.

Let's talks about parameterless macros. Adding a “prefix” or a “suffix” doesn't require any special code:

\newcommand{\world}{world}
\AddToHook{cmd/world/before}{Hello }
\AddToHook{cmd/world/after}{!}

\world

enter image description here

Let's say instead you want to colorize math symbols possibly according to a color scheme.

The color scheme should take care of assigning actual colors to abstract names:

%%% Color scheme
\colorlet{OP}{<color>}
\colorlet{REL}{<color>}
\colorlet{FENCE}{<color>}
%%%

Then we can define a \colorize abstraction.

\documentclass{article}
\usepackage{xcolor}

%%% Color scheme
\colorlet{OP}{red!90!green}
\colorlet{REL}{blue!70}
\colorlet{FENCE}{green!70!blue}
%%%

\ExplSyntaxOn

\NewDocumentCommand{\colorize}{mm}{%
  \paul_colorize:cNn { __paul_colorize_ \cs_to_str:N #1 : } #1 { #2 }
}
\cs_new_protected:Nn \paul_colorize:NNn
 {
  \NewCommandCopy{#1}{#2}
  \RenewDocumentCommand{#2}{}{\mathcolor{#3}{#1}}
 }
\cs_generate_variant:Nn \paul_colorize:NNn { c }

\ExplSyntaxOff

\colorize{\lbrack}{FENCE}
\colorize{\rbrack}{FENCE}
\colorize{\sum}{OP}
\colorize{\leq}{REL}

\begin{document}

\[
\sum_{k=1}^n a_k \leq \lbrack 3+x\rbrack
\]

\end{document}

enter image description here

The original meaning of, say, \lbrack, is saved in \__paul_colorize_lbrack: and this is used in the redefinition, where it is wrapped as \mathcolor{FENCE}{\__paul_colorize_lbrack:}

Now you can work out for yourself an abstraction of the abstraction…

2

In OpTeX, your \addSuffix is almost equivalent with \addto:

\def\hello{hello}
\addto\hello{ world}

\hello % prints hello world

The colors of a math objects defined by a control sequence can be set by \colorset macro:

\def\colorset#1#2{\slet{ori:\csstring#2}{\csstring#2}% \let\ori:csn=\csn
   \def#2{\begingroup#1\cs{ori:\csstring#2}\endgroup}% \def\csn{{\color\ori:csn}}
}

\colorset\Red\sum   % each \sum will be in Red color
\colorset\Green\pi  % each \pi will be in Green color

$\sum_{i=1}^n a_n = {\pi\over2}$

$$
  \sum_{i=1}^n a_n = {\pi\over2}
$$

\bye

The \begingroup...\endgroup is used instead {...} because we want to keep the math class of the colorized object. Moreover, OpTeX's colors don't insert any \pdfliterals into the typesetting material because LuaTeXs attributes are used. So, you don't have to worry about the inserted color switchers like in pdftex.

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .