5

I like a command that typesets i.e. with a half blank after the i. - i.e. i.\,e.

Now the tricky issue is what to include after the e..

The MWE contains a few commands that i would like to see integrated. I tried using xspace, but it did not seem to help.

\documentclass{article}
\newcommand{\ie}{i.\,e. }%1.5 blank
\newcommand{\iens}{i.\,e.}no blank IF followed by sign.
\newcommand{\iesb}{i.\,e.\ }%single blank

\begin{document}
    \ie without full stop or comma gets me a 1.5 * blank after the \ie's `.'.

    \iens: with a full stop or comma (or similar sign)  works as intended.

    \iesb gets me a correct blank of factor 1.

    Can I integrate these commands into a single command that dynamically adds a simple factor 1 blank after the `.` IF no sign directly follows whilst not inserting a blank at all IF a sign directly follows the command?
\end{document}
  • 3
    Here is a solution on the meta-level. Most style guides require a comma after i.e., so you don't have to worry about spaces after this abbreviations. Second, avoid the use of i.e., because in most cases it is used wrongly. "i.e." requires that the clause before and the one after it are identical in meaning, where one clause could replace the other one. People often use "i.e." to add some consequence, but then i.e. is inadequate. – gernot Mar 18 '17 at 10:31
  • 1
    You have contradictory requirements: how can the single macro distinguish between cases 1 and 3? – egreg Mar 18 '17 at 11:24
  • thanks @gernot. In this case I am actually certain I still want to know about this. I agree about your semantic convention of how to use "i.e." – ingli Mar 18 '17 at 12:28
6

The xspace package takes care about whether to insert a space or not, but not whether it is supposed to be an inter-word-space or an inter-sentence-space.

As explained in this answer, you can use \@ to mark both the end of a sentence and no end of a sentence depending on whether it stands in front of the fullstop or after it.

Thus (as you have already figured out) the command you were looking for is \newcommand{\iex}{i.\,e.\@\xspace}.

Please keep in mind, though, that even with a command like this, one still should not always use a normal space without thinking. Depending on what else this approach is used for, a ~ would sometimes be better because it prohibits a line break, see TeXbook pages 74, 91-93:

The tie mark is best for abbreviations within a name, and after several other common abbreviations like 'Fig.' and 'cf.' and 'vs.' and 'resp.'; you will find that it's easy to train yourself to type cf.~Fig.~5. In fact, it's usually wise to type ~ (instead of a space) just after a common abbreviation that occurs in the middle of a sentence.

I have used \xspace a lot in my bachelor thesis until I encountered a problem where it did not decide correctly. I did not have the time to figure out what it was but I was assuming that I was nesting my commands too much. In the end I went through the entire code and handled all the spacing manually, after all. Nowadays I know that the xspace documentation says that it only gets most cases correct and what to do if it does not (see pages 1 and 2).

I, however, have made the decision for myself to not use xspace again. The fact, that TeX eats up spaces after control words can always be avoided by adding a {} after it. But typing them is annoying and if one forgets them one does not even get a warning. Therefore I prefer to use a parameter delimiter, a non-letter character directly following the name of the control sequence, i.e. \def\ie/{i.\,e.\@} (see TeXbook page 204). One still needs to type the parameter delimiter but if one forgets to type it TeX complains with an error. And because the space does not directly follow a control sequence but the parameter delimiter, it is not gobbled. This approach has still two issues: (1) \def does not check whether the control sequence is already existing or not (if it is it will be replaced silently) and (2) you still need to type the parameter delimiter. But with some trickery one can convince TeXStudio's autocompletion to insert it for you:

