5

Is there a way to replace automatically := by the command \coloneqq ?

I would like to still be able to type := in the .tex files but that it compiles the symbol \coloneqq instead.

In a way, I'm asking if it's possible to do something like \newcommand{:=}{\coloneqq}

Thanks

PS: if possible, I'm looking for a solution that is compatible with \usepackage[french]{babel}.

Colas
  • 6,772
  • 4
  • 46
  • 96

3 Answers3

8

Don't try this with babel-french, when using pdflatex. It should work as is if you use XeLaTeX or LuaLaTeX.

\documentclass{article}
\usepackage{mathtools}

\AtBeginDocument{% \mathchardef\ordinarycolon=\mathcode: \mathcode:="8000 } \makeatletter \newcommand{\coloncheck}{@ifnextchar={\coloneqq@gobble}{\ordinarycolon}} \makeatother \begingroup\lccode~=: \lowercase{\endgroup\let~}\coloncheck

\begin{document}

$a := b$ $a \ordinarycolon= b$ $a:b$

\end{document}

Redefining \ordinarycolon is necessary.

enter image description here

For babel-french, under pdflatex

\documentclass{article}
\usepackage[T1]{fontenc}
\usepackage[french]{babel}
\usepackage{mathtools}

\AtBeginDocument{% \mathchardef\ordinarycolon=\mathcode: \mathcode:="8000 } \makeatletter \declare@shorthand{french}{:}{% \ifmmode \expandafter\coloncheck \else \ifFB@spacing \ifhmode \ifdim\lastskip>1sp \unskip\penalty@M\FBcolonspace \else \FDP@colonspace \fi \fi \fi \string:% \fi } \newcommand{\coloncheck}{@ifnextchar={\coloneqq@gobble}{\ordinarycolon}} \makeatother \begingroup\lccode~=: \lowercase{\endgroup\let~}\coloncheck

\begin{document}

Un example: et voilà.

$a := b$ $a \ordinarycolon= b$ $a:b$

\end{document}

enter image description here

egreg
  • 1,121,712
  • Thanks. Unfortunately, I'm using \usepackage[french]{babel}. – Colas Mar 31 '21 at 13:49
  • out of curiosity: what exactly breaks with French and not other languages? – Willie Wong Mar 31 '21 at 13:56
  • 1
    @WillieWong With babel-french the colon is already active and some more somersaults are necessary. – egreg Mar 31 '21 at 14:35
  • 1
    @Colas Well, I suspected it. I added a workaround. But the simplest thing is to never use \coloneqq. I've been doing mathematics for several years and I never felt any need for it. – egreg Mar 31 '21 at 14:44
  • @egreg I also don't feel any need for \coloneq but I think that it is because my eyes are used to the :=. Thanks for your help. – Colas Mar 31 '21 at 14:49
  • 1
    Please note that babel-french makes the colon (and ; ! ?) active /only/ with pdflatex. Using a `"modern" engine (LuaTeX or XeTeX) is a good way to avoid all problems caused by active characters. – Daniel Flipo Mar 31 '21 at 16:26
  • 1
    @DanielFlipo Yes, probably I should have added that. – egreg Mar 31 '21 at 16:38
  • \coloncheck should definitely be \protected. Otherwise you're going to have a bad time when typing : in an \edef context. – Henri Menke Apr 04 '21 at 09:34
  • @HenriMenke No, why? Assuming : is not active (so no babel-french), \coloncheck would never be seen in an \edef, because math active characters are macro-like and expanded only when it's time to process them in a math list and \edef would just see a regular catcode 12 character. With babel-french it would fail anyway… – egreg Apr 04 '21 at 09:59
5

Here is a tokcycle solution that will work with or without [french]{babel} loaded. If not loaded, it intercepts the normal : in the Character directive. If loaded, it must intercept it in the Macro directive.

Just surround the desired test area with \subcoloneqq...\endsubcoloneqq. That can start right after \begin{document} and end right before \end{document}.

See SUPPLEMENT for FUTURE improvement.

\documentclass{article}
\usepackage{tokcycle,mathtools}
\usepackage[french]{babel}
\def\coltype{}
\newcommand\notcoleq{\ifcolon\addcytoks[1]{\coltype}\fi\colreset}
\newcommand\colreset{\colonfalse\def\coltype{}}
\newif\ifcolon
\stripgroupingtrue
\tokcycleenvironment\subcoloneqq
%%% CHARACTER DIRECTIVE
{%
\tctestifx{=##1}
  {\tctestifcon{\ifcolon}
    {\addcytoks{\coloneqq}\colreset}
    {\notcoleq\addcytoks{##1}}%
  }
  {\tctestifx{:##1}
    {\colontrue\def\coltype{##1}}
    {\notcoleq\addcytoks{##1}}%
  }%
}
%%% GROUP DIRECTIVE
{\notcoleq\groupedcytoks{\processtoks{##1}\notcoleq}}
%%% MACRO DIRECTIVE
{\tctestifcon{\if\detokenize{:}\detokenize{##1}}
  {\colontrue\def\coltype{##1}}
  {\notcoleq\addcytoks{##1}}}
%%% SPACE DIRECTIVE
{\notcoleq\addcytoks{##1}}
%%%
\begin{document}
\subcoloneqq
Un example: et voilà.

$a := b$ $a \ordinarycolon= b$ $a:b$ \endsubcoloneqq \end{document}

enter image description here


SUPPLEMENT

I have recently began a tokcycle package improvement cycle to add look-ahead features to the token cycle. In the above "standard" approach, only one token is handled in the input stream at a time. Therefore, to look for a multi-byte sequence, I have to set flags and macros, so that one directive can communicate with another.

EDIT: tokcycle[2021-05-27] has been released which incorporates code to peek ahead at the input stream. Thus, \makeatletter code has been excised from this supplement. As you can see, the directives of the \subcoloneqq environment become greatly simplified.

\documentclass{article}
\usepackage{tokcycle,mathtools}
\usepackage[french]{babel}
\newcommand\coleqchek[1]{\tcpeek\z
  \ifx=\z\tcpop\z\addcytoks{\coloneqq}\else\addcytoks{#1}\fi}
\tokcycleenvironment\subcoloneqq
%%% CHARACTER DIRECTIVE
{\tctestifx{:##1}{\coleqchek{##1}}{\addcytoks{##1}}}
%%% GROUP DIRECTIVE
{\processtoks{##1}}
%%% MACRO DIRECTIVE
{\tctestifcon{\if\detokenize{:}\detokenize{##1}}
  {\coleqchek{##1}}{\addcytoks{##1}}}
%%% SPACE DIRECTIVE
{\addcytoks{##1}}
%%%
\begin{document}
\subcoloneqq
Un example: et voilà.

$a := b$ $a \ordinarycolon= b$ $a:b$ \endsubcoloneqq \end{document}

2

In Emacs with AUCTeX you can use this ELisp:

(defun user/insert-coloneqq ()
 (interactive)
 (when (eq (char-before) ?:)
  (delete-char -1)
  (insert "\\coloneqq")))
(define-key LaTeX-mode-map (kbd "=") 'user/insert-coloneqq)
Henri Menke
  • 109,596