Skip to main content
โšก Calmops

LaTeX Custom Commands and Macros: Automating Your Documents

Introduction

LaTeX’s true power emerges through custom commands and macros. Rather than repeatedly typing complex formatting or remembering inconsistent syntax, you can define shortcuts that ensure consistency while dramatically improving productivity.

This guide covers creating custom commands, environments, and package-level configurations that streamline your document creation.

Basic Command Definitions

Simple Commands with \newcommand

\newcommand{\companyname}{Acme Corporation}
\newcommand{\productname}{SuperWidget}

The \productname\ is produced by \companyname.

This creates expandable text substitutionsโ€”no formatting, just consistent text replacement.

Commands with Arguments

% One argument
\newcommand{\highlight}[1]{\textbf{#1}}

This is \highlight{important text}.

% Multiple arguments (up to 9)
\newcommand{\term}[2]{\textit{#1} (#2)}

\term{Algorithm}{A step-by-step procedure}

Argument syntax: #1 through #9 represent each argument.

Default Arguments

% First argument has default value
\newcommand{\emphasize}[2][red]{\textcolor{#1}{\textbf{#2}}}

\emphasize{Red text}                    % Uses default red
\emphasize[blue]{Blue emphasized text}  % Overrides default

Advanced Command Features

Optional Arguments

\usepackage{xparse}

\NewDocumentCommand{\highlight}{O{blue} m}{%
  \textcolor{#1}{\textbf{#2}}%
}

\highlight{Default blue}
\highlight[red]{Red highlight}
\highlight[green]{Green highlight}

The xparse package provides more flexible argument parsing than \newcommand.

Conditional Commands

\newif\ifdebug
\debugfalse

\ifdebug
  \newcommand{\trace}[1]{\textit{#1}}
\else
  \newcommand{\trace}[1]{}
\fi

\trace{This shows in debug mode}

Robust Commands

Commands using fragile content should be robust:

\usepackage{etoolbox}

\robustcommand{\myst command}[1]{%
  \textbf{#1}%
}

Or use \DeclareRobustCommand:

\DeclareRobustCommand{\strong}[1]{%
  \textbf{#1}%
}

Custom Environments

Basic Environment Definition

\newenvironment{important}%
  {\begin{trivlist}\item[\hskip\labelsep\bfseries Important:]}%
  {\end{trivlist}}

\begin{important}
This is an important note that stands out from regular text.
\end{important}

Environments with Arguments

\newenvironment{boxed}[1][Warning]%
  {\begin{trivlist}\item[\hskip\labelsep\sbox0{#1}\textbf{\usebox0}:]}%
  {\end{trivlist}}

\begin{boxed}{Note}
This is a note in a box.
\end{boxed}

\begin{boxed}
This uses the default "Warning" title.
\end{boxed}

Counter Environments

\newcounter{example}
\newenvironment{example}%
  {\refstepcounter{example}%
   \par\medskip\noindent\textbf{Example \theexample:}%
   \nopagebreak\par\nobreak%
   \nopagebreak}
  {\par\medskip}

\begin{example}
First example content.
\end{example}

\begin{example}
Second example content.
\end{example}

Programming Constructs

Definitions and Assignments

% Simple definitions
\def\myvar{value}

% Math definitions
\gdef\constant{42}

% Conditional definitions
\ifdefined\existing
  % Use existing definition
\else
  \def\existing{default}
\fi

Length and Counters

% Length variables
\newlength{\mylength}
\setlength{\mylength}{2cm}
\addtolength{\mylength}{5mm}
\the\mylength

% Counter operations
\newcounter{mycounter}
\stepcounter{mycounter}
\addtocounter{mycounter}{5}
\them ycounter

Arithmetic

\usepackage{calc}

\newlength{\computed}
\setlength{\computed}{\linewidth - 2cm}

\newcounter{computed}
\settocounter{computed}{\linewidth / 50}

Package Development Basics

Creating a Style Package

% mypackage.sty
\NeedsTeXFormat{LaTeX2e}
\ProvidesPackage{mypackage}[2026/01/01 Custom Package]

% Package options
\DeclareOption{compact}{\gdef\pack@option{compact}}
\DeclareOption{verbose}{\gdef\pack@option{verbose}}
\ExecuteOptions{compact}
\ProcessOptions\relax

% Required packages
\RequirePackage{xcolor}
\RequirePackage{todonotes}

% Custom commands
\newcommand{\mypackagecmd}[1]{\textbf{#1}}

% Configuration
\gdef\mypackage@version{1.0}

\endinput

Using Your Package

\documentclass{article}
\usepackage[verbose]{mypackage}

\begin{document}
\mypackagecmd{Content}
\end{document}

Utility Commands

Helper Macros

% Check if command is defined
\ifdefined\command
  \command is defined
\else
  \command is not defined
\fi

% Provide command if not defined
\providecommand{\maybeDefined}{default value}

% Check for empty arguments
\newcommand{\checkempty}[1]{%
  \ifx&#1&%
    Argument is empty
  \else%
    Argument: #1
  \fi%
}

String Manipulation

\usepackage{xstring}

\StrGobbleLeft{string}{1}[\result]  % Remove first char
\StrGobbleRight{string}{1}[\result] % Remove last char
\StrMid{string}{3}{7}[\result]       % Extract substring
\StrLen{string}[\result]             % Get length

Iteration

\usepackage{pgffor}

\foreach \x in {1,2,3,4,5} {
  Item \x
}

\foreach \x/\y in {a/1,b/2,c/3} {
  \x = \y
}

Document-Specific Automation

Metadata Commands

\newcommand{\docauthor}[1]{\gdef\@author{#1}}
\newcommand{\docdate}[1]{\gdef\@date{#1}}
\newcommand{\docversion}[1]{\gdef\doc@version{#1}}

\docauthor{Your Name}
\docversion{1.0}

% Use in document
Version \doc@version\ by \@author

Section Styling

% Custom section command
\newcommand{\mysection}[1]{%
  \section*{#1}%
  \addcontentsline{toc}{section}{#1}%
}

% Numbered custom sections
\newcommand{\specialsection}[1]{%
  \section{#1}%
  \sectionmark{#1}%
}

Table and Figure Helpers

% Quick figure
\newcommand{\fig}[3]{%
  \begin{figure}[htbp]
    \centering
    \includegraphics[width=#2]{#1}
    \caption{#3}
  \end{figure}%
}

% Usage
\fig{image}{0.8\linewidth}{My caption}

% Quick table
\newcommand{\simpletable}[3]{%
  \begin{table}[htbp]
    \centering
    \caption{#3}
    \begin{tabular}{#1}#2\end{tabular}
  \end{table}%
}

LaTeX Programming Patterns

Hooks and Filters

% At beginning of document
\AtBeginDocument{%
  \hypersetup{colorlinks=true}
}

% At end of document
\AtEndDocument{%
  \clearpage
  \begin{center}
    Document version: \doc@version
  \end{center}
}

% Before/after specific commands
\let\oldsection\section
\RenewDocumentCommand\section{som+O{}}{\oldsection[#1]{#2}}

Expansion Control

% Prevent expansion
\noexpand\command

% Expand once
\expandafter\command

% Fully expand
\edef\expanded{\detokenize\expandafter{\somecommand}}

Performance Optimization

Efficient Macros

% Store repeated calculations
\newlength{\cachedlen}
\settowidth{\cachedlen}{\textbf{Some Text}}

% Reuse cached values
\the\cachedlen

% Use token registers for large text
\newtoks\mytoks
\mytoks={Some text content}
\the\mytoks

Conditional Loading

\@ifpackageloaded{package}{true}{false}

\@ifclassloaded{article}{yes}{no}

\@ifdefined\command{exists}{undefined}

Best Practices

Command Naming

  1. Use meaningful, descriptive names
  2. Avoid conflicting with existing commands
  3. Prefix project-specific commands
  4. Document all custom commands

Error Handling

\newcommand{\critical}[1]{%
  \ifmmode
    \PackageError{mypkg}{Use \string\critical\space in text mode only}%
  \else
    \textbf{#1}%
  \fi
}

Testing Macros

% Debug output
\show\mycommand

% Trace expansion
\tracingonline=1
\meaning\mycommand

Conclusion

Custom commands and macros transform LaTeX from a typesetting system into a programmable document creation environment. The techniques in this guide enable automation that ensures consistency while dramatically improving productivity.

Start with simple text substitutions, progress to argument-based commands, and eventually develop custom packages for large projects. Each level of sophistication brings new capabilities.

Resources

Comments