\makeatletter
% #1: macro name, #2: parameter delimiter
% The last '#' is an exceptional parameter delimiter standing for an opening brace (TeXbook page 204).
\def\@parameterless@newcommand#1#2#{%
    % the name of the macro without the leading escape character
    \edef\tmp@macroname{\expandafter\@gobble\string#1}%
    % if #1 is undefined
    % I am using here that \csname is letting #1 to \relax if it is undefined
    \expandafter\ifx \csname\tmp@macroname\endcsname \relax
    % then
        \def\@parameterless@do{\def#1#2}%
    \else
        \GenericError{}{Command \@backslashchar\tmp@macroname\space already defined}{}{Your command was ignored.}%
        \let\@parameterless@do=\@gobble
    \fi
    \@parameterless@do
}
% To strip the braces around macro name and parameter delimiter.
\def\@parameterless\newcommand#1{%
    \@parameterless@newcommand#1%
}
% TeXstudio does not recognize the parameter delimiter "\newcommand".
% Therefore I deceive it so that it sees \parameterless as a simple macro without parameters.
% Otherwise the autocompletion would insert an argument between \parameterless and \newcommand.
\let\parameterless=\@parameterless%
\makeatother

\parameterless\newcommand{\ie/}{i.\,e.\@}

If you need the \parameterless command to work with \renewcommand or \providecommand as well, you can use the following definition:

