1

i'm trying to write a command that checks whether the next character after it is invoked is a dot (.), but can't seem to figure it out.

i'm kinda new to LaTeX and have written a command to stylize the writing of centuries. the command adds the . character in the end by default. the problem is that, if I use it at the end of a sentence, I end up with two dots (..). i'm trying to lookahead for the next character to see if it's a dot or not, in order to conditionally decide whether to add a dot at the end. i tried using the \@ifnextchar marco, but can't seem to figure it out (despite searching through the TeX StackExchange and the docs). what am i doing wrong?

update with minimal working example:

\documentclass[a4paper,12pt,twoside]{book}
\usepackage[english, french]{babel}
\usepackage[utf8x]{inputenc}
\usepackage[T1]{fontenc}
\usepackage{fontspec}
\usepackage{lmodern}
\usepackage{rotating}

\newcommand{\scl}[1]{%
    % #1 : the century in question
    #1%
    \ifthenelse{\equal{#1}{I}}{\up{er}}{\up{ème}}%
    ~s%
    \@ifnextchar.{}{.}% this is the line that causes a problem: checks if next char is `.`
}

\begin{document}
    This is where I use the command \scl{XIX}. Ideally, the command 
    should not have added a `.` since it is followed by a dot.
\end{document}

output:

I just found out that without using rotating (which was loaded before I made this command), I get the following error: Undefined control sequence. This is where I use the command \scl{XIX}. When using rotating, this is the output:

output

for info, i use XeLaTeX on TeXstudio.

thanks for your help !

4
  • have you made this definition at a point @ is a letter? (in a package or after \makeatletter)? Please always provide full examples, we can not run your code and you have not shown the error you got. Sep 11, 2022 at 20:17
  • I just edited my post with a MWE working example, error log and screen capture, sorry to have forgotten that ! i didn't use \makeatletter, but adding that solved the issue, so thanks !!
    – paulhector
    Sep 11, 2022 at 20:44
  • Don't load \usepackage[utf8x]{inputenc}! First: You're using XeLaTeX, that doesn't need inputenc as it is a unicode engine. Second: It is very dated, nowadays utf8 is better than utf8x in pdfLaTeX.
    – Skillmon
    Sep 11, 2022 at 21:08
  • Also, even if it does no harm here (since \@ifnextchar ignores spaces) you really should put the % immediately after the closing brace to remove the spurious space here as well (or else it'll need to ignore that space on every call)
    – Skillmon
    Sep 11, 2022 at 21:10

2 Answers 2

1

You need @ to be a letter:

enter image description here

\documentclass[a4paper,12pt,twoside]{book}
\usepackage[english, french]{babel}
% no: (ignored with xetex) \usepackage[utf8x]{inputenc}
% no: does real harm with xetex (breaks hyphenation) \usepackage[T1]{fontenc}
\usepackage{fontspec}
\usepackage{lmodern}
\usepackage{rotating}

\makeatletter
\newcommand{\scl}[1]{%
    % #1 : the century in question
    #1%
    \ifthenelse{\equal{#1}{I}}{\up{er}}{\up{ème}}%
    ~s%
    \@ifnextchar.{}{. }% this is the line that causes a problem: checks if next char is `.`
}

\makeatother

\begin{document}
    This is where I use the command \scl{XIX}. Ideally, the command 
    should not have added a `.` since it is followed by a dot.

    This is where I use the command \scl{XIX} ideally, the command 
    should  have added a `.` since it is not followed by a dot.
\end{document}
1
  • thank you for your help ! indeed, that's what was missing, i don't know why i hadn't thought about it before.
    – paulhector
    Sep 11, 2022 at 23:16
1

You're missing \makeatletter to allow \@ifnextchar to be interpreted correctly.

As other have commented, never use utf8x (with any engine) and don't load neither fontenc nor lmodern with Unicode engines (XeLaTeX or LuaLaTeX).

Your command is missing robustness and wouldn't work in section titles or captions, for instance. Use

\DeclareRobustCommand{\scl}[1]{...}

instead.

An even more robust implementation with expl3 would be

\documentclass[a4paper,12pt,twoside]{book}
\usepackage[english, french]{babel}
\usepackage{fontspec}

\ExplSyntaxOn

\NewDocumentCommand{\scl}{m}
 {% #1 : the century in question
  #1
  \str_if_eq:nnTF { I } { #1 }{\up{er}}{\up{ème}}
  \nobreakspace s
  \peek_charcode:NF . { . }
}
\ExplSyntaxOff

\begin{document}

This is where I use the command \scl{XIX}. Ideally, the command 
should not have added a `.' since it is followed by a period.

\end{document}

enter image description here

However, in my opinion, it would be easier inputting a standard numeral rather than a Roman one.

\documentclass[a4paper,12pt,twoside]{book}
\usepackage[english, french]{babel}
\usepackage{fontspec}

\ExplSyntaxOn

\NewDocumentCommand{\scl}{m}
 {% #1 : the century in question in standard numeric form
  \int_to_Roman:n { #1 }
  \int_compare:nTF { #1 == 1 }{\up{er}}{\up{ème}}
  \nobreakspace s
  \peek_charcode:NF . { . }
}
\ExplSyntaxOff

\begin{document}

This is where I use the command \scl{19}. Ideally, the command 
should not have added a `.' since it is followed by a period.

\end{document}

The output is the same.

It's even possible to have both types of input (not that I recommend it, though).

\documentclass[a4paper,12pt,twoside]{book}
\usepackage[english, french]{babel}
\usepackage{fontspec}

\ExplSyntaxOn

\NewDocumentCommand{\scl}{m}
 {
  \regex_match:nnTF { \A [0-9]* \Z } { #1 }
   {% the input is numeric
    \int_to_Roman:n { #1 }
    \int_compare:nTF { #1 == 1 }{\up{er}}{\up{ème}}
   }
   {% assume the input is a Roman numeral
    #1
    \str_if_eq:nnTF { I } { #1 }{\up{er}}{\up{ème}}
   }
  \nobreakspace s
  \peek_charcode:NF . { . }
}
\ExplSyntaxOff

\begin{document}

This is where I use the command \scl{19}. Ideally, the command 
should not have added a `.' since it is followed by a period.

This is where I use the command \scl{XIX}. Ideally, the command 
should not have added a `.' since it is followed by a period.

\end{document}

Two copies of the same text are generated.

1
  • thanks for the very detailed answer ! adding \makeatletter worked, i don't know why i never thought about it.
    – paulhector
    Sep 11, 2022 at 23:12

You must log in to answer this question.

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