3

I want to declare a variable in class that takes in the font name from the preamble of the TeX file. Something like \docFont{<Variable>}. Is there a command that could nullify the space key in latex? For example \docFont{ Arial } would return the same result as \docFont{Arial}.

My myclass.cls File is something like this:

\NeedsTeXFormat{LaTeX2e}
\ProvidesClass{myclass}[2019/04/09 Standard HomeWork Template]
\LoadClass[a4paper,12pt,onecolumn,final]{article}
\RequirePackge{etoolbox}
\def\hFont#1{\gdef\@hFont{#1}}
\def\@hFont{\@latex@warning@no@line{No \noexpand\hFont given}}
\BeforeBeginEnvironment{document}{
\RequirePackage{xepersian}
\settextfont{\@hFont}
}

And my *.Tex file is something like this:

\documentclass{myclass}
\hFont{Arial}   %Document Persian Font
\begin{document}
something
\end{document}
  • 2
    Are you talking about some sort of string.Trim() you would find in other languages? You can check out \tl_trim_spaces:n from expl3 – texdoc interface3 has the documentation. – Sean Allred Apr 11 at 10:00
  • @SeanAllred This is exactly what I am looking for – Al_Fh Apr 11 at 10:00
  • 2
    Can you expand your question with a complete MWE? Due to expansion concerns, the exact context of how you want to use this macro will determine its implementation. – Sean Allred Apr 11 at 10:02
  • @SeanAllred edited. – Al_Fh Apr 11 at 10:13
6

You can use the trimspaces package for this purpose.

Simple examples

\documentclass{article}
\usepackage{trimspaces}

\makeatletter
\newcommand*{\trim}[1]{%
  \trim@spaces@noexp{#1}%
}
\makeatother

\begin{document}
\textbar \trim{a bcd ef}\textbar

\textbar \trim{ a bcd ef }\textbar
\end{document}

enter image description here

Here is another way that first stores the result of the trimming operation in a macro (\my@tmp@trimmed), then expands this macro:

\documentclass{article}
\usepackage{trimspaces}

\makeatletter

\newcommand*{\trim}[1]{%
  \begingroup
    \edef\my@tmp@trimmed{\trim@spaces@noexp{#1}}%
    \expandafter
  \endgroup
  \my@tmp@trimmed
}

\makeatother

\begin{document}
X\trim{a bc def}Y

X\trim{ a bc def  }Y
\end{document}

enter image description here

Overview of the possibilities

The trimspaces package offers several variants depending on what you want:

  • left-only, right-only or both-sides trimming (left: \trim@pre@space and \trim@pre@space@noexp; right: \trim@post@space, \trim@post@space@noexp; both: \trim@spaces, \trim@spaces@noexp);
  • whether you want to expand tokens while trimming, or not (so far, I chose the @noexp variant in the examples, that just trims without expanding; otherwise, see \trim@spaces in the package documentation and below).

It also allows one to trim the contents of an already-existing macro. Here is the example from the documentation concerning this point:

\def\b{ b \foo ! }
\trim@spaces@in\b

is equivalent to

\def\b{b \foo !}

\trim@pre@space@in and \trim@post@space@in offer analoguous functionality for left-only, resp. right-only trimming.

Difference between \trim@spaces and \trim@spaces@noexp

The following example illustrates the functional difference between \trim@spaces and \trim@spaces@noexp1: the former expands tokens from its argument whereas the latter doesn't (they can then be expanded “at the last moment”, which is often desirable).

\documentclass{article}
\usepackage{trimspaces}

\makeatletter
\newcommand*{\storeTrimmedImmediateExp}[2]{%
  \xdef#1{\trim@spaces{#2}}%
}

\newcommand*{\storeTrimmedNoExp}[2]{%
  \xdef#1{\trim@spaces@noexp{#2}}%
}
\makeatother

\newcommand*{\foo}{[default foo]}
\storeTrimmedImmediateExp{\immediateExp}{ a\foo b } % \foo is expanded now
\storeTrimmedNoExp{\delayedExp}{ a\foo b }          % \foo is not expanded yet
\renewcommand*{\foo}{[updated foo]}


\begin{document}
\textbar \immediateExp \textbar % there is no \foo inside \immediateExp

\textbar \delayedExp \textbar % \foo is expanded after \delayedExp
\end{document}

enter image description here

Corner cases

This last example explores a few corner cases with various kinds of spaces:

\documentclass{article}
\usepackage{trimspaces}

\makeatletter
\newcommand*{\trim}[1]{%
  \trim@spaces@noexp{#1}%
}
\makeatother

% Define \implicitSpace to be \let-equal to a space token
\begingroup
  \def\\{\global\let\implicitSpace= }\\ % cf. TeXbook exercise 24.6
\endgroup

\begin{document}
A\trim{a bc def}B

C\trim{ a bc def }D

E\trim{\ a bc def\ }F % control spaces aren't trimmed

% Implicit space tokens are... sometimes trimmed (?)
G\trim{\implicitSpace a bc def\implicitSpace}H
\end{document}

enter image description here

Footnote

  1. The other difference being that \trim@spaces@noexp requires an eTeX engine, while \trim@spaces doesn't.
  • Simple and easy to grasp. Thank you very much. – Al_Fh Apr 11 at 10:39
  • 1
    I'm glad it helped you. I realized there was an even simpler method, therefore I have expanded my answer starting with that one, then showing the difference between \trim@spaces and \trim@spaces@noexp, and finally testing the behavior of \trim@spaces@noexp with various kinds of spaces. – frougon Apr 11 at 22:12
5

Here, I preprocess the argument to \docfont and pass the result to \docfontcore, which solely for the purposes of demonstration, detokenizes its argument, so that you can see that it gives the originally specified tokens, trimmed of leading and trailing (but not intermediate) spaces.

The last MWE example shows that passing macros poses no impediment to the approach.

\documentclass{article}
\usepackage[T1]{fontenc}
\usepackage{listofitems}
\newcommand\docfont[1]{%
  \setsepchar{!!!!}% USE SOMETHING NOT IN THE FONTNAMES
  \readlist*\trimmedvar{#1}%
  \itemtomacro\trimmedvar[1]\thetrimmedvar%
  \expandafter\docfontcore\expandafter{\thetrimmedvar}%
}
\newcommand\docfontcore[1]{[\detokenize{#1}]}
\begin{document}
\docfont{ Arial Bold }
\docfont{Arial Bold  }
\docfont{Arial Bold}

\newcommand\myfont{Palatino}
\docfont{ \myfont-oblique }
\end{document}

enter image description here

  • Thank you very much. I will start reading more into this later. Much appreciated. – Al_Fh Apr 11 at 10:39

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.