\makeatletter
% #1: \newcommand, \renewcommand or \providecommand, #2: control sequence followed by parameter delimiter
\def\@parameterless#1#2{%
    \ifx\newcommand#1%
        \@parameterless@ifundefined#2{%
            % then
            \def\@parameterless@do{\def#2}%
        }{%
            % else
            \GenericError{}{Command \@backslashchar\tmp@macroname\space already defined}{as \expandafter\meaning\csname\tmp@macroname\endcsname}{Your command was ignored.}%
            \let\@parameterless@do=\@gobble
        }%
    \else\ifx\renewcommand#1%
        \@parameterless@ifundefined#2{%
            % then
            \GenericError{}{\@backslashchar\tmp@macroname\space undefined}{}{Your command was ignored.}%
            \let\@parameterless@do=\@gobble
        }{%
            % else
            \def\@parameterless@do{\def#2}%
        }%
    \else\ifx\providecommand#1%
        \@parameterless@ifundefined#2{%
            % then
            \def\@parameterless@do{\def#2}%
        }{%
            % else
            \let\@parameterless@do=\@gobble
        }%
    \else
        \GenericError{}{Use of \@backslashchar parameterless doesn't match its definition}{It should be directly followed by either one of \string\newcommand, \string\renewcommand\space or \string\providecommand.}{Your command was ignored.}%
        \let\@parameterless@do=\@gobble
    \fi\fi\fi
    \@parameterless@do
}
% #1: control sequence, #2: parameter delimiter
% The last '#' is an exceptional parameter delimiter standing for an opening brace (TeXbook page 204).
% if (#1 is defined) {\@firstoftwo} else {\@secondoftwo}
\def\@parameterless@ifundefined#1#2#{%
    % the name of the macro without the leading escape character
    \edef\tmp@macroname{\expandafter\@gobble\string#1}%
    % if #1 is undefined
    % I am using here that \csname is letting #1 to \relax if it is undefined
    \expandafter\ifx \csname\tmp@macroname\endcsname \relax
    % then
        \expandafter\@firstoftwo
    \else
        \expandafter\@secondoftwo
    \fi
}
% To deceive TeXstudio into believing \parameterless was a macro without parameters.
% Otherwise the autocompletion would insert undesired braces.
\let\parameterless=\@parameterless%
\makeatother

But, there is still something to be considered: what if the abbreviation stands at the end of a sentence? You probably would not want two dots. And the space after the dot should be an inter-sentence-space. This macro, however, ensures that the following space will be an inter-word-space. Looking ahead whether the next token is a dot is not possible because \@ifnextchar gobbles following spaces (The LaTeX 2e Sources page 35).

One might however replace the parameter delimiter for a parameter and insert an explicit end-of-sentence-dot or not-end-of-sentence-dot depending on the argument. So normally, inside of a sentence, one uses the above syntax \ie/ but at the end of a sentence the slash is replaced by a fullstop: \ie. A space after it will still not be eaten up because it does not directly follow a control word but an argument. If, however, one forgets the argument, TeX will no longer complain. But as long as one uses the autocompletion one can not forget to insert the argument.

Please note that with the following definition the replacement text must end with a . (without a \@).

\makeatletter
% #1: \newcommand, \renewcommand or \providecommand, #2: control sequence followed by parameter delimiter, #3: replacement text
\def\@abbr#1#2#3{%
    \ifx\newcommand#1%
        \@abbr@ifundefined#2{%
        % then
            \edef\@abbr@do{\def\expandafter\noexpand\csname\tmp@macroname\endcsname####1}%
        }{%
        % else
            \GenericError{}{Command \@backslashchar\tmp@macroname\space already defined}{as \expandafter\meaning\csname\tmp@macroname\endcsname}{Your command was ignored.}%
            \let\@abbr@do=\@gobble
        }%
    \else\ifx\renewcommand#1%
        \@abbr@ifundefined#2{%
        % then
            \GenericError{}{\@backslashchar\tmp@macroname\space undefined}{}{Your command was ignored.}%
            \let\@abbr@do=\@gobble
        }{%
        % else
            \edef\@abbr@do{\def\expandafter\noexpand\csname\tmp@macroname\endcsname####1}%
        }%
    \else\ifx\providecommand#1%
        \@abbr@ifundefined#2{%
        % then
            \edef\@abbr@do{\def\expandafter\noexpand\csname\tmp@macroname\endcsname####1}%
        }{%
        % else
            \let\@abbr@do=\@gobble
        }%
    \else
        \GenericError{}{Use of \@backslashchar abbr doesn't match its definition}{It should be directly followed by one of \string\newcommand, \string\renewcommand\space or \string\providecommand.}{Your command was ignored.}%
        \let\@abbr@do=\@gobble
    \fi\fi\fi
    % strip the trailing dot so that I can replace it by an explicit end-of-sentence-dot or not-end-of-sentence-dot. (so that it works with upper case abbreviations, too.)
    \@abbr@def\@abbr@content#3\@abbr@enddef%
    \expandafter\@abbr@do\expandafter{\@abbr@content\ifx.##1\@.\else.\@\fi}%
}
\def\@abbr@def#1#2.\@abbr@enddef{\def#1{#2}}%
% #1: control sequence, #2: parameter delimiter
% The last '#' is an exceptional parameter delimiter standing for an opening brace (TeXbook page 204).
% if (#1 is defined) {\@firstoftwo} else {\@secondoftwo}
\def\@abbr@ifundefined#1#2#{%
    % the name of the macro without the leading escape character
    \edef\tmp@macroname{\expandafter\@gobble\string#1}%
    % if #1 is undefined
    % I am using here that \csname is letting #1 to \relax if it is undefined
    \expandafter\ifx \csname\tmp@macroname\endcsname \relax
    % then
        \expandafter\@firstoftwo
    \else
        \expandafter\@secondoftwo
    \fi
}
% To deceive TeXstudio into believing \abbr was a macro without parameters.
% Otherwise the autocompletion would insert undesired braces.
\let\abbr=\@abbr%
\makeatother

\abbr\newcommand{\ie/}{i.\,e.}

And while we are already at it, we might as well make the dots active so that we do not need to type in the \, manually:

\def\makedotactive{\catcode`.=\active}
\def\makedotother{\catcode`.=12\relax}
\def\dotOther{.}

\makeatletter
% #1: \newcommand, \renewcommand or \providecommand, #2: control sequence followed by parameter delimiter, #3: replacement text
\def\@abbr#1#2#3{%
    \makedotother
    \ifx\newcommand#1%
        \@abbr@ifundefined#2{%
        % then
            \edef\@abbr@do{\def\expandafter\noexpand\csname\tmp@macroname\endcsname####1}%
        }{%
        % else
            \GenericError{}{Command \@backslashchar\tmp@macroname\space already defined}{as \expandafter\meaning\csname\tmp@macroname\endcsname}{Your command was ignored.}%
            \let\@abbr@do=\@gobble
        }%
    \else\ifx\renewcommand#1%
        \@abbr@ifundefined#2{%
        % then
            \GenericError{}{\@backslashchar\tmp@macroname\space undefined}{}{Your command was ignored.}%
            \let\@abbr@do=\@gobble
        }{%
        % else
            \edef\@abbr@do{\def\expandafter\noexpand\csname\tmp@macroname\endcsname####1}%
        }%
    \else\ifx\providecommand#1%
        \@abbr@ifundefined#2{%
        % then
            \edef\@abbr@do{\def\expandafter\noexpand\csname\tmp@macroname\endcsname####1}%
        }{%
        % else
            \let\@abbr@do=\@gobble
        }%
    \else
        \GenericError{}{Use of \@backslashchar abbr doesn't match its definition}{It should be directly followed by one of \string\newcommand, \string\renewcommand\space or \string\providecommand.}{Your command was ignored.}%
        \let\@abbr@do=\@gobble
    \fi\fi\fi
    % strip the trailing dot so that I can replace it by an explicit end-of-sentence-dot or not-end-of-sentence-dot. (so that it works with upper case abbreviations, too.)
    \@abbr@def\@abbr@content#3\@abbr@enddef%
    \expandafter\@abbr@do\expandafter{\@abbr@content\ifx.##1\@.\else.\@\fi}%
}

% #1: control sequence, #2: parameter delimiter
% The last '#' is an exceptional parameter delimiter standing for an opening brace (TeXbook page 204).
% if (#1 is defined) {\@firstoftwo} else {\@secondoftwo}
\def\@abbr@ifundefined#1#2#{%
    % the name of the macro without the leading escape character
    \edef\tmp@macroname{\expandafter\@gobble\string#1}%
    % if #1 is undefined
    % I am using here that \csname is letting #1 to \relax if it is undefined
    \expandafter\ifx \csname\tmp@macroname\endcsname \relax
    % then
        \expandafter\@firstoftwo
    \else
        \expandafter\@secondoftwo
    \fi
}

\makedotactive
\def\@abbr@def#1#2.\@abbr@enddef{\edef#1{#2}}%
\newcommand{\defdot}{\def.}
\makedotother

\outer\def\abbr{%
    \makedotactive
    \@abbr
}
\makeatother

\defdot{\dotOther\noexpand\,}
\abbr\newcommand{\ie/}{i.e.}

In the above code the \edef in \@abbr@def causes TeX to expand the active dot when defining the abbreviation (in contrast to when using the abbreviation). And it requires that if one wants to use commands like \emph in the replacement text of the abbreviation that command needs to be preceeded by a \noexpand.

If the active dot should be expanded when using an abbreviation the \edef in \@abbr@def would have to be replaced by a normal \def. Also the \noexpand in \defdot would have to be removed.

If you get the error message ! Paragraph ended before \@abbr@def was complete the replacement text does not end with an (active) dot as it should.

\abbr intends to change catcodes in it's argument. Therefore it can not be used in an argument or in a replacement text. I am ensuring that by declaring it as \outer. If you try to do so anyway, you will get the error message ! Forbidden control sequence found.

Anyway, this is what the TeXbook says regarding the abbreviation 'i.e.' (page 74):

Manuals of style will tell you that the abbreviations 'e.g.' and 'i.e.' should always be followed by commas, never by spaces, so those particular cases shouldn't need any special treatment.

2

Drawing on the detailed discussion at Usage of LaTeX macro \space (compared with \␣) I figured out the following solution

\documentclass{article}
\usepackage{xspace} 
\newcommand{\iex}{i.\,e.\@\xspace}
\begin{document}
    \iex, bla c

    \iex bla c
\end{document}

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.