TransWikia.com

How to command LaTeX to treat a non-value as 0

TeX - LaTeX Asked on January 12, 2021

I have this command

newcommand{lines}[1]{multido{}{#1}{vskip 5mm makebox[linewidth]{dotfill}} vskip 8mmsetlength{rightmargin}{5em}}

It allows me to create dotted lines with ease.
For example:

When I write lines{3} it will produce:

.........................................
.........................................
.........................................

How can I tell LaTeX to treat lines{} as lines{0}

Thank you.

4 Answers

Just put a leading zero so the number of loops is 0#1. When #1 is empty you have zero, otherwise you have #1.

documentclass{article}
usepackage{xparse}
ExplSyntaxOn
NewDocumentCommand lines { m }
  {
    int_step_inline:nn { 0#1 }
      { vskip 5mm~noindent makebox[linewidth]{dotfill} }
    vskip 8mm~setlength{rightmargin}{5em}%
  }
ExplSyntaxOff
begin{document}
alines{}

blines{3}
end{document}

Here's a very slightly more elaborate version that accepts count registers and a few more edge cases (definitely not fool-proof)?

documentclass{article}
usepackage{xparse}
ExplSyntaxOn
NewDocumentCommand lines { m }
  {
    int_step_inline:nn { tl_if_blank:eT {#1} { 0 } #1 }
      { vskip 5mm~noindent makebox[linewidth]{dotfill} }
    vskip 8mm~setlength{rightmargin}{5em}%
  }
ExplSyntaxOff
begin{document}
alines{}

blines{3}

clines{ 3 }

count178=3
dlines{count178}

newcountxx=3
elines{x}

chardefx=3
flines{x}

glines{numexpr 1+1+1}

hlines{dimexpr 0.00005pt}

defempty{}
ilines{empty}

defempty{}
jlines{ empty}

% Still fails in this case, but then you're asking for it ;-)
protecteddefempty{}
% klines{empty}

end{document}

Correct answer by Phelype Oleinik on January 12, 2021

I would do this slightly differently and make the argument to lines an optional argument, which defaults to zero. This way lines prints zero dotted lines and lines[3] prints lines etc.

Here's the modified code:

documentclass{article}
usepackage{multido}

newcommand{lines}[1][0]{%
  multido{}{#1}{vskip 5mm makebox[linewidth]{dotfill}}%
  vskip 8mmsetlength{rightmargin}{5em}%
}

begin{document}

  lines

  lines[3]

  lines[6]

end{document}

Btw, rather than posting code snippets it is always better to post a full minimal working example as this makes it easier for people to play with and modify your code.

Edit If in your use-case you need line{} to be the same as line{0} then you can use detokenize:

documentclass{article}
usepackage{multido}
usepackage{xparse}

newcommand{lines}[1]{%
multido{}{ifrelaxdetokenize{#1}relax0else#1fi}{vskip 5mm makebox[linewidth]{dotfill}}%
  vskip 8mmsetlength{rightmargin}{5em}%
}

begin{document}

  lines{}

  lines{3}

  lines{6}

end{document}

The detokenize{#1} "neutralises" all of the category codes that appear in #1 so that no surprises can arise. After the the "content" of #1 is compared with relax. If #1 is empty then detokenize{#1} is nothing so the if statement expands to ifrelaxrelax0else#1fi. In other words, if #1 is blank then if-statement expands to 0 and otherwise it expands to #1.

Answered by user30471 on January 12, 2021

This also will works:

documentclass{book}
usepackage{multido}

begin{document}

newcommand{lines}[1]{%
if!#1!relaxelse
  multido{}{#1}{vskip 5mm makebox[linewidth]{dotfill}}%
fi
  vskip 8mmsetlength{rightmargin}{5em}%

}

lines{}

lines{3}

end{document}

Answered by MadyYuvi on January 12, 2021

Usage of the multido-command is:

multido{⟨variables⟩}{⟨repetitions⟩}{⟨stuff⟩}

Seems ⟨repetitions⟩ can by anything that yields a TeX-⟨number⟩-quantity.

If ⟨repetitions⟩ is negative, ⟨variables⟩ will be counted backwards.

Thus with your code-example lines{3} and lines{-3} yield the same.

If ⟨repetitions⟩ is provided in terms of something that, e.g., denotes a count-register or a countdef-token, just prepending 0 to the ⟨repetitions⟩-argument causes some ! Missing number, treated as zero.-error. If ⟨repetitions⟩ is provided in terms of an alphabetic constant , just prepending 0 to the ⟨repetitions⟩-argument also does not lead to the desired result.

Therefore I suggest something like applying the multido-thing only in case both

romannumeralnumbernumber⟨number⟩␣0

and

romannumeral-numbernumber⟨number⟩␣0

yields emptiness.

(romannumeral does silently not return any token in case the number to convert is not positive. So let's multiply both the number to convert and the negative number to convert by 10 by appending 0 via numbernumber⟨number⟩␣0-trickery for ensuring that the thing works out with things like count20 (whereafter a space is needed for separating the 20, which is the number of the count-register) also. In case the argument holding the ⟨number⟩ consists of something that yields ⟨optional signs⟩ only—the case of the argument holding the ⟨number⟩ being empty or blank/yielding emptiness or blankness falls into this category—, the appendend 0 will turn the expression into a valid ⟨number⟩-quantity whose value is 0.)

documentclass[a4paper]{article}

% Vertically adjust the page layout so that the example creates exactly one page:
csname@ifundefinedendcsname{pdfpagewidth}{}{pdfpagewidth=paperwidthrelax}%
csname@ifundefinedendcsname{pdfpageheight}{}{pdfpageheight=paperheightrelax}%
csname@ifundefinedendcsname{pagewidth}{}{pagewidth=paperwidthrelax}%
csname@ifundefinedendcsname{pageheight}{}{pageheight=paperheightrelax}%
pagestyle{plain}%
headheight=0exrelax
headsep=0exrelax
topmargin=1cmrelax
footskip=.5topmarginrelax
begingroupnormalfont
expandafterendgroupexpandafteradvanceexpandafter
footskipthedimexpr.5htstrutboxrelaxrelax
textheight=paperheightrelax
advancetextheight-2topmarginrelax
advancetopmargin-1inrelax
%%%%%%%%%%%%% Page layout adjustments done. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

usepackage{multido}

makeatletter
newcommandexchange[2]{#2#1}%
newcommand{lines}[1]{%
  if Yexpandafterexchangeexpandafter{romannumeralnumbernumber#1 0}%
       {expandafter@firstofoneexpandafter{romannumeral-numbernumber#1 0}}Y%
    expandafter@gobbleelseexpandafter@firstofonefi
  {multido{}{#1}{vskip 5mm makebox[linewidth]{dotfill}}}%
  vskip8mm setlength{rightmargin}{5em}%
}%
makeatother


begin{document}

verb*|somecount=3|:

verb*|lines{somecount}|:

newcountsomecount
somecount=3

lines{somecount}

hrulekerndpstrutbox

verb*|lines{thesomecount}|:

lines{thesomecount}

{
hrulekerndpstrutbox

verb*|count90=3|

verb*|lines{count90}|:

count90=3 
lines{count90}

hrulekerndpstrutbox

verb*|lines{count90 }|:

lines{count90 }

}

hrulekerndpstrutbox

verb*|lines{3}|:

lines{3}

hrulekerndpstrutbox

verb*|lines{-000003}|:

lines{-000003}

hrulekerndpstrutbox

verb*|lines{}|:

lines{}

hrulekerndpstrutbox

verb*|lines{0}|:

lines{0}

hrulekerndpstrutbox

end{document}

enter image description here

But there are still problems/issues:

  • Both with the variant of the line-command provided in your example and with the variant of the line-command provided in the example above you get a lot of overfull hbox-warnings because the dot-filled lines via makebox get the with linewidth while not taking the insertion of the horizontal parindent-glue into account.
  • As your example works with vskip you may wish to ensure vertical mode.
  • You also may wish to avoid the insertion of horizontal parindent-glue and vertical parskip-glue by not letting TeX enter unrestricted horizontal mode while typesetting the lines.
  • The vertical distance between lines will not be 5mm but will be 5mm+baselineskip. This can be rectified by applying offinterlineskip.
  • It is not clear to me what is intended by setlength{rightmargin}{5em}.

I suppose you wish a command where you can specify

  • the amount of lines—in the example below this is the mandatory argument of lines,
  • the distance between lines—in the example below this is the Distance between lines=...-key of the optional argument of lines (default is dimexpr5mm+baselineskiprelax),
  • a vskip increasing the distance between the bottom of the box forming the previous line of text and the first dotted line—in the example below this is the Distance at top=...-key of the optional argument of lines (default is 8mm) ,
  • a vskip increasing the distance between the last dotted line and the top of the box forming the next line of text—in the example below this is the Distance at bottom=...-key of the optional argument of lines (default is 8mm),
  • a vskip increasing the the distance between the bottom of the box forming the previous line of text and the top of the box forming the next line of text in case no dotted line is typeset at all—in the example below this is the Gap if no dotted lines=...-key of the optional argument of lines (default is 8mm),
  • indenting of the dotted lines from the right—in the example below this is the Indent from the right=...-key of the optional argument of lines (default is 0em),
  • indenting of the dotted lines from the left—in the example below this is the Indent from the left=...-key of the optional argument of lines (default is 0em).

 

documentclass{article}
usepackage{keyval}
usepackage{multido}

makeatletter
newcommandexchange[2]{#2#1}%
@ifdefinablelines@DistanceBetweenLines{edeflines@DistanceBetweenLines{thedimexpr5mm+baselineskiprelax}}%
define@key{dottedlines}{Distance between lines}{edeflines@DistanceBetweenLines{thedimexpr#1relax}}%
@ifdefinablelines@DistanceAtTop{edeflines@DistanceAtTop{thedimexpr8mmrelax}}%
define@key{dottedlines}{Distance at top}{edeflines@DistanceAtTop{thedimexpr#1relax}}%
@ifdefinablelines@DistanceAtBottom{edeflines@DistanceAtBottom{thedimexpr8mmrelax}}%
define@key{dottedlines}{Distance at bottom}{edeflines@DistanceAtBottom{thedimexpr#1relax}}%
@ifdefinablelines@GapIfNoLines{edeflines@GapIfNoLines{thedimexpr8mmrelax}}%
define@key{dottedlines}{Gap if no dotted lines}{edeflines@GapIfNoLines{thedimexpr#1relax}}%
@ifdefinablelines@IndentFromTheRight{edeflines@IndentFromTheRight{thedimexpr0emrelax}}%
define@key{dottedlines}{Indent from the right}{edeflines@IndentFromTheRight{thedimexpr#1relax}}%
@ifdefinablelines@IndentFromTheLeft{edeflines@IndentFromTheLeft{thedimexpr0mmrelax}}%
define@key{dottedlines}{Indent from the left}{edeflines@IndentFromTheLeft{thedimexpr#1relax}}%
newcommand{lines}[2][]{%
  begingroup
  ifvmodeelseparfi
  setkeys{dottedlines}{#1}%
  offinterlineskip
  if Yexpandafterexchangeexpandafter{romannumeralnumbernumber#2 0}%
       {expandafter@firstofoneexpandafter{romannumeral-numbernumber#2 0}}Y%
    expandafter@secondoftwoelseexpandafter@firstoftwofi
  {%
    vskipdimexprlines@DistanceAtTop-lines@DistanceBetweenLinesrelax
    multido{}{#2}{%
      vskiplines@DistanceBetweenLines
      hbox tohsize{kernlines@IndentFromTheLeftrelaxdotfillkernlines@IndentFromTheRightrelaxnull}%
    }%
    vskiplines@DistanceAtBottomrelax
  }%
  {vskiplines@GapIfNoLinesrelax}%
  par
  endgroup
}%
makeatother

begin{document}

hrulekerndpstrutbox

verb*|somecount=3|:

verb*|lines{somecount}|:

newcountsomecount
somecount=3

lines{somecount}

hrulekerndpstrutbox

verb*|lines{thesomecount}|:

lines{thesomecount}

{
hrulekerndpstrutbox

verb*|count90=3|

verb*|lines{count90}|:

count90=3 
lines{count90}

hrulekerndpstrutbox
kern-topsep

begin{verbatim*}
lines[Distance between lines=5mm,
       Distance at top=1cm,
       Distance at bottom=1cm,
       Gap if no dotted lines=0cm,
       Indent from the left=2cm,
       Indent from the right=4cm]{count90 }:
end{verbatim*}
kern-topsepkern-partopsep
lines[Distance between lines=5mm,
       Distance at top=1cm,
       Distance at bottom=1cm,
       Gap if no dotted lines=0cm,
       Indent from the left=2cm,
       Indent from the right=4cm]{count90 }
hrulekerndpstrutbox
}

newpage

hrulekerndpstrutbox

verb*|lines{3}|:

lines{3}

hrulekerndpstrutbox

verb*|lines{ 3 }|:

lines{ 3 }

hrulekerndpstrutbox

verb*|lines{-000003}|:

lines{-000003}

hrulekerndpstrutbox

verb*|lines{}|:

lines{}

hrulekerndpstrutbox

verb*|lines{ }|:

lines{ }

hrulekerndpstrutbox

verb*|lines{0}|:

lines{0}

hrulekerndpstrutbox

end{document}

enter image description here

enter image description here

(Any sequence yielding lines{⟨optional signs⟩} is treated as lines{0}.)

Answered by Ulrich Diez on January 12, 2021

Add your own answers!

Ask a Question

Get help from others!

© 2024 TransWikia.com. All rights reserved. Sites we Love: PCI Database, UKBizDB, Menu Kuliner, Sharing RPP