2

I would like to know if it is possible to program a function that would accept a given symbol an infinite number of times. The application I have in mind is the following. I would like, if possible, a command \spac which would take two booleans and by default be defined as \vspace*{0.5ex}.

It would take two symbols.

  • The * says if there is a line break or not; thus, \spac* is defined as \\[0.5ex].

  • The presence of one + means that there will be a 0.5ex \vspace increment.

  • The specificity here, is that we should be able to add as many + as we want, or, if not possible (this is part of the question, to determine whether it is possible or not), a reasonably high number of them such as 5 or 6.

To sum up, each + will add 0.5ex to the total vertical space. The vertical space will thus always be equal to 0.5*(n+1)ex, n symbolizing the number of +s.

I would like the +(s) to be written directly without separators, just like a t+ argument type.

Examples:

  • \spac+++++ will produce a vspace of 0.5*6 = 3ex, without a line break.
  • \spac*++ will produce a line break and a vspace of 0.5*3 = 1.5ex.

Context

\documentclass{article}
\usepackage{linguex}
\usepackage{etoolbox}

\NewDocumentCommand{\tslt}{m}{`#1'}

      \makeatletter

\patchcmd{\a}{\ifnum\theExDepth=2\topsep .3\Extopsep\else\topsep 0pt\fi 
    \parsep\z@\itemsep\z@}
{\ifnum\theExDepth>1\topsep\csname pxtop\roman{ExDepth}\endcsname
    \itemsep\csname pxitem\roman{ExDepth}\endcsname\else\topsep\z@\itemsep\z@\fi
    \parsep\z@}{}{}

      \makeatother

\newlength{\pxtopii}
\newlength{\pxtopiii}
\newlength{\pxitemii}
\newlength{\pxitemiii}

\newcommand{\spaceab}[1]{\setlength{\pxitemii}{#1}}
\newcommand{\spaceii}[1]{\setlength{\pxitemiii}{#1}}
\newcommand{\spacebefa}[1]{\setlength{\pxtopii}{#1}}
\newcommand{\spacebefi}[1]{\setlength{\pxtopiii}{#1}}

\newcommand{\alignright}{\hspace{1em}\raggedright\hspace*{\fill}}

\NewDocumentCommand{\web}{o}{%
    \begingroup\alignright%
        (\textsc{web}\IfValueT{#1}{,~#1})\endgroup\par}


\begin{document}
    
    \spaceab{1ex}
    \spacebefa{2ex}
    
\ex. Example 1\label{ex1}
\a. Sublevel1a\label{ex1a}\\
\tslt{translation 1a}
\b. Sublevel1b\label{ex1b}\\
\tslt{translation 1b}


\spaceab{2ex}
\spaceii{1ex}   
    
\ex. Example 2\label{ex2}\\
    \a. sublevel2a
        \a. sublevel 2ai\\
            \tslt{translation 2ai}
        \b. sublevel 2aii
            \tslt{translation 2aii}
    \z.
    \b. \a. sublevel 2bi\\
            \tslt{translation 2bi}
        \b. sublevel 2bii\\
            \tslt{translation 2biii}
        \b. sublevel 2biii
            \tslt{translation 2biii}
    \z.
    \b. sublevel2c\\
        \tslt{translation 2c}

\ex. Example XXXXX
\tslt{translation}\web\vspace*{1ex}
    
\end{document}

Depending on how heavy the sentences and translations are, and how the overall look feels, I adjust the spacings. The space before a translation is given with some \vspace*{} value. But the line break sometimes is already given by the previous command (such as \web), so i do not want to systematically integrate it.



12
  • (1) You can't add vertical space in horizontal mode, so the first version can't work. (Or it is not clear what you mean. Maybe you're in vertical mode already?) (2) An infinity of them isn't possible since you will eventually exceed TeX's maximum dimension, if nothing else. An indefinite number is a different matter. But what is the context for this? In most contexts, you shouldn't end a line with \\ or add vertical space without glue.
    – cfr
    Mar 3 at 6:07
  • I'm not sure what you mean, oh you mean adding the second vspace we would be in hmode? But we would add it once at the same time of course. Glue, you mean plus / minus ? so that it can stretch ? There is no specific context, i always have to add manual \vspace according to how much space my examples and their translations take, and the commands are complicated so I won't automatize it. I don't use plus/minus. Mar 3 at 6:13
  • 1
    So are we between paragraphs? Then I don't get the line break toggle. But, really, if you're having to adjust the spacing manually that much, something is wrong. You should only need to do that kind of manual adjustment in corner cases and adding precise amounts of vertical space isn't usually the best solution, even then.
    – cfr
    Mar 3 at 6:17
  • 1
    I think an example would help, at least for non-linguists. Maybe somebody who uses linguex will visualise what you mean and be able to answer without one, but I think it would still be good to see what you're doing now. I suspect this is an XY problem, which makes it hard to help without some context.
    – cfr
    Mar 3 at 6:25
  • 1
    you should probably be using addvspace not vspace so that it automatically adjusts to space added previously. but it's hard to guess with the current description of the problem Mar 3 at 8:33

4 Answers 4

2

The following logs

adding 2.15277pt
adding 4.30554pt
adding 75.34698pt

and produces

enter image description here

I didn't use the * form at all as you need to be in vertical mode to add vertical space.

\documentclass{article}
\newlength\spaclen
\NewDocumentCommand\spac{}{\par\setlength\spaclen{0.5ex}\innerspac}
\NewDocumentCommand\innerspac{t{+}}{%
  \IfBooleanTF{#1}%
  {\addtolength\spaclen{.5ex}\innerspac}%
  {\typeout{adding \the\spaclen}\addvspace\spaclen}}

\begin{document}

aaa\spac b

aaa\spac+ b

aaa\spac++++++++++++++++++++++++++++++++++ b
\end{document}
21
  • 1
    @VincentKrebs you mean mine and wipets? They are similar but mine is using latex constructs (and skips over space so \spac + + + is three +, wipet (as ever) avoids latex constructs and uses tex primitives (and doesn't skip over space) Mar 3 at 10:29
  • 1
    @VincentKrebs It's good (sometimes) to see how things work below the surface but in general it's not advisable to actually use tex primitives in a latex document as you can easily cut through latex conventions and break things. redefining the standard latex command \value for example will have unexpected consequences (eg it breaks the standard bibliography commands) Mar 3 at 10:35
  • 2
    I would definitely use {+} here as + works but + is already a syntax command in the \NewDocumentCommand argument syntax +m is an argument allowing \par so the fact that t+m parses as t{+} m not t +m is true but relying on low level details of the argument parser. @VincentKrebs Mar 3 at 10:37
  • 1
    @VincentKrebs oh yes of course (same as wipet) here \innerspac looks for one + and calls itself so it keeps getting called until there is no + when a space gets added. Mar 3 at 11:12
  • 1
    @VincentKrebs \spac just initializes the loop by setting the length to 0 and calling the inner command. Mar 3 at 11:14
5

Because I don't understand why do you want to insert vertical spaces in horizontal mode (i.e. \spac without*), I show you only the principle of the unlimited + arguments. And, of course, the \par at the beginning of the macro means that we will insert the space in vertical mode only.

Or do you mean \vadjust usage? This is TeX primitive (used in LaTeX \vspace) which is a source of many confusions of LaTeX users, so I don't use it in the \spac macro.

\def\spac{\par \spacA+}
\def\spacA+{\vskip.5ex \futurelet\next\spacB}
\def\spacB{\ifx\next+\expandafter\spacA \fi}

% testing:

\hrule width1cm
\spac
\hrule
\spac+
\hrule
\spac++
\hrule
\spac++++++
\hrule

\bye
5
  • Because some of my commands already include a line break and I don't want to multiply the \\. For example I say \web, it writes [web] (meaning that the sentence is from the web) and auto adds a line break to prepare the translation. If I want to use vspace, i won't use another line break in addition. So I write \web\vspace*{0.5ex} Mar 3 at 6:44
  • Sorry, do you mean to use \par as a simple check? If it's only a check and two \par won't cumulate (no idea), then ok. But they must not cumulate, because if there is already a \par before, i.e. if we are after the \web command for example, I do NOT want to have two breaks. I'd better use \ifvmode and return an error message if \vmodefalse. Mar 3 at 7:57
  • TeX switches between vertical mode and horizontal mode. If there is a first letter in vertical mode, then TeX switch to the horizontal mode and prepares a paragraph as a single horizontal list. The paragraph is finalized by empty line in the source which is transformed to the \par command. The horizontal list is broken to the lines of the paragraph and they are put to the vertical list. \par in vertical mode does nothing. It means that \par\par is the same as \par. The switching between horizontal/vertical mode is basic principle of TeX, it should be known by all TeX users.
    – wipet
    Mar 3 at 8:32
  • Ok, in this case I do not need to worry about redundancy. Thank you for this explanation of a basic principle. Mar 3 at 9:33
  • For vertical/horizontal mode, see tex.stackexchange.com/questions/13177/… Mar 5 at 4:34
2

Count the number of + following \spac or \spac*.

I achieve this by doing a regex search and replace. A space following the last + or the single * is ignored.

\documentclass{article}
\usepackage{indentfirst}% just for alignment after \subsubsection

\ExplSyntaxOn

\NewDocumentCommand\spac{s}
 {
  \IfBooleanTF { #1 }
   {
    \peek_regex_replace_once:nn { (\+*)\s* } { \c{krebs_spac_break:n}\{\1\} }
   }
   {
    \peek_regex_replace_once:nn { (\+*)\s* } { \c{krebs_spac_nobreak:n}\{\1\} }
   }
 }

\cs_new_protected:Nn \krebs_spac_break:n
 {
  \typeout{Adding~\inteval{\tl_count:n{#1}+1}ex}
  \\[\inteval{\tl_count:n{#1}+1}ex]
 }
\cs_new_protected:Nn \krebs_spac_nobreak:n
 {
  \typeout{Adding~\inteval{\tl_count:n{#1}+1}ex}
  \vspace{\inteval{\tl_count:n{#1}+1}ex}
 }

\ExplSyntaxOff

\begin{document}

\subsubsection*{zero}
aaa\spac b

aaa\spac* b

\subsubsection*{one}
aaa\spac+ b

aaa\spac*+ b

\subsubsection*{two}
aaa\spac++ b

aaa\spac*++ b

\subsubsection*{three}
aaa\spac+++ b

aaa\spac*+++ b

\end{document}

enter image description here

Console output (the \typeout instructions are just for this)

Adding 1ex
Adding 1ex
Adding 2ex
Adding 2ex
Adding 3ex
Adding 3ex
Adding 4ex
Adding 4ex
1
  • Wow, an original approach. I need some time to process... Mar 3 at 10:56
0

David Carlisle's command \innerspac can be slightly modified in order to support the minus sign -.

All we have to do is check for a - sign after checking for a +. As long as one of the two symbols is found, the loop goes on. It stops when both boolean values are False.

% !TEX TS-program = lualatex


\documentclass{article}


\newlength\spaclen

\NewDocumentCommand\spac{}{\par\setlength\spaclen{.5ex}\innerspac}

\NewDocumentCommand\innerspac{t{+}t{-}}{%
    \IfBooleanTF{#1}{%
        \addtolength\spaclen{.5ex}%
        \IfBooleanTF{#2}{%
            \addtolength\spaclen{-.5ex}}{}%
        \innerspac}{%
        \IfBooleanTF{#2}{%
            \addtolength\spaclen{-.5ex}\innerspac}{%
            \typeout{adding \the\spaclen}\addvspace\spaclen}}}


\begin{document}
    
    aaa\spac b
    
    aaa\spac+ b
    
    aaa\spac- b
    
    aaa\spac-- b
    
    aaa\spac--- b
    
    aaa\spac++++++++++++++++++++++++++++++++++ b
    
    aaa\spac++--- b
    
    aaa\spac+-+-+-+- b
    
\end{document}

Logs (with LuaTeX engine):

  • adding 2.155pt
  • adding 4.31pt
  • adding 0.0pt
  • adding -2.155pt
  • adding -4.31pt
  • adding 75.42496pt
  • adding 0.0pt
  • adding 2.155pt

enter image description here

1
  • @DavidCarlisle Is this the right way? Mar 7 at 6:47

You must log in to answer this question.

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