% \iffalse % File: numberpt.dtx % % Copyright (C) 2019 Miguel V. S. Frasson (mvsfrasson@gmail.com) % % This work may be distributed and/or modified under the % conditions of the LaTeX Project Public License, either version 1.3c % of this license or (at your option) any later version. % The latest version of this license is in % http://www.latex-project.org/lppl.txt % and version 1.3c or later is part of all distributions of LaTeX % version 2008/05/04 or later. % % This work has the LPPL maintenance status `maintained'. % % The Current Maintainer of this work is the author. % % This work consists of the files numberpt.dtx and numberpt.ins % and the derived file numberpt.sty. % %<*driver> \documentclass{ltxdoc} \usepackage{doc} \usepackage[T1]{fontenc} \usepackage{amstext,makeidx,multicol} \usepackage{numberpt} \begin{document} \DocInput{numberpt.dtx} \end{document} % % \fi % % %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % % \StopEventually % % \changes{1.0}{2019/07/13}{initial version} % % \MakeShortVerb+ % % \title{\textsf{numberpt}: counters spelled out in Portuguese} % \author{Miguel Vin\'\i cius Santini Frasson} % \date{2019--07--13 version 1.0} % % \maketitle % % \tableofcontents % % \section{Introduction} % % The package \textsf{numberpt} provides a counter style like % +\arabic+, +\alph+ etc., but that spells numbers in Portuguese, like % ``um'' (one in Portuguese), ``dois'' (two), ``tr\^es'' (three), % \ldots, up to ``novecentos e noventa e nove mil novecentos e noventa % e nove'' (999{,}999). There are counter commands to output the text % in ``lowercase'', ``First word capitalized'', ``All Words % Capitalized'' ou in ``UPPERCASE''. % % \section{User commands} % % \newcommand{\countername}{\texttt{\textit{counter}}} % % \DescribeMacro{\numberpt} % \DescribeMacro{\Numberpt} % \DescribeMacro{\NumberPt} % \DescribeMacro{\NUMBERPT} % Macros to output counters in Portuguese in ``lowercase'', % ``Capitalized'' or in ``UPPERCASE''---:\\ % + \numberpt{+\countername+}+ (ex: vinte e tr\^es),\\ % + \Numberpt{+\countername+}+ (ex: Vinte e tr\^es),\\ % + \NumberPt{+\countername+}+ (ex: Vinte E Tr\^es),\\ % + \NUMBERPT{+\countername+}+ (ex: VINTE E TR\^ES). % % Example: % %\begin{verbatim} %\renewcommand{\thechapter}{\Numberpt{chapter}} %\end{verbatim} % will produce chapter headers like: % % \centerline{Cap\'itulo Um} % \centerline{Cap\'itulo Dois} % % By default, command +\NumberPt+ for all capitalized numbers output % connectors ``e'' in uppercase. For example, if +page+ counter is 23, % then +\NumberPt{page}+ $\to$ Vinte E Tr\^es. To change this behavior % (connector ``e'' in lowercase), use starred versions +\NumberPt*+. % % \section{Package options} % % \DescribeMacro{catorze} % \DescribeMacro{quatorze} % For 14, both forms ``catorze'' e ``quatorze'' are correct. Use % package option +catorze+ (default) or +quatorze+ to select which % form is used. % % \DescribeMacro{dezesseis} % \DescribeMacro{dezasseis} % In Brazil, the forms for 16, 17 and 19 are ``dezesseis'', % ``dezessete'' and ``de\-ze\-no\-ve''. In Portugal, the forms are % ``dezasseis'', ``dezassete'' and ``dezanove''. To select Brazilian % Portuguese forms (default), use option +dezesseis+; for European % Portuguese form, use +dezasseis+. % % \section{Code} % % \subsection{Package identification} % % \begin{macrocode} \NeedsTeXFormat{LaTeX2e} \ProvidesPackage{numberpt}[2019/07/12 v1.0 Counters as numbers in Portuguese] % \end{macrocode} % % We use \LaTeX3 in this package. % % \begin{macrocode} \RequirePackage{expl3,xparse} \ExplSyntaxOn % \end{macrocode} % % \subsection{Package options} % Package options declarations +catorze+ or +quatorze+, and % +dezasseis+ or +dezesseis+. Creating undocumented ``user commands'' % +\NumberPTcatorze+, +\NumberPTquatorze+, +\NumberPTdezasseis+ and % +\NumberPTdezasseis+ that set switches. % % \begin{macrocode} \bool_new:N \NumberPT_catorze \bool_new:N \NumberPT_dezesseis \newcommand{\NumberPTcatorze}{\bool_set_true:N \NumberPT_catorze} \newcommand{\NumberPTquatorze}{\bool_set_false:N \NumberPT_catorze} \DeclareOption{ catorze }{ \NumberPTcatorze } \DeclareOption{ quatorze }{ \NumberPTquatorze } \ExecuteOptions{ catorze } \newcommand{\NumberPTdezesseis}{\bool_set_true:N \NumberPT_dezesseis} \newcommand{\NumberPTdezasseis}{\bool_set_false:N \NumberPT_dezesseis} \DeclareOption{ dezasseis }{ \NumberPTdezasseis} \DeclareOption{ dezesseis }{ \NumberPTdezesseis} \ExecuteOptions{ dezesseis } \ProcessOptions % \end{macrocode} % % \subsection{Case handling} % Command +\NumberPT_case:nn+ and switches govern capitalization. % % \begin{macrocode} \bool_new:N \NumberPT_capital \bool_new:N \NumberPT_capitalfirst \bool_new:N \NumberPT_capitale \bool_new:N \NumberPT_uppercase \cs_new:Nn \NumberPT_case:nn { \bool_if:NTF \NumberPT_capital { \uppercase { #1 } } { #1 } \bool_if:NTF \NumberPT_uppercase { \uppercase { #2 } } { #2 } \bool_if:NT \NumberPT_capitalfirst { \bool_set_false:N \NumberPT_capital } } % \end{macrocode} % % \subsection{Output for numbers with 1, 2 or 3 digits} % +\NumberPT_u:n{+$U$+}+ takes digit $U$ and outputs ``zero'', ``um'', % ``dois'', \dots, ``nove''. % % \begin{macrocode} \cs_new:Nn \NumberPT_u:n { \if_case:w #1 \NumberPT_case:nn {z}{ero}\or: \NumberPT_case:nn {u}{m}\or: \NumberPT_case:nn {d}{ois}\or: \NumberPT_case:nn {t}{r\^es}\or: \NumberPT_case:nn {q}{uatro}\or: \NumberPT_case:nn {c}{inco}\or: \NumberPT_case:nn {s}{eis}\or: \NumberPT_case:nn {s}{ete}\or: \NumberPT_case:nn {o}{ito}\or: \NumberPT_case:nn {n}{ove}% \fi:} % \end{macrocode} % % Command +\NumberPT_e_u:n{+$U$+}+ outputs `` e um'' etc, if $U>0$, % otherwise outputs nothing. % % \begin{macrocode} \cs_new:Nn \NumberPT_e_u:n { \int_compare:nNnT #1 > 0 { \space \bool_if:nTF \NumberPT_capitale {E}{e} \space \NumberPT_u:n #1 } } % \end{macrocode} % % Commands +\NumberPT_du:nn{+$D$+}{+$U$+}+ and % +\NumberPT_e_du:nn{+$D$+}{+$U$+}+ are similar, with 2 digits. % Numbers from 0 to 19 are all special cases. % % \begin{macrocode} \cs_new:Nn \NumberPT_du:nn { \if_case:w #1 % #1=0 \NumberPT_u:n #2 \or: % #1=1 \if_case:w #2 \NumberPT_case:nn {d}{ez}\or: \NumberPT_case:nn {o}{nze}\or: \NumberPT_case:nn {d}{oze}\or: \NumberPT_case:nn {t}{reze}\or: \bool_if:NTF \NumberPT_catorze { \NumberPT_case:nn {c}{atorze} } { \NumberPT_case:nn {q}{uatorze} }\or: \NumberPT_case:nn {q}{uinze}\or: \bool_if:NTF \NumberPT_dezesseis { \NumberPT_case:nn {d}{ezesseis} } { \NumberPT_case:nn {d}{ezasseis} }\or: \bool_if:NTF \NumberPT_dezesseis { \NumberPT_case:nn {d}{ezessete} } { \NumberPT_case:nn {d}{ezassete} }\or: \NumberPT_case:nn {d}{ezoito}\or: \bool_if:NTF \NumberPT_dezesseis { \NumberPT_case:nn {d}{ezenove} } { \NumberPT_case:nn {d}{ezanove} }\or: \fi: \or: % #1>1 \NumberPT_case:nn {v}{inte} \NumberPT_e_u:n #2 \or: \NumberPT_case:nn {t}{rinta} \NumberPT_e_u:n #2 \or: \NumberPT_case:nn {q}{uarenta} \NumberPT_e_u:n #2 \or: \NumberPT_case:nn {c}{inquenta} \NumberPT_e_u:n #2 \or: \NumberPT_case:nn {s}{essenta} \NumberPT_e_u:n #2 \or: \NumberPT_case:nn {s}{etenta} \NumberPT_e_u:n #2 \or: \NumberPT_case:nn {o}{itenta} \NumberPT_e_u:n #2 \or: \NumberPT_case:nn {n}{oventa} \NumberPT_e_u:n #2 \fi: } \cs_new:Nn \NumberPT_e_du:nn { \int_compare:nNnT { #1 + #2 } > 0 { \space \bool_if:nTF \NumberPT_capitale {E}{e} \space \NumberPT_du:nn #1 #2 } } % \end{macrocode} % % +\NumberPT_cdu:nnn{+$C$+}{+$D$+}{+$U$+}+ takes digits $C$, $D$ and $U$ % and outputs correspondent number. % % \begin{macrocode} \cs_new:Nn \NumberPT_cdu:nnn {% \if_case:w #1 % #1=0 \NumberPT_du:nn #2 #3 \or: % #1=1 \int_compare:nNnTF { #2 + #3 } = 0 % "cem" if 00 or "cento e " + finish { \NumberPT_case:nn {c}{em} } { \NumberPT_case:nn {c}{ento} \NumberPT_e_du:nn #2 #3 } \or: % #1>1 \NumberPT_case:nn {d}{uzentos} \NumberPT_e_du:nn #2 #3 \or: \NumberPT_case:nn {t}{rezentos} \NumberPT_e_du:nn #2 #3 \or: \NumberPT_case:nn {q}{uatrocentos} \NumberPT_e_du:nn #2 #3 \or: \NumberPT_case:nn {q}{uinhentos} \NumberPT_e_du:nn #2 #3 \or: \NumberPT_case:nn {s}{eiscentos} \NumberPT_e_du:nn #2 #3 \or: \NumberPT_case:nn {s}{etecentos} \NumberPT_e_du:nn #2 #3 \or: \NumberPT_case:nn {o}{itocentos} \NumberPT_e_du:nn #2 #3 \or: \NumberPT_case:nn {n}{ovecentos} \NumberPT_e_du:nn #2 #3 \fi: } % \end{macrocode} % % \subsection{Output for numbers with 4, 5 or 6 digits} % % \DeleteShortVerb+ % If a number $abcdef$ has between 4 and 6 digits, the rule for % spelling this number is\footnote{See % \texttt{www.languagesandnumbers.com/como-contar-em-portugues-brasil/pt/por-bra/}}: % \begin{itemize} % \item spell the 3-digits number $abc$ (unless $abc=001$) + ``mil'' % \item stop if $def=000$, otherwise: % \item add the connector ``e'' for numbers % \begin{itemize} % \item finishing in 00, \emph{i.e.}, $e+f=0$ % \item without digit for hundreds , \emph{i.e.}, $d=0$ % \end{itemize}% % \item spell the 3-digits number $def$ % \end{itemize} % % \begin{macrocode} \cs_new:Nn \NumberPT_e_cdu:nnn { \int_compare:nNnF {#1 + #2 + #3} = 0 { \space \bool_if:nT { \int_compare_p:nNn #1 = 0 || \int_compare_p:nNn {#2 + #3} = 0 } { \bool_if:nTF \NumberPT_capitale {E}{e} \space } \NumberPT_cdu:nnn #1 #2 #3 } } % \end{macrocode} % % Output for numbers with up to 6 digits. % % \begin{macrocode} \cs_new:Nn \NumberPT_abcdef:nnnnnn { \int_compare:nNnTF {#1 + #2 + #3} = 0 %abc=000 { \NumberPT_cdu:nnn #4 #5 #6 } % else { % avoid "um mil", using just "mil" \int_compare:nNnF {100 * #1 + 10 * #2 + #3} = 1 { \NumberPT_cdu:nnn #1 #2 #3 \space } \NumberPT_case:nn {m}{il} \NumberPT_e_cdu:nnn #4 #5 #6 } } \cs_generate_variant:Nn \NumberPT_abcdef:nnnnnn {xxxxxx} % \end{macrocode} % % \subsection{Conversion from counter to digits} % % \MakeShortVerb+ % Now, conversion from counter to digits. digits will be stored in % macros +\NumberPT_digit_u+, +\NumberPT_digit_d+, +\NumberPT_digit_c+. % Decomposition is done with mod. % % \begin{macrocode} \int_new:N \NumberPT_digit_u \int_new:N \NumberPT_digit_d \int_new:N \NumberPT_digit_c \int_new:N \NumberPT_digit_um \int_new:N \NumberPT_digit_dm \int_new:N \NumberPT_digit_cm \cs_new:Nn \NumberPT_decompose:n { \int_set:Nn \l_tmpa_int { #1 } \int_set:Nn \NumberPT_digit_u { \int_mod:nn { \l_tmpa_int } { 10 } } \int_set:Nn \l_tmpa_int { ( \l_tmpa_int - \NumberPT_digit_u ) / 10 } \int_set:Nn \NumberPT_digit_d { \int_mod:nn { \l_tmpa_int } { 10 } } \int_set:Nn \l_tmpa_int { ( \l_tmpa_int - \NumberPT_digit_d ) / 10 } \int_set:Nn \NumberPT_digit_c { \int_mod:nn { \l_tmpa_int } { 10 } } \int_set:Nn \l_tmpa_int { ( \l_tmpa_int - \NumberPT_digit_c ) / 10 } \int_set:Nn \NumberPT_digit_um { \int_mod:nn { \l_tmpa_int } { 10 } } \int_set:Nn \l_tmpa_int { ( \l_tmpa_int - \NumberPT_digit_um ) / 10 } \int_set:Nn \NumberPT_digit_dm { \int_mod:nn { \l_tmpa_int } { 10 } } \int_set:Nn \l_tmpa_int { ( \l_tmpa_int - \NumberPT_digit_dm ) / 10 } \int_set:Nn \NumberPT_digit_cm { \int_mod:nn { \l_tmpa_int } { 10 } } } % \end{macrocode} % % Now, command that prints counter: +\NumberPT_print_counter:n+. % Declaring error message in case counter is out of range from 0 to 999. % Even in case of this error, falls back to arabic number. % % \begin{macrocode} \msg_new:nnn { numberpt } { counter-out-of-range } {Counter~`#1'~out~of~range~0~...~999999} \cs_new:Nn \NumberPT_print_counter:n { \int_set:Nn \l_tmpa_int { \value{#1} } \bool_if:nTF { \int_compare_p:n { \l_tmpa_int >= 0 } && \int_compare_p:n { \l_tmpa_int < 1000000 } } { \NumberPT_decompose:n { \l_tmpa_int } \NumberPT_abcdef:xxxxxx { \int_use:N \NumberPT_digit_cm } { \int_use:N \NumberPT_digit_dm } { \int_use:N \NumberPT_digit_um } { \int_use:N \NumberPT_digit_c } { \int_use:N \NumberPT_digit_d } { \int_use:N \NumberPT_digit_u } } { \msg_error:nnn { numberpt } { counter-out-of-range } {#1} \arabic{#1} } } % \end{macrocode} % % \subsection{User macros} % Finally, user macros. Each macro sets switches for capitalization % and calls +\NumberPT_print_counter:n+. % \begin{macrocode} \NewDocumentCommand{\numberpt}{m}{ \bool_set_false:N \NumberPT_capital \bool_set_false:N \NumberPT_capitale \bool_set_false:N \NumberPT_uppercase \NumberPT_print_counter:n { #1 } } \NewDocumentCommand{\NumberPt}{s m}{ \bool_set_true:N \NumberPT_capital \bool_set:Nn \NumberPT_capitale {! #1} \bool_set_false:N \NumberPT_capitalfirst \bool_set_false:N \NumberPT_uppercase \NumberPT_print_counter:n { #2 } } \NewDocumentCommand{\Numberpt}{m}{ \bool_set_true:N \NumberPT_capital \bool_set_false:N \NumberPT_capitale \bool_set_true:N \NumberPT_capitalfirst \bool_set_false:N \NumberPT_uppercase \NumberPT_print_counter:n { #1 } } \NewDocumentCommand{\NUMBERPT}{m}{ \bool_set_true:N \NumberPT_capital \bool_set_true:N \NumberPT_capitale \bool_set_true:N \NumberPT_uppercase \NumberPT_print_counter:n { #1 } } % \end{macrocode} % % End of code. % \begin{macrocode} \ExplSyntaxOff \endinput % \end{macrocode} % % \section{Tests} % % Here we create a counter and spell the numbers for some selected values. % % \newcounter{test} % \newcommand{\test}[1]{\par\setcounter{test}{#1}#1: \numberpt{test}} % \newcommand{\Test}[1]{\par\setcounter{test}{#1}#1: \Numberpt{test}} % \newcommand{\TesT}[1]{\par\setcounter{test}{#1}#1: \NumberPt{test}} % \newcommand{\TesTs}[1]{\par\setcounter{test}{#1}#1: \NumberPt*{test}} % \newcommand{\TEST}[1]{\par\setcounter{test}{#1}#1: \NUMBERPT{test}} % % \subsection{Tests with \texttt{\protect\string\numberpt}} % % \begin{multicols}{3} % \test{1} % \test{2} % \test{3} % \test{4} % \test{5} % \test{6} % \test{7} % \test{8} % \test{9} % \test{10} % \test{11} % \test{12} % \test{13} % \test{14} % \test{15} % \test{16} % \test{17} % \test{18} % \test{19} % \test{20} % \test{21} % \test{22} % \test{30} % \test{31} % \test{40} % \test{41} % \test{50} % \test{51} % \test{60} % \test{61} % \test{70} % \test{71} % \test{80} % \test{81} % \test{90} % \test{91} % \test{100} % \test{101} % \end{multicols} % \subsection{Tests with \texttt{\protect\string\Numberpt}} % \begin{multicols}{2} % \Test{199} % \Test{200} % \Test{201} % \Test{300} % \Test{301} % \Test{400} % \Test{401} % \Test{500} % \Test{501} % \end{multicols} % \subsection{Tests with \texttt{\protect\string\NumberPt}} % \begin{multicols}{2} % \TesT{600} % \TesT{601} % \TesT{700} % \TesT{701} % \end{multicols} % \subsection{Tests with \texttt{\protect\string\NumberPt*}} % \begin{multicols}{2} % \TesTs{800} % \TesTs{801} % \TesTs{900} % \TesTs{999} % \end{multicols} % \subsection{Tests with \texttt{\protect\string\NUMBERPT}} % \begin{multicols}{1} % \end{multicols} % \TEST{1000} % \TEST{1001} % \TEST{1099} % \TEST{1100} % \TEST{1101} % \TEST{2000} % \TEST{2001} % \TEST{2099} % \TEST{2100} % \TEST{2101} % \TEST{2200} % \TEST{2201} % \TEST{2299} % \TEST{2300} % % \subsection{Tests with 14, 16, 17, 19} % % \begin{quote} % % \end{quote} % \NumberPTcatorze % \test{14} (must be ``catorze'')\medskip % \NumberPTquatorze % \test{14} (must be ``quatorze'')\bigskip % % \NumberPTdezasseis % \test{16} (must be ``dezasseis'') % \test{17} (must be ``dezassete'') % \test{19} (must be ``dezanove'')\medskip % \NumberPTdezesseis % \test{16} (must be ``dezesseis'') % \test{17} (must be ``dezessete'') % \test{19} (must be ``dezenove'') % \end{document}