7

I want a macro that somehow replaces whitespace (spaces, newlines, tabs?) from the start of a string.

Something like

mystring.replace(/^\s*/g, "")

in JavaScript.

Is that possible?

2
  • 1
    the stringstrings package has a macro \removeleadingspaces[mode]{string}. Whether this is applicable for you will strongly depend on whether the argument you pass to the macro is pure text or has embedded macros. Commented Jun 2, 2014 at 11:51
  • @StevenB.Segletes : This is what I have been looking for. Submit it as answer and I will accept it. Commented Jun 2, 2014 at 12:03

2 Answers 2

9

Expandable, infinite spaces

Removing space tokens at the begin of a string is possible, but a little cumbersome:

\documentclass{article}

\makeatletter
\let\TrSp@X\relax
\let\TrSp@Y\relax
\edef\TrSp@XSpXNil{%
  \TrSp@X\space\TrSp@X
  \noexpand\noexpand\noexpand\TrSp@NIL
}
\long\edef\trim@pre@spaces#1{%
  \noexpand\romannumeral0%
  \noexpand\TrSp@pre@spaces\TrSp@X#1\TrSp@Y\TrSp@XSpXNil
}
\@firstofone{\long\def\TrSp@pre@spaces#1\TrSp@X} %
#2\TrSp@X#3\TrSp@NIL{%
  \csname TrSp@pre#3\endcsname{#1}{#2}%
}
\long\def\TrSp@pre#1#2{%
  \expandafter
  \TrSp@pre@\expandafter\space\@gobble#1%
}
\long\def\TrSp@pre@#1\TrSp@Y{#1}
\long\expandafter\edef\csname TrSp@pre X\endcsname#1#2{%
  \noexpand\TrSp@pre@spaces\TrSp@X#2\TrSp@XSpXNil
}
\def\TrSp@X{X}
\let\TrSp@Y\TrSp@NIL
\let\trimstartspaces\trim@pre@spaces
\newcommand*{\trimstartspacesin}[1]{%
  \expandafter\expandafter\expandafter\expandafter
  \expandafter\expandafter\expandafter\def
  \expandafter\expandafter\expandafter\expandafter
  \expandafter\expandafter\expandafter#1%
  \expandafter\expandafter\expandafter\expandafter
  \expandafter\expandafter\expandafter{%
    \expandafter\trimstartspaces\expandafter{\foo}%
  }%
}
\makeatother


% create a text with several spaces in a row using a trick:
\newcommand*{\deffoo}[1]{%
  \newcommand*{\foo}{#1#1#1#1a b c }%
}
\deffoo{ }
\let\trimmedfoo\foo
\trimstartspacesin\trimmedfoo

\typeout{[\expandafter\trimstartspaces\expandafter{\foo}]}
\typeout{[\trimmedfoo]}

\begin{document}
[\foo] $\rightarrow$ [\expandafter\trimstartspaces\expandafter{\foo}]
  or [\trimmedfoo]
\end{document}

Result

Expandable, at most one space

Package trimspaces already provides \trim@pre@space or \trim@pre@space@in.

Manually it can be done by

\romannumeral-`\.

\romannumeral applied to negative numbers vanishes and TeX keeps looking for an optional space after the character constant `\..

If the text is inside a macro \foo, then an optional space can be stripped at the beginning by:

\expandafter\def\expandafter\foo\expandafter{%
  \romannumeral-\expandafter`\expandafter\.\foo
}%

Full example:

\documentclass{article}
\newcommand*{\foo}{ a b c }
\expandafter\def\expandafter\trimmedfoo\expandafter{%
  \romannumeral-\expandafter`\expandafter\.\foo
}%
\typeout{[\meaning\trimmedfoo]}

\begin{document}
[\foo] $\rightarrow$ [\trimmedfoo]
\end{document}

Result

Usually removing one optional space is enough, because it is not too easy entering more than one space in a row (TeX collapses them to one space during tokenizing).

Non-expandable, infinite spaces

\@ifnextchar removes spaces before testing the "next" character. In non expandable contexts it can be used to remove infinite spaces from the begin of the text:

\documentclass{article}

% create a text with several spaces in a row using a trick:
\newcommand*{\deffoo}[1]{%
  \newcommand*{\foo}{#1#1#1#1a b c }%
}
\deffoo{ }

\makeatletter
\newcommand*{\stripstartspaces}{%
  \expandafter\@ifnextchar\expandafter X\expandafter{\expandafter
  }\expandafter{\expandafter}%
}
\makeatother

\begin{document}
[\foo] $\rightarrow$ [\stripstartspaces\foo]
\end{document}

Result

4
  • This strips at most one space token.
    – egreg
    Commented Jun 2, 2014 at 12:16
  • @egreg: I have now added expandable and non-expandable methods for stripping infinite space tokens at the begin. Commented Jun 2, 2014 at 12:48
  • 1
    I knew this would have triggered some nice code from you. +1!
    – egreg
    Commented Jun 2, 2014 at 12:55
  • \stripstartspaces works perfectly for my case. Thanks, accepting. Commented Jun 2, 2014 at 14:27
4

The stringstrings package has a \removeleadingspaces macro, which will remove any combination of blanks and hard spaces at the the beginning of the passed text string. The package is generally intended to operate only upon text strings, and has only a very limited ability (not shown in this answer) to handle arguments containing macros.

By default, the macro will output the result immediately to the screen. However, if the processed but unprinted result is desired, a [q] optional argument will instead put the result in \thestring via an \edef for later access. There is also an [e] "encoded" mode, which applies if one is trying to process strings containing a limited number of user-predefined macros (but that's for a different question).

\documentclass{article}
\usepackage{stringstrings}
\begin{document}
.\removeleadingspaces{abc def}

.\removeleadingspaces{ abc def}

.\removeleadingspaces{  abc def}

.\removeleadingspaces{~abc def}

.\removeleadingspaces{~~abc def}

.\removeleadingspaces{~ ~ abc def}

.\removeleadingspaces{~ ~ abc def}
\end{document}

enter image description here

2
  • I originally wanted to accept your answer. However, \removeleadingspaces started to make some problems with "forced" breaking words with \-, which for unknown reasons started to expand as ....... \stripstartspaces from the other answer works better, I am sorry :) Commented Jun 2, 2014 at 14:26
  • 2
    @KarelBílek Go with the best answer. I know that stringstrings suffers severe limitations. I'm glad you found an answer that works for you. Commented Jun 2, 2014 at 14:33

You must log in to answer this question.

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