6

I'm trying to make macro to work in biblatex edition field. Logic is following:

  • if edition =1 there is suffix -li (1-li)
  • if edition>1 and if edition<21 there is prefix me- (me-15,me-20 ..etc)
  • if edition = 40,60,80,100,200,...1000 there is also prefix me-
  • in other cases suffix -e (31-e, 21-e, 129-e, 1010-e)

here is a code which works:

 \protected\def\mkbibmascord#1{%
 \ifnum #1=1 #1-li \else %
 \ifnum #1<21 %
\ifnum #1>1 me-#1 \fi \else %
\ifnum #1 = 40  me-#1 \else%
\ifnum #1 = 60  me-#1 \else%
\ifnum #1 = 80  me-#1 \else%
\ifnum #1 = 100 me-#1 \else %
\ifnum #1 = 200  me-#1 \else %
#1-e
\fi\fi\fi\fi\fi\fi\fi%
}%
\protected\def\mkbibordinal{\mkbibmascord}%
\protected\def\mkbibfemord{\mkbibmascord}%
\protected\def\mkbibneutord{\mkbibmascord}%

but how can i write general code/improve above code? (not only for 200), becouse let say for calendar there will be alot if/fi-s

6
  • There might be some streamlining, if all the possible cases possessed consecutive numbers. But since they do not, nested \ifnum branching is probably the best you can do. Commented Aug 18, 2015 at 15:10
  • you are right , but shortening a code can be possible something like break, and,==' (equality) commands or case`(like \case{n}) switch :) .. Isearch 'math in tex' but search gives just how to write mathequations, not TeX aritmetic :)...I need to learn more :) Commented Aug 18, 2015 at 15:39
  • Are these ordinal numbers? In which language? Is there a reference for the rules? Commented Aug 18, 2015 at 15:39
  • yes. Language is georgian.. here are examples..no general rule is given in English learn101.org/georgian_numbers.php mylanguages.org/georgian_numbers.php .. Actually i run little bit forward..I'm going to write Gregoriancalendar-to-Ald Georgian calendar transliator and will need TeX arithmetic a lot. Commented Aug 18, 2015 at 15:56
  • Can remove ifnum #1 >1 in above code...works also fine \ifnum #1<21 % me-#1 \else % Commented Aug 18, 2015 at 16:05

3 Answers 3

5

Here's an implementation in expl3:

\documentclass{article}

\usepackage{xparse}

