I need to define counters using fractur fonts and hebrew alphabet. For the greek alphabet I'm using the package engrec. Any suggestion? Thanks
2 Answers
What John Kormylo probably meant is that, if it is reasonable to enumerate all cases that can possibly occur, you can paraphrase the definition of \alph
in LaTeX, which relies on TeX's \ifcase
conditional as follows:
\def\alph#1{\expandafter\@alph\csname c@#1\endcsname}
\def\@alph#1{%
\ifcase#1\or a\or b\or c\or d\or e\or f\or g\or h\or i\or j\or
k\or l\or m\or n\or o\or p\or q\or r\or s\or t\or u\or v\or w\or x\or
y\or z\else\@ctrerr\fi}
For instance, the following is a dumb way to format a LaTeX counter using the famous (?) Shadok numeral system. This is a base-4 positional numeral system where the available symbols for each digit are Ga = 0, Bu = 1, Zo = 2 and Meu = 3.
\documentclass{article}
\usepackage{pgffor} % only for the demo code
\usepackage{multicol} % only for the demo code
\makeatletter
\newcommand*{\@shadokNumber}[1]{%
\ifcase #1% #1 is supposed to be a <number>
Ga\or Bu\or Zo\or Meu\or
BuGa\or BuBu\or BuZo\or BuMeu\or
ZoGa\or ZoBu\or ZoZo\or ZoMeu\or
MeuGa\or MeuBu\or MeuZo\or MeuMeu\or
BuGaGa\or BuGaBu\or BuGaZo\or BuGaMeu\or
BuBuGa\or BuBuBu\or BuBuZo\or BuBuMeu\or
BuZoGa\or BuZoBu\or BuZoZo\or BuZoMeu\or
BuMeuGa\or BuMeuBu\or BuMeuZo\or BuMeuMeu\or
ZoGaGa\or ZoGaBu\or ZoGaZo\or ZoGaMeu\or
ZoBuGa\or ZoBuBu\or ZoBuZo\or ZoBuMeu\or
ZoZoGa\or ZoZoBu\or ZoZoZo\or ZoZoMeu\or
ZoMeuGa\or ZoMeuBu\or ZoMeuZo\or ZoMeuMeu\or
MeuGaGa\or MeuGaBu\or MeuGaZo\or MeuGaMeu\or
MeuBuGa\or MeuBuBu\or MeuBuZo\or MeuBuMeu\or
MeuZoGa\or MeuZoBu\or MeuZoZo\or MeuZoMeu\or
MeuMeuGa\or MeuMeuBu\or MeuMeuZo\or MeuMeuMeu\or BuGaGaGa% = 64 in decimal
% etc.
\else \@ctrerr \fi
}
\newcommand*{\shadokNumber}[1]{%
\expandafter\@shadokNumber\csname c@#1\endcsname
}
\makeatother
\newcounter{myctr}
\begin{document}
\begin{multicols}{3}
\noindent
\foreach \i in {0,...,64} {%
\shadokNumber{myctr}\\
\stepcounter{myctr}%
}%
etc.
\end{multicols}
\end{document}
Generalization (positional numeral systems)
Regular positional numeral systems can be handled with generic code. What follows borrows from the expl3
implementation of \int_to_base:nn
and adapts it in order to provide formatting of arbitrary integers in the Shadok numeral system. The available symbols for digits here are still Ga
, Bu
, Zo
and Meu
(several tokens each), but you can replace them with any LaTeX code of your choice. Just don't forget to update the number of available symbols in \g_guidone_nb_symbols_int
(here: 4).
\documentclass{article}
\usepackage{expl3}
\usepackage{multicol} % only for the demo code
\ExplSyntaxOn
% Ga, Bu, Zo, Meu: 4 symbols. Replace with the number of digit symbols you have.
\int_const:Nn \c_guidone_nb_shadok_digit_symbols_int { 4 }
% Replace Ga, Bu, Zo, Meu with LaTeX code producing each possible digit symbol.
\cs_new:Npn \__guidone_to_shadok_digit:n #1
{
\exp_after:wN \__guidone_remove_fi:nw
\if_case:w #1 \c_space_token % this finishes the <number>
{ Ga }
\or:
{ Bu }
\or:
{ Zo }
\or:
{ Meu }
\else:
{ \msg_expandable_error:nnn { guidone } { too-large-for-a-digit } {#1} }
\fi:
}
\msg_new:nnn { guidone } { too-large-for-a-digit }
{ Too~large~for~a~digit:~\exp_not:n {#1}. }
% Define aliases that can be used outside \ExplSyntaxOn ... \ExplSyntaxOff.
\cs_new_eq:NN \nbShadokDigitSymbols \c_guidone_nb_shadok_digit_symbols_int
\cs_new_eq:NN \toShadokDigit \__guidone_to_shadok_digit:n
% The \exp_stop_f: stops f-expansion from the \__guidone_deliver:nfw call.
% \__guidone_to_digit:n should normally be used within f-expansion,
% otherwise the \exp_stop_f: (implicit space token) will precede the wanted
% result (digit).
\cs_new:Npn \__guidone_remove_fi:nw #1#2\fi:
{ \fi: \exp_stop_f: #1 }
% #1: base (= number of available digit symbols)
% #2: function such as \__guidone_to_shadok_digit:n (input: a number between 0
% and #1 - 1, both inclusive; output: a single digit)
% #3: number to format
\cs_new:Npn \guidone_format_number:nNn #1#2#3
{
\exp:w
\__guidone_to_base:nnN {#3} {#1} #2
\q_stop
}
% The \*_to_base:* functions are based on code from l3int.dtx, with
% modifications so that \guidone_format_number:nNn can deliver potentially
% sensitive material with \exp_not:n in exactly two expansion steps.
\cs_new:Npn \__guidone_to_base:nnN #1
{ \exp_args:Nf \__guidone_to_base_aux:nnN { \int_eval:n {#1} } }
\cs_new:Npn \__guidone_to_base_aux:nnN #1#2#3
{
\int_compare:nNnTF {#1} < { 0 }
{ \exp_args:No \__guidone_to_base:nnnN { \use_none:n #1 } {#2} { - } #3 }
{ \__guidone_to_base:nnnN {#1} {#2} { } #3 }
}
% #1: empty or minus sign
% #2: leftmost digit of the number (i.e., the last digit produced by
% \guidone_format_number:nNn)
% #3: the remaining digits
%
% The \exp_end: terminates the expansion started by \exp:w in
% \guidone_format_number:nNn.
\cs_new:Npn \__guidone_deliver:nnw #1#2#3\q_stop
{ \exp_end: \exp_not:n { #1#2#3 } }
\cs_generate_variant:Nn \__guidone_deliver:nnw { nf }
\cs_new:Npn \__guidone_to_base:nnnN #1#2#3#4
{
\int_compare:nNnTF {#1} < {#2}
{ \__guidone_deliver:nfw {#3} { #4 {#1} } }
{
\exp_args:Nf \__guidone_to_base:nnnnN
{ #4 { \int_mod:nn {#1} {#2} } }
{#1}
{#2}
{#3}
#4
}
}
\cs_new:Npn \__guidone_to_base:nnnnN #1#2#3#4#5
{
\exp_args:Nf \__guidone_to_base:nnnN
{ \int_div_truncate:nn {#2} {#3} }
{#3}
{#4}
#5
#1
}
% Define aliases that can be used outside \ExplSyntaxOn ... \ExplSyntaxOff.
% Note that \guideoneFormatNumber is fully expandable and delivers the result
% in two expansion steps.
\cs_new_eq:NN \guideoneFormatNumber \guidone_format_number:nNn
\cs_new_eq:NN \intstepinline \int_step_inline:nnnn
\ExplSyntaxOff
% What follows \shadokNumber in the input stream will be the third argument of
% \guideoneFormatNumber, i.e.: the number to convert.
\newcommand*{\shadokNumber}{%
\guideoneFormatNumber{\nbShadokDigitSymbols}{\toShadokDigit}%
}
\newcounter{myctr}
% Make it so that \themyctr uses our custom numeration style.
\renewcommand{\themyctr}{%
\shadokNumber{\value{myctr}}%
}
\begin{document}
\begin{multicols}{3}
\noindent
% Initial value, step, final value
\intstepinline{0}{1}{64}{%
\themyctr\\
\stepcounter{myctr}%
}%
etc.
\end{multicols}
Most importantly:
\[ 65536 = \shadokNumber{65536} \]
and % We can handle any 〈integer expression〉, including negative ones.
\[ -(3\times 64 + 2\times 16 + 1\times 4 + 0\times 1) =
\shadokNumber{-1*(3*64 + 2*16 + 1*4 + 0*1)} \]
% Verify that the desired result is obtained in exactly two expansion steps.
% If you uncomment the following seven lines, TeX will print on the terminal:
% > \exp_not:n {-MeuZoBuGa}.
%
% \def\zzz#1{\expandafter\showtokens\expandafter{#1}}
% \expandafter\zzz\expandafter{%
% \guideoneFormatNumber
% {\nbShadokDigitSymbols}
% {\toShadokDigit}
% {-1*(3*64 + 2*16 + 1*4 + 0*1)}%
% }
\end{document}
As you can see from the following definition:
\newcommand*{\shadokNumber}{%
\guideoneFormatNumber{\nbShadokDigitSymbols}{\toShadokDigit}%
}
the only thing you need to do in order to define conversion functions for other numeral systems in the same document is to pass \guideoneFormatNumber
:
the number of available digit symbols, i.e. the base (
\nbShadokDigitSymbols
is 4 in our example);a function such as
\toShadokDigit
(i.e.,\__guidone_to_shadok_digit:n
) that converts a number between 0 and base - 1 to its 1-digit representation in the destination numeral system.
The number to convert has to come next in the input stream and doesn't need to be grabbed as an argument by \shadokNumber
(this is a small optimization).
Hebrew numeration
Hebrew numeration seems to be less regular than what the above code is designed to handle. If only a small number of values are needed, you can use the first approach. Otherwise, I'm afraid you'll need another conversion algorithm. The polyglossia
package provides commands such as \hebrewnumeral
, \Hebrewnumeral
and \Hebrewnumeralfinal
that might be of interest to you. You might be interested in this question for instance. Alas, I don't know Hebrew, so can't help you more in this area.
With babel
3.41, just released, comes a bunch of predefined additive and alphabetic numerals for some languages, based on the CSS ready-made counter styles (numeric styles have been available since babel
3.20). More importantly, they are defined with the help of a set of key/value pairs in ini
files, which means you can define your own styles with \babelprovide
, too. Note this tool is meant for xetex
and luatex
, but it may work in pdftex
. Here is an example with some explanations.
\documentclass{article}
\usepackage[italian]{babel}
\babelprovide[
% To define a purely alphabetic numeral, just provide a space-
% separated list of ordered symbols, characters, etc. Let's name
% it 'lower' (you can choose another name):
counters/lower=Aa Bb Cc Dd Ee Ff Gg Hh Ii Jj Kk Ll,
% For additive numerals, a set of four keys are required, numbered
% with a digit from 1 (for 1-9) to 4 (for 1000-9000) preceded by a
% dot. Let's name it 'letters':
counters/letters.1= a b c d e f g h i,
counters/letters.2= k l m n o p q r s,
counters/letters.3= A B C D E F G H I,
counters/letters.4= K L M N O P Q R S,
% Fixed representations for specific values of additive numerals
% are allowed, too. Just end the key with dot, uppercase F, dot,
% number:
counters/letters.F.55 = Oohh
% Redefining \alph to print these numerals is simple:
alph = letters
]{italian}
\begin{document}
\localenumeral{lower}{4} % Prints Dd
\localenumeral{lower}{2} % Prints Bb
\localenumeral{letters}{956} % Prints Iof
\localenumeral{letters}{55} % Prints Oohh
\alph{page} % Prints a, because it's the first page and \alph uses the
% 'letters' numerals
\end{document}
For further details, see What's new in babel 3.41.