Hot answers tagged etoolbox
18
\ifodd is enough to do this
\documentclass[]{scrartcl}
\newcount\myint
\def\IsFourMultiple#1{%
\myint#1\relax
\ifodd\myint
false
\else
\divide\myint by2\relax
\ifodd\myint
false
\else
true
\fi
\fi}%
\begin{document}
\IsFourMultiple{4}
\IsFourMultiple{32}
\IsFourMultiple{15}
\end{document}
16
You can use the logical combination and and or in the test \ifboolexpr
\ifboolexpr{%
test {\ifnumless{a}{b}}
and
test{\ifnumgreater{x}{100}}
}{YES}{NO}
For more details see the documentation (section 3.6.5).
I want to show an example.
\documentclass{article}
\usepackage{etoolbox}
\newcounter{a}\newcounter{b}\newcounter{x}
...
15
You can use pgfmath for this:
\documentclass{article}
\usepackage{pgf}
\begin{document}
\newcommand\ifismultiple[4]{%
\pgfmathparse{mod(#1,#2)==0}
\ifnum \pgfmathresult=1
#3%
\else
#4%
\fi
}
\ifismultiple{15}{4}{true}{false}
\end{document}
15
If you need repeated access to arbitrary items then an "array" of command names \mylist1, \mylist2\ ... might be more suitable than a list.
\documentclass{minimal}
\usepackage{etoolbox}
\newcounter{mylistcounter}
\def\saveitem#1{%
\stepcounter{mylistcounter}%
\expandafter\def\csname mylist\themylistcounter\endcsname{#1}}
\forcsvlist{\saveitem}{%
...
14
NOTE: There are some minor weaknesses in the code shown below, so it's best to use the corresponding package.
The following macros define the commands \xpatchcmd, \xpretocmd and \xapptocmd that recognize robust commands (defined by \DeclareRobustCommand or \newrobustcmd) and also if they have an optional argument.
\usepackage{etoolbox,xparse}
...
14
You can get \\foo@ using \csname\string\foo@\endcsname. The space shown behind it with \show is not part of the macro name (but could be added using a \space before \endcsname).
So you can use:
\expandafter\patchcmd\csname\string\foo@\endcsname{hook}{\label{#1}hook}{success}{failure}
Full example:
\documentclass{article}
\usepackage{etoolbox}
...
14
With eTeX's \numexpr, you can do that easily.
\makeatletter
\newcommand{\doifmultipleof}[2]{%
\ifnum\numexpr((#2)/(#1))*(#1)-(#2)=0
\expandafter\@firstoftwo
\else
\expandafter\@secondoftwo
\fi}
\makeatother
\documentclass{article}
\begin{document}
\doifmultipleof{4} {6}{true}{false} % => false
\doifmultipleof{5}{10}{true}{false} % ...
14
With \def\myrelax{\relax} macro \myrelax is a parameterless macro with replacment text \relax. You get a command sequence with meaning \relax with \let:
\let\myrelax\relax
Also \def\myemptyempty{\myempty} defines a parameterless macro \myemptyempty that is not empty, whose replacement text is \myemptyempty. There is \edef that expands the replacement text ...
13
Just for future reference, expl3 has nice switch/case statement constructs:
\prg_case_str:nnn {\doctype}
{
{SomeString1} {some~ text~ here}
{SomeString2} {some~ different~ text~ here}
}
{else~ clause}
Variations are also provided with integers, dimensions, and token lists; e.g.,
\prg_case_int:nnn{2*5}{
{5}{Small}
{4+6}{Medium}
...
13
If you can use luatex, then the comparison can be easily done at the lua end. Here is a ConTeXt solution (using named macro arguments):
% macros=mkvi
\def\doifmultipleof#{mod}#{num}%
{\ctxcommand{doifelse(math.mod(#{num}, #{mod}) == 0)}}
\starttext
\dorecurse{10}
{\doifmultipleof{4}{\recurselevel}{yes}{no}}
\stoptext
13
You have an end-of-line character after the opening { which causes a space.
It might be better to check if the argument is a single space instead of being empty. You can add one space to the argument yourself to make sure the test is true for a real empty content.
Also you should add % after any { or } at the end of a line inside the macro definition.
...
13
There are a few reasons why defining document commands has always been done using the control sequence for the command (\foo) rather than the control sequence name (foo). Of course, some of this comes down to 'you'd have to ask Leslie Lamport or Don Knuth', as it follows from the TeX basics. (For example, \newcommand\foo mirrors \def\foo, and ...
13
The answer to this is specified in the etoolbox documentation under section 3.5 Boolean Flags (p 12 onward):
3.5.1 TeX Flags
Since the tools in this section are based on \newif internally, they may be used
to test and alter the state of flags previously defined with \newif. They are also
compatible with the boolean tests of the ifthen package and may ...
12
I replaced your if-if-if-if construct with a simple \ifcase test. \moon works just fine now. Though the actual problem was another one. The counter assignments \global\advance\<counter> by 1 should be finished with a \relax. This also applies to the \ifnum but in this instance, it is not needed as math-mode is introduces right away. Without the \relax ...
12
\newbool{mybool} is almost the same as \newif, but it checks whether \ifmybool is already defined, which LaTeX doesn't:
\newrobustcmd*{\newbool}[1]{%
\expandafter\@ifdefinable\csname if#1\endcsname{%
\expandafter\newif\csname if#1\endcsname}}
There's also \providebool which does nothing if the conditional is already defined.
Similarly, \ifbool is a ...
11
Thanks to egreg for pointing me to TeX by Topic. Here's the relevant quote (p. 275):
Quantities that are assigned to inside a group must be restored after
the end of that group. The save stack is where the values to be
restored are kept; the size of the save stack limits the number of
values that can be restored.
Alternating global and local ...
11
As always with (La)TeX: If you know what you are doing you are allowed to do it!
Some local counter changes make perfectly sense, like in the example in the question. However I wouldn't call secnumdepth a real counter. After all it is never incremented. Here simply a counter register was used to store an integer because there is no other suitable type.
Real ...
11
A kind of "switchcase" can be easily programmes:
\documentclass{article}
\makeatletter
\def\ifnumcase#1{%
\edef\elseif@{\string\elseif}\edef\endif@{\string\endif}%
\def\number@test{#1pt}\ifnumcase@i}
\def\ifnumcase@i#1{%
\def\ifnumcase@ii##1{%
\csname
@\ifdim\number@test#1pt first\else second\fi oftwo%
...
11
One of the last things the figure enviroment does is issuing the internal command \@floatboxreset whose definition is
\def\@floatboxreset{%
\reset@font
\normalsize
\@setminipage
}
and this is why the \smaller declaration has no effect, because the tokens in \AtBeginEnvironment are found earlier.
You should instead change the meaning of ...
10
\makeatletter
\def\act@on@bibmacro#1#2{%
\expandafter#1\csname abx@macro@\detokenize{#2}\endcsname}
\def\patchbibmacro{\act@on@bibmacro\patchcmd}
\def\pretobibmacro{\act@on@bibmacro\pretocmd}
\def\apptobibmacro{\act@on@bibmacro\apptocmd}
\def\showbibmacro{\act@on@bibmacro\show}
\makeatother
Now you have available
\patchbibmacro \pretobibmacro ...
10
Here's a possible solution with xparse:
\documentclass{article}
\usepackage{xparse}
\ExplSyntaxOn
\NewDocumentCommand{\newgniourflist}{ m }
{
\seq_new:c { g_gniourf_#1_seq }
}
\newgniourflist{gniourflist}
\NewDocumentCommand{\addtogniourflist}{ O{gniourflist} m }
{
\seq_gput_right:cn { g_gniourf_#1_seq } { #2 }
}
\NewDocumentCommand{\getnthelement}{ ...
10
You need to close the file with \immediate or the operation would be delayed at the next shipout. Similarly, write with \immediate.
But this is not the only precautions to be taken. In the footnote at page 24 in the documentation of etoolbox you find that the list delimiter is | with category code 3. So
\documentclass{article}
\newwrite\outf
\newread\inf
...
10
If you add \tracingpatches to the preamble you find the answer in the log:
[debug] tracing \patchcmd on input line 14
[debug] analyzing '\abc'
[debug] ++ control sequence is defined
[debug] ++ control sequence is a macro
[debug] -- nested patching command and parameters in patch
[debug] -> the patching command seems to be nested in the
[debug] ...
9
The etoolbox manual states for \ifstrequal on page 17: (emphasis mine)
Compares two strings and executes htruei if they are equal, and hfalsei otherwise.
The strings are not expanded in the test and the comparison is category code agnostic.
So you always compare the string "\ab{}" with "a" and "b". If you want to allow macros as input you need to ...
9
There might be an official way, but defining a new command \AfterEndItemize to specify what you want to do after \end{itemize}, and then use \renewcommand to change \AfterEndItemize to not do anything seems to work:
\documentclass{article}
\usepackage{etoolbox}
\newcommand{\AfterEndItemize}{bleat bleat}%
\AfterEndEnvironment{itemize}{\AfterEndItemize}
...
9
The suggestion to use \@for might work out something like
\documentclass{article}
\usepackage{etoolbox}
\makeatletter
\newrobustcmd{\mycommand}[2][]{% first the options that are equal for all
\@for\tmp:=#1\do{%
\expandafter\ifstrequal\expandafter{\tmp}{up}
{'up' seen}%
{%
\expandafter\ifstrequal\expandafter{\tmp}{middle}
...
9
The proper approach to this problem is to use a package written just for this purpose: showlabels.
\documentclass{article}
\usepackage{showlabels}
\begin{document}
\section{Introduction}\label{sec:intro}
Blah
\section{Start}\label{sec:start}
Blah
\subsection{Ready}\label{subsec:ready}
Blah
\subsection{Set}\label{subsec:set}
Blah
...
8
Due to the nature of the TeX stack, you should use registers either locally or globally. Using primitives, that means something like
\newcount\mylocalcount
\newcount\myglobalcount
\begingroup
\mylocalcount 10 %
\global\myglobalcount 10 %
\endgroup
Thus if you want to use \defcounter for local assignments, you should not intermix it with \setcounter ...
8
(Martin has posted an answer, but there is a bit more to this!) The problem arises due to an issue with the definition of \@@end. This is where the LaTeX kernel stores the TeX \end primitive (so that \end can be reused for environments). The bm package does various tests for \@@end which rely on it being the primitive. What is happening is that etoolbox does
...
8
Depending on who else needs to use the code, would lualatex work?
\documentclass{article}
\begin{document}
\directlua{
x=1.5
}
\directlua{
if x<1 then
tex.print('a')
elseif x<2 then
tex.print('b')
elseif x<3 then
tex.print('c')
else
tex.print('d')
end
}
\end{document}
Only top voted, non community-wiki answers of a minimum length are eligible