\ExplSyntaxOn
\cs_new:Nn \georgian_ordinal:n
 {
  \int_compare:nTF { 1 < #1 < 21 }
   { me\mbox{-}#1 }
   { \georgian_ordinal_aux:n { #1 } }
 }

\cs_new:Nn \georgian_ordinal_aux:n
 {
  \int_case:nnF { #1 }
   {
    {    1 }{ #1\mbox{-}li }
    {   40 }{ me\mbox{-}#1 }
    {   60 }{ me\mbox{-}#1 }
    {   80 }{ me\mbox{-}#1 }
    {  100 }{ me\mbox{-}#1 }
    {  200 }{ me\mbox{-}#1 }
    {  300 }{ me\mbox{-}#1 }
    {  400 }{ me\mbox{-}#1 }
    {  500 }{ me\mbox{-}#1 }
    {  600 }{ me\mbox{-}#1 }
    {  700 }{ me\mbox{-}#1 }
    {  800 }{ me\mbox{-}#1 }
    {  900 }{ me\mbox{-}#1 }
    { 1000 }{ me\mbox{-}#1 }
  }
  { #1\mbox{-}e }
 }

\cs_set_eq:NN \mkbibmascord  \georgian_ordinal:n
\cs_set_eq:NN \mkbibordinal  \georgian_ordinal:n
\cs_set_eq:NN \mkbibfemord   \georgian_ordinal:n
\cs_set_eq:NN \mkbibneutcord \georgian_ordinal:n

\ExplSyntaxOff

\begin{document}

% a loop for testing
\ExplSyntaxOn
\int_step_inline:nnnn { 1 } { 1 } { 1010 } { \mkbibmascord { #1 } ~ }
\ExplSyntaxOff

\end{document}

I only show the test between 1 and 210:

enter image description here

Maybe something more efficient can be done if the rules for numbers above 1000 are explained.

4
  • Nice.. I like that for loop in expl3, but will need to learn that language :) Commented Aug 18, 2015 at 16:00
  • Why the \mboxes? In that case, you should use \cs_new_protected:Npn. Commented Aug 18, 2015 at 16:05
  • @Manuel They are to avoid line breaks; actually \mbox is sufficiently robust for being in an expandable command. Commented Aug 18, 2015 at 16:25
  • 1
    @egreg But the rule in expl3 was to define as protected everything that contains non-expandable tokens. Good to know about linebreaks. Commented Aug 18, 2015 at 16:30
4

The solution using \ifnums and using \variants{num}{list}{true-text}{false-text} macro which expands to the "true-text" if num is equal to the number in the list else it expands to the "false-text".

\def\variants#1#2{\variantsA{#1}#2,,\end}
\def\variantsA#1#2,{\ifx,#2,\expandafter\variantsE \else
   \ifnum#1=#2 \variantsC \else
      \expandafter\expandafter\expandafter\variantsA
   \fi\fi{#1}}
\def\variantsC#1\end#2#3{\fi\fi#2}
\def\variantsE#1\end#2#3{#3}

\protected\def\mkbibmascord#1{%
   \ifnum#1<1 #1-e\else
   \ifnum#1=1 #1-li\else
   \ifnum#1<21 me-#1\else
   \variants{#1}{40,60,80,100,200,300,400,500,600,700,800,900,1000}{me-#1}{#1-e}%
   \fi\fi\fi
}
3

The question has two relatively independent aspects:

 1. how to organize gracefully a long list of `\ifnum..` clauses, 
 2. how to automatize over a list.

I won't delve much about the second part here, illustrated in the code below by the handling of 300, 400, .., 1000 via \xintApplyUnbraced from package xinttools. This is expandable. And the Test itself uses an \xintFor loop (non-expandable). For example wipet's answer has one-line macros sufficient here. By laziness I used the loops from xinttools.

My answer is mainly the observation that very simple macros:

\long\def\DoThis #1#2\OrThat #3{\fi #1}
\long\def\OrThat #1{#1}

can be used to handle point 1. No more \fi\fi\fi\fi...\fi. And expandability is maintained.

\long\def\DoThis #1#2\OrThat #3{\fi #1}
\long\def\OrThat #1{#1}

% for the (optional) list manipulations in the code and in the Test
\input xinttools.sty

% Notice that this \georgianordinal is an expandable macro
\def\georgianordinal #1{%
   \ifnum #1=1  \DoThis{1-li}\fi
   \ifnum #1<21 \DoThis{me-#1}\fi
   \ifnum #1=40 \DoThis{me-#1}\fi
   \ifnum #1=60 \DoThis{me-#1}\fi
   \ifnum #1=80 \DoThis{me-#1}\fi
   \ifnum #1=100 \DoThis{me-#1}\fi
   \ifnum #1=200 \DoThis{me-#1}\fi
   \xintApplyUnbraced
        {\georgianordinalaux {#1}}
        {{300}{400}{500}{600}{700}{800}{900}{1000}}%
   \OrThat {#1-e}%
}

% notice the space before \ifnum, which is there to stop 
% an expansion done via \romannumeral-`0 by \xintApplyUnbraced
\def\georgianordinalaux #1#2{ \ifnum #1=#2 \DoThis{me-#1}\fi}

% Test:

\xintFor #1 in {\xintintegers} \do {%
     \georgianordinal {\the#1},
     \ifnum#1>1050 \expandafter\xintBreakFor\fi
}

\bye

enter image description here

You must log in to answer this question.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.