From d6b2eaba6fe47c24603040934903c73535ff09ba Mon Sep 17 00:00:00 2001 From: Norbert Preining Date: Fri, 11 Jun 2021 03:00:56 +0000 Subject: CTAN sync 202106110300 --- .../latex/contrib/cooking-units/cooking-units.dtx | 6369 ++++++++++++-------- .../latex/contrib/cooking-units/cooking-units.ins | 4 +- .../latex/contrib/cooking-units/cooking-units.pdf | Bin 700306 -> 748443 bytes 3 files changed, 3941 insertions(+), 2432 deletions(-) (limited to 'macros/latex/contrib/cooking-units') diff --git a/macros/latex/contrib/cooking-units/cooking-units.dtx b/macros/latex/contrib/cooking-units/cooking-units.dtx index 0e01884a27..ee29c982c3 100644 --- a/macros/latex/contrib/cooking-units/cooking-units.dtx +++ b/macros/latex/contrib/cooking-units/cooking-units.dtx @@ -82,7 +82,7 @@ for the details of that license. %\keepsilent \askforoverwritefalse \preamble -Copyright (C) 2016--2020 by Ben Vitecek (current Maintainer) +Copyright (C) 2016--2021 by Ben Vitecek (current Maintainer) This file may be distributed and/or modified under the conditions of the LaTeX Project Public License, either @@ -182,7 +182,14 @@ and the derived file cooking-units.sty. \NewDocumentCommand \cookingunitsToDo { m } { -% \marginpar { \textcolor{red}{#1} } + \marginpar { \textcolor{red}{#1} } + } +\NewDocumentCommand \cookingunitsTODO { m } { \cookingunitsToDo {#1} } +\NewDocumentCommand \cookingunitsContinue { } { \cookingunitsToDo {Continue} } +\NewDocumentCommand \cookingunitsCONTINUE { } { \cookingunitsContinue } +\NewDocumentCommand \cookingunitsChecked { } + { + \cookingunitsToDo{Checked} } @@ -210,7 +217,10 @@ and the derived file cooking-units.sty. declarecookingderivatives , cufrac , cusetoptionfor, cuaddoptionfor, cuclearoptionfor, - cudeclareunitgroup, cuaddtounitgroup, cuclearunitgroup + cudeclareunitgroup, cuaddtounitgroup, cuclearunitgroup , + cudefinekeys , + , cudefinekeychain , cuaddtokeychain + , cudeclareunitgroup } \NewDocumentCommand \mycs { m } @@ -219,9 +229,9 @@ and the derived file cooking-units.sty. { \cs_if_exist:cTF {#1} { \cs{\textcolor{blue}{#1}} } - { \mycsERRORII } + { \tl_show:n {#1}\mycsERRORII } } - { \mycsERROR } + { \tl_show:n {#1} \mycsERROR } } \newcommand\opt{\texttt} \newcommand\myunit{\texttt} @@ -233,14 +243,12 @@ and the derived file cooking-units.sty. %: \PrintUnit \NewDocumentCommand \PrintUnit { o m } { - \SaveTranslation \l_tmpa_tl { #2 (cu-unitname) } + \__cookingunits_culang_let:nnN { name } {#2} \l_tmpa_tl \tl_if_eq:NNF \l_tmpa_tl \q__cookingunits_no_translation { \l_tmpa_tl } \IfNoValueF {#1} {#1} & - \texttt {#2} - & - \tl_use:c { l__cookingunits_default_unit_ #2 _tl } + \PrintUnitSymbol {#2} } \NewDocumentCommand \PrintUnitSymbol { m } { @@ -258,7 +266,6 @@ and the derived file cooking-units.sty. \msg_redirect_name:nnn { cooking-units } { curef-forbidden-unit } { warning } } - %% Allyourwhitespacearebelongtous (too long) %% 42 %% Miep! @@ -272,16 +279,18 @@ and the derived file cooking-units.sty. { \begin{center} \begin{minipage}{0.4\linewidth} - \tl_replace_all:Nnn \BODY { @ } { \dothewhitespace } - \tl_replace_all:Nnn \BODY { \% } { \color{red} \% \ignorespaces } - \tl_replace_all:Nnn \BODY { \\ } { \\ \color{black} } - \tl_replace_all:Nnn \BODY { & } { \ignorespaces } - \BODY + \hbadness=10000 + \tl_replace_all:Nnn \BODY { @ } { \dothewhitespace } + \tl_replace_all:Nnn \BODY { \% } { \color{red} \% \ignorespaces } + \tl_replace_all:Nnn \BODY { \\ } { \\ \color{black} } + \tl_replace_all:Nnn \BODY { & } { \ignorespaces } + \BODY \end{minipage} #1 \int_zero:N \l_tmpa_int \begin{minipage}{0.5\linewidth} + \hbadness=10000 \ttfamily \tl_set_rescan:Nno \l_tmpa_tl { @@ -289,6 +298,7 @@ and the derived file cooking-units.sty. \char_set_catcode_other:N \} % \char_set_catcode_other:N \_ % \char_set_catcode_other:N \~ % +% \char_set_catcode_other:N \# % } { \BODY } \tl_map_inline:Nn \l_tmpa_tl @@ -297,46 +307,27 @@ and the derived file cooking-units.sty. { \cs_if_eq:NNTF ##1 \\ { \textbackslash\textbackslash \\ } - { - \tl_set_rescan:Nnn \l_tmpb_tl - { - \char_set_catcode_ignore:N \\ % - \char_set_catcode_ignore:N \ % - } - {##1} - \textbackslash \textcolor{blue}{\l_tmpb_tl} - } - } - { - \bool_lazy_any:nTF - { - { \str_if_eq_p:nn {##1} { @ } } - { \str_if_eq_p:nn {##1} { ! } } - { \str_if_eq_p:nn {##1} { & } } - } - { - \str_if_eq:nnTF {##1} { & } - { \space } - { - \str_if_eq:nnTF {##1} { ! } - { \ERROR } - { \\ } - } - } + { \textbackslash \textcolor{blue}{\cs_to_str:N ##1} } + }{ + \token_if_letter:NTF ##1 + {##1} { - \token_if_active:NTF ##1 - {##1} + \str_case:nnF {##1} { - \token_if_parameter:NTF ##1 - { - \int_compare:nNnTF { \l_tmpa_int } = { 0 } + { @ } { \\ } + { & } { \space } + }{ + \token_if_active:NTF ##1 + {##1} + { + \token_if_parameter:NTF ##1 { - \c_hash_str - \int_incr:N \l_tmpa_int + \int_compare:nNnTF { \l_tmpa_int } = { 0 } + { \c_hash_str \int_incr:N \l_tmpa_int } + { \int_zero:N \l_tmpa_int } } - { \int_zero:N \l_tmpa_int } + { ##1 {} } } - { ##1 {} } } } } @@ -417,7 +408,7 @@ and the derived file cooking-units.sty. } \cs_new_eq:NN \__table_default_midrule: \__table_midrule: -\cs_new:Npn \_cook_use:n #1 +\cs_new:Npn \__cu_use:n #1 { \cs_if_exist_use:cF { __cookingunits_#1 } {\ERRORcommandNOTexist} } \NewDocumentCommand \CreateTableForLanguages { s >{\TrimSpaces} m } @@ -445,55 +436,64 @@ and the derived file cooking-units.sty. { THEEND } { \\ \bottomrule } }{ \__table_midrule: - \texttt{##1} - & - \clist_if_in:NnTF \l_list_of_textunits_clist {##1} - { \l_translation_does_not_exist_tl } - { - \_cook_use:n { translate_let:nNnV } {#1} \l_tmpa_tl {##1} \c__cookingunits_postfix_unit_tl - \tl_if_in:NnTF \l_tmpa_tl \q__cookingunits_no_translation - { \l_translation_does_not_exist_tl } - { \l_tmpa_tl } - } - & - \_cook_use:n { translate_let:nNnV } {#1} \l_tmpa_tl {##1} \c__cookingunits_postfix_unitname_tl - \tl_if_in:NnTF \l_tmpa_tl \q__cookingunits_no_translation - { \l_translation_does_not_exist_tl } - { \l_tmpa_tl } - & - \_cook_use:n { translate_let:nNnV } {#1} \l_tmpa_tl {##1} \c__cookingunits_postfix_unitname_tl - \_cook_use:n { translate_let:nNnV } {#1} \l_tmpb_tl {##1} \c__cookingunits_postfix_unitname_pl_tl - \tl_if_eq:NNF \l_tmpa_tl \l_tmpb_tl - { - \tl_if_in:NnTF \l_tmpb_tl \q__cookingunits_no_translation - { \l_translation_does_not_exist_tl } - { (\l_tmpb_tl) } - } - & - \_cook_use:n { translate_let:nNnV } {#1} \l_tmpa_tl {##1} \c__cookingunits_postfix_gender_tl - \tl_if_in:NnTF \l_tmpa_tl \q__cookingunits_no_translation - { \l_translation_does_not_exist_tl } - { \l_tmpa_tl } + \__cookingunits_doc_print_table_row:nn {#1} {##1} } } } -\NewDocumentCommand \CreateTableForPhrases { >{\TrimSpaces} m } +\cs_new:Npn \__cookingunits_doc_print_table_row:nn #1#2 { - \tl_set:Nn \l_tmpa_tl {#1} - \__cookingunits_phrase_list_get_for:NNTF \l_tmpa_prop \l_tmpa_tl + \texttt{#2} + & + \clist_if_in:NnTF \l_list_of_textunits_clist {#2} + { \l_translation_does_not_exist_tl } + { + \__cu_use:n { culang_let_for:nnnN } {#1} { unit-symbol } {#2} \l_tmpa_tl + \tl_if_in:NnTF \l_tmpa_tl \q__cookingunits_no_translation + { \l_translation_does_not_exist_tl } + { \l_tmpa_tl } + } + & + \__cu_use:n { culang_let_for:nnnN } {#1} { name } {#2} \l_tmpa_tl + \tl_if_in:NnTF \l_tmpa_tl \q__cookingunits_no_translation + { \l_translation_does_not_exist_tl } + { \l_tmpa_tl } + & + \__cu_use:n { culang_let_for:nnnN } {#1} { name } {#2} \l_tmpa_tl + \__cu_use:n { culang_let_for:nnnN } {#1} { name-pl } {#2} \l_tmpb_tl + \str_if_eq:NNF \l_tmpa_tl \l_tmpb_tl { - \__cookingunits_translate_let:VNnV \l_tmpa_tl \l_tmpa_seq - { phrase-clist } \c__cookingunits_postfix_phrase_tl + \tl_if_in:NnTF \l_tmpb_tl \q__cookingunits_no_translation + { \l_translation_does_not_exist_tl } + { (\l_tmpb_tl) } + } + & + \__cu_use:n { culang_let_for:nnnN } {#1} { gender } {#2} \l_tmpa_tl + \tl_if_in:NnTF \l_tmpa_tl \q__cookingunits_no_translation + { \l_translation_does_not_exist_tl } + { \l_tmpa_tl } + } + +\NewDocumentCommand \CreateTableForPhrases { >{\TrimSpaces} m } + { + \seq_clear:N \l_tmpa_seq + \__cu_use:n { culang_let_for:nnnN } {#1} { phrase } { phrase-prop } \l_tmpa_prop + \prop_if_exist:NTF \l_tmpa_prop + { + \tl_if_eq:NNTF \q__cooking_units_no_translation \l_tmpa_prop + { \ERRORCreateTablePhraseII } + { + \prop_get:NnN \l_tmpa_prop { seq } \l_tmpa_seq + } } - { \ERRORCreateTable } + { \ERRORCreateTablePhraseI } \seq_gput_right:Nn \l_tmpa_seq { THEEND } \cs_gset_eq:NN \__table_midrule: \__table_default_midrule: - \begin{tabular}{ l l l l l } - \toprule - \meta{Phrase-key} & phrase & (plural) & gender + \begin{tabular}{ l l l l l } + \toprule + \meta{Phrase-key} & phrase & (plural) & gender \CreatePhraseTableRow {#1} - \end{tabular} + \end{tabular} } \NewDocumentCommand \CreatePhraseTableRow { m } @@ -507,16 +507,15 @@ and the derived file cooking-units.sty. }{ \__table_midrule: ##1 - & - \prop_get:NnN \l__cookingunits_phrase_prop {##1} \l_tmpa_tl - \tl_gset:NV \l_tmpa_tl \l_tmpa_tl %% Damit global - \l_tmpa_tl - & - \prop_get:NnN \l__cookingunits_phrase_prop {##1-pl} \l_tmpb_tl - \tl_if_eq:NNF \l_tmpa_tl \l_tmpb_tl { \l_tmpb_tl } - & - \__cookingunits_translate_let:nNnV {#1} - \l_tmpa_tl { ##1 -phrase-gender } \c__cookingunits_postfix_gender_tl + & + \prop_get:NnN \l_tmpa_prop {##1} \l_tmpa_tl + \tl_gset:NV \l_tmpa_tl \l_tmpa_tl %% Damit global + \l_tmpa_tl + & + \prop_get:NnN \l_tmpa_prop {##1-pl} \l_tmpb_tl + \tl_if_eq:NNF \l_tmpa_tl \l_tmpb_tl { \l_tmpb_tl } + & + \prop_get:NnN \l_tmpa_prop {##1-gender} \l_tmpa_tl \l_tmpa_tl } } @@ -593,29 +592,41 @@ and the derived file cooking-units.sty. culabel, curef, cudefinephrase, - declarecookingderivatives + declarecookingderivatives, + , cudefinekeychain + , cuaddtokeychain + , cudeclareunitgroup + , cusetoptionfor + , usepackage } } -\newcommand\eneunit[3]{\sfrac{#1\,#2${}^2$}{#3${}^2$}} -%% Can overflow and takes too long, hard code it -%\declarecookingderivatives{kg,m,s}{#1*#2-#3}{ (#1)*(#2)^2/(#3)^2 } {\eneunit{#1}{#2}{#3}} -\newcookingunit[\eneunit{kg}{m}{s}]{kg*m-s} -\newcookingunit[\eneunit{oz}{in}{min}]{oz*in-min} \newcookingunit {st} \newcookingunit [\ensuremath{ {} ^ { \circ } }\kern-\scriptspace R{\text{\o}}] {Ro} \newcookingunit {ft} +\newcookingunit {km} -\cuaddkeys {lb} - { - {st} { 1/14 } %% 1 lb are 1/14 st - } +%\cuaddkeys {lb} +% { +% {st} { 1/14 } %% 1 lb are 1/14 st +% } +\cuaddtokeychain + { + {lb} { 14 } + {st} { 1 } + } \cuaddtokeys {m} {ft} {0.3048} +\cuaddtokeys {m} {km} {1000} \cuaddsinglekeys {C} { {Ro} { #1*21/40 + 7.5 } } +\newcommand\eneunit[3]{\sfrac{#1\,#2${}^2$}{#3${}^2$}} +%% Can overflow and takes too long, hard code it +\declarecookingderivatives{kg,m,s}{#1*#2:#3}{ (#1)*(#2)^2/(#3)^2 } {\eneunit{#1}{#2}{#3}} +\declarecookingderivatives{m,s}{#1:#2}{ (#1)/(#2) } {\sfrac{#1}{#2}} + \cusetup @@ -772,7 +783,7 @@ and the derived file cooking-units.sty. % \changes {2018/06/05} {1.40} {Bugfix (\texttt{label-not-defined}): Add |'#1'|.} % \changes {2018/06/05} {1.40} {Bugfix (\texttt{unit-change}): \opt{convert-to-eV} % can be again used as a local argument.} -% \changes {2018/06/05} {1.40} {Change order of boolean testing for |\@@_calc_references:NN|.} +% \changes {2018/06/05} {1.40} {Change order of boolean testing for |\@@_calc_references_and_store_in:N|.} % \changes {2018/06/05} {1.40} {Bugfix (\texttt{phrases}): Use the phrase from the first amount to check % the second (and don't parse through the second amount).} % @@ -782,6 +793,16 @@ and the derived file cooking-units.sty. % \changes {2018/09/24} {1.45} {New section in documentation.} % \changes {2018/09/24} {1.45} {Remove exhaustive expansion from internals (shouldn't change anything for users).} % +% \changes {2021/03/21} {2.00} {Overall reworking of internal code.} +% \changes {2021/03/21} {2.00} {Much better error handling.} +% \changes {2021/03/21} {2.00} {Remove exhaustive expansion from translations. Shouldn't really change anything.} +% \changes {2021/03/21} {2.00} {New options: \opt{definition/symbol}, \opt{definition/gender}, \opt{definition/set-option}, \opt{definition/add-to-group}. } +% \changes {2021/03/21} {2.00} {Adding keys to unit definition.} +% \changes {2021/03/21} {2.00} {Updatet |\declarecookingderivatives|.} +% \changes {2021/03/21} {2.00} {New commands: |\cudefinekeychain|, |\cuaddtokeychain|} +% \changes {2021/03/21} {2.00} {New joke options: \opt{nothing-special}, \opt{going-bonkers}, \opt{fully-bonkers} and \opt{xD-lol}.} +% \changes {2021/03/21} {2.00} {New commands to define keys: \mycs{cudefinekeychain} and \mycs{cuaddtokeychain}.} +% \changes {2021/03/21} {2.00} {Using commands as unit-keys now works.} % % % @@ -798,26 +819,26 @@ and the derived file cooking-units.sty. % % \maketitle % +% % \begin{documentation} % \begin{abstract} % This package enables user to globally format units, to switch % between them and change your recipes to a given % number of persons. % -% For not implemented units or differences between Imperial and U.S.\ unit -% you may have a look at \cref{sec:other-units}. +% For not implemented units or differences between Imperial and U.S.\ unit +% you may have a look at \cref{sec:other-units}. % % It should be used for light-hearted things like % cookery books (and not e.g. scientific texts; use e.g.\ \pkg{siunitx} for those). % -% Please read through the section \enquote{Important Changes} +% ^^A Please read through the section \enquote{Important Changes} % \end{abstract} % % \tableofcontents % % \section{Introduction} % -% % While writing on a cookery book I used -- for some reasons whatsoever -- % three different units for weight: kilogram (kg), gram (g) and % decagram (dag, or older: dkg). Later my mother told me that she @@ -830,30 +851,10 @@ and the derived file cooking-units.sty. % more pleasant than \LaTeXe) and here it is. % % -% \begin{comment} -% \subsection{Overview} -% \begin{description} -% \item[Language] I am now using the \pkg{translations} package -% and I hope it makes things easier. As such, declaring the used language -% through class options shouldn't be necessary anymore. -% \item[Phrases] This package now supports the usage of \enquote{phrases} -% (words used instead of certain integers) (which I think are called \enquote{counting -% measures} in english, but I am not sure). -% \item[\cCutext] If no translation is found for a specific language, -% \cCutext\ are replaced by \mycs{cunum} with a warning is given. -% \item[Commands] Currently, it seems that allowing \meta{label} -% to be set by arrow-brackets was not the best idea as it leads to problems -% if they are made active (e.g. \pkg{babel} and option \opt{spanish}). As such, -% |<| is not allowed as a \enquote{special-sign} anymore as this package -% tries to \enquote{fix} this idea (at least make it work). If any problems occur -% (for this specific case or in general) please feel free to contact me. -% \end{description} -% \end{comment} % % % % \subsection{Supported languages} -% \cookingunitsToDo{Passt.} % \begin{itemize} % \item German % \item English @@ -865,9 +866,9 @@ and the derived file cooking-units.sty. % % \section {The Commands} % \label{sec:commands} -% \cookingunitsToDo{Passt.} +% % -% This package offers the following commands for unit printing (and +% This package offers the following commands for number/unit printing (and % converting): % % \begin{itemize} @@ -885,7 +886,7 @@ and the derived file cooking-units.sty. % added and defined, see \cref{sec:pred-units} and % \cref{sec:def-units} for further information.}. It furthermore % allows the sign \texttt{?} to be used as a placeholder for not known -% amounts and raises a warning to remind that this amount needs a +% amounts and raises a warning to remind you that this amount needs a % check-up\footnote{You can customize this behavior, see % \cref{sec:options}}. \oarg{space} adds a space between the number % and the unit using \lstinline|\phantom|. @@ -932,7 +933,6 @@ and the derived file cooking-units.sty. %^^A \lstinline|\Cutext| capitalizing the first letter (using package %^^A \pkg{fmtcount}). % -% % \begin{cuexamplecode} % \cutext{1}{l} \\ % \Cutext{1}{l} \\ @@ -940,7 +940,7 @@ and the derived file cooking-units.sty. % \cutext{12}{l} \\ % \Cutext{13}{l} % \end{cuexamplecode} -% and using (e.g.) package option \opt{use-fmtcount-numerals=true} +% and using (e.g.)\ package option \opt{use-fmtcount-numerals=true} % \cusetup{print-numerals=true} % \begin{cuexamplecode} % \cutext{1}{l} \\ @@ -984,8 +984,9 @@ and the derived file cooking-units.sty. % by a word; such as \enquote{12} becoming \enquote{dozen}\footnote{At least I think}) % which can be activated by the option \opt{use-phrases} % (as I don't know any english phrases, I switched the language to german for the following examples) -% \begin{myde} +%^^A \begin{myde} % \begin{cuexamplecode} +% \selectlanguage{ngerman} @ % \cusetup{use-phrases=true} @ % \cuam{11} \\ % \cuam{12} \\ @@ -996,12 +997,12 @@ and the derived file cooking-units.sty. % \cuam{18} \\ % \cuam{60} % \end{cuexamplecode} -% \end{myde} +%^^A \end{myde} % % % \section{Label \& refs: Changing the amount of the recipe} % \label{sec:labeletref} -% \cookingunitsToDo{Also not much to change} +% % % What if you don't want to change units, but the amounts of the recipe because % you cook not for 4 persons, but for 2 and don't like to do the math? @@ -1061,86 +1062,18 @@ and the derived file cooking-units.sty. % % % -% \begin{comment} -% \section{Some Interesting options} -% \cookingunitsToDo{This section is horrible, change or delete as a whole, but later} -% This package has some options which might be of interest and to highlight them, this section exists. All options can be -% found in \cref{sec:options}. -% -% -%\subsection{Numerals} -% \begin{cuinterest}{use-fmtcount-numerals, use-numerals-below, print-numerals} -% As seen above, you can use the \emph{package}-option -% \opt{use-fmtcount-numerals} to print integers used by \cCutext{} below -% \opt{use-numerals-below} (13 by default) by \pkg{fmtcount}. -% You can still decide if numerals should be printed or not with \opt{print-numerals}. -% -% \begin{cunote} -% \opt{use-fmtcount-numerals} is a package option as it needs to load -% \pkg{fmtcount} which is not loaded by default. -% \end{cunote} -% -% \end{cuinterest} -% -% \subsection{Phrases} -% \begin{cuinterest}{use-phrases} -% In (I presume) all languages there exist phrases for a given -% amount or a number of things (think it is called \enquote{counting measurement}). -% In German you may say instead of -% \enquote{12}: \enquote{ein Dutzend}. Using this option you can tell this -% package to replace predefined integers used in \mycs{cuam} -% by phrases for the currently used language -% (to define new ones, see \cref{sec:phrases}) -% -% Using (for example) language \opt{ngerman} (or \opt{naustrian}, etc.) with -% package option \opt{use-phrases=true} gives: -% \begin{myde} -% \begin{cuexamplecode} -% \cusetup{use-phrases=true} @ -% \cuam{12} \\ -% \cuam{24} \\ -% \cuam{12--24} \\ -% \cuam{12--13} \\ -% \cuam{18} \\ -% \cuam{60} -% \end{cuexamplecode} -% \end{myde} -% This of course also works with the \emph{package}-option \opt{use-fmtcount-numerals}: -% \begin{myde} -% \cusetup{print-numerals=true} -% \begin{cuexamplecode} -% \cusetup{use-phrases=true} @ -% \cuam{12} \\ -% \cuam{24} \\ -% \cuam{12--24} \\ -% \cuam{12--13} \\ -% \cuam{18} \\ -% \cuam{60} -% \end{cuexamplecode} -% \end{myde} -% -% -% \begin{cunote} -% Currently only the lower-case variant for \opt{use-fmtcount-numerals} is -% supported. Furthermore this feature is only available for \mycs{cuam}. -% \end{cunote} -% -% \end{cuinterest} -% -% \end{comment} -% -% % % % % % %\subsection{Rounding temperatures} +% % % By default temperatures are rounded to integers (using \opt{round-precision=0}). -% Since 1.30 it is possible to round amounts to a negative precision. +% Since v1.30 it is possible to round amounts to a negative precision. % If you want to round temperatures to the tens see the following -% example (\opt{set-option-for-\meta{unit}} is described in \cref{sec:opt:unit-spec}). +% example (\mycs{cusetoptionfor} is described in \cref{sec:opt:unit-spec}). % % \begin{cuexamplecode} % \cunum{182}{C} \\ @@ -1148,10 +1081,6 @@ and the derived file cooking-units.sty. % \cunum[C=Re]{180}{C} \\ % \cunum[C=K]{180}{C} \\ % \cusetoptionfor{C,F,K,Re}{ round-precision = -1 } @ -%^^A \cusetup{set-option-for-C = { round-precision = -1 } } @ -%^^A \cusetup{set-option-for-F = { round-precision = -1 } } @ -%^^A \cusetup{set-option-for-Re = { round-precision = -1 } } @ -%^^A \cusetup{set-option-for-K = { round-precision = -1 } } @ % \cunum{182}{C} \\ % \cunum[C=F]{180}{C} \\ % \cunum[C=Re]{180}{C} \\ @@ -1160,38 +1089,27 @@ and the derived file cooking-units.sty. % % \section{Predefined units \& some notes} % \label{sec:pred-units} -% \cookingunitsToDo{Passt.} -% \begin{comment} -% In \cref{tab:def-units} and \cref{tab:some-more-units} (and \cref{tab:strange-units}) -% you can find -% all predefined units. In \cref{sec:Translations} all translations available -% are listed. -% \end{comment} +% +% % % In \cref{tab:def-units} and you can find all predefined units which can be % transformed into each other (sorted by group). Other predefined units -% (which cannot be used for transformation) are shown in \cref{tab:some-more-units}. +% (which cannot be used for transformations) are shown in \cref{tab:some-more-units}. % \Cref{tab:strange-units} pretty much exists just for fun. % % -% \begin{table}[htbp] +% \begin{table}[htb] % \centering % \caption{^^A -%^^A The first column shows a list of predefined unit-keys. -%^^A The column \enquote{default} shows the abbreviation used if -%^^A for given language no translation is defined. The translations used for \cCutext\ -%^^A are shown in \cref{sec:Translations}. -%^^A Note that \enquote{electron volt} exists just for fun. -%^^A % This table shows all units which can be transformed into each other, sorted % by group. The columns \enquote{default} show the abbreviations used if -% for given language no translation is defined. The translations used for \cCutext\ +% no translation is defined for the given language. The translations used for \cCutext\ % are shown in \cref{sec:Translations}. % Note that \enquote{electron volt} exists just for fun. % } % \smallskip % \begin{tabular}{ lll @{\hspace{1cm}} lll } -% \toprule +% \toprule % description & key & default & description & key & default \\ \midrule % \PrintUnit {kg} & \PrintUnit{m} \\ % \PrintUnit {dag} & \PrintUnit{dm} \\ @@ -1216,14 +1134,16 @@ and the derived file cooking-units.sty. % \label{tab:def-units} % \end{table} % -% \begin{table}[htbp] +% \begin{table}[htb] % \centering % \caption{A (not only) spoonful of (more or less) country and % language dependent units. Please note that sometimes a % translation is nearly impossible as a unit % (e.g. \enquote{saltspoonful}) may not exist in another language % (like german; at least I never heard of it). So please only use -% units known to you.} +% units known to you. For \enquote{tablespoon} and \enquote{teaspoon} +% I used the german abbreviations \enquote{EL} and \enquote{TL} (because I forgot to +% change them initially).} % \smallskip % \begin{tabular}{ lll } % \toprule @@ -1240,7 +1160,7 @@ and the derived file cooking-units.sty. % \label{tab:some-more-units} % \end{table} % -% \begin{table}[htbp] +% \begin{table}[htb] % \centering % \caption{List of (not really) nonsense units (exist just for fun, there will be % no support for those units; unless -- of course -- you really want it).} @@ -1261,50 +1181,85 @@ and the derived file cooking-units.sty. % % \section{Defining units} % \label{sec:def-units} -% \cookingunitsToDo{Passt.} +% +% % New units can be defined using % \begin{itemize} -% \item \mycs{declarecookingunit}\oarg{symbol}\marg{unit-key} -% \item \mycs{newcookingunit}\oarg{symbol}\marg{new-unit-key} -% \item \mycs{providecookingunit}\oarg{symbol}\marg{new-unit-key} -% \end{itemize} +% \item \mycs{declarecookingunit}\oarg{symbol/key-val-list}\marg{unit-key} +% \item \mycs{newcookingunit}\oarg{symbol/key-val-list}\marg{unit-key} +% \item \mycs{providecookingunit}\oarg{symbol/key-val-list}\marg{unit-key} +% \end{itemize} % % \begin{function}{\declarecookingunit,\newcookingunit,\providecookingunit} % \begin{syntax} -% \mycs{declarecookingunit}\oarg{symbol}\marg{unit-key} -% \mycs{newcookingunit}\oarg{symbol}\marg{new-unit-key} -% \mycs{providecookingunit}\oarg{symbol}\marg{unit-key} +% \mycs{declarecookingunit}\oarg{symbol/key-val-list}\marg{unit-key} +% \mycs{newcookingunit}\oarg{symbol/key-val-list}\marg{unit-key} +% \mycs{providecookingunit}\oarg{symbol/key-val-list}\marg{unit-key} % \end{syntax} -% These commands define the unit \meta{unit-key}. If the -% key is not the same as the printed symbol use \oarg{symbol}. -% Note that \meta{unit-key} can neither contain |/| nor |,|. % -% Please note due to the current implementation catcodes may cause -% trouble. For example using |:| inside \meta{unit-key} may cause -% the key to \enquote{not be defined} in the document. If that happens -% try removing or changing the \meta{unit-key}. +% These commands define the unit \meta{unit-key}. Note that \meta{unit-key} +% can neither contain |/| nor |,|; but it is allowed to be a command since v2.00 +% (see examples below). % +% If the key is not the same as the printed symbol use the optional argument. +% It can either contain the symbol you want printed or a key-value list (see below) +% for more advanced adjustments. +% % \mycs{newcookingunit} raises an error if the unit is already defined, % \mycs{declarecookingunit} creates or (if given) overwrites \meta{symbol} % and \mycs{providecookingunit} does nothing if the unit is already % defined. % -% All units have male gender |m| by default. +% All units have male gender |m| by default (unless you change it using a key below). % % Some examples: -% \begin{lstlisting} +% \begin{lstlisting}[commentstyle=\color{black}] % \declarecookingunit{kg} % \declarecookingunit{g} % \declarecookingunit[Msp.] {Msp} % \declarecookingunit[\ensuremath{{}^{\circ}}\kern-\scriptspace C] {C} +% \declarecookingunit{\%} % can use commands now % \end{lstlisting} % % \end{function} +% % \begin{cunote} % The definition of the printed degree Celsius is % copied and pasted from (a maybe older version of) \pkg{siunitx}. % \end{cunote} % +% \begin{function}{symbol, gender, set-option, add-to-group, natural-unit} +% +% \begin{syntax} +% symbol = \marg{symbol} +% gender = \marg{m/f/n} +% set-option = \marg{key-val-list} +% add-to-group = \marg{group} +% natural-unit = \marg{true/false} +% \end{syntax} +% +% Those keys can only be used in the optional argument of +% \mycs{declarecookingunit}, \mycs{newcookingunit} or \mycs{providecookingunit}. +% They can be used to define some properties of the unit during its initialization. +% +% \opt{symbol} allows you to set the printed symbol of the unit. A similar effect can be +% achieved by just using the optional argument. Use this option if you want to +% use other keys during the definition. This symbol is used as a fallback for all +% langauges, if no explicit symbol is found for said langauge. +% +% \opt{gender} sets the gender of the unit (default ist |m|). Allowed is |m|, |f| or |n|. +% Note that this sets the default gender for all languages. +% +% \opt{set-option} allows to add some key-vals to the specific unit which are +% activated once the unit is used. See \cpageref{code:set-option}. +% +% \opt{add-to-group} adds the unit defined to \meta{group}. See \cref{sec:opt:unit-spec} +% for more information. +% +% \opt{natural-unit} is a simple true/false switch. If |true| the unit will be specified to be +% a \enquote{natural-unit}. This is more or less a joke option. +% \end{function} +% % % % \begin{function}{\declarecookingderivatives} @@ -1314,7 +1269,7 @@ and the derived file cooking-units.sty. % \end{syntax} % % \emph{This function is experimental}. Defines new units which are a combination -% of the units given in \meta{unit-list} \emph{and} their linked-units. +% of the units given in \meta{unit-list} \emph{and} their key-chain. % \meta{unit-key}, \meta{mathematical-relation} and \meta{unit-symbol} % accept |#1| to |#n| as arguments with $n$ being the number of units % given in \meta{unit-list}. $n$ \emph{cannot} be greater than $8$ (and it will @@ -1326,91 +1281,97 @@ and the derived file cooking-units.sty. % % \end{function} % -% \begin{cunote} -% Due to catcodes (and my inability to deal with them properly) -% there can be problems when using |:| -% (and probably other signs) inside \meta{unit-key}. -% \end{cunote} -% % \begin{cuexample} % Your homework is to change the unit of energy \si{\kg\m\squared\per\s\squared} % into \si{\ounce\inch\squared\per\minute\squared}. To check if you are correct % you use \mycs{declarecookingderivatives}: % \begin{lstlisting} -% \declarecookingderivatives{kg,m,s}{#1*#2-#3} +% \declarecookingderivatives{kg,m,s}{#1*#2:#3} % { (#1)*(#2)^2/(#3)^2 } {\sfrac{#1\,#2${}^2$}{#3${}^2$}} % \end{lstlisting} % -% Using |\cunum[kg*m-s=oz*in-min]{1}{kg*m-s}| shows that -% \cunum{1}{kg*m-s} is equal to \cunum{196829101.34}{oz*in-min}. -% (Note: This is \emph{really} experimental and it can easily happen that -% an \enquote{overflow-error} occurs) (like for me which is why I hard-coded the -% results after testing). +% Using |\cunum[kg*m:s=oz*in:min]{1}{kg*m:s}| shows that +% \cunum{1}{kg*m:s} is equal to \cunum[kg*m:s=oz*in:min]{1}{kg*m:s}. +%^^A\cunum{196829101.34}{oz*in:min} +% +%^^A \cunum[m:s=km:h]{1}{m:s} % % \end{cuexample} % +% \begin{cunote} +% As this is a bit more experimental and can easily lead to overflow-errors, +% no actual \LaTeX\ keys are created with \mycs{declarecookingderivatives}. +% Internally the keys and possible values are stored in a \emph{huge} property list. +% If an unknown key is encountered, it checks if said key can be found in the +% property list. +% \end{cunote} +% +% +% % % % \section{Defining options to change units} % \label{sec:defining-opt} -% \cookingunitsToDo{Passt.} -% Options (to change units) can be newly defined or added to already existing keys (units) +% +% +% +% Options (to change units) can be newly defined or added to already existing ones % using % \begin{itemize} -% \item \mycs{cudefinekeys} +% \item \mycs{cudefinekeychain} +%^^A \item \mycs{cudefinekeys} % \item \mycs{cudefinesinglekey} -% \item \mycs{cuaddkeys} +% \item \mycs{cuaddtokeychain} +%^^A \item \mycs{cuaddkeys} % \item \mycs{cuaddsinglekeys} -% \item \mycs{cuaddtokeys} +%^^A \item \mycs{cuaddtokeys} % \end{itemize} -% I apologize for the (name) inconsistency between \mycs{cudefinekeys} and -% \mycs{cudefinesinglekey} (although they are named similarly, they work differently). % -% \begin{function}{\cudefinekeys,\cudefinesinglekey} -% \begin{syntax} -% \mycs{cudefinekeys}\marg{unit-key-1} -% \ \ \{ -% \ \ \ \ \marg{unit-key-2} \marg{$1$ unit-key-1 are \dots\ unit-key-2} -% \ \ \ \ \marg{unit-key-3} \marg{$1$ unit-key-1 are \dots\ unit-key-3} -% \ \ \ \ \marg{unit-key-4} \marg{$1$ unit-key-1 are \dots\ unit-key-4} +% +% +% \begin{function}{\cudefinekeychain, \cudefinesinglekey } +% \begin{syntax} +% \mycs{cudefinekeychain} +% \ \ \{ +% \ \ \ \ \marg{unit-key-1} \marg{value} +% \ \ \ \ \marg{unit-key-2} \marg{... unit-key-2 are \meta{value} unit-key-1} +% \ \ \ \ \marg{unit-key-3} \marg{... unit-key-3 are \meta{value} unit-key-1} % \ \ \ \ \dots -% \ \ \} -% +% \ \ \} +% % \mycs{cudefinesinglekey}\marg{unit-key-1} % \ \ \{ % \ \ \ \ \marg{unit-key-2} \marg{$1$ unit-key-2 are \dots\ unit-key-1} % \ \ \ \ \marg{unit-key-3} \marg{$1$ unit-key-3 are \dots\ unit-key-1} % \ \ \ \ \dots % \ \ \} -% \end{syntax} -% +% \end{syntax} % If you define new units (see \cref{sec:def-units}) and cannot add -% them to already existing keys you can use -% \lstinline|\cudefinekeys| or \lstinline|\cudefinesinglekey| respectively to -% define new keys. +% them to already existing keys you may use +% \mycs{cudefinekeychain} or \mycs{cudefinesinglekey} respectively to +% define new key-chains or single keys. +% +% \mycs{cudefinekeychain} collects the unit-key's given and defines a key-chain. +% This allows you to change every unit into every other unit given in the list. +% So \meta{unit-key-1} can take \meta{unit-key-1}, \meta{unit-key-2}, \meta{unit-key-3}, +% \dots\ as values; \meta{unit-key-2} can take \meta{unit-key-1}, \meta{unit-key-2}, +% \meta{unit-key-3}, \dots\ as values, etc. Please note that \meta{\dots} has to +% be a number. % -% \lstinline|\cudefinekeys| takes \marg{unit-key-1} as a -% \enquote{basis}, defines a key with the name \meta{unit-key-1} and -% adds the values \meta{unit-key-1}, \meta{unit-key-2}, -% \meta{unit-key-3}, etc. Furthermore this command also defines the -% keys \meta{unit-key-2}, \meta{unit-key-3}, etc. with the same -% values as \meta{unit-key-1}. Please note that \meta{\dots} has to -% be a number. -% % Sometimes it is not that easy and the conversion of one unit into % another needs are more complicated formula (see for example % temperatures). If that is the case use -% \lstinline|\cudefinesinglekey|. As the name says it defines -% \emph{only} the key \meta{unit-key-1} with the values +% \mycs{cudefinesinglekey}. As the name says it defines +% \emph{only} a single key \meta{unit-key-1} with the values % \meta{unit-key-1}, \meta{unit-key-2}, etc. The advantage of this % command is that now \meta{\dots} can be a formula and the -% numerical input can be placed explicitly using \texttt{\#1}. +% numerical input of \mycs{cunum}, etc.\ can be placed explicitly using \texttt{\#1}. +% \end{function} % % -% \end{function} % -% \begin{cuexample} % +% \begin{cuexample} % This example defines following keys with their respective value: % \begin{itemize} % \item the key \myunit{kg} with the values \myunit{kg}, \myunit{dag}, @@ -1421,8 +1382,6 @@ and the derived file cooking-units.sty. % \myunit{g} and \myunit{oz} % \item the key \myunit{oz} with the values \myunit{kg}, \myunit{dag}, % \myunit{g} and \myunit{oz} -% \item the key \myunit{d} with the values \myunit{d}, \myunit{h}, -% \myunit{min} and \myunit{s} % \item \dots % \end{itemize} % \begin{align*} @@ -1433,22 +1392,41 @@ and the derived file cooking-units.sty. % \SI{1}{\kg}&= \SI{2.204 622 6}{\pound} % \end{align*} % \begin{lstlisting} -% \cudefinekeys {kg} +% \cudefinekeychain % { +% {kg} { 1 } % {dag}{ 100 } %% 1 kg are 100 dag % {g} { 1000 } %% 1 kg are 1000 g % {oz} { 35.27399 } %% 1 kg are 35.27399 oz % {lb} { 2.204 622 6 } %% 1 kg are 2.204 622 6 lb % } % -% \cudefinekeys {d} +% \cudefinekeychain % { +% {d} { 1 } % {h} { 24 } %% 1 day are 24 hours % {min}{ 1440 } %% 1 day are 1440 minutes % {s} { 86400 } %% 1 day are 86400 seconds % } % \end{lstlisting} +% \end{cuexample} +% +% \begin{cunote} +% The value of the first item can be something different from $1$. +% So something like this is also possible: +% \begin{lstlisting} +% \cudefinekeychain +% { +% {kg} { 0.4535924 } +% {dag}{ 45.35924 } +% {g} { 453,5924 } +% {oz} { 16 } +% {lb} { 1 } +% } +% \end{lstlisting} +% \end{cunote} % +% \begin{cuexample} % To convert degree Fahrenheit to degree Celsius, kelvin and degree R\'eamur one % needs the formulas\footnote{See Wikipedia.} % \begin{align*} @@ -1459,7 +1437,7 @@ and the derived file cooking-units.sty. % with $T_F$ being the input temperature in degree Fahrenheit and % $T_C$ being the same temperature in degree Celsius, etc. Using % \lstinline|\cudefinesinglekey| the key \myunit{F} with values -% \myunit{C}, \myunit{K} and \myunit{Re} is defined: +% \myunit{C}, \myunit{K} and \myunit{Re} is defined by: % % \begin{lstlisting} % \cudefinesinglekey {F} @@ -1477,14 +1455,13 @@ and the derived file cooking-units.sty. % % % -% \begin{function}{\cuaddkeys,\cuaddsinglekeys} -% +% \begin{function}{\cuaddtokeychain,\cuaddsinglekeys} % \begin{syntax} -% \mycs{cuaddkeys}\marg{unit-key-1} +% \mycs{cuaddtokeychain} % \ \ \{ -% \ \ \ \ \marg{unit-key-2} \marg{$1$ unit-key-1 are \dots\ unit-key-2} -% \ \ \ \ \marg{unit-key-3} \marg{$1$ unit-key-1 are \dots\ unit-key-3} -% \ \ \ \ \marg{unit-key-4} \marg{$1$ unit-key-1 are \dots\ unit-key-4} +% \ \ \ \ \marg{unit-key-1} \marg{value} +% \ \ \ \ \marg{unit-key-2} \marg{... unit-key-2 are \meta{value} unit-key-1} +% \ \ \ \ \marg{unit-key-3} \marg{... unit-key-3 are \meta{value} unit-key-1} % \ \ \ \ \dots % \ \ \} % @@ -1496,28 +1473,27 @@ and the derived file cooking-units.sty. % \ \ \} % \end{syntax} % -% These commands add \meta{unit-key-2}, etc. to the already defined -% key \meta{unit-key-1}. -% -% \lstinline|\cuaddkeys| takes the already defined key -% \marg{unit-key-1} as a \enquote{basis}, and adds -% \meta{unit-key-2}, \meta{unit-key-3}, etc. to its -% values. Furthermore it adds those new values to other keys linked -% to \meta{unit-key-1} and defines the new keys \meta{unit-key-2}, -% etc.\ with the same values as \meta{unit-key-1}. +% \mycs{cuaddtokeychain} first parses through its unit-list and searches for +% a base unit key which is already in a key-chain +% (aka.\ was defined by \mycs{cudefinekeychain}). The other units, not yet +% part of a key-chain, are added to the same key-chain as the base unit. +% So the newly added units are available as a key and a value for the other +% units in the same key-chain. Note that \meta{...} must be a number. % % % If the conversion is more complicated use % \lstinline|\cuaddsinglekeys|. It adds \meta{unit-key-2}, etc.\ as % values to \meta{unit-key-1}. The numerical input can be placed -% using \myunit{\#1} (see \lstinline|\cudefinesinglekey|). This -% command neither defines new keys nor does it add values to other -% keys than \meta{unit-key-1}. +% using \myunit{\#1} (see \mycs{cudefinesinglekey}). This +% command neither defines new keys nor does it add values to +% keys other than \meta{unit-key-1}. % % % \end{function} % % +% +% % \begin{cuexample} % Suppose you are British (I am sorry, I can't think of another % reason to use those units) and you want to implement 'stone' (yes, @@ -1529,10 +1505,11 @@ and the derived file cooking-units.sty. % latter one. % \begin{lstlisting} % \newcookingunit{st} %% defining new unit 'stone' -% \cuaddkeys{lb} %% adding st to lb (could also add to kg, dag and oz) -% { -% {st} { 1/14 } %% 1 lb are 1/14 st as 14 lb are 1 st -% } +% \cuaddtokeychain +% { +% {lb} { 14 } %% unit already in a key-chain. +% {st} { 1 } %% new unit. 1st = 14lb +% } % \end{lstlisting} % \begin{cuexamplecode} % \cunum[lb=st]{1}{lb} \\ @@ -1544,6 +1521,17 @@ and the derived file cooking-units.sty. % \end{cuexamplecode} % \end{cuexample} % +% \begin{cunote} +% Of course using +% \begin{lstlisting} +% \cuaddtokeychain +% { +% {st} { 1/14 } %% 1lb = 1/14st +% {lb} { 1 } %% unit already in a key-chain. +% } +% \end{lstlisting} +% is also possible +% \end{cunote} % % \begin{cuexample} % Now you want to add degree R{\o}mer and convert Celsius to degree @@ -1555,14 +1543,11 @@ and the derived file cooking-units.sty. % \begin{lstlisting} % %% defining new unit 'degree R{\o}mer' % \newcookingunit [\ensuremath{ {} ^ { \circ } }\kern-\scriptspace R{\o}] {Ro} -% \cuaddsinglekeys {C} %% adds value 'Ro' to 'C'. +% \cuaddsinglekeys {C} %% adds value 'Ro' to key 'C'. % { % {Ro} { #1 * 21/40 + 7.5 } % } -% \cusetup %% round to integer automatically -% { -% set-option-for-Ro = { round-precision = 0 } -% } +% \cusetoptionfor{Ro}{ round-precision = 0 } %% round to integer automatically % \end{lstlisting} % \begin{cuexamplecode} % \cunum{10}{C} \\ @@ -1578,55 +1563,65 @@ and the derived file cooking-units.sty. % % % +% % % -% \begin{function}{\cuaddtokeys} -% \begin{syntax} -% \mycs{cuaddtokeys} \marg{unit-key-1} \marg{unit-key-2} \marg{$1$ unit-key-2 are \dots\ unit-key-1} -% \end{syntax} -% Works similar to \mycs{cuaddkeys} regarding the definition of keys. -% \end{function} % -% \begin{cuexample} -% Continuing the example from before, this time with \lstinline|\cuaddtokeys|: -% \begin{lstlisting} -% \newcookingunit{st} %% defining (again) new unit 'stone' -% \cuaddtokeys {lb} {st} { 14 } %% 1 st are 14 lb -% \end{lstlisting} -% \begin{cuexamplecode} -% \cunum[lb=st]{1}{lb} \\ -% \cunum[st=lb]{1}{st} \\ -% \cunum[st=g]{1}{st} \\ -% \cunum[st=kg]{1}{st} \\ -% \cunum[kg=st]{1}{kg} \\ -% \cunum[st=kg]{16}{st} -% \end{cuexamplecode} -% \end{cuexample} % -% \begin{comment} -% \begin{cuexample} -% Implementation of \myunit{stick}. From https://cooking.stackexchange.com/questions/784/translating-cooking-terms-between-us-uk-au-ca-nz -% we know that -% \[ \SI{1}{\stick} = \SI{0.25}{\lb} \] % -% There are two ways to implement \myunit{stick}: -% either use \mycs{cuaddkeys} or \mycs{cuaddtokeys}. +% \subsection{Obsolete Commands} % -% The easier way (in this case) is \mycs{cuaddtokeys} which is pretty straight forward: -% \begin{lstlisting} -% \cuaddtokeys { lb } { st } { 0.25 } -% \end{lstlisting} -% \dots\ and finished -% -% \end{cuexample} -% \end{comment} +% \begin{function}{cudefinekeys} +% \begin{syntax} +% \mycs{cudefinekeys}\marg{unit-key-1} +% \ \ \{ +% \ \ \ \ \marg{unit-key-2} \marg{$1$ unit-key-1 are \dots\ unit-key-2} +% \ \ \ \ \marg{unit-key-3} \marg{$1$ unit-key-1 are \dots\ unit-key-3} +% \ \ \ \ \marg{unit-key-4} \marg{$1$ unit-key-1 are \dots\ unit-key-4} +% \ \ \ \ \dots +% \ \ \} +% \end{syntax} +% +% \emph{This command is going to be obsolete at one point. It is advised to use +% \mycs{cudefinekeychain} instead.} +% +% \mycs{cudefinekeys} takes \marg{unit-key-1} as a +% \enquote{basis}, defines a key with the name \meta{unit-key-1} and +% adds the values \meta{unit-key-1}, \meta{unit-key-2}, +% \meta{unit-key-3}, etc. Furthermore this command also defines the +% keys \meta{unit-key-2}, \meta{unit-key-3}, etc. with the same +% values as \meta{unit-key-1}. Please note that \meta{\dots} has to +% be a number. +% \end{function} % % % +% \begin{function}{\cuaddkeys,\cuaddtokeys} +% \begin{syntax} +% \mycs{cuaddkeys}\marg{unit-key-1} +% \ \ \{ +% \ \ \ \ \marg{unit-key-2} \marg{$1$ unit-key-1 are \dots\ unit-key-2} +% \ \ \ \ \marg{unit-key-3} \marg{$1$ unit-key-1 are \dots\ unit-key-3} +% \ \ \ \ \marg{unit-key-4} \marg{$1$ unit-key-1 are \dots\ unit-key-4} +% \ \ \ \ \dots +% \ \ \} +% +% \mycs{cuaddtokeys} \marg{unit-key-1} \marg{unit-key-2} \marg{$1$ unit-key-2 are \dots\ unit-key-1} +% \end{syntax} % +% \emph{Those commands are going to be obsolete at one point. It is advised to use +% \mycs{cuaddtokeychain} instead.} % % +% \lstinline|\cuaddkeys| takes the already defined key +% \marg{unit-key-1} as a \enquote{basis}, and adds +% \meta{unit-key-2}, \meta{unit-key-3}, etc. to its +% values. Furthermore it adds those new values to other keys linked +% to \meta{unit-key-1} and defines the new keys \meta{unit-key-2}, +% etc.\ with the same values as \meta{unit-key-1}. % +% Works similar to \mycs{cuaddkeys} regarding the definition of keys. +% \end{function} % % % @@ -1636,7 +1631,7 @@ and the derived file cooking-units.sty. % % \section{Language support} % \label{sec:language} -% \cookingunitsToDo{Passt.} +% % % Unit names and symbols depend on the language. To change the % name and symbol for given language you can use \lstinline|\cudefinename|; @@ -1658,11 +1653,10 @@ and the derived file cooking-units.sty. % you may also use the keys \opt{one(m)}, \opt{one(f)} and % \opt{one(n)}. Integers below a certain % value (see option \opt{use-numerals-below}) are written-out. The -% only problem is the written-out \enquote{1} mostly depends on the +% problem is that the written-out \enquote{1} depends on the % gender of the word following (e.g. \enquote{ein Baum} (m), -% \enquote{eine Pflanze} (f) and \enquote{ein Auto} (n)). To set the -% written-out \enquote{1} to be correct with the gender of the used unit, use -% these keys (see also examples below) +% \enquote{eine Pflanze} (f) and \enquote{ein Auto} (n)). Use those keys +% to set the specific gender of \enquote{1} (see also examples below). % \end{function} % % \begin{function}{\cudefinename} @@ -1688,7 +1682,7 @@ and the derived file cooking-units.sty. % \lstinline|\Cutext| is equal to $1$. % % \meta{gender} can be \texttt{m} (maskulin), \texttt{f} (feminin) or -% \texttt{n} (neutrum). If not given \texttt{m} is used as default. +% \texttt{n} (neutrum). If not given, \texttt{m} is used as default. % \end{function} % % \begin{lstlisting} @@ -1807,7 +1801,7 @@ and the derived file cooking-units.sty. % % Each language has synonyms for certain (integer) numbers. This package % supports those phrases and they can be implemented with the following -% command and used by \mycs{cuam}: +% command to be used by \mycs{cuam}: % % \begin{function}{\cudefinephrase} % \begin{syntax} @@ -1821,11 +1815,12 @@ and the derived file cooking-units.sty. % % This command pairs for a given \marg{Language} (see package \pkg{translations}) % the number \marg{integer-1} -% with \marg{phrase-1} (\& plural and gender). The package then checks if the amount +% with \marg{phrase-1} (\& \meta{phrase-1-plural} and \meta{gender-1}). +% Afterwards the package can check if an amount % given in \mycs{cuam} is either this number or a \emph{multiple} of it. % % If the behavior of checking for a multiple is not wanted, you can use the optional -% star \texttt{*} for a given \marg{integer} +% star \texttt{*}. % % \meta{gender} can be \opt{m}, \opt{f} or \opt{n}. It is \opt{m} by default. % @@ -1833,9 +1828,6 @@ and the derived file cooking-units.sty. % the phrase with the highest number is used (if used at all). % % Furthermore, it chooses star (|*|) phrases over non-star phrases. -% \begin{cunote} -% Numbers with the optional star |*| are stored as negative numbers. -% \end{cunote} % \end{function} % \begin{cuexample} % The following example creates some phrases for the language @@ -1857,17 +1849,20 @@ and the derived file cooking-units.sty. % } % \end{lstlisting} % Let's just use them (german language activated!): -% \begin{myde} +%^^A \begin{myde} % \begin{cuexamplecode} +% \selectlanguage{ngerman} @ % \cusetup{use-phrases=true} @ % \cuam{12} \\ % \cuam{24} \\ +% \cuam{25} \\ % \cuam{60} \\ % \cuam{120} \\ +% \cuam{121} \\ % \cuam{6} \\ % \cuam{18} % \end{cuexamplecode} -% \end{myde} +%^^A \end{myde} % % As you can see, \enquote{Schock} ($60$) is preferred over \enquote{Dutzend} ($12$) % as it linked to the higher number. Furthermore, for $6$ the phrase \enquote{halbes @@ -1880,7 +1875,6 @@ and the derived file cooking-units.sty. % \section{Options} % \label{sec:options} % -% \cookingunitsToDo{Done. Passr.} % % Options in \pkg{cooking-units} can mostly be set globally using % \lstinline|\cusetup| or locally using the optional argument of the @@ -1897,7 +1891,7 @@ and the derived file cooking-units.sty. % % % \begin{function}{\cusetoptionfor,\cuaddoptionfor,\cuclearoptionfor} -% +% \label{code:set-option} % \begin{syntax} % \mycs{cusetoptionfor}\marg{unit-list}\marg{options} % \mycs{cuaddoptionfor}\marg{unit-list}\marg{options} @@ -2044,7 +2038,7 @@ and the derived file cooking-units.sty. % \mycs{cudeclareunitgroup} \marg{group-name} \marg{unit-list} % \end{syntax} % Defines the group \meta{group-name} containing the list \meta{unit-list}. -% This allows the usage of |\meta{group-name}=\meta{unit-key}| to +% This allows the usage of \texttt{\meta{group-name}=\meta{unit-key}} to % change all units in the group \meta{group-name} to \meta{unit-key} % (which has to be part of \meta{unit-list}). % \end{function} @@ -2090,33 +2084,34 @@ and the derived file cooking-units.sty. % \ \dots % \ \} % \end{syntax} +% \emph{This option is going to be obsolete at one point.} % Adds each \meta{unit-key} in \meta{unit-keys-list} to \meta{group}. % The key-val equivalent of \mycs{cuaddtounitgroup}. % \end{function} -% \begin{cuexample} -% The same as above: -% This example adds the unit \myunit{st} to the group \mygroup{weight} -% and \myunit{Ro} to \mygroup{temperature}. -% \begin{lstlisting} -% \cusetup -% { -% add-unit-to-group = { weight = {st} , temperature = {Ro} } -% } -% \end{lstlisting} -% -% \cusetup{ add-unit-to-group = { weight = {st} } } -% -% \begin{cuexamplecode} -% \cusetup{weight=g} @ -% \cunum{1}{kg} \\ -% \cunum{1}{dag} \\ -% \cunum{1}{g} \\ -% \cunum{1}{oz} \\ -% \cunum{1}{lb} \\ -% \cunum{1}{stick} \\ -% \cunum{1}{st} -% \end{cuexamplecode} -% \end{cuexample} +%^^A \begin{cuexample} +%^^A The same as above: +%^^A This example adds the unit \myunit{st} to the group \mygroup{weight} +%^^A and \myunit{Ro} to \mygroup{temperature}. +%^^A \begin{lstlisting} +%^^A \cusetup +%^^A { +%^^A add-unit-to-group = { weight = {st} , temperature = {Ro} } +%^^A } +% ^^A\end{lstlisting} +%^^A +%^^A \cusetup{ add-unit-to-group = { weight = {st} } } +%^^A +%^^A \begin{cuexamplecode} +%^^A \cusetup{weight=g} @ +%^^A \cunum{1}{kg} \\ +%^^A \cunum{1}{dag} \\ +%^^A \cunum{1}{g} \\ +%^^A \cunum{1}{oz} \\ +%^^A \cunum{1}{lb} \\ +%^^A \cunum{1}{stick} \\ +%^^A \cunum{1}{st} +%^^A \end{cuexamplecode} +%^^A \end{cuexample} % % % @@ -2125,6 +2120,7 @@ and the derived file cooking-units.sty. % set-option-for-\meta{unit-key} = \marg{ key1 = value1, \dots\ } % add-option-for-\meta{unit-key} = \marg{ key1 = value1, \dots\ } % \end{syntax} +% \emph{This option is going to be obsolete at one point.} % Sets and adds \meta{key1=value1,\dots} to a specific % \meta{unit-key}, % \opt{erase-all-options} (see below) is used to erase all options for all @@ -2147,24 +2143,23 @@ and the derived file cooking-units.sty. % % \end{function} % -% \begin{cuexample} -% The following rounds the values to integers for \myunit{F}, \myunit{C}, -% \myunit{K} and \myunit{Re}: -% \begin{lstlisting} -% \cusetup -% { -% set-option-for-F = { round-precision = 0 } , -% set-option-for-C = { round-precision = 0 } , -% set-option-for-K = { round-precision = 0 } , -% set-option-for-Re = { round-precision = 0 } -% } -% \end{lstlisting} -% although note that it would be easier to simply write -% \begin{lstlisting} -% \cusetoptionfor {F,C,K,Re} { round-precision = 0 } -% \end{lstlisting} -% -% \end{cuexample} +%^^A \begin{cuexample} +%^^A The following rounds the values to integers for \myunit{F}, \myunit{C}, +%^^A \myunit{K} and \myunit{Re}: +%^^A \begin{lstlisting} +%^^A \cusetup +%^^A { +%^^A set-option-for-F = { round-precision = 0 } , +%^^A set-option-for-C = { round-precision = 0 } , +%^^A set-option-for-K = { round-precision = 0 } , +%^^A set-option-for-Re = { round-precision = 0 } +%^^A } +%^^A \end{lstlisting} +%^^A although note that it would be easier to simply write +%^^A \begin{lstlisting} +%^^A \cusetoptionfor {F,C,K,Re} { round-precision = 0 } +%^^A \end{lstlisting} +%^^A \end{cuexample} % % % \begin{function}{set-option-for, add-option-for} @@ -2182,6 +2177,7 @@ and the derived file cooking-units.sty. % \ \dots % \ \} % \end{syntax} +% \emph{This option is going to be obsolete at one point.} % Sets/adds each \meta{keys=vals} to the specific \meta{unit-key}. Works pretty much % the same way their \opt{set-option-for-\meta{unit-key}} and % \opt{add-option-for-\meta{unit-key}} counterparts. @@ -2190,27 +2186,28 @@ and the derived file cooking-units.sty. % \mycs{cuaddoptionfor}. % \end{function} % -% \begin{cuexample} -% The following example does the same as the example above: -% \begin{lstlisting} -% \cusetup -% { -% set-option-for = -% { -% F = { round-precision = 0 } , -% C = { round-precision = 0 } , -% K = { round-precision = 0 } , -% Re = { round-precision = 0 } -% } -% } -% \end{lstlisting} -% \end{cuexample} +%^^A \begin{cuexample} +%^^A The following example does the same as the example above: +%^^A \begin{lstlisting} +%^^A \cusetup +%^^A { +%^^A set-option-for = +%^^A { +%^^A F = { round-precision = 0 } , +%^^A C = { round-precision = 0 } , +%^^A K = { round-precision = 0 } , +%^^A Re = { round-precision = 0 } +%^^A } +%^^A } +%^^A \end{lstlisting} +%^^A \end{cuexample} % % \begin{function}{erase-all-options, erase-all-options-for} % \begin{syntax} % erase-all-options % erase-all-options-for = \marg{unit-key1, unit-key2, \dots} % \end{syntax} +% \emph{This option is going to be obsolete at one point.} % Erase options added to units. \opt{erase-all-options} erases all options % for \emph{all} \meta{unit-key}s. % @@ -2222,18 +2219,18 @@ and the derived file cooking-units.sty. % % \end{function} % -% \begin{cuexample} -% The following code erases all attached options from \myunit{C}, \myunit{F}, -% \myunit{K} and \myunit{Re}: -% -% \begin{lstlisting} -% \cusetup{ erase-all-options-for = {C, F, K, Re} } -% \end{lstlisting} -% It's the same as -% \begin{lstlisting} -% \cuclearoptionfor {C, F, K, Re} -% \end{lstlisting} -% \end{cuexample} +%^^A \begin{cuexample} +%^^A The following code erases all attached options from \myunit{C}, \myunit{F}, +%^^A \myunit{K} and \myunit{Re}: +%^^A +%^^A \begin{lstlisting} +%^^A \cusetup{ erase-all-options-for = {C, F, K, Re} } +%^^A \end{lstlisting} +%^^A It's the same as +%^^A \begin{lstlisting} +%^^A \cuclearoptionfor {C, F, K, Re} +%^^A \end{lstlisting} +%^^A \end{cuexample} % % % @@ -2395,7 +2392,8 @@ and the derived file cooking-units.sty. % \begin{syntax} % set-cutext-translation-message = \meta{error/warning/none} % \end{syntax} -% If a translation for \cCutext\ is not available the commands are replaced +% If a translation for \cCutext\ is not available for the language, +% the commands are replaced % by \mycs{cunum}. Currently -- if this is happening -- a warning is shown, % you may change the behavior of the message (error, warning or not showing at all) % using this option. @@ -2406,14 +2404,14 @@ and the derived file cooking-units.sty. % print-numerals = \meta{true/false} % \end{syntax} % -% Prints numerals for integers smaller then \opt{use-numerals-below} if +% Prints numerals for integers smaller than \opt{use-numerals-below} if % set to \true. If set to \false\ no numerals are printed. % % If you use the package option \opt{use-fmtcount-numerals} this option % is automatically set to \true. % % If you want to use another package, just set this option to \true\ and -% use \opt{numeral-function} and \opt{Numeral-function}. +% use \opt{numeral-function} and \opt{Numeral-function}). % %^^A If the package option \opt{use-fmtcount-numerals} is set to \true\ you can %^^A deactivate the printing of numerals by setting \opt{print-numerals} to @@ -2526,7 +2524,7 @@ and the derived file cooking-units.sty. % % % -% \begin{function}{range-sign} +% \begin{function}{range-sign, cunum-range-sign, cutext-range-sign} % \begin{syntax} % range-sign = \marg{string} % cunum-range-sign = \marg{string} @@ -2542,7 +2540,7 @@ and the derived file cooking-units.sty. % The default for \meta{string} is \texttt{-{}-} (for both). % \end{function} % -% Since version 1.45 there also exits the language symbol \opt{cutext-range-sign} +% Since version 1.45 there also exists the language symbol \opt{cutext-range-sign} % (see \cref{sec:language}). If the \emph{option} \opt{cutext-range-sign} is set % the language symbol will be ignored. % @@ -2583,9 +2581,10 @@ and the derived file cooking-units.sty. % \end{function} % % \begin{cuexample} -% \begin{myde} +%^^A \begin{myde} % For the German language: % \begin{cuexamplecode} +% \selectlanguage{ngerman} @ % \cuam{12} \\ % \cuam{12--24} \\ % \cuam{36} \\ @@ -2598,7 +2597,7 @@ and the derived file cooking-units.sty. % \cuam{12--24} \\ % \cuam{36} \\ % \end{cuexamplecode} -% \end{myde} +%^^A \end{myde} % \end{cuexample} % % @@ -2610,8 +2609,7 @@ and the derived file cooking-units.sty. % \end{syntax} % Rounds the amount automatically to \meta{integer} digits after the % colon. Note that units like \myunit{C}, \myunit{F}, \myunit{K} and -% \myunit{Re} are still rounded to integers due to -% \texttt{set-option-for-}. +% \myunit{Re} are still rounded to integers due to \mycs{cusetoptionfor}. % \end{function} % % @@ -2631,7 +2629,7 @@ and the derived file cooking-units.sty. % \end{cuexamplecode} % % \begin{cunote} -% Also negative numbers are allowed. +% Negative numbers are also allowed. % \begin{cuexamplecode} % \cusetoptionfor{C,F}{round-precision=-1} @ % \cunum{-271,2}{C} \\ @@ -2710,7 +2708,7 @@ and the derived file cooking-units.sty. % \cunum{1_1/2}{kg} \\ % \cunum[kg=g]{1_1/2}{kg} \\ % \cunum[kg=g]{-1_1/2}{kg} \\ -% \cunum[kg=g]{1_?/2}{kg} \\ +% \cunum[kg=g]{1_2/?}{kg} \\ % \end{cuexamplecode} % % @@ -2731,7 +2729,7 @@ and the derived file cooking-units.sty. % \cunum[kg=g]{1/3}{kg} \\ % \cunum{1_1/2}{kg} \\ % \cunum[kg=g]{1_1/2}{kg} \\ -% \cunum[kg=g]{1_?/2}{kg} \\ +% \cunum[kg=g]{1_?/3}{kg} \\ % \end{cuexamplecode} % % @@ -2813,13 +2811,12 @@ and the derived file cooking-units.sty. % cutext-space = \marg{string} % \end{syntax} % \meta{string} is inserted between the numeral part and the unit part -% when using \cCutext. By default it is set to \cs{space}. Use this option -% if you want to e.g.\ insert an unbreakable space. +% when using \cCutext. By default it is set an unbreakable space |~|. % \end{function} % \begin{cuexamplecode} % \cutext{1}{kg}\\ % \Cutext{10}{kg}\\ -% \cusetup { cutext-space = ~ } @ +% \cusetup { cutext-space = \space } @ % \cutext{1}{kg}\\ % \Cutext{10}{kg}\\ % \cusetup { cutext-space = {} } @ @@ -2836,16 +2833,17 @@ and the derived file cooking-units.sty. % phrase-space = \marg{string} % \end{syntax} % \meta{string} is inserted between the numeral part and the phrase part -% while using \mycs{cuam}. By default it is set to \cs{space}. Use this option -% if you want to e.g.\ insert an unbreakable space. +% while using \mycs{cuam}. By default it is set to the unbreakable space |~|. Use this option +% if you want to e.g.\ insert a normal space. % \end{function} -% \begin{myde} +%^^A \begin{myde} % \cusetup{use-phrases=true} % (Switching to german) % \begin{cuexamplecode} +% \selectlanguage{ngerman} @ % \cuam{12}\\ % \cuam{144}\\ -% \cusetup { phrase-space = ~ } @ +% \cusetup { phrase-space = \space } @ % \cuam{12}\\ % \cuam{144}\\ % \cusetup { phrase-space = {} } @ @@ -2856,7 +2854,7 @@ and the derived file cooking-units.sty. % \cuam{144}\\ % \end{cuexamplecode} % \cusetup{use-phrases=false} -% \end{myde} +%^^A \end{myde} % % \begin{function}{amount-unit-space} % \begin{syntax} @@ -2909,32 +2907,31 @@ and the derived file cooking-units.sty. % \curef{anotherrecipe}~persons \\ % \cunum{1}{kg}\\ % \cuam{1}\\ -% \cutext{1}{kg}\\ -% \curef{anotherrecipe}~persons \\ @ +% \Cutext[ref=anotherrecipe]{10}{kg}\\ +% & % \cusetup{ recalculate-amount = true } @ % \curef{anotherrecipe}~persons \\ % \cunum{1}{kg}\\ % \cuam{1}\\ -% \cutext{1}{kg}\\ -% \Cutext[ref=anotherrecipe]{10}{kg}\\ @ -% \cusetup { set-number-of-persons = 3 } @ +% \Cutext[ref=anotherrecipe]{10}{kg}\\ +% & +% \cusetup { set-number-of-persons = 3 } @ % \curef{anotherrecipe}~persons \\ -% \cunum{1}{kg}\\ -% \cuam{1}\\ -% \cutext{1}{kg}\\ -% \Cutext[ref=anotherrecipe]{10}{kg}\\ @ +% \cunum{1}{kg} \\ +% \cuam{1} \\ +% \Cutext[ref=anotherrecipe]{10}{kg}\\ +% & % \cusetup { set-number-of-persons = 2 } @ % \curef{anotherrecipe}~persons \\ % \cunum{1}{kg}\\ % \cuam{1}\\ -% \cutext{1}{kg}\\ -% \Cutext[ref=anotherrecipe]{10}{kg}\\ @ +% \cutext{10}{kg}\\ +% & % \cusetup { set-number-of-persons = 1 } @ -% \curef{anotherrecipe}~person \\ +% \curef{anotherrecipe}~persons \\ % \cunum{1}{kg}\\ -% \cuam{1}\\ -% \cutext{1}{kg}\\ -% \Cutext[ref=anotherrecipe]{10}{kg}\\ +% \cuam{1}\\ +% \Cutext[ref=anotherrecipe]{10}{kg}\\ % \end{cuexamplecode} % % @@ -2972,7 +2969,7 @@ and the derived file cooking-units.sty. % \curef{Schinken} \\ % \cusetup { recalculate-amount = true } @ % \cusetup{get-label=Schinken} \\ -% \curef{Schinken} \\ +% \curef{Schinken} % \end{cuexamplecode} % % \begin{cunote} @@ -3124,7 +3121,7 @@ and the derived file cooking-units.sty. % Converts (nearly) every unit in \cref{tab:def-units} % to electron volt or the respective derivative (if possible). Note that this % option is: -% a) experimental and probably will forever be and b) just a joke, you are not +% a) experimental and probably will forever be and (b) just a joke, you are not % supposed to use this units in a cookery book (and as you see this package % doesn't support the arrangement of such huge numbers). Also you may % want to check the values if you really want to use them, just to be sure @@ -3143,6 +3140,7 @@ and the derived file cooking-units.sty. % \cunum{1}{s} % \end{cuexamplecode} % +% % \begin{function}{add-natural-unit} % \begin{syntax} % add-natural-unit = \meta{unit-key} @@ -3167,12 +3165,39 @@ and the derived file cooking-units.sty. % \cunum[kg=g]{1}{kg} \\ % \cunum{1.5}{J} \\ % \cunum{180}{C} \\ -% \cunum{15}{s} +% \cunum{15/4}{s} \\ +% \cunum{1--2}{min} \\ +% \cunum{?}{l} % \end{cuexamplecode} % % +% \begin{function}{nothing-special, going-bonkers, fully-bonkers, xD-lol} +% \begin{syntax} +% nothing-special = \meta{true/false} +% going-bonkers = \meta{true/false} +% fully-bonkers = \meta{true/false} +% xD-lol = \meta{true/false} +% \end{syntax} +% Options that do \dots\ stuff. The four stages of madness in option for. +% +% \begin{description} +% \item[nothing-special] is your default. The package behaves as intended. +% +% \item[going-bonkers] is a bit more strange. It converts an unit into another random unit +% (if it can) and does so throughout the document. So if |unit-A| is converted +% into |unit-B|, it is going to be converted this way the entire document through. +% For an unit to be converted it must have a key, see \cref{sec:defining-opt}. +% % +% \item[fully-bonkers] converts one unit into another random unit (if it can) and does so for +% each unit it encounters. So |unit-A| might be converted into |unit-B| the first time, +% but |unit-C| the second. Each conversion picks a random unit for the conversion +% (but the conversion itself makes sense, e.g.\ |kg| into |g|, but not into |cm|). % +% \item[xD-lol] is pure insanity. A unit is transformed into another, if it makes sense +% or not, and its value is replaced by a random number. +% \end{description} +% \end{function} % % % @@ -3222,6 +3247,7 @@ and the derived file cooking-units.sty. %\clearpage % % \section{Bens Einheitensammelsurium (Bens unit Almanac)} +% \label{sec:unit-almanac} % % Units are a fascinating mess. There are so many different ones which are different and % the few ones which are the same (in name at least) are \emph{also} different, depending on @@ -3246,21 +3272,6 @@ and the derived file cooking-units.sty. % am not including units which I found in the internet is that I would like to % see those units in their \enquote{natural environment}. % -% \begin{comment} -% \begin{tabular}{lllllll} -% \toprule -% unit & original & abréviation & type & source \\ \midrule -% -% Batman & & & weight\\ -%^^A Rottel\txtupde & Sicilian: \emph{rotolo} && length & \cite{Gattopardo}\\ -%^^A Rute\txtupde & Sicilian: \emph{canna} & & weight & \cite{Gattopardo}\\ -% rotolo\txtupsic & Rottel\txtupde && length & \cite{Gattopardo}\\ -% canna\txtupsic & rod\txtupen, Rute\txtupde & & weight & \cite{Gattopardo}\\ -% \bottomrule -% \end{tabular} -% -% {\footnotesize \txtupde German } -% \end{comment} % % \begin{description} % @@ -3355,13 +3366,6 @@ and the derived file cooking-units.sty. % \end{description} % % -% \begin{comment} -% Fun Wikipedia articles: -% \begin{itemize} -% \item Old Austrian units: https://en.wikipedia.org/wiki/Obsolete_Austrian_units_of_measurement -% \end{itemize} -% \end{comment} -% % % % @@ -3525,8 +3529,8 @@ and the derived file cooking-units.sty. %\end{center} % % -% -% +% If you ever encounter in a german cookery book the word \enquote{Packerl}, +% check out its entry in \cref{sec:unit-almanac}. % % % @@ -3657,7 +3661,7 @@ and the derived file cooking-units.sty. % % % -% \end{documentation} +%\end{documentation} % % % @@ -3699,14 +3703,14 @@ and the derived file cooking-units.sty. % \begin{macrocode} \ProvidesExplPackage {cooking-units} - {2020/01/13} - {1.46} + {2021/05/16} + {2.00} {Ein Paket fuer Kocheinheiten} % \end{macrocode} % % Checking if \pkg{expl3} is up-to-date, otherwise abort the loading of the package. % \begin{macrocode} -\@ifpackagelater { expl3 } { 2018/08/23 } +\@ifpackagelater { expl3 } { 2021/05/07 } { } { \PackageError { cooking-units } { Support~package~expl3~too~old } @@ -3727,7 +3731,7 @@ and the derived file cooking-units.sty. % % Checking if \pkg{translations} is up-to-date, otherwise abort the loading of the package. % \begin{macrocode} -\@ifpackagelater { translations } { 2017/08/31 } +\@ifpackagelater { translations } { 2021/01/17 } { } { \PackageError { cooking-units } { Support~package~translations~too~old } @@ -3748,6 +3752,12 @@ and the derived file cooking-units.sty. Please \ replace \ the \ option. \msg_see_documentation_text:n { cooking-units } } +\msg_new:nnnn { cooking-units } { key-unknown } + { The~key~'#1'~is~unknown~and~is~being~ignored. } + { + The~module~'#2'~does~not~have~a~key~called~'#1'.\\ + Check~that~you~have~spelled~the~key~name~correctly. + } % \end{macrocode} % \begin{macrocode} \bool_new:N \g_@@_opt_numeral_bool @@ -3761,6 +3771,9 @@ and the derived file cooking-units.sty. use-numerals .default:n = { false }, use-fmtcount-numerals .bool_gset:N = \g_@@_opt_numeral_bool , use-fmtcount-numerals .default:n = { false }, + unknown .code:n = { \msg_error:nnxx { cooking-units } { key-unknown } + { \l_keys_path_str } { cooking-units } + } } % \end{macrocode} % Now process the package options \dots @@ -3778,9 +3791,9 @@ and the derived file cooking-units.sty. use-numerals .code:n = { \msg_warning:nnnn { cooking-units } { Option-deprecated } { use-numerals } { use-fmtcount-numerals } - \msg_error:nnn { cooking-units } { load-time-option } { fmtcount } + \msg_error:nnn { cooking-units } { load-time-option } { use-fmtcount-numerals } } , - use-fmtcount-numerals .code:n = { \msg_error:nnn { cooking-units } { load-time-option } { fmtcount } } , + use-fmtcount-numerals .code:n = { \msg_error:nnn { cooking-units } { load-time-option } { use-fmtcount-numerals } } , } % \end{macrocode} % @@ -3788,33 +3801,28 @@ and the derived file cooking-units.sty. % % \subsection {Defining Variables} % -% \begin{macro} -% { -% \tl_replace_all:NVn, -% \tl_replace_once:NVn , -% \tl_if_in:nVTF , -% \tl_if_in:NVTF , -% \tl_if_in:NVT , -% \fp_compare:vNnT , -% \prop_get:cVc , -% \tl_set_rescan:NnV, -% \msg_error:nnnV, \msg_error:nnV, \msg_warning:nnV, -% \prop_put:cnx -% } +% \begin{macro} { cs variants } % Some variations of commands we will need later. % \begin{macrocode} +\cs_generate_variant:Nn \msg_redirect_name:nnn { nnV } \cs_generate_variant:Nn \tl_replace_all:Nnn { NVn } \cs_generate_variant:Nn \tl_replace_once:Nnn { NVn } \cs_generate_variant:Nn \tl_if_in:nnTF { nV } \cs_generate_variant:Nn \tl_if_in:NnTF { NVTF } \cs_generate_variant:Nn \tl_if_in:NnT { NVT } \cs_generate_variant:Nn \fp_compare:nNnT { vNnT } -\cs_generate_variant:Nn \prop_get:NnN { cVc } +\cs_generate_variant:Nn \prop_get:NnN { cVc, Nnc } +\cs_generate_variant:Nn \prop_get:NnNF { Nnc } \cs_generate_variant:Nn \tl_set_rescan:Nnn { NnV } \cs_generate_variant:Nn \msg_error:nnnn { nnnV } \cs_generate_variant:Nn \msg_error:nnn { nnV } \cs_generate_variant:Nn \msg_warning:nnn { nnV } \cs_generate_variant:Nn \prop_put:Nnn { cnx } +\cs_generate_variant:Nn \seq_remove_all:Nn { NV } +\cs_generate_variant:Nn \prop_gput:Nnn { Nnv, Nxv } +\cs_generate_variant:Nn \prop_get:NnN { cnc } +\cs_generate_variant:Nn \prg_new_conditional:Npnn { c } +\cs_generate_variant:Nn \text_uppercase:n { x } % \end{macrocode} % \end{macro} % @@ -3828,11 +3836,22 @@ and the derived file cooking-units.sty. % \end{macrocode} % \end{macro} % -% \begin{macro}{\@@_set_amount:Nn,\@@_set_unit:Nn} +% \begin{macro}{\l_@@_unit_argument_spec_tl , \l_@@_unit_argument_spec_tl } % Allows for potential parsing of amount and or unit. % \begin{macrocode} +\tl_new:N \l_@@_unit_argument_spec_tl +\tl_new:N \l_@@_expand_amount_tl +\tl_set:Nn \l_@@_unit_argument_spec_tl { n } +\tl_set:Nn \l_@@_expand_amount_tl { n } +% \end{macrocode} +% \end{macro} +% \begin{macro}{\@@_set_amount:Nn , \@@_set_unit:Nn , \@@_to_unit:n } +% Definitions to set the amount and the unit. Made so that it can be changed globally. +% By default, the amount is just taken as is while the unit is changed into a string. +% \begin{macrocode} \cs_new_eq:NN \@@_set_amount:Nn \tl_set:Nn -\cs_new_eq:NN \@@_set_unit:Nn \tl_set:Nn +\cs_new_eq:NN \@@_set_unit:Nn \str_set:Nn +\cs_new_eq:NN \@@_to_unit:n \tl_to_str:n % \end{macrocode} % \end{macro} % @@ -3849,6 +3868,8 @@ and the derived file cooking-units.sty. \cs_set_eq:NN \@@_print_numeral:n \numberstringnum \cs_set_eq:NN \@@_print_Numeral:n \Numberstringnum } +\cs_generate_variant:Nn \@@_print_numeral:n { V } +\cs_generate_variant:Nn \@@_print_Numeral:n { V } % \end{macrocode} % \end{macro} % @@ -3878,39 +3899,60 @@ and the derived file cooking-units.sty. % \end{macrocode} % \end{macro} % -% +% \begin{macro} { \g_@@_convert_bonkers_remember_prop , \g_@@_convert_to_eV_remember_prop } +% If the unit is changed in a \enquote{not normal} way, store +% some things in one of the two lists. They are just used as shortcuts +% to remember which unit is changed into which. They are one level above +% |\g_@@_master_changer_prop|. +% \begin{macrocode} +\prop_new:N \g_@@_convert_to_eV_remember_prop +\prop_new:N \g_@@_convert_bonkers_remember_prop +% \end{macrocode} +% \end{macro} % % \begin{macro} % { -% \l_@@_number_tmpa_tl, -% \l_@@_number_tmpb_tl, -% \l_@@_mixed_fraction_tl, -% \l_@@_original_amount_tl, -% \l_@@_original_unit_tl, -% \l_@@_option_unit_tl, -% \l_@@_language_tl, -% \l_@@_cunum_range_sign_tl, -% \l_@@_cutext_range_sign_tl, -% \l_@@_value_unit_space_tl, -% \l_@@_input_digits_tl , -% \l_@@_input_decimal_mark_tl, -% \l_@@_input_value_signs_tl, -% \l_@@_input_allowed_special_signs_tl , -% \g_@@_input_str_hash_one_tl , -% \l_@@_input_range_sign_tl, -% \l_@@_cutext_space_tl, -% \l_@@_cuphrase_space_tl, -% \l_@@_translation_tmpa_tl, -% \l_@@_cutext_last_value_tl, -% \l_@@_phantom_tl, -% \l_@@_phrase_phrase_tl, -% \l_@@_unit_letter_not_allowed_tl, -% \l_@@_input_fraction_sign_tl, -% \l_@@_input_mixed_fraction_sign_tl, -% \l_@@_list_of_units_tl, -% \l_@@_list_of_values_tl, -% \l_@@_cunum_hook_tl , \l_@@_cutext_hook_tl , -% \l_@@_Cutext_hook_tl , \l_@@_cuam_hook_tl +% , \l_@@_number_tmpa_tl +% , \l_@@_number_tmpb_tl +% , \l_@@_mixed_fraction_tl +% , \l_@@_original_amount_tl +% , \l_@@_original_unit_tl +% , \l_@@_option_unit_tl +% , \l_@@_language_tl +% , \l_@@_cunum_range_sign_tl +% , \l_@@_cutext_range_sign_tl +% , \l_@@_value_unit_space_tl +% , \l_@@_input_digits_tl +% , \l_@@_input_decimal_mark_tl +% , \l_@@_input_value_signs_tl +% , \l_@@_input_allowed_special_signs_tl +% , \g_@@_input_str_hash_one_tl +% , \l_@@_input_range_sign_tl +% , \l_@@_cutext_space_tl +% , \l_@@_cutext_numeral_space_tl +% , \l_@@_cuphrase_space_tl +% , \l_@@_translation_tmpa_tl +% , \l_@@_cutext_last_value_tl +% , \l_@@_phantom_tl +% , \l_@@_phrase_text_tl +% , \l_@@_unit_letter_not_allowed_tl +% , \l_@@_input_fraction_sign_tl +% , \l_@@_input_mixed_fraction_sign_tl +% , \l_@@_list_of_units_tl +% , \l_@@_list_of_values_tl +% , \l_@@_allwed_integer_math_operators_tl +% , \l_@@_curr_group_tl +% , \l_@@_curr_unit_tl +% , \l_@@_cmd_hook_tl +% , \l_@@_cunum_hook_tl +% , \l_@@_cutext_hook_tl +% , \l_@@_Cutext_hook_tl +% , \l_@@_cuam_hook_tl +% , \l_@@_new_key_base_tl +% , \l_@@_decided_unit_tl +% , \l_@@_stored_units_tl +% , \l_@@_stored_formula_tl +% , \l_@@_base_tl % } % Quite a lot of tl's. % \begin{macrocode} @@ -3931,18 +3973,28 @@ and the derived file cooking-units.sty. \tl_new:N \g_@@_input_str_hash_one_tl \tl_new:N \l_@@_input_range_sign_tl \tl_new:N \l_@@_cutext_space_tl +\tl_new:N \l_@@_cutext_numeral_space_tl \tl_new:N \l_@@_cuphrase_space_tl \tl_new:N \l_@@_translation_tmpa_tl \tl_new:N \l_@@_cutext_last_value_tl \tl_new:N \l_@@_phantom_tl -\tl_new:N \l_@@_phrase_phrase_tl +\tl_new:N \l_@@_phrase_text_tl \tl_new:N \l_@@_unit_letter_not_allowed_tl \tl_new:N \l_@@_input_fraction_sign_tl \tl_new:N \l_@@_input_mixed_fraction_sign_tl \tl_new:N \l_@@_list_of_units_tl \tl_new:N \l_@@_list_of_values_tl +\tl_new:N \l_@@_allwed_integer_math_operators_tl +\tl_new:N \l_@@_curr_group_tl +\tl_new:N \l_@@_curr_unit_tl +\tl_new:N \l_@@_new_key_base_tl +\tl_new:N \l_@@_decided_unit_tl +\tl_new:N \l_@@_stored_units_tl +\tl_new:N \l_@@_stored_formula_tl +\tl_new:N \l_@@_base_tl % \end{macrocode} % \begin{macrocode} +\tl_new:N \l_@@_cmd_hook_tl \tl_new:N \l_@@_cunum_hook_tl \tl_new:N \l_@@_cutext_hook_tl \tl_new:N \l_@@_Cutext_hook_tl @@ -3964,16 +4016,19 @@ and the derived file cooking-units.sty. \tl_set:Nn \l_@@_input_allowed_special_signs_tl { ? } \tl_gset_rescan:Nnn \g_@@_input_str_hash_one_tl { \char_set_catcode_letter:N \# } {#1} +\tl_set:Nn \l_@@_allwed_integer_math_operators_tl { +-()*/ } % \end{macrocode} % \begin{macrocode} \tl_set:Nn \l_@@_cunum_range_sign_tl { -- } \tl_set:Nn \l_@@_cutext_range_sign_tl { } \tl_set:Nn \l_@@_value_unit_space_tl { \thinspace } -\tl_set:Nn \l_@@_cutext_space_tl { \space } +\tl_set:Nn \l_@@_cutext_space_tl { ~ } +\tl_set:Nn \l_@@_cutext_numeral_space_tl { \space } \tl_set:Nn \l_@@_cuphrase_space_tl { \space } \tl_set:Nn \l_@@_unit_letter_not_allowed_tl { , / } % \end{macrocode} % +% \begin{macro}{\c_@@_minus_tl} % Flat out stolen from \pkg{siunitx}. % \begin{macrocode} \AtBeginDocument { @@ -4001,6 +4056,7 @@ and the derived file cooking-units.sty. { } } % \end{macrocode} +% \end{macro} % % \begin{macro}{ \l_@@_mixed_frac_dim } % The dimension between the fraction and the mixed fraction part is @@ -4054,18 +4110,20 @@ and the derived file cooking-units.sty. % \end{macro} % % -% \begin{macro}{ \l_@@_phrase_number_tl } -% Stores the current \enquote{phrase number}. For \enquote{Dutzend} this would -% be \enquote{12}, etc. +% \begin{macro}{ \l_@@_phrase_number_tl , \l_@@_phrase_gender_tl } +% Stores the current \enquote{phrase number} (and gender). +% For \enquote{Dutzend} this would +% be \enquote{12}, etc. The second stores the gender (m, f or n) % \begin{macrocode} \int_new:N \l_@@_phrase_number_tl +\int_new:N \l_@@_phrase_gender_tl % \end{macrocode} % \end{macro} % % \begin{macro}{ \l_@@_list_of_defined_keys_clist , \g_@@_list_of_defined_units_clist } -% Sequence of defined units and keys. Units are defined +% Sequence of defined units and keys. Units are defined % globally as they create new commands, keys do not do that -% (I think). Could be my mistake. +% (I think). Could be my mistake. % \begin{macrocode} \seq_new:N \l_@@_list_of_defined_keys_seq \seq_new:N \g_@@_list_of_defined_units_seq @@ -4093,27 +4151,35 @@ and the derived file cooking-units.sty. % \end{macro} % % -% \begin{macro}{\l_@@_number_of_iterations_seq, \l_@@_derivative_unit_list_seq , -% \l_@@_derivative_symbol_list_seq , \l_@@_derivative_value_list_seq +% \begin{macro}{ +% , \g_@@_stored_derived_unit_symbol_seq +% , \g_@@_stored_derived_formula_seq +% , \g_@@_stored_derived_unit_print_seq % } % Variables used in \mycs{declarecookingderivatives}. % \begin{macrocode} -\seq_new:N \l_@@_number_of_iterations_seq -\seq_new:N \l_@@_derivative_unit_list_seq -\seq_new:N \l_@@_derivative_symbol_list_seq -\seq_new:N \l_@@_derivative_value_list_seq +\seq_new:N \g_@@_stored_derived_unit_symbol_seq +\seq_new:N \g_@@_stored_derived_formula_seq +\seq_new:N \g_@@_stored_derived_unit_print_seq % \end{macrocode} % \end{macro} % -% \begin{macro}{\l_@@_max_depth_int, \l_@@_curr_depth_int} -% Also some variables used in \mycs{declarecookingderivatives}. +% +% \begin{macro}{\l_@@_nr_of_units_int, \l_@@_depth_int} +% Also some variables used in \mycs{declarecookingderivatives}. (And for one check during +% definitions of keys). % \begin{macrocode} -\int_new:N \l_@@_max_depth_int -\int_new:N \l_@@_curr_depth_int +\int_new:N \l_@@_nr_of_units_int +\int_new:N \l_@@_depth_int % \end{macrocode} % \end{macro} % -% +% \begin{macro}{\g_@@_natural_units_seq } +% Remembers which unit foes to which natural unit. +% \begin{macrocode} +\seq_new:N \g_@@_natural_units_seq +% \end{macrocode} +% \end{macro} % % \begin{macro} { \l_@@_temperatures_to_check_seq } % \changes {1.02h} {New.} @@ -4139,82 +4205,85 @@ and the derived file cooking-units.sty. % \end{macrocode} % \end{macro} % +% \begin{macro} { \l_@@_derived_units_prop } +% Stores \emph{via} key-value all defined derived units as keys +% and the formula to calculate the derived unit as value.. +% \begin{macrocode} +\prop_new:N \l_@@_derived_units_prop +% \end{macrocode} +% \end{macro} +% % % % \begin{macro} % { -% \l_@@_minus_bool, -% \l_@@_round_number_bool, -% \l_@@_error_bool, -% \l_@@_unit_error_bool, -% \l_@@_eval_fractions_bool, -% \l_@@_convert_fractions_bool, -% \l_@@_draft_bool, -% \l_@@_round_to_int_bool, -% \l_@@_special_sign_bool, -% \l_@@_single_key_bool, -% \l_@@_check_temperature_bool, -% \l_@@_convert_to_eV_bool, -% \l_@@_cutext_uppercase_word_bool, -% \l_@@_using_cutext_bool, -% \l_@@_cuam_old_bool, -% \l_@@_change_number_of_persons_bool, -% \l_@@_calc_because_ref_was_given_bool, -% \l_@@_lokal_persons_bool, -% \l_@@_cutext_to_cunum_bool, -% \l_@@_cutext_old_bool, -% \l_@@_cutext_keep_unit_bool, -% \l_@@_round_commercial_bool, -% \l_@@_use_phrases_bool, -% \l_@@_lokal_phrase_bool, -% \l_@@_print_numeral_bool, -% \l_@@_lokal_numeral_bool, -% \l_@@_round_precision_negative_bool, -% \l_@@_fourty_two_bool, -% \l_@@_phrase_negative_bool , -% \l_@@_range_in_input_bool, \l_@@_lokal_fraction_bool , -% \l_@@_print_fraction_bool, \l_@@_check_decimal_bool , +% , \l_@@_pckopt_eval_fractions_bool +% , \l_@@_pckopt_convert_fractions_bool +% , \l_@@_pckopt_draft_bool +% , \l_@@_pckopt_round_to_int_bool +% , \l_@@_pckopt_check_temperature_bool +% , \l_@@_pckopt_convert_to_eV_bool +% , \l_@@_pckopt_cuam_old_bool +% , \l_@@_pckopt_recalculate_amount_bool +% , \l_@@_pckopt_cutext_to_cunum_bool +% , \l_@@_pckopt_cutext_old_bool +% , \l_@@_pckopt_cutext_keep_unit_bool +% , \l_@@_pckopt_round_commercial_bool +% , \l_@@_pckopt_use_phrases_bool +% , \l_@@_pckopt_round_precision_negative_bool +% , \l_@@_pckopt_fourty_two_bool +% , \l_@@_pckopt_bonkers_bool +% , \l_@@_minus_bool +% , \l_@@_round_number_bool +% , \l_@@_single_key_bool +% , \l_@@_cutext_uppercase_word_bool +% , \l_@@_reference_given_bool +% , \l_@@_lokal_recalc_for_people_bool +% , \l_@@_lokal_phrase_bool +% , \l_@@_lokal_change_unit_bool +% , \l_@@_pckopt_print_numeral_bool +% , \l_@@_lokal_numeral_bool +% , \l_@@_phrase_negative_bool +% , \l_@@_cutext_last_amount_equ_one_bool +% , \l_@@_symbol_was_set_by_key_bool +% , \l_@@_contains_valid_key_bool +% , \l_@@_check_decimal_bool +% , \l_@@_unit_error_bool % } % Some booleans we need later. % \begin{macrocode} +\bool_new:N \l_@@_pckopt_eval_fractions_bool +\bool_new:N \l_@@_pckopt_convert_fractions_bool +\bool_new:N \l_@@_pckopt_draft_bool +\bool_new:N \l_@@_pckopt_round_to_int_bool +\bool_new:N \l_@@_pckopt_check_temperature_bool +\bool_new:N \l_@@_pckopt_convert_to_eV_bool +\bool_new:N \l_@@_pckopt_cuam_old_bool +\bool_new:N \l_@@_pckopt_recalculate_amount_bool +\bool_new:N \l_@@_pckopt_cutext_to_cunum_bool +\bool_new:N \l_@@_pckopt_cutext_old_bool +\bool_new:N \l_@@_pckopt_cutext_keep_unit_bool +\bool_new:N \l_@@_pckopt_round_commercial_bool +\bool_new:N \l_@@_pckopt_use_phrases_bool +\bool_new:N \l_@@_pckopt_round_precision_negative_bool +\bool_new:N \l_@@_pckopt_fourty_two_bool +\bool_new:N \l_@@_pckopt_bonkers_bool \bool_new:N \l_@@_minus_bool \bool_new:N \l_@@_round_number_bool -\bool_new:N \l_@@_error_bool -\bool_new:N \l_@@_unit_error_bool -\bool_new:N \l_@@_eval_fractions_bool -\bool_new:N \l_@@_convert_fractions_bool -\bool_new:N \l_@@_draft_bool -\bool_new:N \l_@@_round_to_int_bool -\bool_new:N \l_@@_special_sign_bool \bool_new:N \l_@@_single_key_bool -\bool_new:N \l_@@_check_temperature_bool -\bool_new:N \l_@@_convert_to_eV_bool \bool_new:N \l_@@_cutext_uppercase_word_bool -\bool_new:N \l_@@_using_cutext_bool -\bool_new:N \l_@@_cuam_old_bool -\bool_new:N \l_@@_change_number_of_persons_bool -\bool_new:N \l_@@_calc_because_ref_was_given_bool -\bool_new:N \l_@@_lokal_persons_bool -\bool_new:N \l_@@_cutext_to_cunum_bool -\bool_new:N \l_@@_cutext_old_bool -\bool_new:N \l_@@_cutext_keep_unit_bool -\bool_new:N \l_@@_round_commercial_bool -\bool_new:N \l_@@_use_phrases_bool +\bool_new:N \l_@@_reference_given_bool +\bool_new:N \l_@@_lokal_recalc_for_people_bool \bool_new:N \l_@@_lokal_phrase_bool -\bool_new:N \l_@@_print_numeral_bool +\bool_new:N \l_@@_lokal_change_unit_bool +\bool_new:N \l_@@_pckopt_print_numeral_bool \bool_new:N \l_@@_lokal_numeral_bool -\bool_new:N \l_@@_round_precision_negative_bool -\bool_new:N \l_@@_fourty_two_bool \bool_new:N \l_@@_phrase_negative_bool -% \end{macrocode} -% -% While rewriting the code I searched for those -% booleans a lot. -% \begin{macrocode} -\bool_new:N \l_@@_range_in_input_bool -\bool_new:N \l_@@_lokal_fraction_bool -\bool_new:N \l_@@_print_fraction_bool +\bool_new:N \l_@@_cutext_last_amount_equ_one_bool +\bool_new:N \l_@@_symbol_was_set_by_key_bool +\bool_new:N \l_@@_contains_valid_key_bool \bool_new:N \l_@@_check_decimal_bool +\bool_new:N \l_@@_unit_error_bool % \end{macrocode} % \end{macro} % @@ -4222,8 +4291,8 @@ and the derived file cooking-units.sty. % % Setting some of them to \true\ or another boolean respectively. % \begin{macrocode} -\bool_set_false:N \l_@@_cutext_keep_unit_bool -\bool_set_eq:NN \l_@@_print_numeral_bool \g_@@_opt_numeral_bool +\bool_set_false:N \l_@@_pckopt_cutext_keep_unit_bool +\bool_set_eq:NN \l_@@_pckopt_print_numeral_bool \g_@@_opt_numeral_bool % \end{macrocode} % % @@ -4238,20 +4307,30 @@ and the derived file cooking-units.sty. % Checking value if a translation is avaiable. % \begin{macrocode} \quark_new:N \q_@@_no_translation +%\cs_new:Npn \q_@@_no_translation { asdasd\ewhkerhjkwejhk } % \end{macrocode} %\end{macro} % % % \begin{macro}{ -% \l_@@_tmpa_tl , \l_@@_tmpb_tl , \l_@@_tmp_unit_tl , -% \l_@@_tmpa_fp , -% \l_@@_tmpa_clist , -% \l_@@_tmpa_prop , \l_@@_tmpb_prop , -% \l_@@_tmpa_seq , -% \l_@@_tmpa_int , \l_@@_tmpb_int , +% , \l_@@_scrap_tl +% , \l_@@_tmpa_tl +% , \l_@@_tmpb_tl +% , \l_@@_tmp_unit_tl +% , \l_@@_tmpa_fp +% , \l_@@_tmpa_clist +% , \l_@@_tmpa_prop +% , \l_@@_tmpb_prop +% , \l_@@_tmpa_seq +% , \l_@@_tmpb_seq +% , \l_@@_tmpa_int +% , \l_@@_tmpb_int +% , \l_@@_tmpa_bool +% , \l_@@_tmpb_bool % } % Some temporal stores which are used throughout the code. % \begin{macrocode} +\tl_new:N \l_@@_scrap_tl \tl_new:N \l_@@_tmpa_tl \tl_new:N \l_@@_tmpb_tl \tl_new:N \l_@@_tmp_unit_tl @@ -4260,8 +4339,11 @@ and the derived file cooking-units.sty. \prop_new:N \l_@@_tmpa_prop \prop_new:N \l_@@_tmpb_prop \seq_new:N \l_@@_tmpa_seq +\seq_new:N \l_@@_tmpb_seq \int_new:N \l_@@_tmpa_int \int_new:N \l_@@_tmpb_int +\bool_new:N \l_@@_tmpa_bool +\bool_new:N \l_@@_tmpb_bool % \end{macrocode} %\end{macro} % @@ -4322,8 +4404,9 @@ and the derived file cooking-units.sty. % \begin{macrocode} erase-all-options .code:n = { - \exp_args:Nx \cuclearoptionfor { \seq_use:Nn \g_@@_list_of_defined_units_seq { , } } - }, + \clist_set_from_seq:NN \l_@@_tmpa_clist \g_@@_list_of_defined_units_seq + \@@_clear_options_for:V \l_@@_tmpa_clist + }, erase-all-options .value_forbidden:n = { true } , % \end{macrocode} % \end{macro} @@ -4334,11 +4417,7 @@ and the derived file cooking-units.sty. % \begin{macrocode} erase-all-options-for .code:n = { - \cuclearoptionfor {#1} -% \keyval_parse:NNn -% \@@_erase_options_for:n -% \@@_erase_options_for_error:nn -% {#1} + \@@_clear_options_for:n {#1} }, erase-all-options-for .value_required:n = { true } , % \end{macrocode} @@ -4353,7 +4432,7 @@ and the derived file cooking-units.sty. % Don't want any \mycs{cutext} (or \mycs{Cutext}) in your % document? Use this option! % \begin{macrocode} - cutext-to-cunum .bool_set:N = \l_@@_cutext_to_cunum_bool , + cutext-to-cunum .bool_set:N = \l_@@_pckopt_cutext_to_cunum_bool , cutext-to-cunum .default:n = { false } , cutext-to-cunum .groups:n = { change-command } , % \end{macrocode} @@ -4362,7 +4441,7 @@ and the derived file cooking-units.sty. % \begin{macro}{ cutext-change-unit } % Do not wanna change units in \mycs{cutext}? Use this option. % \begin{macrocode} - cutext-change-unit .bool_set_inverse:N = \l_@@_cutext_keep_unit_bool , + cutext-change-unit .bool_set_inverse:N = \l_@@_pckopt_cutext_keep_unit_bool , cutext-change-unit .default:n = { true } , cutext-change-unit .groups:n = { change-unit } , % \end{macrocode} @@ -4377,21 +4456,23 @@ and the derived file cooking-units.sty. { \int_case:nn { \l_keys_choice_int } { - { 1 } { \bool_set_false:N \l_@@_cuam_old_bool } - { 2 } { \bool_set_true:N \l_@@_cuam_old_bool } + { 1 } { \bool_set_false:N \l_@@_pckopt_cuam_old_bool } + { 2 } { \bool_set_true:N \l_@@_pckopt_cuam_old_bool } } } , cuam-version .default:n = { new } , + cuam-version .groups:n = { parse } , cutext-version .choices:nn = { new , old } { \int_case:nn { \l_keys_choice_int } { - { 1 } { \bool_set_false:N \l_@@_cutext_old_bool } - { 2 } { \bool_set_true:N \l_@@_cutext_old_bool } + { 1 } { \bool_set_false:N \l_@@_pckopt_cutext_old_bool } + { 2 } { \bool_set_true:N \l_@@_pckopt_cutext_old_bool } } } , cutext-version .default:n = { new } , + cutext-version .groups:n = { parse } , % \end{macrocode} % \end{macro} % @@ -4400,26 +4481,29 @@ and the derived file cooking-units.sty. expand-both .choices:nn = { n , o , f , x } { - \cs_set_eq:Nc \@@_set_unit:Nn { tl_set:N \l_keys_choice_tl } - \cs_set_eq:Nc \@@_set_amount:Nn { tl_set:N \l_keys_choice_tl } + \tl_set_eq:NN \l_@@_unit_argument_spec_tl \l_keys_choice_tl + \tl_set_eq:NN \l_@@_expand_amount_tl \l_keys_choice_tl } , expand-both .default:n = { n } , + expand-both .groups:n = { parse } , % \end{macrocode} % \begin{macrocode} expand-amount .choices:nn = { n , o , f , x } { - \cs_set_eq:Nc \@@_set_amount:Nn { tl_set:N \l_keys_choice_tl } + \tl_set_eq:NN \l_@@_expand_amount_tl \l_keys_choice_tl } , expand-amount .default:n = { n } , + expand-amount .groups:n = { parse } , % \end{macrocode} % \begin{macrocode} expand-unit .choices:nn = { n , o , f , x } { - \cs_set_eq:Nc \@@_set_unit:Nn { tl_set:N \l_keys_choice_tl } + \tl_set_eq:NN \l_@@_unit_argument_spec_tl \l_keys_choice_tl } , expand-unit .default:n = { n } , + expand-unit .groups:n = { parse } , % \end{macrocode} % \end{macro} % @@ -4442,6 +4526,7 @@ and the derived file cooking-units.sty. } \use:n { \tl_set:Nn \l_@@_input_allowed_special_signs_tl {#1} } } , + set-special-sign .groups:n = { parse } , % \end{macrocode} %\end{macro} %\begin{macro}{ add-special-sign } @@ -4460,6 +4545,7 @@ and the derived file cooking-units.sty. } } , add-special-sign .default:n = { } , + add-special-sign .groups:n = { parse } , % \end{macrocode} %\end{macro} % @@ -4470,21 +4556,21 @@ and the derived file cooking-units.sty. set-unknown-message .choices:nn = { error , warning , none } { - \msg_redirect_name:nnn { cooking-units } { amount-not-known } - { \l_keys_choice_tl } + \msg_redirect_name:nnV { cooking-units } { amount-not-known } + \l_keys_choice_tl } , set-unknown-message .default:n = { warning } , % \end{macrocode} %\end{macro} % -% \begin{macro}{ set-unknown-message } +% \begin{macro}{ set-cutext-translation-message } % Sets the message for a special-sign to error, warning or none. % \begin{macrocode} set-cutext-translation-message .choices:nn = { error , warning , none } { - \msg_redirect_name:nnn { cooking-units } { cutext-no-translation-available } - { \l_keys_choice_tl } + \msg_redirect_name:nnV { cooking-units } { cutext-no-translation-available } + \l_keys_choice_tl } , set-cutext-translation-message .default:n = { warning } , % \end{macrocode} @@ -4494,7 +4580,7 @@ and the derived file cooking-units.sty. % \begin{macro}{ print-numerals } % A not very good name, but I couldn't think of a better name. % \begin{macrocode} - print-numerals .bool_set:N = \l_@@_print_numeral_bool , + print-numerals .bool_set:N = \l_@@_pckopt_print_numeral_bool , print-numerals .default:n = { true } , % \end{macrocode} % \end{macro} @@ -4510,8 +4596,9 @@ and the derived file cooking-units.sty. %\begin{macro}{ parse-number } % Parse the input? If no the input is printed as is (after some safety parsing). % \begin{macrocode} - parse-number .bool_set_inverse:N = \l_@@_draft_bool , + parse-number .bool_set_inverse:N = \l_@@_pckopt_draft_bool , parse-number .default:n= { true } , + parse-number .groups:n = { parse } , % \end{macrocode} %\end{macro} % @@ -4535,7 +4622,7 @@ and the derived file cooking-units.sty. % \begin{macro}{ use-phrases } % Do not wanna use phrases in \mycs{cuam}? Use this option! % \begin{macrocode} - use-phrases .bool_set:N = \l_@@_use_phrases_bool , + use-phrases .bool_set:N = \l_@@_pckopt_use_phrases_bool , use-phrases .default:n = { true } , % \end{macrocode} % \end{macro} @@ -4555,7 +4642,7 @@ and the derived file cooking-units.sty. \int_compare:nNnTF {#1} < { 0 } { \bool_set_true:N } { \bool_set_false:N } - \l_@@_round_precision_negative_bool + \l_@@_pckopt_round_precision_negative_bool } , round-precision .default:n = { 2 } , % \end{macrocode} @@ -4564,7 +4651,7 @@ and the derived file cooking-units.sty. %\begin{macro}{ round-to-int } % Rounding the results to an integer. % \begin{macrocode} - round-to-int .bool_set:N = \l_@@_round_to_int_bool , + round-to-int .bool_set:N = \l_@@_pckopt_round_to_int_bool , round-to-int .choices:nn = { true , false } { @@ -4575,7 +4662,7 @@ and the derived file cooking-units.sty. }{ } - \use:c { bool_set_ \l_keys_choice_tl :N } \l_@@_round_to_int_bool + \use:c { bool_set_ \l_keys_choice_tl :N } \l_@@_pckopt_round_to_int_bool } , round-to-int .default:n = { false } , % \end{macrocode} @@ -4585,13 +4672,15 @@ and the derived file cooking-units.sty. % Choosing between \enquote{normal} rounding to even % and commercial rounding and sets the boolean accordingly. % \begin{macrocode} +% TODO: uodate doch und so round-half .choices:nn = - { default , commercial } + { default , commercial , up } { \int_case:nn { \l_keys_choice_int } { - { 1 } { \bool_set_false:N \l_@@_round_commercial_bool } - { 2 } { \bool_set_true:N \l_@@_round_commercial_bool } + { 1 } { \bool_set_false:N \l_@@_pckopt_round_commercial_bool } + { 2 } { \bool_set_true:N \l_@@_pckopt_round_commercial_bool } + { 3 } { \bool_set_true:N \l_@@_pckopt_round_commercial_bool } } }, round-half .default:n = { default }, @@ -4601,7 +4690,7 @@ and the derived file cooking-units.sty. %\begin{macro}{ eval-fraction } % If set to true the fractions are evaluated. % \begin{macrocode} - eval-fraction .bool_set:N = \l_@@_eval_fractions_bool , + eval-fraction .bool_set:N = \l_@@_pckopt_eval_fractions_bool , eval-fraction .default:n = { false } , % \end{macrocode} %\end{macro} @@ -4609,7 +4698,7 @@ and the derived file cooking-units.sty. %\begin{macro}{ convert-fraction } % If set to true the fractions are evaluated \emph{if} the unit is transformed! % \begin{macrocode} - convert-fraction .bool_set:N = \l_@@_convert_fractions_bool , + convert-fraction .bool_set:N = \l_@@_pckopt_convert_fractions_bool , convert-fraction .default:n = { true } , % \end{macrocode} %\end{macro} @@ -4645,11 +4734,20 @@ and the derived file cooking-units.sty. %\end{macro} % % \begin{macro}{ cutext-space } -% The space used in \mycs{cutext} between the number (or numeral) +% The space used in \mycs{cutext} between the \emph{number} % and unit. % \begin{macrocode} cutext-space .tl_set:N = \l_@@_cutext_space_tl , - cutext-space .default:n = { \space } , + cutext-space .default:n = { ~ } , +% \end{macrocode} +% \end{macro} +% +% \begin{macro}{ cutext-space } +% The space used in \mycs{cutext} between the \emph{numeral} +% and unit. +% \begin{macrocode} + cutext-numeral-space .tl_set:N = \l_@@_cutext_numeral_space_tl , + cutext-numeral-space .default:n = { \space } , % \end{macrocode} % \end{macro} % @@ -4657,7 +4755,7 @@ and the derived file cooking-units.sty. % Same as before, but for phrases % \begin{macrocode} phrase-space .tl_set:N = \l_@@_cuphrase_space_tl , - phrase-space .default:n = { \space } , + phrase-space .default:n = { ~ } , % \end{macrocode} % \end{macro} % @@ -4679,7 +4777,7 @@ and the derived file cooking-units.sty. % is not enough; it is also needed to tell the package to % recalculate the amounts. % \begin{macrocode} - recalculate-amount .bool_set:N = \l_@@_change_number_of_persons_bool , + recalculate-amount .bool_set:N = \l_@@_pckopt_recalculate_amount_bool , recalculate-amount .default:n = { false } , % \end{macrocode} % \end{macro} @@ -4704,7 +4802,7 @@ and the derived file cooking-units.sty. % \mycs{curef} as a key. % \begin{macrocode} get-label .code:n = \@@_curef:n {#1} , - label .value_required:n = { true } , + get-label .value_required:n = { true } , % \end{macrocode} % \end{macro} % @@ -4725,7 +4823,7 @@ and the derived file cooking-units.sty. % Weird option. Checking the temperature, if the temperature is below the absolute zero temperature % it raises an error. % \begin{macrocode} - check-temperature .bool_set:N = \l_@@_check_temperature_bool , + check-temperature .bool_set:N = \l_@@_pckopt_check_temperature_bool , check-temperature .default:n = { true } , % \end{macrocode} % @@ -4751,9 +4849,9 @@ and the derived file cooking-units.sty. % As this is a unit transformation, it needs to be inside the % group. % \begin{macrocode} - convert-to-eV .bool_set:N = \l_@@_convert_to_eV_bool , + convert-to-eV .bool_set:N = \l_@@_pckopt_convert_to_eV_bool , convert-to-eV .default:n = { true } , - convert-to-eV .groups:n = { change-unit } , +% convert-to-eV .groups:n = { change-unit } , % \end{macrocode} %\end{macro} % @@ -4764,10 +4862,10 @@ and the derived file cooking-units.sty. \seq_set_from_clist:Nn \l_@@_tmpa_seq {#1} \seq_map_inline:Nn \l_@@_tmpa_seq { - \@@_error_if_unit_not_defined:nF {##1} + \@@_error_if_unit_not_defined:nNF {##1} \l_@@_curr_unit_tl { - \seq_if_in:NnF \g_@@_natural_units_seq {##1} - { \seq_gput_right:Nn \g_@@_natural_units_seq {##1} } + \seq_if_in:NVF \g_@@_natural_units_seq \l_@@_curr_unit_tl + { \seq_gput_right:NV \g_@@_natural_units_seq \l_@@_curr_unit_tl } } } } , @@ -4778,9 +4876,10 @@ and the derived file cooking-units.sty. % \begin{macro}{ 42 } % \begin{macrocode} 42 .choice: , - 42 / true .code:n = { \bool_set_true:N \l_@@_fourty_two_bool } , + 42 / true .code:n = { \bool_set_true:N \l_@@_pckopt_fourty_two_bool } , 42 / false .code:n = { \msg_fatal:nnn { cooking-units } { 42-is-...-wrong? } } , 42 .default:n = { true } , + 42 .groups:n = { parse } , % \end{macrocode} % \end{macro} % @@ -4808,6 +4907,7 @@ and the derived file cooking-units.sty. % \begin{macrocode} input-range-sign .tl_set:N = \l_@@_input_range_sign_tl , input-range-sign .default:n = { -- } , + input-range-sign .groups:n = { parse } , % \end{macrocode} %\end{macro} % @@ -4839,6 +4939,11 @@ and the derived file cooking-units.sty. cutext-add-hook .code:n = { \tl_put_right:Nn \l_@@_cutext_hook_tl {#1} } , Cutext-add-hook .code:n = { \tl_put_right:Nn \l_@@_Cutext_hook_tl {#1} } , cuam-add-hook .code:n = { \tl_put_right:Nn \l_@@_cuam_hook_tl {#1} } , + cunum-add-hook .groups:n = { parse } , + cutext-add-hook .groups:n = { parse } , + Cutext-add-hook .groups:n = { parse } , + cuam-add-hook .groups:n = { parse } , + commands-add-hook .groups:n = { parse } , % \end{macrocode} % \end{macro} % @@ -4879,6 +4984,165 @@ and the derived file cooking-units.sty. % % % +% \begin{macro}{symbol} +% To be implemented. Key used during definition of new units. +% Defines the printed symbol of the unit (both do the same). +% \begin{macrocode} + definition / symbol .code:n = + { + \bool_set_true:N \l_@@_contains_valid_key_bool + \bool_set_true:N \l_@@_symbol_was_set_by_key_bool + \tl_set:cn { l_@@_default_unit_ \l_@@_original_unit_tl _tl } {#1} + }, + definition / symbol .value_required:n = { true } , +% \end{macrocode} +% \end{macro} +% +% \begin{macro}{gender} +% To be implemented. Key used during definition of new units. +% Defines the gender of the unit. +% \begin{macrocode} + definition / gender .code:n = + { + \bool_set_true:N \l_@@_contains_valid_key_bool + \@@_if_gender_error:nTF {#1} + { \@@_culang_def_base:nVn { gender } \l_@@_original_unit_tl { m } } + { \@@_culang_def_base:nVn { gender } \l_@@_original_unit_tl {#1} } + }, + definition / gender .value_required:n = { true } , +% \end{macrocode} +% \end{macro} +% +% \begin{macro}{set-option} +% To be implemented. Key used during definition of new units. +% Adds options to a specific key during definition of unit. +% \begin{macrocode} + definition / set-option .code:n = + { + \bool_set_true:N \l_@@_contains_valid_key_bool + \@@_set_options_for:Vn \l_@@_original_unit_tl {#1} + }, + definition / set-option .value_required:n = { true } , +% \end{macrocode} +% \end{macro} +% +% \begin{macro}{add-to-group} +% To be implemented. Key used during definition of new units. +% Adds unit to given group. +% \begin{macrocode} + definition / add-to-group .code:n = + { + \bool_set_true:N \l_@@_contains_valid_key_bool + \@@_add_to_unit_group:nV {#1} \l_@@_original_unit_tl + }, + definition / add-to-group .value_required:n = { true } , +% \end{macrocode} +% \end{macro} +% +% \begin{macro}{natural-unit} +% To be implemented. Key used during definition of new units. +% Defines this unit as a natural unit. +% \begin{macrocode} + definition / natural-unit .code:n = + { + \bool_set_true:N \l_@@_contains_valid_key_bool + \seq_if_in:NVF \g_@@_natural_units_seq \l_@@_original_unit_tl + { \seq_gput_right:NV \g_@@_natural_units_seq \l_@@_original_unit_tl } + }, + definition / natural-unit .default:n = { true } , +% \end{macrocode} +% \end{macro} +% +% \begin{macro}{unit-names} +% To be implemented. Key used during definition of new units. +% Defines written out unit name for \cCutext for given language. +% Also suspended. Would need to give language and it would be too +% complicated (I think) +% \begin{macrocode} +% definition / unit-names .code:n = { }, +% \end{macrocode} +% \end{macro} +% +% +% You get here during the definition of a new unit if you use the optional +% argument. As symbols cannot contain |=| the argument |#1| is going +% to be empty. I also assume that none of the above keys are used as an +% unit-symbol. If |#1| is non-empty (aka.\ the key has a value) throw an error. +% \begin{macrocode} + definition / unknown .code:n = + { + \tl_if_empty:nF {#1} + { + \msg_error:nnxx + { cooking-units } + { definition-key-mistyped? } + \l_keys_key_str + {#1} + } + }, +% \end{macrocode} +% +% +% +% \begin{macro}{nothing-special} +% Stage 0 of being bonkers. Do nothing special in this one. Reset everything. +% \begin{macrocode} + nothing-special .code:n = + { + \prop_gclear:N \g_@@_master_changer_prop + \prop_gclear:N \g_@@_convert_bonkers_remember_prop + \bool_set_false:N \l_@@_pckopt_bonkers_bool + \tl_set_eq:NN \l_@@_bonkers_state_tl \c_@@_bonkers_state_normal_tl + }, + nothing-special .value_forbidden:n = { true } , +% \end{macrocode} +% \end{macro} +% +% \begin{macro}{going-bonkers} +% Stage 1 of being bonkers. +% \begin{macrocode} + going-bonkers .code:n = + { + \prop_gclear:N \g_@@_convert_bonkers_remember_prop + \bool_set_true:N \l_@@_pckopt_bonkers_bool + \tl_set_eq:NN \l_@@_bonkers_state_tl \c_@@_bonkers_state_going_tl + }, + going-bonkers .value_forbidden:n = { true } , +% \end{macrocode} +% \end{macro} +% +% \begin{macro}{fully-bonkers} +% Stage 2 of being bonkers. +% \begin{macrocode} + fully-bonkers .code:n = + { + \prop_gclear:N \g_@@_master_changer_prop + \prop_gclear:N \g_@@_convert_bonkers_remember_prop + \bool_set_true:N \l_@@_pckopt_bonkers_bool + \tl_set_eq:NN \l_@@_bonkers_state_tl \c_@@_bonkers_state_fully_tl + }, + fully-bonkers .value_forbidden:n = { true } , +% \end{macrocode} +% \end{macro} +% +% \begin{macro}{xD-lol} +% Stage 3 of being bonkers. +% \begin{macrocode} + xD-lol .code:n = + { + \prop_gclear:N \g_@@_master_changer_prop + \prop_gclear:N \g_@@_convert_bonkers_remember_prop + \bool_set_true:N \l_@@_pckopt_bonkers_bool + \tl_set_eq:NN \l_@@_bonkers_state_tl \c_@@_bonkers_state_xD_tl + }, + xD-lol .value_forbidden:n = { true } , +% \end{macrocode} +% \end{macro} +% +% +% +% +% % % % @@ -4887,6 +5151,7 @@ and the derived file cooking-units.sty. % Ending the definition of keys. % \begin{macrocode} } +%\keys_set:nn { cooking-units } {#2} % \end{macrocode} % \end{macro} % @@ -4894,7 +5159,6 @@ and the derived file cooking-units.sty. % % % -% % \subsection {Messages} % % Defining messages. @@ -4977,6 +5241,18 @@ and the derived file cooking-units.sty. \msg_see_documentation_text:n {cooking-units} } % \end{macrocode} +% +% +% \begin{macrocode} +\msg_new:nnnn { cooking-units } { symbol-and-special-keys-error } + { You \ cannot \ use \ special-key \ '#1' \ with \ symbol \ '#2' \ definitions. } + { + You \ cannot \ redefine \ a \ symbol \ of \ a \ special-key. + \msg_see_documentation_text:n {cooking-units} + } +% \end{macrocode} +% +% % If fractions are evaluated division by zero is not allowed. % \begin{macrocode} \msg_new:nnnn { cooking-units } { Division-by-zero } @@ -5032,6 +5308,19 @@ and the derived file cooking-units.sty. } % \end{macrocode} % +% Error message for an undefined key. +% \begin{macrocode} +\msg_new:nnnn { cooking-units } { Key-chain-unit-not-found } + { + It \ appears \ that \ \token_to_str:N \cuaddtokeychain\ was \ not \ able \ to \ find + a \ key-chain-unit. Define \ key-chains \ first \ using \token_to_str:N \cudefinekeychain. + } + { + No \ key-chain-unit\ was \ found, \ perhaps \ you \ misspelled \ it? + \msg_see_documentation_text:n {cooking-units} + } +% \end{macrocode} +% % If the temperature is too low print this error message. % Now prints all units for which a zero-point is defined. % \begin{macrocode} @@ -5061,6 +5350,17 @@ and the derived file cooking-units.sty. \msg_see_documentation_text:n {cooking-units} } % \end{macrocode} +% If for an unit-key the value is wrong the following error message is shown. +% \begin{macrocode} +\msg_new:nnnn { cooking-units } { key-no-knows-value } + { + It \ appears \ that \ the \ key \ '#1' \ does \ not \ accept \ the \ value + '#2'. \ Are \ you \ sure \ it \ is \ in \ the \ same \ key-chain? + }{ + The \ key \ accepts \ only \ a \ fixed \ set \ of \ choices. \ + \msg_see_documentation_text:n {cooking-units} + } +% \end{macrocode} % Adding a message for unit-groups. % \begin{macrocode} \msg_new:nnnn { cooking-units } { group-choice-not-allowed } @@ -5137,6 +5437,17 @@ and the derived file cooking-units.sty. % \end{macrocode} % % \begin{macrocode} +\msg_new:nnnn { cooking-units } { Adding-single-to-multi-key-or-vice-verca } + { + You \ are \ trying \ to \ add \ a \ single-key \ to \ a \ multi-key \ + or \ vice-versa. + }{ + This \ is \ not \ allowed! + \msg_see_documentation_text:n { cooking-units } + } +% \end{macrocode} +% +% \begin{macrocode} \msg_new:nnnn { cooking-units } { Value-not-allowed } { The \ key-list \ in \ '#1' \ does \ not \ take \ a \ value. @@ -5258,6 +5569,16 @@ and the derived file cooking-units.sty. } % \end{macrocode} % +% \begin{macrocode} +\msg_new:nnnn { cooking-units } { formula-in-non-singlekeys } + { + The \ conversion \ value \ '#1' \ seems \ to \ be \ a \ formula. \ + This \ is \ not \ allowed \ for \ NON-\ singlekeys! + }{ + \msg_see_documentation_text:n { cooking-units } + } +% \end{macrocode} +% % % \begin{macrocode} \msg_new:nnnn { cooking-units } { <-not-allowed-as-special-sign } @@ -5284,6 +5605,18 @@ and the derived file cooking-units.sty. % % % \begin{macrocode} +\msg_new:nnnn { cooking-units } { no-natural-unit-known } + { + It \ seems\ that \ I \ cannot \ convert \ '#1' \ in \ a \ natural \ + unit \ as \ there \ is \ no \ conversion-factor \ defined. + }{ + Not \ converting \ the \unit. + \msg_see_documentation_text:n { cooking-units } + } +% \end{macrocode} +% +% +% \begin{macrocode} \msg_new:nnnn { cooking-units } { curef-not-inside-list } { '#1' \ cannot \ be \ removed \ from \ the \ 'forbidden \ unit' \ list \ because @@ -5356,6 +5689,13 @@ and the derived file cooking-units.sty. \msg_see_documentation_text:n { cooking-units } } % +\msg_new:nnnn { cooking-units } { unknown-unit-option } + { + The \ unit-option \ '#1' \ is \ not \ defined. + }{ + Please \ define \ the \ key \ '#1' \ via \ \newcukeysadd \ and \ friends. + \msg_see_documentation_text:n { cooking-units } + } \msg_new:nnnn { cooking-units } { unknown-option } { The \ option \ '#1' \ is \ not \ defined. @@ -5363,6 +5703,13 @@ and the derived file cooking-units.sty. Perhaps \ you \ misspelled \ the \ option. \msg_see_documentation_text:n { cooking-units } } +\msg_new:nnnn { cooking-units } { unknown-choice } + { + The \ choice \ '#2' \ for \ key \ '#1' \ is \ not \ defined. + }{ + Perhaps \ you \ misspelled \ the \ choice. + \msg_see_documentation_text:n { cooking-units } + } % \end{macrocode} % % @@ -5371,52 +5718,102 @@ and the derived file cooking-units.sty. { This \ error \ shouldn't \ show. \ This \ means \ I \ (the \ package \ author) \ screwed - \ up. \ The \ error \ code \ is \ '#1'. + \ up. \ The \ error \ code \ is \ '#1'. \ + Addition \ is \ '#2'. }{ Please \ send \ me \ a \ bug \ report. \msg_see_documentation_text:n { cooking-units } } % \end{macrocode} +% +% +% \begin{macrocode} +\msg_new:nnnn { cooking-units } { definition-key-mistyped? } + { + This \ message \ shows \ during \ the \ definition \ of \ unit-keys. \ + You \ may \ have \ mistyped \ the \ key \ '#1'. \ You \ may \ see \ + this \ message \ because \ you \ have \ used \ a \ '=' \ sign \ in \ the \ + optional \ argument. \ If \ this \ is \ the \ case \ and \ you \ still \ want + \ to \ use \ '=' \ in \ a \ symbol, \ please \ wrap \ the \ symbol + \ in \ two \ braces: \ {{#1=#2}}. + }{ + Or \ try \ using \ the \ 'symbol' \ option. + \msg_see_documentation_text:n { cooking-units } + } +% \end{macrocode} % \end{macro} % % \section {Helper Macros} % % The name says it all. % +% +% +% %\begin{macro} % { -% \@@_error_if_unit_not_defined:n, +% \@@_if_unit_defined:nN, +% \@@_error_if_unit_not_defined:nNTF, % \@@_error_if_unit_not_defined:nTF, % \@@_error_if_unit_not_defined:VTF, % } % A little helper macro. Checks if the unit is defined, if not raise an error. % \begin{macrocode} -\prg_new_protected_conditional:Npnn \@@_error_if_unit_not_defined:n #1 { TF, T, F } +\prg_new_protected_conditional:Npnn \@@_if_unit_defined:nN #1 #2 { TF , T } { - \seq_if_in:NnTF \g_@@_list_of_defined_units_seq {#1} + \@@_set_unit:Nn #2 {#1} + \seq_if_in:NVTF \g_@@_list_of_defined_units_seq #2 + { \prg_return_true: } + { \prg_return_false: } + } +\prg_new_protected_conditional:Npnn \@@_error_if_unit_not_defined:nN #1#2 { TF, T, F } + { + \@@_if_unit_defined:nNTF {#1} #2 { \prg_return_false: } { \msg_error:nnn { cooking-units } { unknown-unit } {#1} \prg_return_true: } } -\cs_new:Npn \@@_error_if_unit_not_defined:n #1 - { \@@_error_if_unit_not_defined:nTF {#1} { } { } } +\prg_new_protected_conditional:Npnn \@@_error_if_unit_not_defined:n #1 { TF, T, F } + { + \@@_error_if_unit_not_defined:nNTF {#1} \l_@@_scrap_tl + { \prg_return_true: } + { \prg_return_false: } + } \cs_generate_variant:Nn \@@_error_if_unit_not_defined:nTF { V } % \end{macrocode} %\end{macro} % % +% +% \begin{macro} { \@@_if_unit_has_a_key:n, \@@_if_unit_has_a_key:V } +% A little helper macro. Checks if the unit is defined, if not raise an error. +% \begin{macrocode} +\prg_new_protected_conditional:Npnn \@@_if_unit_has_a_key:n #1 { T , F, TF } + { + \keys_if_exist:nnTF { cooking-units } {#1} + { \prg_return_true: } + { \prg_return_false: } + } +\prg_generate_conditional_variant:Nnn \@@_if_unit_has_a_key:n { V } { T, TF } +% \end{macrocode} +%\end{macro} +% +% +% \begin{macro} { \@@_seq_use_msg:N, \@@_seq_use_msg:c } +% Used in error messages for units. Prints the units in a comma-seperated list. % \begin{macrocode} \cs_new:Npn \@@_seq_use_msg:N #1 { \seq_use:Nnnn #1 { ' , ~ ' } { ' , ~ ' } { ' ~ and ~ ' } } \cs_generate_variant:Nn \@@_seq_use_msg:N { c } % \end{macrocode} +% \end{macro} % % -% -% \begin{macro}{ \@@_if_integer:n } -% Checking if the input consists only of numbers. +% \begin{macro}{ \@@_if_integer:n , \@@_if_integer:V , \@@_if_evaluation_is_integer:nN } +% Checking if the input consists only of numbers; or only of numbers and +% the allowed math operators % \begin{macrocode} \prg_new_protected_conditional:Npnn \@@_if_integer:n #1 { TF , F } { @@ -5424,71 +5821,115 @@ and the derived file cooking-units.sty. { \tl_if_in:NnF \l_@@_input_digits_tl {##1} { - \tl_map_break:n { \use_iii:nnn } + \tl_map_break:n { \use_i:nn \prg_return_false: } } } - \use_i:nn \prg_return_true: \prg_return_false: + \prg_return_true: } \cs_generate_variant:Nn \@@_if_integer:nTF { V } -\cs_generate_variant:Nn \@@_if_integer:nF { V } -% \end{macrocode} -% \end{macro} -% -% \begin{macro}{ \@@_if_integer:n } -% Checking if the input consists only of numbers. -% \begin{macrocode} -\cs_new:Npn \@@_bool_set_if_integers:NNN #1#2#3 +\prg_new_protected_conditional:Npnn \@@_if_evaluation_is_integer:n #1 { TF , T , F } { - \@@_if_integer:VTF #2 - { \bool_set_true:N #1 } - { \bool_set_false:N #1 } - \bool_lazy_and:nnT - { \l_@@_range_in_input_bool } {#1} + \tl_concat:NNN \l_@@_tmpa_tl + \l_@@_input_digits_tl \l_@@_allwed_integer_math_operators_tl + \tl_map_inline:nn {#1} { - \@@_if_integer:VF #3 - { \bool_set_false:N #1 } + \tl_if_in:NnF \l_@@_tmpa_tl {##1} + { \tl_map_break:n { \use_iii:nnn } } } + \use_i:nn + { \prg_return_true: } + { \prg_return_false: } } % \end{macrocode} % \end{macro} % % % -% \begin{macro}[TF]{ \@@_fp_if_equal_one:n} -% \begin{macro}[TF]{ \@@_int_if_equal_one:n} +% \begin{macro}{ \@@_if_integers:NNTF } +% Checking if the input consists only of numbers, which works correctly for ranges. % \begin{macrocode} -\prg_new_conditional:Npnn \@@_fp_if_equal_one:n #1 { TF } - { - \fp_compare:nNnTF {#1} = { 1.0 } - { \prg_return_true: } - { \prg_return_false: } - } -\prg_new_conditional:Npnn \@@_int_if_equal_one:n #1 { TF } +\prg_new_conditional:Npnn \@@_if_integers:NN #1#2 { TF } { - \int_compare:nNnTF {#1} = { 1 } - { \prg_return_true: } + \@@_if_integer:VTF #1 + { + \@@_if_print_type_equal:nTF { range } + { + \@@_if_integer:VTF #2 + { \prg_return_true: } + { \prg_return_false: } + } + { \prg_return_true: } + } { \prg_return_false: } } % \end{macrocode} -% \end{macro} \end{macro} +% \end{macro} % % +% \begin{macro}{ \@@_if_contains_decimal:NTF , \@@_check_for_decimal:w } +% A fast check if |#1| contains a decimal point. This is only +% used for already parsed input, so the input is already safe to check. +% +% If |#1| does not contain a decimal point, |\@@_check_for_decimal:w| +% |#2| is equal to |\q_nil|, the test is true and the false branch is executed. % -% \begin{macro}{} +% If |#1| does contain a decimal point, |#2| is going equal to |<...>.\q_nil| +% where |<...>| is the stuff after the decimal point. The test is false, thus the +% true branch is ignored (ignoring all other tokens in |#2|). % \begin{macrocode} -\prg_new_conditional:Npnn \@@_change_cutext_to_cunum:n #1 { TF } +\prg_new_conditional:Npnn \@@_if_contains_decimal:N #1 { TF } { - \keys_set_groups:nnn { cooking-units } { change-command } {#1} - \bool_if:NTF \l_@@_cutext_to_cunum_bool - { \prg_return_true: } - { \prg_return_false: } + \exp_after:wN \@@_check_for_decimal:w #1 . \q_nil . \q_stop } -% \end{macrocode} +\cs_new:Npn \@@_check_for_decimal:w #1 . #2 . \q_stop + { + \if_meaning:w \q_nil #2 + \exp_after:wN \prg_return_false: + \else: + \exp_after:wN \prg_return_true: + \fi: + } +% \end{macrocode} +% \end{macro} +% \begin{macro}{\@@_if_contain_decimals:NNTF} +% Same as |\@@_if_integers:NNTF| only for decimal points. +% \begin{macrocode} +\prg_new_conditional:Npnn \@@_if_contain_decimals:NN #1#2 { TF } + { +% \@@_if_contains_decimal:NTF #1 +% { +% \@@_if_print_type_equal:nTF { range } +% { +% \@@_if_contains_decimal:NTF #2 +% { \prg_return_true: } +% { \prg_return_false: } +% } +% { \prg_return_true: } +% } +% { \prg_return_false: } + \@@_if_contains_decimal:NTF #1 + { \prg_return_true: } + { + \@@_if_print_type_equal:nTF { range } + { + \@@_if_contains_decimal:NTF #2 + { \prg_return_true: } + { \prg_return_false: } + } + { \prg_return_false: } + } + } +% \end{macrocode} % \end{macro} % -% \begin{macro}{ \@@_check_if_correct_gender_input:n } +% +% +% +% +% +% \begin{macro}{ \@@_if_gender_error:n } % \begin{macrocode} -\prg_new_conditional:Npnn \@@_if_gender_error:n #1 { TF } +\prg_new_conditional:Npnn \@@_if_gender_error:n #1 { TF, F , T } { \str_case:nnTF {#1} { @@ -5497,145 +5938,233 @@ and the derived file cooking-units.sty. { n } { } } { \prg_return_false: } - { + { \msg_error:nnn { cooking-units } { unknown-gender } {#1} \prg_return_true: - } + } } -\cs_new:Npn \@@_check_if_correct_gender_input:n #1 +% \end{macrocode} +% \end{macro} +% +% +% +% +% +% +% \begin{macro}{\@@_error_if_group_not_defined:nN, \@@_error_if_group_not_defined:n} +% \begin{macrocode} +\prg_new_conditional:Npnn \@@_error_if_group_not_defined:nN #1#2 { F, T , TF } { - \str_case:nnF {#1} - { - { m } { } - { f } { } - { n } { } - } { \msg_error:nnn { cooking-units } { unknown-gender } {#1} } + \@@_set_unit:Nn #2 {#1} + \seq_if_exist:cTF { l_@@_group_ #2 _seq } + { \prg_return_false: } + { + \msg_error:nn { cooking-units} { group-key-unknown } + \prg_return_true: + } + } +\prg_new_conditional:Npnn \@@_error_if_group_not_defined:n #1 { F } + { + \seq_if_exist:cTF { l_@@_group_ \@@_to_unit:n {#1} _seq } + { \prg_return_false: } + { + \msg_error:nn { cooking-units} { group-key-unknown } + \prg_return_true: + } } % \end{macrocode} % \end{macro} % -% \begin{macro}{\@@_define_clear_unit_group:nn,\@@_add_to_unit_group_error:n,\@@_add_to_unit_group:nn} +% +% +% \begin{macro}{\@@_define_clear_unit_group:n} % \begin{macrocode} -\cs_new:Npn \@@_define_clear_unit_group:nn #1#2 +\cs_new:Npn \@@_define_clear_unit_group:n #1 { - \seq_clear_new:c { l_@@_group_ #1 _seq } - \keys_define:nn { cooking-units } + \@@_set_unit:Nn \l_@@_tmpa_tl {#1} + \seq_clear_new:c { l_@@_group_ \l_@@_tmpa_tl _seq } + \keys_define:nn { cooking-units } { #1 .code:n = { \@@_unit_group_convert_units:nn {#1} {##1} } , #1 .groups:n = { change-unit } , } } +% \end{macrocode} +% \end{macro} % -\cs_new:Npn \@@_add_to_unit_group_error:n #1 - { \msg_error:nnn { cooking-units } { No-Value-given } { add-unit-to-group } } % -\cs_new:Npn \@@_add_to_unit_group:nn #1#2 +% \begin{macro}{\@@_unit_group_convert_units:nn} +% \begin{macrocode} +\cs_new:Npn \@@_unit_group_convert_units:nn #1#2 { - \@@_error_if_group_not_defined:nF {#1} + \bool_set_true:N \l_@@_tmpa_bool + \@@_error_if_group_not_defined:nNT {#1} \l_@@_curr_group_tl + { \bool_set_false:N \l_@@_tmpa_bool } + \@@_error_if_unit_not_defined:nNT {#2} \l_@@_curr_unit_tl + { \bool_set_false:N \l_@@_tmpa_bool } + \bool_if:NT \l_@@_tmpa_bool { - \clist_map_inline:nn {#2} + \seq_if_in:cVTF { l_@@_group_ \l_@@_curr_group_tl _seq } \l_@@_curr_unit_tl { - \@@_error_if_unit_not_defined:nF {##1} - { - \seq_if_in:cnF { l_@@_group_ #1 _seq } {##1} - { \seq_put_right:cn { l_@@_group_ #1 _seq } {##1} } - } + \seq_map_inline:cn { l_@@_group_ \l_@@_curr_group_tl _seq } + { \@@_keys_set:nnn { cooking-units } {##1} {#2} } + }{ + \msg_error:nnxxx + { cooking-units } + { group-choice-not-allowed } + { \l_@@_curr_group_tl } { \l_@@_curr_unit_tl } + { \@@_seq_use_msg:c { l_@@_group_ \l_@@_curr_group_tl _seq } } } } } % \end{macrocode} % \end{macro} % -% \begin{macro}{\@@_error_if_group_not_defined:n} +% +% +% \begin{macro}{\@@_add_to_unit_group_error:n , \@@_add_to_unit_group:nn } % \begin{macrocode} -\prg_new_conditional:Npnn \@@_error_if_group_not_defined:n #1 { F } - { - \seq_if_exist:cTF { l_@@_group_ #1 _seq } - { \prg_return_false: } - { - \msg_error:nn { cooking-units} { group-key-unknown } - \prg_return_true: - } - } +\cs_new:Npn \@@_add_to_unit_group_error:n #1 + { \msg_error:nnn { cooking-units } { No-Value-given } { add-unit-to-group } } % \end{macrocode} -% \end{macro} -% -% \begin{macro}{\@@_unit_group_convert_units:nn} -% Didn't feel like intending the groups, as such use |\use_none:nnnnn(nnn)|. -% (Always wanted to use those |\use_none:|) % \begin{macrocode} -\cs_new:Npn \@@_unit_group_convert_units:nn #1#2 +\cs_new:Npn \@@_add_to_unit_group:nn #1#2 { - \@@_error_if_group_not_defined:nF {#1} + \@@_error_if_group_not_defined:nNF {#1} \l_@@_curr_group_tl { - \@@_error_if_unit_not_defined:nF {#2} + \clist_map_inline:nn {#2} { - \seq_if_in:cnTF { l_@@_group_ #1 _seq } {#2} + \@@_error_if_unit_not_defined:nNF {##1} \l_@@_curr_unit_tl { - \seq_map_inline:cn { l_@@_group_ #1 _seq } - { \@@_keys_set:nnn { cooking-units } {##1} {#2} } - }{ - \msg_error:nnxxx - { cooking-units } - { group-choice-not-allowed } - {#1} {#2} - { \@@_seq_use_msg:c { l_@@_group_ #1 _seq } } + \seq_if_in:cVF { l_@@_group_ \l_@@_curr_group_tl _seq } \l_@@_curr_unit_tl + { + \seq_put_right:cV + { l_@@_group_ \l_@@_curr_group_tl _seq } + \l_@@_curr_unit_tl + } } } } } +\cs_generate_variant:Nn \@@_add_to_unit_group:nn { nV } % \end{macrocode} % \end{macro} % % +% +% % \begin{macro}{\@@_convert_to_eV:} % Still work in progress. Will probably forever be. Changes all % predefined units into natural units (except for those who cannot % be changed, like |Msp.| for example). % % \begin{macrocode} -\seq_new:N \g_@@_natural_units_seq -\prop_new:N \g_@@_convert_to_eV_remember_prop -\seq_gset_from_clist:Nn \g_@@_natural_units_seq +\cs_new:Npn \@@_seq_get_overlap:NNTF #1#2 #3#4 { - eV , - eVc-2 , - hbareV-1 , - chbareV-1 , - (chbareV-1)3 , + \seq_map_inline:Nn #1 + { + \seq_if_in:NnT #2 {##1} + { #3 \seq_map_break:n { \use_none:nn } } + } + \use:n {#4} } +% \end{macrocode} +% \begin{macrocode} \cs_new:Npn \@@_keys_set:nnn #1#2#3 { \keys_set:nn {#1} { #2 = #3 } } \cs_generate_variant:Nn \@@_keys_set:nnn { nVV , nVn } -\cs_new:Npn \@@_convert_to_eV: +% \end{macrocode} +% \begin{macrocode} +\cs_new:Npn \@@_convert_to_eV:N #1 { - \tl_set_eq:Nc \l_@@_tmp_unit_tl { l_@@_base_key_unit_ \l_@@_original_unit_tl _tl } - \tl_if_empty:NF \l_@@_tmp_unit_tl + \prop_get:NVNTF \g_@@_convert_to_eV_remember_prop + #1 \l_@@_tmpa_tl + { \@@_keys_set:nVV { cooking-units } #1 \l_@@_tmpa_tl } { - \prop_get:NVNTF \g_@@_convert_to_eV_remember_prop - \l_@@_original_unit_tl \l_@@_tmpa_tl - { \@@_keys_set:nVV { cooking-units } \l_@@_original_unit_tl \l_@@_tmpa_tl } +% #1 is already a string + \@@_if_unit_has_a_key:VTF #1 { - \prop_get:cnNTF { l_@@_cukeys_ \l_@@_tmp_unit_tl _prop } { Liste } \l_@@_tmpa_seq + \tl_set_eq:Nc \l_@@_tmp_unit_tl { l_@@_base_key_unit_ #1 _tl } + \prop_get:cnNT { l_@@_new_cukeys_ \l_@@_tmp_unit_tl _prop } + { Liste } \l_@@_tmpa_seq { - \seq_map_inline:Nn \g_@@_natural_units_seq + \@@_seq_get_overlap:NNTF \g_@@_natural_units_seq \l_@@_tmpa_seq { - \seq_if_in:NnT \l_@@_tmpa_seq {##1} - { - \prop_gput:NVn \g_@@_convert_to_eV_remember_prop - \l_@@_original_unit_tl {##1} - \@@_keys_set:nVn { cooking-units } \l_@@_original_unit_tl {##1} - \seq_map_break: - } + \prop_gput:NVn \g_@@_convert_to_eV_remember_prop #1 {##1} + \@@_keys_set:nVn { cooking-units } #1 {##1} } + { \msg_warning:nnx { cooking-units } { no-natural-unit-known } {#1} } } - { \msg_error:nnn { cooking-units } { internal-error } { convert-to-eV } } } + { \msg_warning:nnx { cooking-units } { Key-not-defined } {#1} } } } % \end{macrocode} %\end{macro} % +% \begin{macrocode} +\cs_new:Npn \@@_changing_unit_bonkers:N #1 + { + \prop_get:NVNTF \g_@@_convert_bonkers_remember_prop + #1 \l_@@_tmpa_tl + { \@@_keys_set:nVV { cooking-units } #1 \l_@@_tmpa_tl } + { + \tl_case:NnF \l_@@_bonkers_state_tl + { + \c_@@_bonkers_state_going_tl { \@@_convert_going_bonkers:N #1 } + \c_@@_bonkers_state_fully_tl { \@@_convert_fully_bonkers:N #1 } + \c_@@_bonkers_state_xD_tl { \@@_convert_xD_bonkers:N #1 } + } + { \@@_create_internal_error:nN { going-bonkers } \l_@@_bonkers_state_tl } + } + } +\cs_new:Npn \@@_convert_going_bonkers:N #1 + { + \@@_if_unit_has_a_key:VT #1 + { + \@@_prepare_going_bonkers:N #1 + \keys_set:nn { cooking-units } { eval-fraction = true } + \@@_keys_set:nVV { cooking-units } #1 \l_@@_tmpa_tl + \prop_gput:NVV \g_@@_convert_bonkers_remember_prop #1 \l_@@_tmpa_tl + } + } +\cs_new:Npn \@@_convert_fully_bonkers:N #1 + { + \@@_if_unit_has_a_key:VT #1 + { + \@@_prepare_going_bonkers:N #1 + \keys_set:nn { cooking-units } + { eval-fraction = true , curef-clear-forbidden-units = true } + \prop_put:NVV \l_@@_change_unit_prop {#1} \l_@@_tmpa_tl + \@@_cukeys_calculate_change_value:VVV #1 \l_@@_tmpa_tl \l_@@_tmp_unit_tl + } + } +\cs_new:Npn \@@_prepare_going_bonkers:N #1 + { + \tl_set_eq:Nc \l_@@_tmp_unit_tl { l_@@_base_key_unit_ #1 _tl } + \prop_get:cnN { l_@@_new_cukeys_ \l_@@_tmp_unit_tl _prop } { Liste } \l_@@_tmpa_seq + \bool_set_false:N \l_@@_tmpa_bool + \bool_until_do:Nn \l_@@_tmpa_bool + { + \tl_set:Nf \l_@@_tmpa_tl { \seq_rand_item:N \l_@@_tmpa_seq } + \seq_if_in:NVF \g_@@_natural_units_seq \l_@@_tmpa_tl + { \bool_set_true:N \l_@@_tmpa_bool } + } + } +\cs_new:Npn \@@_convert_xD_bonkers:N #1 + { + \keys_set:nn { cooking-units } { eval-fraction = true , curef-clear-forbidden-units = true } + \bool_set_false:N \l_@@_tmpa_bool + \bool_until_do:Nn \l_@@_tmpa_bool + { + \tl_set:Nx \l_@@_tmpa_tl { \seq_rand_item:N \g_@@_list_of_defined_units_seq } + \@@_if_no_unit_marker:NF \l_@@_tmpa_tl + { \bool_set_true:N \l_@@_tmpa_bool } + } + \prop_put:NVV \l_@@_change_unit_prop {#1} \l_@@_tmpa_tl + \tl_set:cf { l_@@_unit_change_ #1 _tl } { \fp_eval:n { rand() * randint(255) } } + } +% \end{macrocode} % % % @@ -5643,7 +6172,7 @@ and the derived file cooking-units.sty. % I am using this construction often enough, so \dots\ yeah. % \begin{macrocode} \cs_new:Npn \@@_tl_eval:Nn #1#2 { \tl_set:Nf #1 { \fp_eval:n {#2} } } -\cs_generate_variant:Nn \@@_tl_eval:Nn { Nv } +\cs_generate_variant:Nn \@@_tl_eval:Nn { Nv, cn } % \end{macrocode} % \end{macro} % @@ -5653,16 +6182,15 @@ and the derived file cooking-units.sty. % I am using this construction often enough, so \dots\ yeah. % Note that if the evaluation is |true|, the path taken is the |false| one. % \begin{macrocode} -\prg_new_conditional:Npnn \@@_change_unit: { TF , T } +\prg_new_conditional:Npnn \@@_change_unit: { TF } { - \bool_lazy_any:nTF - { - { \l_@@_lokal_fraction_bool } - { \l_@@_special_sign_bool } - { \l_@@_draft_bool } - } + \@@_if_print_type_equal:nTF { fraction } { \prg_return_false: } - { \prg_return_true: } + { + \@@_if_state_equal:nTF { special_sign } + { \prg_return_false: } + { \prg_return_true: } + } } % \end{macrocode} % \end{macro} @@ -5681,43 +6209,36 @@ and the derived file cooking-units.sty. } \cs_new:Npn \@@_temperatures_to_check_define:nn #1#2 { - \@@_error_if_unit_not_defined:nF {#1} + \@@_error_if_unit_not_defined:nNF {#1} \l_@@_curr_unit_tl { - \fp_if_exist:cTF { l_@@_ #1 _min_fp } - { -% \msg_warning:nnn { cooking-units } { Minimum-already-defined } {#1} - \fp_set:cn { l_@@_ #1 _min_fp } {#2} - }{ - \seq_put_right:Nn \l_@@_temperatures_to_check_seq {#1} - \fp_new:c { l_@@_ #1 _min_fp } - \fp_set:cn { l_@@_ #1 _min_fp } {#2} + \fp_if_exist:cF { l_@@_ \l_@@_curr_unit_tl _min_fp } + { + \seq_put_right:NV \l_@@_temperatures_to_check_seq \l_@@_curr_unit_tl + \fp_new:c { l_@@_ \l_@@_curr_unit_tl _min_fp } } + \fp_set:cn { l_@@_ \l_@@_curr_unit_tl _min_fp } {#2} } } % \end{macrocode} % \end{macro} % -% \begin{macro}{ \@@_set_options_for_error:n , \@@_set_options_for:nn } +% \begin{macro}{ \@@_set_options_for_error:n } % \begin{macrocode} \cs_new:Npn \@@_set_options_for_error:n #1 { \@@_error_if_unit_not_defined:n {#1} \msg_error:nnn { cooking-units } { No-Value-given } { set-option-for } } -\cs_new:Npn \@@_set_options_for:nn #1#2 - { \cusetoptionfor {#1} {#2} } % \end{macrocode} % \end{macro} % -% \begin{macro}{ \@@_add_options_for_error:n , \@@_add_options_for:nn } +% \begin{macro}{ \@@_add_options_for_error:n } % \begin{macrocode} \cs_new:Npn \@@_add_options_for_error:n #1 { \@@_error_if_unit_not_defined:n {#1} \msg_error:nnn { cooking-units } { No-Value-given } { add-option-for } } -\cs_new:Npn \@@_add_options_for:nn #1#2 - { \cuaddoptionfor {#1} {#2} } % \end{macrocode} % \end{macro} % @@ -5728,7 +6249,7 @@ and the derived file cooking-units.sty. { #1 , \l_@@_round_precision_int - \bool_if:NT \l_@@_round_commercial_bool + \bool_if:NT \l_@@_pckopt_round_commercial_bool { , #1 } } % \end{macrocode} @@ -5738,12 +6259,9 @@ and the derived file cooking-units.sty. % \begin{macrocode} \cs_new:Npn \@@_label_and_persons:n #1 { - \tl_if_in:nnTF {#1} { * } - { - \@@_label_and_persons_times_persons:ww #1 \q_stop - }{ - \msg_error:nnn { cooking-units} { Number-of-persons-missing } {#1} - } + \str_if_in:nnTF {#1} { * } + { \@@_label_and_persons_times_persons:ww #1 \q_stop } + { \msg_error:nnn { cooking-units} { Number-of-persons-missing } {#1} } } % \end{macrocode} % \end{macro} @@ -5760,13 +6278,13 @@ and the derived file cooking-units.sty. \cs_new:Npn \@@_culabel:nn #1#2 { \int_if_exist:cTF { g_@@_number_of_persons_ #1 _int } + { \msg_error:nnn { cooking-units } { label-already-defined } {#1} } { - \msg_error:nnn { cooking-units } { label-already-defined } {#1} - }{ - \@@_if_integer:nTF {#2} + \@@_if_evaluation_is_integer:nTF {#2} { + \int_set:Nn \l_@@_tmpa_int {#2} \int_new:c { g_@@_number_of_persons_ #1 _int } - \int_gset:cn { g_@@_number_of_persons_ #1 _int } {#2} + \int_gset_eq:cN { g_@@_number_of_persons_ #1 _int } \l_@@_tmpa_int } { \msg_error:nnn { cooking-units } { Number-of-persons-is-not-an-integer } {#2} } } @@ -5780,7 +6298,7 @@ and the derived file cooking-units.sty. { \int_if_exist:cTF { g_@@_number_of_persons_ #1 _int } { - \bool_set_true:N \l_@@_calc_because_ref_was_given_bool + \bool_set_true:N \l_@@_reference_given_bool \int_set_eq:Nc \l_@@_local_number_of_persons_int { g_@@_number_of_persons_ #1 _int } } @@ -5795,7 +6313,7 @@ and the derived file cooking-units.sty. { \int_if_exist:cTF { g_@@_number_of_persons_ #1 _int } { - \bool_if:NTF \l_@@_change_number_of_persons_bool + \bool_if:NTF \l_@@_pckopt_recalculate_amount_bool { \int_use:N \l_@@_wanted_number_of_persons_int } { \int_use:c { g_@@_number_of_persons_ #1 _int } } }{ \msg_error:nnn { cooking-units } { label-not-defined } {#1} } @@ -5813,27 +6331,21 @@ and the derived file cooking-units.sty. % % % -% \begin{macro}{ \@@_bool_reverse:N, \@@_check_minus_remove_and_reverse:NN } +% \begin{macro}{ \@@_check_minus_remove_and_reverse:NN } % Can probably optimize this as the sign is always at the first place % (this is done after cheking the input, so the assumption is safe), but yeah \dots % \begin{macrocode} -\cs_new:Npn \@@_bool_reverse:N #1 - { - \bool_if:NTF #1 - { \bool_set_false:N } - { \bool_set_true:N } - #1 - } \cs_new:Npn \@@_check_minus_remove_and_reverse:NN #1#2 { \quark_if_nil:NF #2 { + %% Maybe simplify by a command? \tl_if_in:NnT #2 { - } { \tl_remove_once:Nn #2 { - } - \@@_bool_reverse:N #1 + \bool_if:NTF #1 { \bool_set_false:N } { \bool_set_true:N } #1 } - \@@_check_minus_remove_and_reverse:NN #1 + \@@_check_minus_remove_and_reverse:NN #1 } } % \end{macrocode} @@ -5841,285 +6353,977 @@ and the derived file cooking-units.sty. % % % -% \subsection{Language Macros} % -% \begin{macrocode} -\tl_const:Nn \c_@@_postfix_unit_tl { ( cu-unit ) } -\tl_const:Nn \c_@@_postfix_unit_pl_tl { ( cu-unit-pl ) } -\tl_const:Nn \c_@@_postfix_unitname_tl { ( cu-unitname ) } -\tl_const:Nn \c_@@_postfix_unitname_pl_tl { ( cu-unitname-pl ) } -\tl_const:Nn \c_@@_postfix_gender_tl { ( cu-unitgender ) } -\tl_const:Nn \c_@@_postfix_phrase_tl { ( cu-unitphrase ) } -% \end{macrocode} % -% \begin{macro}{\@@_deftranslation_base:nnn, \@@_deftranslation_base:xVn } -% \begin{macro}{\@@_deftranslation_to:nnnn , \@@_deftranslation_to:VxVv,\@@_deftranslation_to:VxVV,\@@_deftranslation_to:VxVn} +% +% +% +% % \begin{macrocode} -\cs_new:Npn \@@_deftranslation_base:nnn #1#2#3 +\cs_new:Npn \@@_add_forbidden_unit:n #1 { - \declaretranslationfallback { #1 #2 } {#3} + \seq_set_from_clist:Nn \l_@@_tmpa_seq {#1} + \seq_map_inline:Nn \l_@@_tmpa_seq + { + \@@_error_if_unit_not_defined:nNF {##1} \l_@@_curr_unit_tl + { + \seq_if_in:NVF \l_@@_curef_do_not_change_seq \l_@@_curr_unit_tl + { \seq_put_right:NV \l_@@_curef_do_not_change_seq \l_@@_curr_unit_tl } + } + } } -\cs_new:Npn \@@_deftranslation_to:nnnn #1#2#3#4 +\cs_new:Npn \@@_remove_forbidden_unit:n #1 { - \declaretranslation {#1} { #2 #3 } {#4} + \seq_set_from_clist:Nn \l_@@_tmpa_seq {#1} + \seq_map_inline:Nn \l_@@_tmpa_seq + { + \@@_error_if_unit_not_defined:nNF {##1} \l_@@_curr_unit_tl + { + \seq_if_in:NVTF \l_@@_curef_do_not_change_seq \l_@@_curr_unit_tl + { \seq_remove_all:NV \l_@@_curef_do_not_change_seq \l_@@_curr_unit_tl } + { + \msg_warning:nnnn { cooking-units } { curef-not-inside-list } {##1} + { \@@_seq_use_msg:N \l_@@_curef_do_not_change_seq } + } + } + } } -\cs_generate_variant:Nn \@@_deftranslation_base:nnn { xV } -\cs_generate_variant:Nn \@@_deftranslation_to:nnnn { VxVv, VxVV , VxVn } +\cs_new:Npn \@@_clear_forbidden_unit: + { \seq_clear:N \l_@@_curef_do_not_change_seq } % \end{macrocode} -% \end{macro} -% \end{macro} % % % -% \begin{macro}{\@@_newtranslation:xxn } -% \begin{macro}{\@@_newtranslation:nxxn } +% +% +% % \begin{macrocode} -\cs_new:Npn \@@_newtranslation_base:nnn #1#2#3 +\NewDocumentCommand \cudeclareunitgroup { m m } + { + \@@_define_clear_unit_group:n {#1} + \@@_add_to_unit_group:nn {#1} {#2} + } +\NewDocumentCommand \cuaddtounitgroup { m m } { - \definetranslationfallback { #1 #2 } {#3} + \@@_add_to_unit_group:nn {#1} {#2} } -\cs_new:Npn \@@_newtranslation_to:nnnn #1#2#3#4 +\NewDocumentCommand \cuclearunitgroup { m } { - \definetranslation {#1} { #2 #3 } {#4} + \@@_error_if_group_not_defined:nF {#1} + { \@@_define_clear_unit_group:n {#1} } } -\cs_generate_variant:Nn \@@_newtranslation_base:nnn { nVn } -\cs_generate_variant:Nn \@@_newtranslation_to:nnnn { nnVn } % \end{macrocode} -% \end{macro} +% +% +% +% +% +% +% +% +% \begin{macro}{ \cusetoptionfor , \cuaddoptionfor , \cuclearoptionfor} +% \pkg{cooking-units} allows to attach options to units. Every time the unit +% is used, the option is executed (technically it is similar or equal to a hook). +% Using these commands, one can set (overwrites all previous options), +% add or clear options for a unit or a list of units. +% \begin{macrocode} +\NewDocumentCommand \cusetoptionfor { m m } + { \@@_set_options_for:nn {#1} {#2} } +\NewDocumentCommand \cuaddoptionfor { m m } + { \@@_add_options_for:nn {#1} {#2} } +\NewDocumentCommand \cuclearoptionfor { m } + { \@@_clear_options_for:n {#1} } +% \end{macrocode} % \end{macro} % +% \begin{macro}{\@@_set_options_for:nn , \@@_add_options_for:nn , \@@_clear_options_for:n} +% These commands are quite similar, excpet for a few details. +% First, store the unit or list of units |#1| and the list of options |#2|. +% At the end, for each unit in |#1| a clist will be created (if not already existing) +% where the options will be put \emph{via} |\clist_set:cn|, |\clist_put_right:cn| +% or will be cleared (see there). % -% \begin{macro}{\@@_translate:nn , \@@_translate:xV } -% \begin{macro}{\@@_translate_let:Nnn , \@@_translate_let:NnV } -% \begin{macro}{\@@_translate_let:nNnn , \@@_translate_let:VNnV } +% E.g.\ |\clist_set:cn| will get something like |\clist_set:cV {...unit...clist} \clist_containing_options_clist|. +% As |\clist_clear:c| does not take a second argument, we will eat it \emph{via} +% |\use_i_ii:nnn|. % \begin{macrocode} -\cs_new:Npn \@@_translate:nn #1#2 +\cs_new:Npn \@@_set_options_for:nn #1#2 { - \GetTranslation { #1 #2 } + \@@_map_trough_valid_unit_options:nnn {#1} {#2} { \clist_set:cV } } -\cs_new:Npn \@@_translate_let:Nnn #1#2#3 +\cs_new:Npn \@@_add_options_for:nn #1#2 { - \SaveTranslation {#1} { #2 #3 } + \@@_map_trough_valid_unit_options:nnn {#1} {#2} { \clist_put_right:cV } } -\cs_new:Npn \@@_translate_let:nNnn #1#2#3#4 +\cs_new:Npn \@@_clear_options_for:n #1 { - \SaveTranslationFor {#2} {#1} { #3 #4 } + \@@_map_trough_valid_unit_options:nnn {#1} { \q_no_value } { \clist_clear:c } } -\cs_generate_variant:Nn \@@_translate:nn { VV, nV } -\cs_generate_variant:Nn \@@_translate_let:Nnn { NnV } -\cs_generate_variant:Nn \@@_translate_let:nNnn { VNnV, nNnV } +\cs_generate_variant:Nn \@@_set_options_for:nn { V } +\cs_generate_variant:Nn \@@_clear_options_for:n { V } % \end{macrocode} % \end{macro} -% \end{macro} -% \end{macro} -% -% \begin{macro}[TF]{\@@_unitname_get:Nn,\@@_unitname_get:Nx } +% +% \begin{macro}{\@@_map_trough_valid_unit_options:nnn} +% The first thing is command does is to map through the given unit list |#1| +% and check if the unit(s) exist or not. If they exist, store them in the sequence +% |\l_@@_tmpa_seq| for later use. Else, ignore it and print a warning. +% +% If |#2| is a |\q_no_value| we know that there is no need to map through |#2|. +% Whatever the command |#3| does, it does so only to the clist +% |l_@@_unit_option_ _clist|. +% +% If |#2| is anything else, follow the |else| branch. After veryfing that |#2| +% is non-empty map through the option list given in |#2|. All valid keys +% (and their agrument) is stored in |\l_@@_tmpa_clist|. +% Afterwards, the clist for each unit in |\l_@@_tmpa_seq| is modified by the command +% in |#3| and is given the list of options |\l_@@_tmpa_clist| as an argument. +% (Note: |\l_@@_tmpa_clist| can be empty). % \begin{macrocode} -\prg_new_conditional:Npnn \@@_unitname_get:Nn #1#2 { F } +\cs_new:Npn \@@_map_trough_valid_unit_options:nnn #1#2 #3 { - \@@_translate_let:NnV #1 {#2} \c_@@_postfix_unitname_tl - \tl_if_eq:NNTF #1 \q_@@_no_translation - { \prg_return_false: } - { \prg_return_true: } + \seq_clear:N \l_@@_tmpa_seq + \clist_clear:N \l_@@_tmpa_clist + \clist_map_inline:nn {#1} + { + \@@_error_if_unit_not_defined:nNF {##1} \l_@@_curr_unit_tl + { \seq_put_right:NV \l_@@_tmpa_seq \l_@@_curr_unit_tl } + } + \quark_if_no_value:nTF {#2} + { + \seq_map_inline:Nn \l_@@_tmpa_seq + { #3 { l_@@_unit_option_ ##1 _clist } } + }{ + \tl_if_empty:nF {#2} + { \@@_unit_options_check_validity:n {#2} } + \seq_map_inline:Nn \l_@@_tmpa_seq + { #3 { l_@@_unit_option_ ##1 _clist } \l_@@_tmpa_clist } + } } -\cs_generate_variant:Nn \@@_unitname_get:NnF { Nx } % \end{macrocode} % \end{macro} % -% \begin{macro}{\@@_translate_one_and_check_existance:Nx } -% As |#2| is already going to be expanded, using |\@@_translate_let:NnV| is safe. +% \begin{macro}{ \@@_unit_options_check_validity:n } +% If the list of options is non-empty, we parse over them using +% |\keyval_parse:NNn|. For this we need two commands, one for keys +% with argument, one without arguments. All the commands do is to check +% if the key given does exist. And if they do, store them in |\l_@@_tmpa_clist|. % \begin{macrocode} -\cs_new:Npn \@@_translate_one_and_check_existance:Nn #1#2 +\cs_new:Npn \@@_unit_options_check_validity:n #1 { - \@@_translate_let:NnV #1 {#2} \c_@@_postfix_gender_tl - \@@_unitname_get:NxF #1 { one (#1) } - { - \@@_translate_let:NnV #1 {#2} \c_@@_postfix_gender_tl - \msg_error:nnn { cooking-units } { Translation-not-available } { one (#1) } - } + \keyval_parse:NNn + \@@_unit_options_check_validity_aux_i:n + \@@_unit_options_check_validity_aux_ii:nn + {#1} } -\cs_generate_variant:Nn \@@_translate_one_and_check_existance:Nn { Nx } % \end{macrocode} % \end{macro} % -% \begin{macro}{ decimal-mark, one(m), one(f), one(n) } -% Defining the translation for the decimal-mark. Note that those -% 'phrases' are stored inside -% \verb|\g_@@_allowed_special_keys_seq|. -% Furthermore some translations are defined. +% \begin{macro}{ \@@_unit_options_check_validity_aux_i:n , +% \@@_unit_options_check_validity_aux_ii:nn } +% Check if the key exist; if it is then put it in |\l_@@_tmpa_clist| (just the key, or with the value). +% Sadly, checking if the value |#2| can be accepted by the key is not really testable. % \begin{macrocode} -\seq_gset_from_clist:Nn \g_@@_allowed_special_keys_seq +\cs_new:Npn \@@_unit_options_check_validity_aux_i:n #1 { - decimal-mark , - one (m) , - one (f) , - one (n) + \keys_if_exist:nnTF { cooking-units } {#1} + { \clist_put_right:Nn \l_@@_tmpa_clist {#1} } + { \msg_error:nnn { cooking-units } { unknown-option } {#1} } + } +\cs_new:Npn \@@_unit_options_check_validity_aux_ii:nn #1#2 + { + \keys_if_exist:nnTF { cooking-units } {#1} + { + \clist_put_right:Nn \l_@@_tmpa_clist { #1= {#2} } +% \keys_if_choice_exist:nnnTF { cooking-units } {#1} {#2} +% { \clist_put_right:Nn \l_@@_tmpa_clist { #1= {#2} } } +% { \msg_error:nnnn { cooking-units } { unknown-choice } {#1} {#2} } + } + { \msg_error:nnn { cooking-units } { unknown-option } {#1} } } % \end{macrocode} % \end{macro} -% \begin{macrocode} -\@@_newtranslation_base:nVn { decimal-mark } \c_@@_postfix_unitname_tl { . } -\@@_newtranslation_base:nVn { decimal-mark } \c_@@_postfix_unitname_pl_tl { \q_@@_no_translation } -\@@_newtranslation_to:nnVn { German } { decimal-mark } \c_@@_postfix_unitname_tl { , } -% \end{macrocode} -% Note that the plural versions just exist for completing the set. -% \begin{macrocode} -\@@_newtranslation_base:nVn { one (m) } \c_@@_postfix_unitname_tl { \q_@@_no_translation } -\@@_newtranslation_base:nVn { one (f) } \c_@@_postfix_unitname_tl { \q_@@_no_translation } -\@@_newtranslation_base:nVn { one (n) } \c_@@_postfix_unitname_tl { \q_@@_no_translation } -\@@_newtranslation_base:nVn { one (m) } \c_@@_postfix_unitname_pl_tl { \q_@@_no_translation } -\@@_newtranslation_base:nVn { one (f) } \c_@@_postfix_unitname_pl_tl { \q_@@_no_translation } -\@@_newtranslation_base:nVn { one (n) } \c_@@_postfix_unitname_pl_tl { \q_@@_no_translation } -% \end{macrocode} -% \begin{macrocode} -\@@_newtranslation_to:nnVn { English } { one (m) } \c_@@_postfix_unitname_tl { one } -\@@_newtranslation_to:nnVn { English } { one (f) } \c_@@_postfix_unitname_tl { one } -\@@_newtranslation_to:nnVn { English } { one (n) } \c_@@_postfix_unitname_tl { one } -% \end{macrocode} -% \begin{macrocode} -\@@_newtranslation_to:nnVn { German } { one (m) } \c_@@_postfix_unitname_tl { ein } -\@@_newtranslation_to:nnVn { German } { one (f) } \c_@@_postfix_unitname_tl { eine } -\@@_newtranslation_to:nnVn { German } { one (n) } \c_@@_postfix_unitname_tl { ein } -% \end{macrocode} +% % -% \begin{macrocode} -\@@_newtranslation_base:nVn { cutext-range-sign } \c_@@_postfix_unitname_tl { -- } -\@@_newtranslation_base:nVn { cutext-range-sign } \c_@@_postfix_unitname_pl_tl { \q_@@_no_translation } -\@@_newtranslation_to:nnVn { German } { cutext-range-sign } \c_@@_postfix_unitname_tl { ~bis~ } -\@@_newtranslation_to:nnVn { English } { cutext-range-sign } \c_@@_postfix_unitname_tl { ~to~ } -% \end{macrocode} % % -% \section{General} % -% This section collects commands which are used by all four main commands +% +% +% +% +% +% \subsection{Language Macros} +% +% +% The following commands are just wrapper around the commands from the +% \pkg{translations} package. +% +% \begin{macro}{ \@@_culang_def_base:nnn , \@@_culang_def_base:nnv , \@@_culang_def_base:nVn} +% \begin{macrocode} +\cs_new:Npn \@@_culang_def_base:nnn #1#2#3 + { \declaretranslationfallback { #2 - #1 (@@) } {#3} } +\cs_generate_variant:Nn \@@_culang_def_base:nnn { nnv, nVn } +% \end{macrocode} +% \end{macro} +% +% \begin{macro}{ \@@_culang_def_for:nnnn, \@@_culang_def_for:VnnV , \@@_culang_def_for:Vnnn } +% \begin{macrocode} +\cs_new:Npn \@@_culang_def_for:nnnn #1#2#3#4 + { \declaretranslation {#1} { #3 - #2 (@@) } {#4} } +\cs_generate_variant:Nn \@@_culang_def_for:nnnn { VnnV, V } +% \end{macrocode} +% \end{macro} +% +% \begin{macro}{ \@@_culang_print:nn , \@@_culang_print:nV } +% \begin{macrocode} +\cs_new:Npn \@@_culang_print:nn #1#2 + { \GetTranslation { #2 - #1 (@@) } } +\cs_generate_variant:Nn \@@_culang_print:nn { nV } +% \end{macrocode} +% \end{macro} +% +% \begin{macro}{ \@@_culang_let:nnN } +% \begin{macrocode} +\cs_new:Npn \@@_culang_let:nnN #1#2#3 + { \SaveTranslation #3 { #2 - #1 (@@) } } +% \end{macrocode} +% \end{macro} +% +% \begin{macro}{ \@@_culang_let_for:nnnN , \@@_culang_let_for:VnnN } +% \begin{macrocode} +\cs_new:Npn \@@_culang_let_for:nnnN #1#2#3#4 + { \SaveTranslationFor #4 {#1} { #3-#2 (@@) } } +\cs_generate_variant:Nn \@@_culang_let_for:nnnN { V } +% \end{macrocode} +% \end{macro} +% +% \begin{macro}[TF]{ \@@_culang_if_translation_exists_for:nnn, \@@_culang_if_translation_exists_for:Vnn} +% \begin{macrocode} +\cs_new:Npn \@@_culang_if_translation_exists_for:nnnTF #1#2#3 + { \IfTranslation {#1} { #3 - #2 (@@) } } +\cs_generate_variant:Nn \@@_culang_if_translation_exists_for:nnnTF { V } +% \end{macrocode} +% \end{macro} +% +% +% +% +% +% \begin{macro}[TF, F]{\@@_culang_unitname_let:Nn , \@@_culang_unitname_let:NV } +% \begin{macrocode} +\prg_new_conditional:Npnn \@@_culang_unitname_let:Nn #1#2 { TF, F , T } + { + \@@_culang_let:nnN { name } {#2} #1 + \tl_if_eq:NNTF #1 \q_@@_no_translation + { \prg_return_false: } + { \prg_return_true: } + } +\cs_generate_variant:Nn \@@_culang_unitname_let:NnTF { NV, Nx } +\cs_generate_variant:Nn \@@_culang_unitname_let:NnT { Nx } +% \end{macrocode} +% \end{macro} +% +% \begin{macro}{ \@@_culang_one_let:Nn , \@@_culang_one_let:NV , +% \@@_culang_one_let_by_gender:Nn , \@@_culang_one_let_by_gender:NV +% } +% \begin{macrocode} +\prg_new_conditional:Npnn \@@_culang_one_let:Nn #1#2 { T } + { + \@@_culang_let:nnN { gender } {#2} \l_@@_tmpa_tl + \@@_culang_one_let_by_gender:NVTF #1 \l_@@_tmpa_tl + { \prg_return_true: } + { + \tl_set:Nn #1 { 1 } + \prg_return_false: + } + } +\cs_generate_variant:Nn \@@_culang_one_let:NnT { NV } +\prg_new_conditional:Npnn \@@_culang_one_let_by_gender:Nn #1#2 { TF } + { + \@@_culang_unitname_let:NnTF #1 { one (#2) } + { \prg_return_true: } + { + \msg_error:nnx { cooking-units } { Translation-not-available } { one (#2) } + \prg_return_false: + } + } +\cs_generate_variant:Nn \@@_culang_one_let_by_gender:NnTF { NV } +% \end{macrocode} +% \end{macro} +% +% \begin{macro}{ \g_@@_allowed_special_keys_seq } +% Defining the translation for the decimal-mark. Note that those +% 'phrases' are stored inside +% \verb|\g_@@_allowed_special_keys_seq|. +% Furthermore some translations are defined. +% \begin{macrocode} +\seq_gset_from_clist:Nn \g_@@_allowed_special_keys_seq + { + cutext-range-sign , + decimal-mark , + one (m) , + one (f) , + one (n) + } +% \end{macrocode} +% \end{macro} +% +% \begin{macrocode} +\@@_culang_def_base:nnn { name } { decimal-mark } { . } +\@@_culang_def_base:nnn { name-pl } { decimal-mark } { \q_@@_no_translation } +\@@_culang_def_for:nnnn { German } { name-pl } { decimal-mark } { , } +% \end{macrocode} +% Note that the plural versions just exist for completing the set. +% \begin{macrocode} +\@@_culang_def_base:nnn { name } { one (m) } { \q_@@_no_translation } +\@@_culang_def_base:nnn { name } { one (f) } { \q_@@_no_translation } +\@@_culang_def_base:nnn { name } { one (n) } { \q_@@_no_translation } +\@@_culang_def_base:nnn { name-pl } { one (m) } { \q_@@_no_translation } +\@@_culang_def_base:nnn { name-pl } { one (f) } { \q_@@_no_translation } +\@@_culang_def_base:nnn { name-pl } { one (n) } { \q_@@_no_translation } +% \end{macrocode} +% \begin{macrocode} +\@@_culang_def_for:nnnn { English } { name } { one (m) } { one } +\@@_culang_def_for:nnnn { English } { name } { one (f) } { one } +\@@_culang_def_for:nnnn { English } { name } { one (n) } { one } +% \end{macrocode} +% \begin{macrocode} +\@@_culang_def_for:nnnn { German } { name } { one (m) } { ein } +\@@_culang_def_for:nnnn { German } { name } { one (f) } { eine } +\@@_culang_def_for:nnnn { German } { name } { one (n) } { ein } +% \end{macrocode} +% +% \begin{macrocode} +\@@_culang_def_base:nnn { name } { cutext-range-sign } { -- } +\@@_culang_def_base:nnn { name-pl } { cutext-range-sign } { \q_@@_no_translation } +\@@_culang_def_for:nnnn { German } { name } { cutext-range-sign } { ~bis~ } +\@@_culang_def_for:nnnn { English } { name } { cutext-range-sign } { ~to~ } +% \end{macrocode} +% +% +% \section{General} +% +% This section collects commands which are used by all four main commands % (\mycs{cunum}, \cCutext, \mycs{cuam}), hence the name. % % -% \begin{macro}{\@@_initialise_default:n , -% \@@_initialise_unit_change:n , -% \@@_initialise_after_unit_change:nn -% } -% Functions shared by all initialization functions: +% \subsection{Enums \& States} +% +% These variables decide what the main commands (\cs{cunum}, etc.) should do. +% Is there an error? Special-sign? Fraction? Range? Which command is used? +% This is defined here. +% +% \begin{macro}{ \@@_def_new_type:nnn , \@@_def_new_type_aux:cnn , \@@_def_new_type_aux:Nnn} +% Defines my variants, all in one handy command (well, two commands). +% |#1| is the base name of the new state. |#2| are the conditions for +% |\prg_new_conditional|. |#3| are the possible states, given as a comma list. +% \begin{macrocode} +\cs_new:Npn \@@_def_new_type:nnn #1#2#3 + { + \tl_new:c { l_@@_ #1 _tl } + \clist_map_inline:nn {#3} + { \tl_const:cn { c_@@_ #1 _ ##1 _tl } {##1} } + \@@_def_new_type_aux:cnn { l_@@_ #1 _tl } {#1} {#2} + } +% \end{macrocode} +% Defines the commands |@@_set__to:n| and (if wanted) +% |@@_if_ _equal:n|. For maybe optimization (not sure why) +% I decided that |#1| is the token varable which stores the state we are currently +% in. +% \begin{macrocode} +\cs_new:Npn \@@_def_new_type_aux:Nnn #1#2#3 + { + \cs_new:cpn { @@_set_ #2 _to:n } ##1 + { + \tl_if_exist:cF { c_@@_#2_ ##1 _tl } { \tl_show:n { ERROR-set-#2-##1 } } + \tl_set_eq:Nc #1 { c_@@_#2_ ##1 _tl } + } + \tl_if_empty:nF {#3} + { + \prg_new_conditional:cpnn { @@_if_ #2 _equal:n } ##1 {#3} + { + \tl_if_exist:cF { c_@@_#2_ ##1 _tl } { \tl_show:n { ERROR-check-#2-##1 } } + \tl_if_eq:NcTF #1 { c_@@_#2_ ##1 _tl } + { \prg_return_true: } + { \prg_return_false: } + } + } + } +\cs_generate_variant:Nn \@@_def_new_type_aux:Nnn { c } +% \end{macrocode} +% \end{macro} +% +% Defining some states. +% \begin{macrocode} +\@@_def_new_type:nnn { state } { TF , T , F , p } + { normal , special_sign , 42 , error } +\@@_def_new_type:nnn { cmd_type } { TF , T , p } + { cunum , cCutext , cuam } +\@@_def_new_type:nnn { parse_and_process_type } { TF , T } + { number , range , fraction } +\@@_def_new_type:nnn { print_type } { TF , T } + { unknown , number , range , fraction } +\@@_def_new_type:nnn { bonkers_state } { } + { normal , going , fully , xD } +% \end{macrocode} +% +% Setting a default state.. +% \begin{macrocode} +\tl_set_eq:NN \l_@@_bonkers_state_tl \c_@@_bonkers_state_normal_tl +% \end{macrocode} +% +% +% \subsection{The main stuff} +% +% \begin{macro} { \@@_expand_unit_input:Nn , \@@_expand_amount_input:Nn } +% \begin{macrocode} +\cs_new:Npn \@@_expand_unit_input:Nn #1#2 + { + \cs_if_exist_use:c { exp_args:NN \l_@@_unit_argument_spec_tl } + \@@_set_unit:Nn #1 {#2} + } +\cs_new:Npn \@@_expand_amount_input:Nn #1#2 + { + \cs_if_exist_use:c { exp_args:NN \l_@@_expand_amount_tl } + \@@_set_amount:Nn #1 {#2} + } +% \end{macrocode} +% \end{macro} +% +% +% +% \begin{macro}{ \@@_do_the_stuff:nnnnn , \@@_do_the_stuff:nnnnn } +% Main command shared by |\cunum|, etc.\ It reads the input +% parses options and decides (depending on which command was used) +% what to do with the stuff and how to print it. +% \begin{macrocode} +\bool_new:N \l_@@_skip_first_part_bool +\cs_new:Npn \@@_do_the_stuff:nnnnnn #1#2#3#4#5#6 + { +% #1 -- label +% #2 -- options +% #3 -- amount +% #4 -- space +% #5 -- unit + \@@_initialice_accordingly:nnnn {#1} {#4} {#2} {#5} + \@@_use_hook_accordingly: + \@@_parse_the_amount:n {#3} + \@@_general_checkups: + \@@_if_state_equal:nTF { normal } + { \@@_process_amount_normally:n {#2} } + { \@@_process_amount_special: } + \@@_new_print_amount_correctly: + \@@_new_print_unit_correctly: + } +\cs_generate_variant:Nn \@@_do_the_stuff:nnnnnn { nnnnV } +% \end{macrocode} +% \end{macro} +% +% \begin{macro}{\@@_initialice_accordingly:nnnn , \@@_initialice_addon_cutext: } +% This cs first initializes stuff that is equal for all commands, then +% does command-specific things. The default stuff includes checking if the +% unit is valid, setting some bools, sets options (including change of units), etc. +% +% For |\cunum| we set the space used for |\phantom|, for |\cuam| we do nothing. +% \begin{macrocode} +\cs_new:Npn \@@_initialice_accordingly:nnnn #1#2#3#4 + { + \@@_initialize_new_default:nnn {#1} {#3} {#4} + \@@_initialize_new_default_units: + \tl_case:NnF \l_@@_cmd_type_tl + { + \c_@@_cmd_type_cunum_tl { \tl_set:Nn \l_@@_phantom_tl {#2} } + \c_@@_cmd_type_cCutext_tl { \@@_initialice_addon_cutext: } + \c_@@_cmd_type_cuam_tl { } + } + { \@@_create_internal_error:nN { init-acc } \l_@@_cmd_type_tl } + } +% \end{macrocode} +% For \cCutext\ we first check if the user wants to use \cCutext\ at all. +% If not, change it to |\cunum|. +% \begin{macrocode} +\cs_new:Npn \@@_initialice_addon_cutext: + { + \bool_if:NT \l_@@_pckopt_cutext_to_cunum_bool + { \@@_set_cmd_type_to:n { cunum } } + \bool_set_false:N \l_@@_cutext_last_amount_equ_one_bool + } +% \end{macrocode} +% \end{macro} +% +% +% \begin{macro}{ \@@_initialize_new_default:nnn , \@@_initialize_new_default:nnV , +% \@@_intialize_new_default_units: +% } +% Shared by all commands and (nearly) first thing done. Sets the options, +% sets the unit (and expands it if necessary), checks if unit is defined. +% For |\cuam| the unit is a special |\c_@@_no_unit_marker_tl|. I could just check +% if |\cuam| is used, but I think this is more general. If the marker is used +% we do nothing, else we we check how the units change. +% \begin{macrocode} +\cs_new:Npn \@@_initialize_new_default:nnn #1#2#3 + { + \tl_clear:N \l_@@_option_unit_tl + \tl_if_empty:nF {#2} { \keys_set:nn { cooking-units } {#2} } + \IfNoValueF {#1} + { \@@_reference_label_and_persons:n {#1} } + \@@_expand_unit_input:Nn \l_@@_original_unit_tl {#3} + \@@_error_if_unit_not_defined:VTF \l_@@_original_unit_tl + { + \@@_set_state_to:n { error } + \bool_set_true:N \l_@@_unit_error_bool + } + { \@@_set_state_to:n { normal } } + \@@_set_parse_and_process_type_to:n { number } + \@@_set_print_type_to:n { unknown } + \tl_clear:N \l_@@_phantom_tl + \@@_initialize_new_default_units: + } +% \end{macrocode} +% First, convert the original unit to eV or a bonkers unit if necessary. +% If we have an unit-change, store the wanted unit in |\l_@@_option_unit_tl|. +% \begin{macrocode} +\cs_new:Npn \@@_initialize_new_default_units: + { + \@@_if_no_unit_marker:NTF \l_@@_original_unit_tl + { \tl_set_eq:NN \l_@@_option_unit_tl \l_@@_original_unit_tl } + { \@@_intialize_new_default_units_aux: } + } +\cs_new:Npn \@@_intialize_new_default_units_aux: + { + \bool_if:NTF \l_@@_pckopt_bonkers_bool + { \@@_changing_unit_bonkers:N \l_@@_original_unit_tl } + { + \bool_if:NT \l_@@_pckopt_convert_to_eV_bool + { \@@_convert_to_eV:N \l_@@_original_unit_tl } + } + \prop_get:NVNF \l_@@_change_unit_prop \l_@@_original_unit_tl \l_@@_option_unit_tl + { \tl_set_eq:NN \l_@@_option_unit_tl \l_@@_original_unit_tl } + } +% \end{macrocode} +% \end{macro} +% +% \begin{macro}{\@@_initialise_new_after_parsing:n} +% As the name suggests, this one is used \emph{after} parsing the amount. +% This is done in order to know if there is an error, if the unit needs +% to be changed and if this command needs to be called at all. +% +% It is kinda difficult to decide which unit is the correct one, as it may change +% due to unit-options. In theory this could lead to an infinite loop, +% so I decide in this place how things are printed and which unit +% is used. +% +% Well, in the end I only decide if a fraction is printed or not. The case of error or +% special signs were already sorted out. +% +% To make sure the lokal options override the unit-options, we set +% the options again after unit-options. +% \begin{macrocode} +\cs_new_protected:Npn \@@_initialise_new_after_parsing:n #1 + { + \clist_if_empty:cF { l_@@_unit_option_ \l_@@_decided_unit_tl _clist } + { + \keys_set_filter:nnv + { cooking-units } + { change-unit } + { l_@@_unit_option_ \l_@@_decided_unit_tl _clist } + \tl_if_empty:nF {#1} { \keys_set:nn { cooking-units } {#1} } + } + \bool_set_eq:NN \l_@@_lokal_numeral_bool \l_@@_pckopt_print_numeral_bool + } +\cs_new:Npn \@@_decide_unit: + { + \@@_change_unit:TF + { \tl_set_eq:NN \l_@@_decided_unit_tl \l_@@_option_unit_tl } + { \tl_set_eq:NN \l_@@_decided_unit_tl \l_@@_original_unit_tl } + } +% \end{macrocode} +% \end{macro} +% +% \begin{macro}{\@@_new_setup_bools_for_process_and_prints:} +% Determines some stuff for later use in the processing/printing department. +% It checks if the amount needs to be recalculated; and if fractions should be +% printed or not. +% \begin{macrocode} +\cs_new:Npn \@@_new_setup_bools_for_process_and_prints: + { + \bool_set_false:N \l_@@_lokal_recalc_for_people_bool + \bool_lazy_and:nnT + { \l_@@_reference_given_bool } + { \l_@@_pckopt_recalculate_amount_bool } + { + \int_compare:nNnF + { \l_@@_wanted_number_of_persons_int } + = + { \l_@@_local_number_of_persons_int } + { \bool_set_true:N \l_@@_lokal_recalc_for_people_bool } + } + \@@_if_print_type_equal:nT { fraction } + { + \bool_lazy_or:nnTF + { \l_@@_pckopt_eval_fractions_bool } + { \l_@@_lokal_recalc_for_people_bool } + { \@@_set_print_type_to:n { number } } + { +% "Convert" fractions \emph{only} if a unit change is requested. + \bool_lazy_and:nnT + { \l_@@_pckopt_convert_fractions_bool } + { ! \tl_if_eq_p:NN \l_@@_option_unit_tl \l_@@_original_unit_tl } + { \@@_set_print_type_to:n { number } } + } + } + } +% \end{macrocode} +% \end{macro} +% +% \begin{macro}{ \@@_use_hook_accordingly: } +% Hooks are straightforward. I know which command I used and thus set the +% respective hook. +% \begin{macrocode} +\cs_new:Npn \@@_use_hook_accordingly: + { + \l_@@_cmd_hook_tl + \tl_case:NnF \l_@@_cmd_type_tl + { + \c_@@_cmd_type_cunum_tl { \l_@@_cunum_hook_tl } + \c_@@_cmd_type_cCutext_tl + { + \bool_if:NTF \l_@@_cutext_uppercase_word_bool + { \l_@@_Cutext_hook_tl } + { \l_@@_cutext_hook_tl } + } + \c_@@_cmd_type_cuam_tl { \l_@@_cuam_hook_tl } + } + { \@@_create_internal_error:nN { use-hook-acc } \l_@@_cmd_type_tl } + } +% \end{macrocode} +% \end{macro} +% +% +% +% \begin{macro}{ \@@_general_checkups: } +% Doing some general stuff and tests which are done before further processing +% the amount. +% \begin{macrocode} +\cs_new:Npn \@@_general_checkups: + { + \tl_set_eq:NN \l_@@_print_type_tl \l_@@_parse_and_process_type_tl + \@@_if_state_equal:nT { normal } + { \@@_new_setup_bools_for_process_and_prints: } + \@@_decide_unit: + \@@_if_cmd_type_equal:nT { cCutext } + { \@@_cutext_check_if_translation_available: } + } +% \end{macrocode} +% \end{macro} +% +% +% +% \begin{macro}{\@@_process_amount_normally:n} +% This command is called after parsing the amount if no special-sign, error +% or so is encountered. First, initialize some stuff that is going to be important. +% Afterwards, if \cCutext\ is used, check if a translation is available. +% Then process the input depending on which case (number, range, fraction) we had. +% \begin{macrocode} +\cs_new:Npn \@@_process_amount_normally:n #1 + { + \@@_initialise_new_after_parsing:n {#1} + \tl_case:NnF \l_@@_parse_and_process_type_tl + { + \c_@@_parse_and_process_type_number_tl \@@_new_process_number_in_input: + \c_@@_parse_and_process_type_range_tl \@@_new_process_range_in_input: + \c_@@_parse_and_process_type_fraction_tl \@@_new_process_fraction_in_input: + } + { \@@_create_internal_error:nN { process_the_input } \l_@@_parse_and_process_type_tl } + } +% \end{macrocode} +% \end{macro} +% +% \begin{macro} +% This is called if the state is not \enquote{normal}. So the whole \enquote{process} +% part is skipped. If a special sign was detected, print a warining. If +% the 42-bool is true, change the amount accordingly. Nothing else is done. +% \begin{macrocode} +\cs_new:Npn \@@_process_amount_special: + { + \@@_if_state_equal:nT { special_sign } + { \msg_warning:nnV { cooking-units } { amount-not-known } \l_@@_original_amount_tl } + \bool_if:NT \l_@@_pckopt_fourty_two_bool + { \@@_prepare_fourty_two_amount: } + } +% \end{macrocode} +% \end{macro} +% +% +% \begin{macro}{ \@@_prepare_fourty_two_amount: } +% Simply replaces all variables with |42|. We can change all (except for the mixed fraction tl) +% as we know if we are going to print a \enquote{number}, \enquote{range} or +% \enquote{fraction}. +% \begin{macrocode} +\cs_new:Npn \@@_prepare_fourty_two_amount: + { + \tl_set:Nn \l_@@_number_tmpa_tl { 42 } + \tl_set:Nn \l_@@_number_tmpb_tl { 42 } + \tl_if_empty:NF \l_@@_mixed_fraction_tl + { \tl_set:Nn \l_@@_mixed_fraction_tl { 42 } } + \@@_if_state_equal:nT { special_sign } + { + \tl_put_right:Nn \l_@@_number_tmpa_tl { (!) } + \tl_put_right:Nn \l_@@_number_tmpb_tl { (!) } + \tl_if_empty:NF \l_@@_mixed_fraction_tl + { \tl_put_right:Nn \l_@@_mixed_fraction_tl { (!) } } + } + } +% \end{macrocode} +% \end{macro} +% +% +% +% \subsubsection{Process the input} +% +% \begin{macro}{ \@@_new_process_number_in_input: } +% Straightforward. The number only consists of a number. Thus +% calculate the things necessary and post process it depending on the command +% (|\cunum|, etc.)\ used. +% \begin{macrocode} +\cs_new:Npn \@@_new_process_number_in_input: + { + \@@_calculate_and_store_in:N \l_@@_number_tmpa_tl + \@@_post_process_accordingly:NN \l_@@_number_tmpa_tl \q_no_value + } +% \end{macrocode} +% \end{macro} +% +% \begin{macro}{ \@@_new_process_range_in_input: } +% Same as before, this time with two variables. +% \begin{macrocode} +\cs_new:Npn \@@_new_process_range_in_input: + { + \@@_calculate_and_store_in:N \l_@@_number_tmpa_tl + \@@_calculate_and_store_in:N \l_@@_number_tmpb_tl + \@@_post_process_accordingly:NN \l_@@_number_tmpa_tl \l_@@_number_tmpb_tl + } +% \end{macrocode} +% \end{macro} +% +% \begin{macro}{ \@@_new_process_range_in_input: } +% Here we are a bit more complicated, but not much. +% For fractions, we generally do not calculate the several numbers. +% +% First, remove the minus signs from the numbers (if any). +% Afterwards check if the printing type is a \enquote{number} (\enquote{range} is +% not possible). If a \enquote{number} is requested, convert the fraction +% to a number (simply by calculating the fraction). If we have a fraction, nothing +% else needs to be done. +% \begin{macrocode} +\cs_new:Npn \@@_new_process_fraction_in_input: + { + \@@_process_and_remove_minus_in_fraction:NNNN \l_@@_minus_bool + \l_@@_mixed_fraction_tl + \l_@@_number_tmpa_tl + \l_@@_number_tmpb_tl + \@@_if_print_type_equal:nT { number } + { + \@@_convert_fraction_to_number_in_input:NNN + \l_@@_mixed_fraction_tl + \l_@@_number_tmpa_tl + \l_@@_number_tmpb_tl + } + } +% \end{macrocode} +% This command loops over each variable, removes the minus and reverses the +% bool if needed. +% \begin{macrocode} +\cs_new:Npn \@@_process_and_remove_minus_in_fraction:NNNN #1 #2#3#4 + { + \bool_set_false:N #1 + \@@_check_minus_remove_and_reverse:NN + #1 #2#3#4 + \q_nil + } +% \end{macrocode} +% Convert a fraction to a number. Check if the denominator is 0, if so, print an +% error. Else, simply evaluate the fraction. If the minus bool is true, +% add a minus sign on the left. Afterwards, process it as a number. +% \begin{macrocode} +\cs_new:Npn \@@_convert_fraction_to_number_in_input:NNN #1#2#3 + { + \fp_compare:nNnTF {#3} = { 0 } + { \@@_create_error:n { Division-by-zero } } + { + \@@_tl_eval:Nn \l_@@_number_tmpa_tl { #1 + #2 / #3 } + \bool_if:NT \l_@@_minus_bool + { \tl_put_left:Nn \l_@@_number_tmpa_tl { - } } + \@@_new_process_number_in_input: + } + } +% \end{macrocode} +% \end{macro} +% +% +% \begin{macro}{ \@@_new_print_amount_correctly: } +% After parsing, processing, etc.\ it is time to print the amount. +% If an error was raised, simply print the \enquote{unparsed} original amount. +% +% Else, print the amount depending on \enquote{number}, \enquote{range} +% or \enquote{fraction}. \enquote{number} and \enquote{range} are printed +% according to the command used (|\cunum|, etc.). Fractions are printed +% indipendently from the commands. +% \begin{macrocode} +\cs_new:Npn \@@_new_print_amount_correctly: + { + \@@_if_state_equal:nTF { error } + { \l_@@_original_amount_tl } + { + \tl_case:NnF \l_@@_print_type_tl + { + \c_@@_print_type_number_tl + { + \@@_print_number_accordingly:N + \l_@@_number_tmpa_tl + } + \c_@@_print_type_range_tl + { + \@@_print_range_accordingly:NN + \l_@@_number_tmpa_tl + \l_@@_number_tmpb_tl + } + \c_@@_print_type_fraction_tl + { + \@@_culang_let:nnN { name } { decimal-mark } \l_@@_translation_tmpa_tl + \tl_replace_once:Nnn \l_@@_mixed_fraction_tl { . } \l_@@_translation_tmpa_tl + \tl_replace_once:Nnn \l_@@_number_tmpa_tl { . } \l_@@_translation_tmpa_tl + \tl_replace_once:Nnn \l_@@_number_tmpb_tl { . } \l_@@_translation_tmpa_tl + \@@_print_fractions:Nnn + \l_@@_mixed_fraction_tl + \l_@@_number_tmpa_tl + \l_@@_number_tmpb_tl + } + } + { \@@_create_internal_error:nN { print_the_input } \l_@@_print_type_tl } + } + } +% \end{macrocode} +% \end{macro} +% +% \begin{macro}{ \@@_new_print_unit_correctly: , \@@_print_unit_in_case_of_error: } +% Prints the unit. In case of error, print the unit more or less directly. +% Even in case of error there needs to be the correct spacing, etc. +% +% Else, parse the unit depending on the command used. For |\cuam| no unit +% is printed, but a phrase can be required. +% \begin{macrocode} +\cs_new:Npn \@@_new_print_unit_correctly: + { + \@@_if_state_equal:nTF { error } + { \@@_print_unit_in_case_of_error: } + { + \tl_case:NnF \l_@@_cmd_type_tl + { + \c_@@_cmd_type_cunum_tl { \@@_cunum_print_correct_unit: } + \c_@@_cmd_type_cCutext_tl { \@@_cutext_print_correct_unitname: } + \c_@@_cmd_type_cuam_tl { \@@_cuam_print_correct_unitphrase: } +% \c_@@_cmd_type_cucomp_tl { \@@_cunum_print_correct_unit: } + } + { \@@_create_internal_error:nN { print-unit-acc } \l_@@_cmd_type_tl } + } + } +% \end{macrocode} +% Prints the unit in case of error. Make sure the unit is printed correctly +% with the correct spacing. If the unit is unknown, just print the input. +% \begin{macrocode} +\cs_new:Npn \@@_print_unit_in_case_of_error: + { + \tl_if_empty:NF \l_@@_phantom_tl { \phantom { \l_@@_phantom_tl } } + \tl_use:N \l_@@_value_unit_space_tl + \bool_if:NTF \l_@@_unit_error_bool + { \l_@@_original_unit_tl } + { \@@_culang_print:nV { unit-symbol } \l_@@_original_unit_tl } + } +% \end{macrocode} +% \end{macro} +% +% +% \begin{macro} { \@@_print_number_accordingly:N } +% Prints the input |#1| according to the used command. +% This command is +% also used in ranges. % \begin{macrocode} -\cs_new_protected:Npn \@@_initialise_default:n #1 +\cs_new:Npn \@@_print_number_accordingly:N #1 { - \@@_set_unit:Nn \l_@@_original_unit_tl {#1} - \bool_set_false:N \l_@@_error_bool - \@@_error_if_unit_not_defined:VTF \l_@@_original_unit_tl - { - \bool_set_true:N \l_@@_unit_error_bool - \cs_set_eq:NN \@@_print_correct_unit: \@@_print_default_unit: - } - { \bool_set_false:N \l_@@_unit_error_bool } - \bool_set_false:N \l_@@_special_sign_bool - \bool_set_false:N \l_@@_range_in_input_bool - \bool_set_false:N \l_@@_lokal_fraction_bool - \bool_set_false:N \l_@@_minus_bool + \tl_case:NnF \l_@@_cmd_type_tl + { + \c_@@_cmd_type_cunum_tl { \@@_print_numerical_input:N #1 } + \c_@@_cmd_type_cCutext_tl { \@@_cutext_print_input:N #1 } + \c_@@_cmd_type_cuam_tl { \@@_cuam_print_numerical_input:N #1 } + } + { \@@_create_internal_error:nN { print-input-acc } \l_@@_cmd_type_tl } } % \end{macrocode} -% Some units have options added to them. To get those options it is first -% needed to know which unit will be used at all. Therefore units will -% be changed first and afterwards the other options are processed. +% \end{macro} % -% |\l_@@_convert_to_eV_bool| must be checked after processing the keys -% as the option \opt{convert-to-eV} is set during this process. +% \begin{macro} { \@@_print_range_accordingly:NN , \@@_print_range_sign: } +% Prints ranges. It simply prints the numbers twice, inbetween a range sign. % \begin{macrocode} -\cs_new_protected:Npn \@@_initialise_unit_change:n #1 +\cs_new:Npn \@@_print_range_accordingly:NN #1#2 { - \tl_if_empty:nF {#1} - { \keys_set_groups:nnn { cooking-units } { change-unit } {#1} } - \bool_if:NT \l_@@_convert_to_eV_bool - { \@@_convert_to_eV: } - \prop_get:NVNF \l_@@_change_unit_prop \l_@@_original_unit_tl \l_@@_option_unit_tl - { \tl_set_eq:NN \l_@@_option_unit_tl \l_@@_original_unit_tl } + \@@_print_number_accordingly:N #1 + \@@_print_range_sign: + \@@_print_number_accordingly:N #2 } % \end{macrocode} % \begin{macrocode} -\cs_new_protected:Npn \@@_initialise_after_unit_change:nn #1#2 +\cs_new:Npn \@@_print_range_sign: { - \IfNoValueF {#1} - { \@@_reference_label_and_persons:n {#1} } - \clist_if_empty:cF { l_@@_unit_option_ \l_@@_option_unit_tl _clist } - { - \keys_set_filter:nnv - { cooking-units } - { change-unit } - { l_@@_unit_option_ \l_@@_option_unit_tl _clist } - } - \tl_if_empty:nF {#2} - { \keys_set_filter:nnn { cooking-units } { change-unit } {#2} } - \bool_lazy_and:nnTF - { \l_@@_calc_because_ref_was_given_bool } { \l_@@_change_number_of_persons_bool } - { \bool_set_true:N \l_@@_lokal_persons_bool } - { \bool_set_false:N \l_@@_lokal_persons_bool } - \bool_set_eq:NN \l_@@_lokal_numeral_bool \l_@@_print_numeral_bool + \@@_if_cmd_type_equal:nTF { cunum } + { \tl_use:N \l_@@_cunum_range_sign_tl } + { + \bool_lazy_or:nnTF + { \@@_if_cmd_type_equal_p:n { cCutext } } + { \l_@@_lokal_numeral_bool } + { + \bool_set_false:N \l_@@_cutext_uppercase_word_bool + \tl_if_empty:NTF \l_@@_cutext_range_sign_tl + { \@@_culang_print:nn { name } { cutext-range-sign } } + { \tl_use:N \l_@@_cutext_range_sign_tl } + } + { \tl_use:N \l_@@_cunum_range_sign_tl } + } } % \end{macrocode} % \end{macro} % -% -% \begin{macro}{ \@@_print_input:N , \@@_print_correct_unit: , -% \@@_post_process_input:NN , \@@_pre_process_input:NN} -% Wrapper macro for printing the (not)calculated output. Note that if no -% calculation happens in \mycs{cutext} (and \mycs{Cutext}) \cs{l_@@_option_unit_tl} -% is set to \cs{l_@@_original_unit_tl} (the unit given in the second argument of -% \mycs{cutext} or \mycs{Cutext}) by default. -% \begin{macrocode} -\cs_new_protected:Npn \@@_print_input:N #1 { } -\cs_new_protected:Npn \@@_print_correct_unit: { } -\cs_new_protected:Npn \@@_do_not_process_input:NN #1#2 { } -\cs_new_eq:NN \@@_pre_process_input:NN \@@_do_not_process_input:NN -\cs_new_eq:NN \@@_post_process_input:NN \@@_do_not_process_input:NN -% \end{macrocode} -% \end{macro} -% -% \begin{macro} { \@@_set_process_and_print_for_cunum: , -% \@@_set_process_and_print_for_cutext: , -% \@@_set_process_and_print_for_cuam: -% } -% It is handy to set the \enquote{print} and \enquote{process} -% command all in one go. It's also less messy to use. +% \begin{macro}{ \@@_post_process_accordingly:NN } +% After evaluating and changing the amounts (due to unit changing, rounding, etc.) +% we post process the input (only for numbers and ranges). For |\cunum| nothing +% needs to be done. For \cCutext\ and |\cuam| we post process the values accordingly +% (checking if integer, etc.) % \begin{macrocode} -\cs_new_protected:Npn \@@_set_process_and_print_for_cunum: - { - \cs_set_eq:NN \@@_print_input:N \@@_print_numerical_input:N - \cs_set_eq:NN \@@_print_correct_unit: \@@_cunum_print_correct_unit: - \cs_set_eq:NN \@@_pre_process_input:NN \@@_do_not_process_input:NN - \cs_set_eq:NN \@@_post_process_input:NN \@@_do_not_process_input:NN - } -\cs_new_protected:Npn \@@_set_process_and_print_for_cutext: - { - \cs_set_eq:NN \@@_print_input:N \@@_cutext_print_input:N - \cs_set_eq:NN \@@_print_correct_unit: \@@_cutext_print_correct_unitname: - \cs_set_eq:NN \@@_pre_process_input:NN \@@_cutext_pre_process_input:NN - \cs_set_eq:NN \@@_post_process_input:NN \@@_cutext_post_process_input:NN - } -\cs_new_protected:Npn \@@_set_process_and_print_for_cuam: - { - \cs_set_eq:NN \@@_print_input:N \@@_cuam_print_numerical_input:N - \cs_set_eq:NN \@@_print_correct_unit: \@@_cuam_print_correct_unitphrase: - \cs_set_eq:NN \@@_pre_process_input:NN \@@_do_not_process_input:NN - \cs_set_eq:NN \@@_post_process_input:NN \@@_cuam_post_process_input:NN +\cs_new:Npn \@@_post_process_accordingly:NN #1#2 + { + \tl_case:NnF \l_@@_cmd_type_tl + { + \c_@@_cmd_type_cunum_tl { } + \c_@@_cmd_type_cCutext_tl { \@@_cutext_post_process_input:NN #1#2 } + \c_@@_cmd_type_cuam_tl { \@@_cuam_post_process_input:NN #1#2 } +% \c_@@_cmd_type_cucomp_tl { } + }{ + \@@_create_internal_error:nN { post-process } \l_@@_cmd_type_tl + } } % \end{macrocode} % \end{macro} % -% -% -% -% % \begin{macro}{ \@@_print_numerical_input:N } -% Prints the numerical output (if it is not a fraction). -% -% Changed \lstinline|\l_@@_tmpa_tl| by |\l_@@_translation_tmpa_tl|, it's better that way. +% The base printing command for numbers. Makes sure the minus sign +% and decimal-mark are correct. % \begin{macrocode} \cs_new_protected:Npn \@@_print_numerical_input:N #1 { \tl_if_in:NnT #1 { . } { - \@@_translate_let:NnV \l_@@_translation_tmpa_tl - { decimal-mark } \c_@@_postfix_unitname_tl + \@@_culang_let:nnN { name } { decimal-mark } \l_@@_translation_tmpa_tl \tl_replace_once:Nnn #1 { . } { \l_@@_translation_tmpa_tl } } \tl_replace_once:Nnn #1 { - } \c_@@_minus_tl @@ -6158,88 +7362,48 @@ and the derived file cooking-units.sty. % \end{macro} % % -% \begin{macro}{ \@@_print_ranges:NN } -% \begin{macrocode} -\cs_new:Npn \@@_print_ranges:NN #1#2 - { - \@@_print_input:N #1 - \bool_if:NTF \l_@@_using_cutext_bool - { -% \tl_use:N \l_@@_cutext_range_sign_tl - \tl_if_empty:NTF \l_@@_cutext_range_sign_tl - { \@@_translate:nV { cutext-range-sign } \c_@@_postfix_unitname_tl } - { \tl_use:N \l_@@_cutext_range_sign_tl } - \bool_set_false:N \l_@@_cutext_uppercase_word_bool - } - { \tl_use:N \l_@@_cunum_range_sign_tl } - \@@_print_input:N #2 - } -% \end{macrocode} -% \end{macro} -% -% -% % % % \subsection {Parsing and checking numbers} % -% This subsection contains macros for splitting an checking the input. +% This subsection contains macros for splitting and checking the input. % % \begin{macro}{\@@_create_error:n, \@@_create_error_and_stop:n , \@@_create_error:nn } +% Create error messages and set case to \enquote{error}. % \begin{macrocode} +\cs_new:Npn \@@_create_internal_error:nN #1#2 + { + \@@_set_case_to:n { error } + \msg_error:nnnV { cooking-units } { internal-error } {#1} #2 + } \cs_new:Npn \@@_create_error:n #1 { - \bool_set_true:N \l_@@_error_bool + \@@_set_case_to:n { error } \msg_error:nnV { cooking-units } {#1} \l_@@_original_amount_tl } \cs_new:Npn \@@_create_error_and_stop:n #1 { - \bool_set_true:N \l_@@_error_bool - \msg_error:nnV { cooking-units } {#1} \l_@@_original_amount_tl + \@@_create_error:n {#1} \use_none_delimit_by_q_nil:w } \cs_new:Npn \@@_create_error:nn #1#2 { - \bool_set_true:N \l_@@_error_bool + \@@_set_case_to:n { error } \msg_error:nnnV { cooking-units } {#1} {#2} \l_@@_original_amount_tl } % \end{macrocode} % \end{macro} % -% The following command is needed after the parsing. It further processes -% the parsed input and prints. The actual parsing and printing process (|\@@_process_tmp|) -% depends on the command (|\cunum|, etc.) used. -% \begin{macrocode} -\cs_new:Npn \@@_process_tmp: { } -\cs_new:Npn \@@_process_and_print_input: - { - \bool_lazy_or:nnTF - { \l_@@_error_bool } - { \l_@@_unit_error_bool } - { \l_@@_original_amount_tl } - { \@@_process_tmp: } - } -% \end{macrocode} -% If there is an error or there is a special case (like \opt{42=true}) these commands -% are used. -% \begin{macrocode} -\cs_new:Npn \@@_process_default: { \l_@@_original_amount_tl } -\cs_new:Npn \@@_print_default_unit: - { - \tl_if_empty:NF \l_@@_phantom_tl { \phantom { \l_@@_phantom_tl } } - \,\l_@@_original_unit_tl - } -% \end{macrocode} -% -% \begin{macro}{ \@@_parse_input:n } -% Rescans the input to get rid of spaces and to make \_ and ? inactive -% (french with babel makes |?| active and changes the definition of it). -% \lstinline|--| is replaced by \lstinline|\q_@@_range| and the input is parsed -% (if not empty). Afterwards the units are printed. +% \begin{macro} { \@@_parse_the_amount:n } +% Does what the name suggests. |#1| is the input given by the user without changes. +% It is then stored in |\l_@@_original_amount_tl| (which can be expanded, etc.). +% Afterwards we rescan the input to remove spaces and make sure \_ and ? have +% correct catcodes (last one can be active; screws some stuff up if it is so). +% Then decides what's supposed to happen next. % \begin{macrocode} -\cs_new:Npn \@@_parse_input:n #1 +\cs_new:Npn \@@_parse_the_amount:n #1 { - \@@_set_amount:Nn \l_@@_original_amount_tl {#1} + \@@_expand_amount_input:Nn \l_@@_original_amount_tl {#1} \tl_set_rescan:NnV \l_@@_original_amount_tl { \char_set_catcode_letter:N \_ % @@ -6248,114 +7412,144 @@ and the derived file cooking-units.sty. } \l_@@_original_amount_tl \bool_lazy_any:nTF { - { \l_@@_fourty_two_bool } - { \l_@@_draft_bool } { \tl_if_empty_p:N \l_@@_original_amount_tl } - }{ - \cs_set_eq:NN \@@_process_tmp: \@@_process_default: - \tl_if_empty:NT \l_@@_original_amount_tl - { \msg_error:nnV { cooking-units } { empty-amount } \l_@@_original_amount_tl } - \bool_if:NT \l_@@_fourty_two_bool - { \tl_set:Nn \l_@@_original_amount_tl { 42 } } - }{ - \tl_set_eq:NN \l_@@_tmpa_tl \l_@@_original_amount_tl - \@@_split_input:N \l_@@_tmpa_tl + { \l_@@_pckopt_draft_bool } } + { \@@_prepare_just_print_input: } + { \@@_split_and_parse_input: } + } +% \end{macrocode} +% \end{macro} +% \begin{macro}{\@@_split_and_parse_input: } +% If the weitd option \opt{42} is used, set the state to \enquote{42}. +% Copy the original amount and prepapre to split the input. +% \begin{macrocode} +\cs_new:Npn \@@_split_and_parse_input: + { + \bool_if:NT \l_@@_pckopt_fourty_two_bool + { \@@_set_state_to:n { 42 } } + \tl_set_eq:NN \l_@@_tmpa_tl \l_@@_original_amount_tl + \@@_prepare_to_split_input:N \l_@@_tmpa_tl + } +% \end{macrocode} +% \end{macro} +% \begin{macro}{\@@_prepare_just_print_input: } +% If we decide the input is just to be printed, set it to \enquote{error} +% (because I am lazy and do not want to create another case to check). +% \begin{macrocode} +\cs_new:Npn \@@_prepare_just_print_input: + { + \@@_set_state_to:n { error } + \tl_if_empty:NT \l_@@_original_amount_tl + { \@@_create_error:nn { cooking-units } { empty-amount } } } % \end{macrocode} % \end{macro} % -% \begin{macro}{ \@@_split_input:N , \@@_process_and_print_input: , \@@_process_tmp: } -% I would need to check for |/| and |_| anyway. So let's do it here -% and use the booleans for error-checking. +% \begin{macro}{ \@@_prepare_to_split_input:N} +% Adapts the state into \enquote{range} or \enquote{fraction} if needed. +% By default it is set to \enquote{number}. Ranges and Fractions are not allowed +% together. Afterwards, split the input. If we encounter an error, we can use +% |\use_none_delimit_by_q_nil:w| during the code to jump to this point. +% This makes bailing out from the command more easy. % \begin{macrocode} -\cs_new:Npn \@@_split_input:N #1 +\cs_new:Npn \@@_prepare_to_split_input:N #1 { \tl_if_in:NVT #1 \l_@@_input_range_sign_tl { \tl_replace_once:NVn #1 \l_@@_input_range_sign_tl { \q_@@_range } - \bool_set_true:N \l_@@_range_in_input_bool + \@@_set_parse_and_process_type_to:n { range } } \tl_if_in:NnT #1 { / } { - \bool_set_true:N \l_@@_lokal_fraction_bool - \bool_if:NT \l_@@_range_in_input_bool + \@@_if_parse_and_process_type_equal:nT { range } { \@@_create_error_and_stop:n { fraction-not-allowed-with-range } } + \@@_set_parse_and_process_type_to:n { fraction } } - \@@_split:N #1 + \@@_split_and_parse:N #1 \use_none_delimit_by_q_nil:w \q_nil } % \end{macrocode} % \end{macro} % -% \begin{macro}{ \@@_split_input:} -% Splits the input into fractions or ranges. -% Errors are already checked at this point. +% +% \begin{macro}{ \@@_split_and_parse:} +% Splits the input into fractions or ranges (or numbers). % \begin{macrocode} -\cs_new:Npn \@@_split:N #1 +\cs_new:Npn \@@_split_and_parse:N #1 { - \bool_if:NTF \l_@@_lokal_fraction_bool - { \@@_split_fraction:V } + \tl_case:NnF \l_@@_parse_and_process_type_tl { - \bool_if:NTF \l_@@_range_in_input_bool - { \@@_split_range:V } - { \@@_split_number:V } - } + \c_@@_parse_and_process_type_number_tl { \@@_split_and_parse_number:V } + \c_@@_parse_and_process_type_range_tl { \@@_split_and_parse_range:V } + \c_@@_parse_and_process_type_fraction_tl { \@@_split_and_parse_fraction:V } + } + { \@@_create_internal_error:nN { split } \l_@@_parse_and_process_type_tl } #1 } % \end{macrocode} +% \end{macro} +% +% \begin{macro}{ \@@_split_and_parse_number:n } +% Gets the input , parses it and stores it into |\l_@@_number_tmpa_tl|. % \begin{macrocode} -\cs_new:Npn \@@_split_number:n #1 +\cs_new:Npn \@@_split_and_parse_number:n #1 { - \cs_set_eq:NN \@@_process_tmp: \@@_process_number_in_input: \@@_parse_input_and_safe_in:nN {#1} \l_@@_number_tmpa_tl } % \end{macrocode} +% \end{macro} +% +% \begin{macro}{ \@@_split_and_parse_range:n , \@@_split_and_parse_range_aux:ww } +% Splits the input along |\q_@@_range|, parses the two parts and that's it. % \begin{macrocode} -\cs_new:Npn \@@_split_range:n #1 +\cs_new:Npn \@@_split_and_parse_range:n #1 { - \cs_set_eq:NN \@@_process_tmp: \@@_process_range_in_input: - \@@_split_range_aux:ww #1 \q_stop + \@@_split_and_parse_range_aux:ww #1 \q_stop } -\cs_new:Npn \@@_split_range_aux:ww #1 \q_@@_range #2 \q_stop +\cs_new:Npn \@@_split_and_parse_range_aux:ww #1 \q_@@_range #2 \q_stop { \@@_parse_input_and_safe_in:nN {#1} \l_@@_number_tmpa_tl \@@_parse_input_and_safe_in:nN {#2} \l_@@_number_tmpb_tl } % \end{macrocode} +% \end{macro} +% +% \begin{macro}{ \@@_split_and_parse_fraction:n , \@@_split_and_parse_fraction_mixed:ww , \@@_split_and_parse_fraction_frac:ww } +% A bit more tricky. We check first if a mixed fraction part exists. If not the function +% get's |\q_nil|. Then we read the nominator and denominator. Inbetween we check +% for errors % \begin{macrocode} -\cs_new:Npn \@@_split_fraction:n #1 +\cs_new:Npn \@@_split_and_parse_fraction:n #1 { - \cs_set_eq:NN \@@_process_tmp: \@@_process_generel_fraction_in_input: - \@@_split_fraction_mixed:ww + \@@_split_and_parse_fraction_mixed:ww #1 \q_stop / \q_recursion_tail _ \q_nil \q_stop \q_recursion_stop -% \end{macrocode} -% At this point we have all information we need to determine whatever or not -% the fractions should be evaluated or if the units should be changed. -% \begin{macrocode} - \bool_lazy_or:nnT - { \l_@@_lokal_persons_bool }{ \l_@@_eval_fractions_bool } - { \bool_set_false:N \l_@@_lokal_fraction_bool } - \bool_if:NT \l_@@_convert_fractions_bool - { - \tl_if_eq:NNF \l_@@_original_unit_tl \l_@@_option_unit_tl - { \bool_set_false:N \l_@@_lokal_fraction_bool } - } } +% \end{macrocode} +% Gets the mixed fraction part (if it exists). If |#2| is |\q_nil| the part does not +% exist. |#1| must then be of part |a/b|. % -\cs_new:Npn \@@_split_fraction_mixed:ww #1 _ #2 \q_stop +% If |#2| is \emph{not} |\q_nil| it contains the fraction part with |a/b|. +% Parse the mixed fraction part and store it. Seperate |#2|. +% \begin{macrocode} +\cs_new:Npn \@@_split_and_parse_fraction_mixed:ww #1 _ #2 \q_stop { \quark_if_nil:nTF {#2} { \tl_clear:N \l_@@_mixed_fraction_tl - \@@_split_fraction_frac:ww #1 \q_stop + \@@_split_and_parse_fraction_frac:ww #1 \q_stop }{ \@@_parse_input_and_safe_in:nN {#1} \l_@@_mixed_fraction_tl - \@@_split_fraction_frac:ww #2 \q_stop + \@@_split_and_parse_fraction_frac:ww #2 \q_stop } } -\cs_new:Npn \@@_split_fraction_frac:ww #1 / #2 \q_stop +% \end{macrocode} +% Seperates nominator and denominator. If |#2| is equal to |\q_recursion_tail| +% we probably had a construction like |a/b_c|, which is wrong. If so, create an error. +% If everything is correct, parse the input and store it. +% \begin{macrocode} +\cs_new:Npn \@@_split_and_parse_fraction_frac:ww #1 / #2 \q_stop { \quark_if_recursion_tail_stop_do:nn {#2} { \@@_create_error:n { fraction-wrong-order } } @@ -6364,17 +7558,21 @@ and the derived file cooking-units.sty. \use_none_delimit_by_q_recursion_stop:w } % \end{macrocode} +% \end{macro} +% \begin{macro}{ \@@_split_and_parse_number:V , +% \@@_split_and_parse_range:V , \@@_split_and_parse_fraction:V } +% Some variants. % \begin{macrocode} -\cs_generate_variant:Nn \@@_split_number:n { V } -\cs_generate_variant:Nn \@@_split_range:n { V } -\cs_generate_variant:Nn \@@_split_fraction:n { V } +\cs_generate_variant:Nn \@@_split_and_parse_number:n { V } +\cs_generate_variant:Nn \@@_split_and_parse_range:n { V } +\cs_generate_variant:Nn \@@_split_and_parse_fraction:n { V } % \end{macrocode} % \end{macro} % % \begin{macro}{ \@@_parse_input_and_safe_in:nN } -% Used to check the input. \lstinline|\l_@@_tmpa_tl| is cleared -% at the beginning. At first it checks if the first token -% is a sign or not. The parsed input is stored into \lstinline|\l_@@_tmpa_tl|. +% Parses through |#1| and makes sure it is correct. This includes checking if there +% is only one decimal sign and other stuff. The \enquote{correct} +% parsed stuff is stored in |\l_@@_tmpa_tl|. % \begin{macrocode} \cs_new:Npn \@@_parse_input_and_safe_in:nN #1 #2 { @@ -6382,21 +7580,20 @@ and the derived file cooking-units.sty. \bool_set_false:N \l_@@_check_decimal_bool \cs_set_eq:NN \@@_parse:N \@@_start_loop:N \tl_map_function:nN {#1} \@@_parse:N - \bool_if:NTF \l_@@_error_bool - { } + \@@_if_state_equal:nF { error } { \tl_set_eq:NN #2 \l_@@_tmpa_tl } } % \end{macrocode} % \end{macro} % -% \begin{macro}{ \@@_start_loop:Nw } +% \begin{macro}{ \@@_start_loop:N } % This function seperates the input into two parts with the first -% part being the first token. This token is checked whetever or not +% part being the first token. This token is checked if or if not % it is a sign. If it is a sign it is put into % \lstinline|\l_@@_tmpa_tl|, if not it is checked normally by % \lstinline|\@@_parse_input_loop_aux:N|. \#2 (the other % tokens) is then given to \lstinline|\tl_map_function:nN|. This -% also works if the input only conists of one token with \#2 being +% also works if the input only consists of one token with \#2 being % empty (hopefully). % \begin{macrocode} \cs_new:Npn \@@_start_loop:N #1 @@ -6404,19 +7601,18 @@ and the derived file cooking-units.sty. \cs_set_eq:NN \@@_parse:N \@@_parse_input_loop_aux:N \tl_if_in:NnTF \l_@@_input_value_signs_tl {#1} { \tl_put_right:Nn \l_@@_tmpa_tl {#1} } - { - \tl_map_function:nN {#1} \@@_parse:N - } + { \tl_map_function:nN {#1} \@@_parse:N } } % \end{macrocode} % \end{macro} % -% \begin{macro}{ \@@_parse_input_loop_aux:N } +% \begin{macro}{ \@@_parse_input_loop_aux:N , \@@_check_which_error:n , \@@_check_repitition:N } % Parses the input. It also is more or less (more less then more) copied from % \texttt{siunitx}. Checks if the input consists only of numbers, -% one decimal-sign and the allowed special input. If an allowed -% token is found the boolean \lstinline|\l_@@_special_sign_bool| is -% set to true. +% one decimal-sign and the allowed special input. +% In other cases, raise an error. Note that the state special-sign +% can only be set if there is no error. +% % \begin{macrocode} \cs_new:Npn \@@_parse_input_loop_aux:N #1 { @@ -6429,13 +7625,12 @@ and the derived file cooking-units.sty. \tl_put_right:Nn \l_@@_tmpa_tl { . } }{ \tl_if_in:NnTF \l_@@_input_allowed_special_signs_tl {#1} - { - \bool_set_true:N \l_@@_special_sign_bool + { + \@@_if_state_equal:nF { error } + { \@@_set_state_to:n { special_sign } } \tl_put_right:Nn \l_@@_tmpa_tl {#1} - }{ - \bool_set_true:N \l_@@_error_bool - \@@_check_error:n {#1} } + { \@@_check_which_error:n {#1} } } } } @@ -6447,14 +7642,14 @@ and the derived file cooking-units.sty. % for |_| without |/| would happen before parsing starts). Therefore % all |/| and |_| in the input \emph{must} (hopefully) be inside a second time. % \begin{macrocode} -\cs_new:Npn \@@_check_error:n #1 +\cs_new:Npn \@@_check_which_error:n #1 { \tl_if_in:NnTF \l_@@_input_fraction_sign_tl {#1} { \@@_create_error:n { Second-fraction-sign-not-allowed } } { \tl_if_in:NnTF \l_@@_input_mixed_fraction_sign_tl {#1} { - \bool_if:NTF \l_@@_lokal_fraction_bool + \@@_if_parse_and_process_type_equal:nTF { fraction } { \@@_create_error:n { Second-mixed-fraction-sign-not-allowed } } { \@@_create_error:n { missing-slash } } } @@ -6462,6 +7657,8 @@ and the derived file cooking-units.sty. } } % \end{macrocode} +% Back then this contained more checks, but now it just checks +% if we have a second error decimal sign. % \begin{macrocode} \cs_new:Npn \@@_check_repitition:N #1 { @@ -6473,196 +7670,91 @@ and the derived file cooking-units.sty. % \end{macro} % % -% \begin{macro}{\@@_process_number_in_input:} -% If no fractions and ranges are used this macro activated. -% It just checks the input, stores the checked (and a bit -% changed) input into a macro. This macro is given to another -% function to calculate the input and print it. -% \begin{macrocode} -\cs_new:Npn \@@_process_number_in_input: - { - \@@_process_and_print_number_in_input:N \l_@@_number_tmpa_tl - } -\cs_new:Npn \@@_process_and_print_number_in_input:N #1 - { - \@@_pre_process_input:NN #1 \q_no_value - \@@_calculate_and_store_in:N #1 - \@@_post_process_input:NN #1 \q_no_value - \@@_print_input:N #1 - } -% \end{macrocode} -% \end{macro} -% -% \begin{macro}{ \@@_process_range_in_input: } -% Is used if a \lstinline|\q_@@_range| is found inside the input. -% Seperates the input, checks it and prints it (after calculating -% it). Furthermore a boolean is set to true, is used to check for -% errors (ergo if fractions are used). -% -% Set |\l_@@_cutext_uppercase_word_bool| to false -% so that the second numeral is not capitalized. -% \begin{macrocode} -\cs_new:Npn \@@_process_range_in_input: - { - \@@_pre_process_input:NN \l_@@_number_tmpa_tl \l_@@_number_tmpb_tl - \@@_calculate_and_store_in:N \l_@@_number_tmpa_tl - \@@_calculate_and_store_in:N \l_@@_number_tmpb_tl - \@@_post_process_input:NN \l_@@_number_tmpa_tl \l_@@_number_tmpb_tl - \@@_print_ranges:NN \l_@@_number_tmpa_tl \l_@@_number_tmpb_tl - } -% \end{macrocode} -% \end{macro} -% -% \begin{macro}{ \@@_process_generel_fraction_in_input: } -% This function prints both mixed and normal fractions. Those was done -% by two functions beforehand, but they shared mostly the same code, so I -% managed to fuse them. -% -% The first part removes the minus sign. It cycles through the variables -% (|\l_@@_mixed_fraction_tl| can be emtpy) and removes the minus signs. -% It furthermore saves how many minuses are used by reversing a bool. -% If a minus sign is found, the bool is reversed to true (from false). Another -% minus: minus and minus is plus, reverse bool again (to false this time), etc. -% -% Afterwards: Is a fraciton printed, or is the input evaluated. Printing is -% straight forward. -% -% Due to how mixed fractions are evaluated, one can just evaluate the -% absolute values of the inputs and add a minus sign on the left side afterwards -% (if necessary). -% \begin{align} -% \cuam{1_2/3} &= 1 + 2/3 \\ -% \cuam{-1_2/3} &= -1 - 2/3 = - ( 1 + 2/3 ) -% \end{align} % -% If |\l_@@_mixed_fraction_tl| is empty the calculation just evaluates to -% |+\l_@@_number_tmpa_tl / \l_@@_number_tmpb_tl|, which is also valid. -% -% \begin{macrocode} -\cs_new:Npn \@@_process_generel_fraction_in_input: - { - \@@_check_minus_remove_and_reverse:NN - \l_@@_mixed_fraction_tl - \l_@@_number_tmpa_tl - \l_@@_number_tmpb_tl - \q_nil - \bool_lazy_or:nnTF - { \l_@@_lokal_fraction_bool } - { \l_@@_special_sign_bool } - { - \bool_if:NT \l_@@_special_sign_bool - { - \msg_warning:nnV { cooking-units } { amount-not-known } \l_@@_original_amount_tl - } - \@@_print_fractions:Nnn - \l_@@_mixed_fraction_tl - { \l_@@_number_tmpa_tl } - { \l_@@_number_tmpb_tl } - }{ - \fp_compare:nNnT { \l_@@_number_tmpb_tl } = { 0 } - { \msg_error:nnV { cooking-units } { Division-by-zero } \l_@@_original_amount_tl } - \@@_tl_eval:Nn \l_@@_number_tmpa_tl - { - \l_@@_mixed_fraction_tl + - \l_@@_number_tmpa_tl / \l_@@_number_tmpb_tl - } - \bool_if:NT \l_@@_minus_bool - { \tl_put_left:Nn \l_@@_number_tmpa_tl { - } } - \@@_process_and_print_number_in_input:N \l_@@_number_tmpa_tl - } - } -% \end{macrocode} -% \end{macro} % -% % +% \subsection {Formatiere \& Calculiere} % % % -% \subsection {Formatiere \& Calculiere} % % \begin{macro}{ \@@_calculate_and_store_in:N } % % \changes {v0.98a} {2016/06/11} {Added warning to show if an unknown value is used.} % -% After parsing the input, it is given to this function. If a not -% allowed token is found (and \lstinline|\l_@@_error_bool| is set to -% true) it just prints the input. Otherwise it checks if a allowed sign was -% found. If so it is just stored inside \lstinline|\l_@@_tmpa_tl|, -% otherwise it is calulcated and stored in \lstinline|\l_@@_tmpa_tl|. The input -% \#1 can be either a token or a number. +% The main calculation command. The split amount is given to this +% command. It is seperated into several smaller macros. Unit-changing +% the amount, referencing, rounding and temperature checks are done +% here. Note that we are only here if the state is \enquote{normal}. % \begin{macrocode} \cs_new:Npn \@@_calculate_and_store_in:N #1 { - \bool_if:NTF \l_@@_special_sign_bool - { - \msg_warning:nnV { cooking-units } { amount-not-known } #1 - }{ - \bool_lazy_and:nnTF - { \l_@@_using_cutext_bool } { \l_@@_cutext_keep_unit_bool } - { \tl_set_eq:NN \l_@@_tmpa_tl #1 } - { \@@_calculate_input_and_store_in:nN {#1} \l_@@_tmpa_tl } - \@@_calc_references:NN \l_@@_tmpa_tl \l_@@_tmpa_tl - \@@_round_calculated_input:NV \l_@@_tmpa_tl \l_@@_tmpa_tl - \@@_check_temperature_limit:N \l_@@_tmpa_tl - \tl_set_eq:NN #1 \l_@@_tmpa_tl - } + \@@_calculate_input_and_store_in:N #1 + \@@_calc_references_and_store_in:N #1 + \@@_round_calculated_input_and_store_in:N #1 + \@@_check_temperature_limit:N #1 } % \end{macrocode} % \end{macro} % -% \begin{macro}{ \@@_calculate_input_and_store_in:nN } -% Well \dots\ this function calculates the input. First checks if the -% wanted conversion contains a \lstinline|\l_@@_tmpa_fp| (ergo a \#1 in -% the key definition). If true the conversion token (which already has -% \lstinline|\l_@@_tmpa_fp| in its input) is executed, else the input -% number is multiplicated with the conversion token. +% \begin{macro}{ \@@_calculate_input_and_store_in:NN } +% Well \dots\ this function calculates the input. +% First check if the units need to be changes at all (if no unit change +% is wanted, |\l_@@_option_unit_tl| is set to |\l_@@_original_unit_tl| at the +% beginning. If we are in one case were no unit change is happening +% (\enquote{special-sign}, \enquote{error}, \enquote{fraction}) we wouldn't be +% here in the first place, so need to worry about this. +% +% As the input is parsed and good for evaluation, store it in +% |\l_@@_tmpa_fp|. +% +% If the key definition contained a |#1| (aka, is a single key), +% it was replaced by |\l_@@_tmpa_fp|. +% Thus simply evaluate the tl if one or more |\l_@@_tmpa_fp| are inside. +% +% If no |\l_@@_tmpa_fp| is found, we have a simple multiplication with the +% current amount. % \begin{macrocode} -\cs_new:Npn \@@_calculate_input_and_store_in:nN #1#2 +\cs_new:Npn \@@_calculate_input_and_store_in:N #1 { - \fp_set:Nn \l_@@_tmpa_fp {#1} - \tl_if_in:cnTF { l_@@_unit_change_ \l_@@_original_unit_tl _tl } { \l_@@_tmpa_fp } - { - \@@_tl_eval:Nv #2 { l_@@_unit_change_ \l_@@_original_unit_tl _tl } - }{ - \@@_tl_eval:Nn #2 - { \l_@@_tmpa_fp * \tl_use:c { l_@@_unit_change_ \l_@@_original_unit_tl _tl } } + \tl_if_eq:NNF \l_@@_decided_unit_tl \l_@@_original_unit_tl + { + \fp_set:Nn \l_@@_tmpa_fp {#1} + \tl_if_in:cnTF { l_@@_unit_change_ \l_@@_original_unit_tl _tl } { \l_@@_tmpa_fp } + { + \@@_tl_eval:Nv #1 { l_@@_unit_change_ \l_@@_original_unit_tl _tl } + }{ + \@@_tl_eval:Nn #1 + { \l_@@_tmpa_fp * \tl_use:c { l_@@_unit_change_ \l_@@_original_unit_tl _tl } } + } } } % \end{macrocode} % \end{macro} % -% \begin{macro}{ \@@_calc_references:NN,\@@_calc_references_aux:NN } -% As comparing integers is faster then checking if something is inside -% the sequence, first (after the boolean) check if there needs to be a calculation -% at all. +% \begin{macro}{ \@@_calc_references_and_store_in:N,\@@_calc_references_and_store_in_aux:N } +% All necessary checks were already done at the beginning. +% so we know that a reference was given and that the wanted number of +% persons is different then the one given by |\culabel|. Before +% evaluation, check if the unit is one of those that cannot be changed. % \begin{macrocode} -\cs_new:Npn \@@_calc_references:NN #1#2 +\cs_new:Npn \@@_calc_references_and_store_in:N #1 { - \bool_if:NT \l_@@_lokal_persons_bool + \bool_if:NT \l_@@_lokal_recalc_for_people_bool { - \int_compare:nNnF - { \l_@@_wanted_number_of_persons_int } - = - { \l_@@_local_number_of_persons_int } - { - \tl_set_eq:NN \l_@@_tmpb_tl \l_@@_original_unit_tl - \seq_if_in:NVTF \l_@@_curef_do_not_change_seq \l_@@_tmpb_tl - { \msg_error:nnV { cooking-units } { curef-forbidden-unit } \l_@@_tmpb_tl } - { \@@_calc_references_aux:NN #1 #2 } - } + \seq_if_in:NVTF \l_@@_curef_do_not_change_seq \l_@@_decided_unit_tl + { \msg_error:nnV { cooking-units } { curef-forbidden-unit } \l_@@_decided_unit_tl } + { \@@_calc_references_and_store_in_aux:N #1 } } } % \end{macrocode} -% I hope that by putting |#2| to the front of the calculation, it will increase the -% precision of the calculation (not that it is necessary). I don't really know if this -% makes sense, but \dots\ eh. +% Just calculate the stuff % \begin{macrocode} -\cs_new:Npn \@@_calc_references_aux:NN #1#2 +\cs_new:Npn \@@_calc_references_and_store_in_aux:N #1 { \@@_tl_eval:Nn #1 { - #2 * + #1 * \l_@@_wanted_number_of_persons_int / \l_@@_local_number_of_persons_int } @@ -6670,13 +7762,33 @@ and the derived file cooking-units.sty. % \end{macrocode} % \end{macro} % +% +% \begin{macro}{ \@@_round_calculated_input_and_store_in:Nn,\@@_round_calculated_input_and_store_in:NV } +% After calculation, the numbers are rounded (if needed). +% If the rounding precision is negative (can be), just set the bool to true and go +% to the rounding function. +% Else check if the number needs rounding at all. +% Afterwards, round if necessary +% \begin{macrocode} +\cs_new:Npn \@@_round_calculated_input_and_store_in:N #1 + { + \bool_if:NTF \l_@@_pckopt_round_precision_negative_bool + { \bool_set_true:N \l_@@_round_number_bool } + { \@@_check_number_for_rounding:V #1 } + \bool_if:NT \l_@@_round_number_bool + { \@@_tl_eval:Nn #1 { round ( \@@_rounding_function:n {#1} ) } } + } +% \end{macrocode} +% \end{macro} +% % \begin{macro}{\@@_check_number_for_rounding:n,\@@_check_number_after_dot_aux:ww} % Check if rounding is needed. The auxilary function splits the number into % the integer and non-integer part ($12.45$ to $12$ and $45$). -% -% If the non-integer part exists its number of digits $n$ are counted checked -% if it is smaller then $a$, which depends on |\l_@@_round_to_int_bool|. -% +% +% Set |\l_@@_round_number_bool| to |false| in case of no decimal places found. +% +% If the rounding precision is positive, use the helper function to split the +% amount. % \begin{macrocode} \cs_new:Npn \@@_check_number_for_rounding:n #1 { @@ -6684,39 +7796,26 @@ and the derived file cooking-units.sty. \@@_check_number_after_dot_aux:ww #1 . \q_recursion_tail . \q_recursion_stop } +\cs_generate_variant:Nn \@@_check_number_for_rounding:n { V } +% \end{macrocode} +% The function splitting the amount. So $a.b$ is split into $a$ and $b$. +% If $b$ does not exist (so the amount is an integer), no rounding is needed. +% If $b$ does exist, count how many tokens it conists of (e.g.\ $12$ = 2 tokens; +% $1755$ = 4 tokens). If the number of tokens is larger then the wanted round precision, +% round the input. +% \begin{macrocode} \cs_new:Npn \@@_check_number_after_dot_aux:ww #1 . #2 . { - \quark_if_recursion_tail_stop_do:nn {#2} - { - \bool_if:NT \l_@@_round_precision_negative_bool - { \bool_set_true:N \l_@@_round_number_bool } - } - \int_compare:nNnT - { \tl_count:n {#2} } > - { \l_@@_round_precision_int } - { \bool_set_true:N \l_@@_round_number_bool } + \quark_if_recursion_tail_stop:n {#2} + \int_compare:nNnT + { \tl_count:n {#2} } > + { \l_@@_round_precision_int } + { \bool_set_true:N \l_@@_round_number_bool } \use_none_delimit_by_q_recursion_stop:w } % \end{macrocode} % \end{macro} % -% \begin{macro}{ \@@_round_calculated_input:Nn,\@@_round_calculated_input:NV } -% After calculating the numbers are rounded (if needed, safed inside \cs{l_tmpa_bool}). -% We test at first if -% the input needs to be rounded by comparing the number of tokens after the -% decimal with the round precision. Afterwards the -% input is expanded and stored in \#1. If rounding needs to be done it happens now. -% \begin{macrocode} -\cs_new:Npn \@@_round_calculated_input:Nn #1#2 - { - \@@_check_number_for_rounding:n {#2} - \bool_if:NTF \l_@@_round_number_bool - { \@@_tl_eval:Nn #1 { round ( \@@_rounding_function:n {#2} ) } } - { \tl_set:Nn #1 {#2} } - } -\cs_generate_variant:Nn \@@_round_calculated_input:Nn { NV } -% \end{macrocode} -% \end{macro} % % % @@ -6727,25 +7826,24 @@ and the derived file cooking-units.sty. % % \begin{macro}{\@@_check_temperature_limit:N} % If \lstinline|check_temperature_bool| is set to true it now checks -% if the value is below the absolute temperature. \lstinline|\clist_if_in:nVT| -% is needed due to \myunit{Re}, a \lstinline|\tl_if_in:nVT| would also check for \myunit{R} -% and \myunit{e} instead of only \myunit{Re}. +% if the value is below the absolute temperature. Maybe this should be done +% before rounding? % \begin{macrocode} \cs_new:Npn \@@_check_temperature_limit:N #1 { - \bool_if:NT \l_@@_check_temperature_bool + \bool_if:NT \l_@@_pckopt_check_temperature_bool { - \seq_if_in:NVT \l_@@_temperatures_to_check_seq \l_@@_option_unit_tl + \seq_if_in:NVT \l_@@_temperatures_to_check_seq \l_@@_decided_unit_tl { \fp_compare:vNnT - { l_@@_ \l_@@_option_unit_tl _min_fp } > {#1} - { + { l_@@_ \l_@@_decided_unit_tl _min_fp } > {#1} + { \msg_error:nnxx { cooking-units } { Temperature-too-low } - { #1 \space \l_@@_option_unit_tl } + { #1 \space \l_@@_decided_unit_tl } { - \fp_use:c { l_@@_ \l_@@_option_unit_tl _min_fp } - \space \l_@@_option_unit_tl + \fp_use:c { l_@@_ \l_@@_decided_unit_tl _min_fp } + \space \l_@@_decided_unit_tl } } } @@ -6763,35 +7861,39 @@ and the derived file cooking-units.sty. % % % +% \subsection {Main commands helper} % -% +% \begin{macro}{ \@@_if_arrow_grab_until_close_do:nnTF , +% \@@_grab_arrows_for_safety_do_afterwards:nN } +% I really do not like this constuction, but due to catcodes it can happen +% that the main commands are unable to get the first command inside <>. +% In order to fix this, I use this bloody construction. % \begin{macrocode} -\cs_new_nopar:Npn \@@_grab_arrows_for_safety_do_afterwards:nN #1#2 - { - \str_if_eq:nnTF {#2} { > } - { - \tl_put_right:Nx \l_@@_tmpa_tl { \tl_to_str:N > } - \exp_last_unbraced:NV #1 \l_@@_tmpa_tl - }{ - \tl_put_right:Nn \l_@@_tmpa_tl {#2} - \@@_grab_arrows_for_safety_do_afterwards:nN {#1} - } - } \cs_new_nopar:Npn \@@_if_arrow_grab_until_close_do:nnTF #1#2#3#4 { \str_if_eq:nnTF {#1} { < } - { + { \tl_if_in:NoT \l_@@_input_allowed_special_signs_tl { < } { \msg_error:nn { cooking-units } { <-not-allowed-as-special-sign } } \tl_clear:N \l_@@_tmpa_tl \tl_put_right:Nx \l_@@_tmpa_tl { \tl_to_str:N < } - \@@_grab_arrows_for_safety_do_afterwards:nN - {#3} #2 + \@@_grab_arrows_for_safety_do_afterwards:nN {#3} #2 } {#4} } +\cs_new_nopar:Npn \@@_grab_arrows_for_safety_do_afterwards:nN #1#2 + { + \str_if_eq:nnTF {#2} { > } + { + \tl_put_right:Nx \l_@@_tmpa_tl { \tl_to_str:N > } + \exp_last_unbraced:NV #1 \l_@@_tmpa_tl + }{ + \tl_put_right:Nn \l_@@_tmpa_tl {#2} + \@@_grab_arrows_for_safety_do_afterwards:nN {#1} + } + } % \end{macrocode} -% +% \end{macro} % % % \subsection {\mycs{cunum}} @@ -6815,44 +7917,19 @@ and the derived file cooking-units.sty. % % % \begin{macro}{ \@@_cunum:nnnnn } +% The \enquote{helper} command. It essentially only sets +% the command type to \enquote{cunum} and calls the command that does +% everything else. % \begin{macrocode} \cs_new:Npn \@@_cunum:nnnnn #1#2#3#4#5 { - \@@_cunum_initialise:nnnnn {#1} {#2} {#3} {#4} {#5} - \l_@@_cunum_hook_tl - \@@_parse_input:n {#3} - \@@_process_and_print_input: - \@@_print_correct_unit: - } -% \end{macrocode} -% \end{macro} -% -% -% \begin{macro}{ \@@_cunum_initialise:nnnn } -% Lots of things to do in this function. It checks if the unit is defined or not, -% sets the keys for converting the unit and sets the optional unit (the unit -% our input is converted to) accordingly, sets the options again (to get the -% option-specific options) and \dots\ yeah. -% -% First parses the change of unit ('set groups'), afterwards set -% the predefined options for the new unit. Afterwards -% set the 'normal' options given by the optional argument. -% -% \begin{macrocode} -\cs_new_protected:Npn \@@_cunum_initialise:nnnnn #1#2#3#4#5 - { - \@@_set_process_and_print_for_cunum: - \tl_set:Nn \l_@@_phantom_tl {#4} - \@@_initialise_default:n {#5} - \@@_initialise_unit_change:n {#2} - \@@_initialise_after_unit_change:nn {#1} {#2} + \@@_set_cmd_type_to:n { cunum } + \@@_do_the_stuff:nnnnnn {#1} {#2} {#3} {#4} {#5} { } } % \end{macrocode} % \end{macro} % % -% -% % \begin{macro}{ \@@_cunum_print_correct_unit: } % The invisible space is added by a \lstinline|\phantom|, afterwards % \lstinline|value_unit_space_tl| is used (which is set to @@ -6864,9 +7941,7 @@ and the derived file cooking-units.sty. { \tl_if_empty:NF \l_@@_phantom_tl { \phantom { \l_@@_phantom_tl } } \tl_use:N \l_@@_value_unit_space_tl - \@@_change_unit:TF - { \@@_translate:VV \l_@@_option_unit_tl \c_@@_postfix_unit_tl } - { \@@_translate:VV \l_@@_original_unit_tl \c_@@_postfix_unit_tl } + \@@_culang_print:nV { unit-symbol } \l_@@_decided_unit_tl } % \end{macrocode} % \end{macro} @@ -6875,8 +7950,10 @@ and the derived file cooking-units.sty. % \section { cutext \& Cutext } % % -% A better implemantation of \opt{cutext-to-cunum}, but -% sufficient for now. +% \begin{macro}{\cutext} +% The other main command It is essentially similar to \mycs{cunum}, +% only that we also need to take care of uppercasing the word if necessary +% (which it is not for this command). % \begin{macrocode} \NewDocumentCommand \cutext { d<> O{} m m } { @@ -6884,17 +7961,16 @@ and the derived file cooking-units.sty. { \cutext } { \group_begin: - \@@_change_cutext_to_cunum:nTF {#2} - { \@@_cunum:nnnnn {#1} {#2} {#3} { } {#4} } - { - \bool_set_false:N \l_@@_cutext_uppercase_word_bool - \@@_cutext:nnnn {#1} {#2} {#3} {#4} - } + \bool_set_false:N \l_@@_cutext_uppercase_word_bool + \@@_cutext:nnnn {#1} {#2} {#3} {#4} \group_end: } } % \end{macrocode} +% \end{macro} % +% \begin{macro}{\Cutext} +% Here we do need the uppercasing. % \begin{macrocode} \NewDocumentCommand \Cutext { d<> O{} m m } { @@ -6902,159 +7978,185 @@ and the derived file cooking-units.sty. { \Cutext } { \group_begin: - \@@_change_cutext_to_cunum:nTF {#2} - { \@@_cunum:nnnnn {#1} {#2} {#3} { } {#4} } - { - \bool_set_true:N \l_@@_cutext_uppercase_word_bool - \@@_cutext:nnnn {#1} {#2} {#3} {#4} - } + \bool_set_true:N \l_@@_cutext_uppercase_word_bool + \@@_cutext:nnnn {#1} {#2} {#3} {#4} \group_end: } } % \end{macrocode} +% \end{macro} % -% \begin{macrocode} -\cs_new_protected:Npn \@@_cutext_initialise:nnn #1#2#3 - { - \bool_set_true:N \l_@@_using_cutext_bool - \@@_set_process_and_print_for_cutext: - \@@_initialise_default:n {#3} - \@@_initialise_unit_change:n {#2} - \bool_if:NT \l_@@_cutext_keep_unit_bool - { \tl_set_eq:NN \l_@@_option_unit_tl \l_@@_original_unit_tl } - \@@_initialise_after_unit_change:nn {#1} {#2} - \bool_if:NT \l_@@_fourty_two_bool - { \tl_set:Nn \l_@@_cutext_last_value_tl { 42 } } - } -% \end{macrocode} % -%^^A #1: label, #2: Options, #3: Values, #4: unit +% \begin{macro}{ \@@_cutext:nnnn } +% Same as the \mycs{cunum} equivalent, just setting the command to +% \enquote{cCutext}. % \begin{macrocode} \cs_new:Npn \@@_cutext:nnnn #1#2#3#4 { - \@@_cutext_initialise:nnn {#1} {#2} {#4} - \bool_if:NTF \l_@@_cutext_uppercase_word_bool - { \l_@@_Cutext_hook_tl } - { \l_@@_cutext_hook_tl } - \bool_if:NTF \l_@@_cutext_old_bool - { \@@_old_cutext:nnn {#2} {#3} {#4} } - { - \@@_parse_input:n {#3} - \@@_process_and_print_input: - } - \@@_print_correct_unit: + \@@_set_cmd_type_to:n { cCutext } + \@@_do_the_stuff:nnnnnn {#1} {#2} {#3} { } {#4} { } } % \end{macrocode} +% \end{macro} % % % -% \begin{macro} {\@@_cutext_print_input:Nn , \@@_cutext_print_input:NV} +% \begin{macro} {\@@_cutext_print_input:N , \@@_cutext_print_input_aux:Nn , \@@_cutext_print_input_aux:NV } % \changes {2016/06/11} {0.99} {New.} % -% +% This prints the amount for the \enquote{cCutext} commands. +% At first, check if a numeral should be used (\enquote{1} to \enquote{one}, etc.). +% If not, just print the number. If a numeral should be used, make sure the correct +% unit is used and go to the next command. % \begin{macrocode} -\cs_new_protected:Npn \@@_cutext_print_input:Nn #1#2 +\cs_new_protected:Npn \@@_cutext_print_input:N #1 { \bool_if:NTF \l_@@_lokal_numeral_bool { - \@@_int_if_equal_one:nTF {#1} + \@@_cutext_print_input_aux:NV #1 \l_@@_decided_unit_tl + } + { \@@_print_numerical_input:N #1 } + } +% \end{macrocode} +% If a numeral is used, make sure the correct one is printed. +% If the amount is equal to \enquote{1}, get the gender correct \enquote{one}. +% Else, print the numeral either in upperacse of lowercase. +% +% As we could be in a range, we cannot check via a bool if |#1| is 1. +% +% Furthermore, make sure the translation of \enquote{1} exists. If not, +% set input it set to \enquote{1}. +% \begin{macrocode} +\cs_new_protected:Npn \@@_cutext_print_input_aux:Nn #1#2 + { + \int_compare:nNnTF {#1} = { 1 } + { + \@@_culang_one_let:NnT \l_@@_translation_tmpa_tl {#2} { - \@@_translate_one_and_check_existance:Nx \l_@@_translation_tmpa_tl {#2} - \bool_if:NTF \l_@@_cutext_uppercase_word_bool + \bool_if:NT \l_@@_cutext_uppercase_word_bool { - \exp_args:Nx \tl_upper_case:n { \tl_head:V \l_@@_translation_tmpa_tl } - \tl_tail:V \l_@@_translation_tmpa_tl + \text_uppercase:x { \tl_head:V \l_@@_translation_tmpa_tl } + \tl_tail:V } - { \l_@@_translation_tmpa_tl } - }{ - \bool_if:NTF \l_@@_cutext_uppercase_word_bool - { \@@_print_Numeral:n {#1} } - { \@@_print_numeral:n {#1} } } + \l_@@_translation_tmpa_tl + }{ + \bool_if:NTF \l_@@_cutext_uppercase_word_bool + { \@@_print_Numeral:V #1 } + { \@@_print_numeral:V #1 } } - { \@@_print_numerical_input:N #1 } - } -\cs_generate_variant:Nn \@@_cutext_print_input:Nn { NV } -\cs_new_protected:Npn \@@_cutext_print_input:N #1 - { - \@@_change_unit:TF - { \@@_cutext_print_input:NV #1 \l_@@_option_unit_tl } - { \@@_cutext_print_input:NV #1 \l_@@_original_unit_tl } } +\cs_generate_variant:Nn \@@_cutext_print_input_aux:Nn { NV } % \end{macrocode} % \end{macro} % +% \begin{macro}{\@@_cutext_print_correct_unitname:} +% As the name suggests, it prints the unitname. At this point we already +% know that a translation exists, so no bother checking again. % \begin{macrocode} \cs_new:Npn \@@_cutext_print_correct_unitname: { - \l_@@_cutext_space_tl - \@@_change_unit:TF - { - \@@_fp_if_equal_one:nTF { \l_@@_cutext_last_value_tl } - { \@@_translate:VV \l_@@_option_unit_tl \c_@@_postfix_unitname_tl } - { \@@_translate:VV \l_@@_option_unit_tl \c_@@_postfix_unitname_pl_tl } - } - { \@@_translate:VV \l_@@_original_unit_tl \c_@@_postfix_unitname_pl_tl } + \bool_if:NTF \l_@@_lokal_numeral_bool + { \l_@@_cutext_numeral_space_tl } + { \l_@@_cutext_space_tl } + \bool_if:NTF \l_@@_cutext_last_amount_equ_one_bool + { \@@_culang_print:nV { name } \l_@@_decided_unit_tl } + { \@@_culang_print:nV { name-pl } \l_@@_decided_unit_tl } } % \end{macrocode} +% \end{macro} % +% \begin{macro}{ \@@_cutext_check_if_translation_available: } +% Checks if a unitname of the current unit exists. If yes, continue. +% here we can also decide if the unit should be kept the same or not +% as we know that we stay in \enquote{cCutext}. +% If not, change the command to \enquote{cunum}. % \begin{macrocode} -\cs_new:Npn \@@_cutext_pre_process_input:NN #1#2 +\cs_new:Npn \@@_cutext_check_if_translation_available: { - \@@_change_unit:TF - { \tl_set_eq:NN \l_@@_tmpb_tl \l_@@_option_unit_tl } - { \tl_set_eq:NN \l_@@_tmpb_tl \l_@@_original_unit_tl } - \@@_unitname_get:NxF \l_@@_tmpa_tl \l_@@_tmpb_tl - { + \bool_if:NTF \l_@@_pckopt_cutext_keep_unit_bool + { \tl_set_eq:NN \l_@@_curr_unit_tl \l_@@_original_unit_tl } + { \tl_set_eq:NN \l_@@_curr_unit_tl \l_@@_decided_unit_tl } + \@@_culang_unitname_let:NVTF \l_@@_scrap_tl \l_@@_curr_unit_tl + { + \bool_if:NT \l_@@_pckopt_cutext_keep_unit_bool + { + \tl_set_eq:NN \l_@@_decided_unit_tl \l_@@_original_unit_tl + \tl_set_eq:NN \l_@@_option_unit_tl \l_@@_original_unit_tl + } + }{ \msg_warning:nnx { cooking-units } { cutext-no-translation-available } - \l_@@_tmpb_tl - \bool_set_false:N \l_@@_using_cutext_bool - \@@_set_process_and_print_for_cunum: + \l_@@_curr_unit_tl + \@@_set_cmd_type_to:n { cunum } + \@@_decide_unit: } } -% \end{macrocode} +% \end{macrocode} +% \end{macro} % % +% \begin{macro}{ \@@_cutext_post_process_input:NN } +% |#1| is always a number, |#2| only is valid if we have a range. +% For later, check if either |#1| or |#2| is equal to one. % +% Then (Than?) check if a numeral is requested. If yes, |#1| (and if range also |#2|) +% need to be integers. If they are not, numerals cannot be used. If one or both +% are integers, if they are below |\l_@@_print_numerals_below_int|. % \begin{macrocode} \cs_new:Npn \@@_cutext_post_process_input:NN #1#2 { - \bool_if:NF \l_@@_special_sign_bool - { - \@@_cutext_post_process_input_aux:NN #1#2 + \@@_if_parse_and_process_type_equal:nTF { range } + { \@@_cutext_check_if_amount_single:N #2 } + { \@@_cutext_check_if_amount_single:N #1 } + \bool_if:NT \l_@@_lokal_numeral_bool + { + \@@_if_contain_decimals:NNTF #1#2 + { \bool_set_false:N \l_@@_lokal_numeral_bool } + { \@@_check_if_integer_can_be_numerals:NN #1#2 } } } % \end{macrocode} +% \end{macro} +% \begin{macro} { \@@_cutext_check_if_amount_single:N } +% Check if the input is equal to |#1|. Use fp as it is not necessary an integer. +% Set the boolean according to the result. % \begin{macrocode} -\cs_new:Npn \@@_cutext_post_process_input_aux:NN #1#2 +\cs_new:Npn \@@_cutext_check_if_amount_single:N #1 { - \bool_if:NTF \l_@@_range_in_input_bool - { \tl_set_eq:NN \l_@@_cutext_last_value_tl #2 } - { \tl_set_eq:NN \l_@@_cutext_last_value_tl #1 } - \bool_if:NT \l_@@_lokal_numeral_bool - { \@@_cutext_post_process_input_numerals:NN #1#2 } + \fp_compare:nNnTF {#1} = { 1.0 } + { \bool_set_true:N } { \bool_set_false:N } + \l_@@_cutext_last_amount_equ_one_bool } -\cs_new:Npn \@@_cutext_post_process_input_numerals:NN #1#2 +% \end{macrocode} +% \end{macro} +% \begin{macro} { \@@_check_if_integer_can_be_numerals:NN } +% At this point we know that we have integers, so check if they are +% below |\l_@@_print_numerals_below_int|. If they are, fine. Else, +% set the boolean to false. +% \begin{macrocode} +\cs_new:Npn \@@_check_if_integer_can_be_numerals:NN #1#2 { - \@@_bool_set_if_integers:NNN \l_@@_tmpa_bool #1 #2 - \bool_if:NTF \l_@@_tmpa_bool + \@@_if_parse_and_process_type_equal:nTF { range } { - \bool_if:NTF \l_@@_range_in_input_bool + \bool_lazy_all:nF { - \bool_lazy_and:nnF - { \int_compare_p:nNn {#1} < { \l_@@_print_numerals_below_int } } - { \int_compare_p:nNn {#2} < { \l_@@_print_numerals_below_int } } - { \bool_set_false:N \l_@@_lokal_numeral_bool } - }{ - \int_compare:nNnF {#1} < { \l_@@_print_numerals_below_int } - { \bool_set_false:N \l_@@_lokal_numeral_bool } + { \int_compare_p:nNn {#1} < { \l_@@_print_numerals_below_int } } + { \int_compare_p:nNn {#2} < { \l_@@_print_numerals_below_int } } + { \int_compare_p:nNn {#1} > { 0 } } + { \int_compare_p:nNn {#2} > { 0 } } } + { \bool_set_false:N \l_@@_lokal_numeral_bool } + }{ + \bool_lazy_and:nnF + { \int_compare_p:nNn {#1} < { \l_@@_print_numerals_below_int } } + { \int_compare_p:nNn {#1} > { 0 } } + { \bool_set_false:N \l_@@_lokal_numeral_bool } } - { \bool_set_false:N \l_@@_lokal_numeral_bool } } % \end{macrocode} +% \end{macro} % % % @@ -7066,15 +8168,25 @@ and the derived file cooking-units.sty. % % \section{cuam} % +% \begin{macro}{ \c_@@_no_unit_marker_tl , \@@_if_no_unit_marker:NTF } +% A marker used for \mycs{cuam}. It essentially tells that no unit is used. +% Define some commands to avoid some errors and add it to the unit list. % \begin{macrocode} -\tl_const:Nn \c_@@_cuam_marker_tl { @@_cunum } -\tl_new:c { l_@@_unit_change_ \c_@@_cuam_marker_tl _tl } -\tl_set:cn { l_@@_unit_change_ \c_@@_cuam_marker_tl _tl } { 1.0 } -\clist_new:c { l_@@_unit_option_ \c_@@_cuam_marker_tl _clist } +\tl_const:Nx \c_@@_no_unit_marker_tl { \@@_to_unit:n { @@_no_unit } } +\prg_new_conditional:Npnn \@@_if_no_unit_marker:N #1 { TF , F } + { + \tl_if_eq:NNTF \c_@@_no_unit_marker_tl #1 + { \prg_return_true: } + { \prg_return_false: } + } +\seq_gput_right:NV \g_@@_list_of_defined_units_seq \c_@@_no_unit_marker_tl +\tl_new:c { l_@@_unit_change_ \c_@@_no_unit_marker_tl _tl } +\tl_set:cn { l_@@_unit_change_ \c_@@_no_unit_marker_tl _tl } { 1.0 } +\clist_new:c { l_@@_unit_option_ \c_@@_no_unit_marker_tl _clist } % \end{macrocode} % -% Replaces and extends \mycs{cufrac}. % \begin{macro}{\cuam} +% Replaces and extends \mycs{cufrac}. Essentially the same as the other commands. % \begin{macrocode} \NewDocumentCommand \cuam { d<> O{} m } { @@ -7089,41 +8201,20 @@ and the derived file cooking-units.sty. % \end{macrocode} % \end{macro} % +% \begin{macro}{\@@_cuam:nnn} +% Nothing really special happening here. Use |\c_@@_no_unit_marker_tl| +% to tell the internal thing that we have a valid no-unit-exists case. % \begin{macrocode} \cs_new:Npn \@@_cuam:nnn #1#2#3 { - \@@_cuam_initialise:nn {#1} {#2} - \l_@@_cuam_hook_tl - \bool_if:NTF \l_@@_cuam_old_bool - { \@@_cuam_old:n {#3} } - { - \@@_parse_input:n {#3} - \@@_process_and_print_input: - \@@_print_correct_unit: - } + \@@_set_cmd_type_to:n { cuam } + \@@_do_the_stuff:nnnnVn {#1} {#2} {#3} { } \c_@@_no_unit_marker_tl { } } % \end{macrocode} +% \end{macro} % -% \begin{macrocode} -\cs_new_protected:Npn \@@_cuam_initialise:nn #1#2 - { - \@@_set_process_and_print_for_cuam: - \tl_set_eq:NN \l_@@_original_unit_tl \c_@@_cuam_marker_tl - \tl_set_eq:NN \l_@@_option_unit_tl \c_@@_cuam_marker_tl - \bool_set_false:N \l_@@_lokal_phrase_bool - \@@_initialise_after_unit_change:nn {#1} {#2} - } -% \end{macrocode} +% \begin{macro}{\@@_cuam_post_process_input} % -% Important thing is: This whole process must not acticate if a -% special sign is in the input. This is due to mathematical comparisons. -% \begin{macrocode} -\cs_new_protected:Npn \@@_cuam_post_process_input:NN #1#2 - { - \bool_if:NF \l_@@_special_sign_bool - { \@@_cuam_post_process_input_aux:NN #1 #2 } - } -% \end{macrocode} % % Just a helper macro to tidy up the main macro. The first thing to % do is to check if the nummerical input consits of integers. This @@ -7131,53 +8222,59 @@ and the derived file cooking-units.sty. % Afterwards check if phrases are used and can be used at all. This needs % to be done before the numeral check as it can change the input. % \begin{macrocode} -\cs_new:Npn \@@_cuam_post_process_input_aux:NN #1#2 +\cs_new_protected:Npn \@@_cuam_post_process_input:NN #1#2 { - \@@_bool_set_if_integers:NNN \l_@@_tmpa_bool #1 #2 - \bool_lazy_and:nnT - { \l_@@_use_phrases_bool } { \l_@@_tmpa_bool } - { \@@_cuam_post_process_input_phrases:NN #1#2 } - \bool_if:NT \l_@@_lokal_numeral_bool - { \@@_cuam_post_process_input_numerals:NN #1#2 } + \@@_if_contain_decimals:NNTF #1#2 + { \bool_set_false:N \l_@@_lokal_numeral_bool } + { + \bool_if:NT \l_@@_pckopt_use_phrases_bool + { \@@_cuam_post_process_input_phrases:NN #1#2 } + \bool_if:NT \l_@@_lokal_numeral_bool + { \@@_check_if_integer_can_be_numerals:NN #1#2 } + } } % \end{macrocode} +% \end{macro} +%\begin{macro}{ \@@_cuam_post_process_input_phrases:NN} % -% This command is more or less straightforward. Does a list of phrases exist +% I really do not like this command, but I still do not have a bette idea +% how to handle the whole thing. +% +% Does a list of phrases exist % for the current language? If yes, parse the input and check if phrases are used. % It is important for ranges to check both values and then decide if phrases % are used or not. % \begin{macrocode} \cs_new:Npn \@@_cuam_post_process_input_phrases:NN #1#2 { - \@@_get_phrase_for_current_langauge:NNT - \l_@@_phrase_prop - \l_@@_phrase_numbers_seq + \@@_culang_let:nnN { phrase } { phrase-prop } \l_@@_phrase_prop + \tl_if_eq:NNT \q_@@_no_translation \l_@@_phrase_prop + { \use_none_delimit_by_q_stop:w } + \prop_get:NnN \l_@@_phrase_prop { seq } \l_@@_phrase_numbers_seq +% + \@@_cuam_post_process_input_phrases_aux:NNN + #1 \l_@@_tmpa_int \l_@@_phrase_number_tl + \bool_if:NF \l_@@_lokal_phrase_bool + { \use_none_delimit_by_q_stop:w } +% + \@@_if_parse_and_process_type_equal:nTF { range } { - \@@_cuam_post_process_input_phrases_aux:NNN - #1 \l_@@_tmpa_int \l_@@_phrase_number_tl - \bool_if:NT \l_@@_lokal_phrase_bool - { - \bool_if:NTF \l_@@_range_in_input_bool - { - \bool_if:NF \l_@@_phrase_negative_bool - { - \@@_cuam_post_process_input_phrases_range:NN - #2 \l_@@_tmpb_int - \bool_if:NT \l_@@_lokal_phrase_bool - { - \tl_set:NV #1 \l_@@_tmpa_int - \tl_set:NV #2 \l_@@_tmpb_int - \@@_cuam_get_phrase_name:NVN - \l_@@_phrase_phrase_tl \l_@@_phrase_number_tl \l_@@_tmpb_int - } - } - }{ - \tl_set:NV #1 \l_@@_tmpa_int - \@@_cuam_get_phrase_name:NVN - \l_@@_phrase_phrase_tl \l_@@_phrase_number_tl \l_@@_tmpa_int - } - } + \bool_if:NT \l_@@_phrase_negative_bool + { \use_none_delimit_by_q_stop:w } + \@@_cuam_post_process_input_phrases_range:NN + #2 \l_@@_tmpb_int + \bool_if:NF \l_@@_lokal_phrase_bool + { \use_none_delimit_by_q_stop:w } + \tl_set:NV #1 \l_@@_tmpa_int + \tl_set:NV #2 \l_@@_tmpb_int + \@@_cuam_get_phrase_name:NVN + \l_@@_phrase_text_tl \l_@@_phrase_number_tl #2 + }{ + \tl_set:NV #1 \l_@@_tmpa_int + \@@_cuam_get_phrase_name:NVN + \l_@@_phrase_text_tl \l_@@_phrase_number_tl #1 } + \use_none_delimit_by_q_stop:w \q_stop } % \end{macrocode} % \begin{macrocode} @@ -7188,15 +8285,16 @@ and the derived file cooking-units.sty. { \int_compare:nNnF { \int_abs:n {##1} } > {#1} { - \int_compare:nNnTF {##1} < { 0 } + \prop_get:NnN \l_@@_phrase_prop { ##1-singlebool } \l_tmpa_tl + \int_compare:nNnTF { \l_tmpa_tl } = { 1 } + { \bool_set_true:N \l_@@_phrase_negative_bool } { - \bool_set_true:N \l_@@_phrase_negative_bool - \int_set:Nn \l_tmpa_int { 1 } + \bool_set_false:N \l_@@_phrase_negative_bool + \tl_set:Nf \l_tmpa_tl { \int_div_truncate:nn {#1} {##1} } } - { \int_set:Nn \l_tmpa_int { \int_div_truncate:nn {#1} {##1} } } - \int_compare:nNnT { \int_abs:n {##1} * \l_tmpa_int } = {#1} + \int_compare:nNnT { \int_abs:n {##1} * \l_tmpa_tl } = {#1} { - \int_set_eq:NN #2 \l_tmpa_int + \tl_set_eq:NN #2 \l_tmpa_tl \tl_set:Nn #3 {##1} \bool_set_true:N \l_@@_lokal_phrase_bool \seq_map_break: @@ -7206,8 +8304,11 @@ and the derived file cooking-units.sty. } \cs_new:Npn \@@_cuam_post_process_input_phrases_range:NN #1#2 { - \int_set:Nn \l_tmpa_int { \int_div_truncate:nn {#1} { \l_@@_phrase_number_tl } } - \int_compare:nNnTF { \l_@@_phrase_number_tl * \l_tmpa_int } = {#1} + \int_set:Nn \l_tmpa_int + { + \int_div_truncate:nn {#1} { \int_abs:n {\l_@@_phrase_number_tl } } + } + \int_compare:nNnTF { \int_abs:n {\l_@@_phrase_number_tl} * \l_tmpa_int } = {#1} { \int_set_eq:NN #2 \l_tmpa_int \bool_set_true:N \l_@@_lokal_phrase_bool @@ -7217,274 +8318,594 @@ and the derived file cooking-units.sty. } \cs_new:Npn \@@_cuam_get_phrase_name:NnN #1#2#3 { - \@@_int_if_equal_one:nTF {#3} + \int_compare:nNnTF {#3} = { 1 } { \prop_get:NnN \l_@@_phrase_prop {#2} #1 } { \prop_get:NnN \l_@@_phrase_prop { #2-pl } #1 } + \prop_get:NnN \l_@@_phrase_prop { #2-gender } \l_@@_phrase_gender_tl } \cs_generate_variant:Nn \@@_cuam_get_phrase_name:NnN { NVN } % \end{macrocode} +% \end{macro} % % -% Processing numerals. This function only happens if numerals are used -% and because numerals have to be integers I can set the numeral boolean -% false if there is no integer. -% -% Furthermore, due to knowing that we have integers we can use -% |\int_compare_p:nNn| instead of the |fp|-equivalent. +% \begin{macro}{\@@_cuam_print_numerical_input:N, \@@_cuam_print_numerical_input_aux:Nn, \@@_cuam_print_numerical_input_aux:NV } +% Printing the numerical input for \mycs{cuam}. If both phrases and numerals +% are requested, go to the helper macro. Else, just print the numerical input. +% We need both to be true or else it can happen that numerals are used +% without anything to follow it up (Instead of \enquote{zwei Dutzend} we simply would +% have \enquote{zwei}). % \begin{macrocode} -\cs_new:Npn \@@_cuam_post_process_input_numerals:NN #1#2 +\cs_new_protected:Npn \@@_cuam_print_numerical_input:N #1 { - \bool_if:NTF \l_@@_tmpa_bool + \bool_lazy_and:nnTF + { \l_@@_lokal_phrase_bool } + { \l_@@_lokal_numeral_bool } { - \bool_if:NTF \l_@@_range_in_input_bool - { - \bool_lazy_and:nnF - { \int_compare_p:nNn {#1} < { \l_@@_print_numerals_below_int } } - { \int_compare_p:nNn {#2} < { \l_@@_print_numerals_below_int } } - { \bool_set_false:N \l_@@_lokal_numeral_bool } - }{ - \int_compare:nNnF {#1} < { \l_@@_print_numerals_below_int } - { \bool_set_false:N \l_@@_lokal_numeral_bool } - } + \@@_cuam_print_numerical_input_aux:NV #1\l_@@_phrase_number_tl } - { \bool_set_false:N \l_@@_lokal_numeral_bool } + { \@@_print_numerical_input:N #1 } } % \end{macrocode} -% -% -% Note: This command checks if \emph{both} a phrase and a numeral is -% used to decide whetever or not to print numerals. This is due to -% the $1$ being dependent (in some languages) depending on the gender -% of the following word. Currently testing only |\l_@@_lokal_numeral_bool| doesn't -% work due to the $1$ having a special parsing. +% Currently \mycs{cuam} only allows for lowercase numerals. % \begin{macrocode} -\cs_new_protected:Npn \@@_cuam_print_numerical_input:N #1 +\cs_new:Npn \@@_cuam_print_numerical_input_aux:Nn #1#2 { - \bool_lazy_and:nnTF - { \l_@@_lokal_phrase_bool } - { \l_@@_lokal_numeral_bool } + \int_compare:nNnTF {#1} = { 1 } { - \@@_int_if_equal_one:nTF {#1} - { - \@@_translate_one_and_check_existance:Nx - \l_@@_translation_tmpa_tl - { \l_@@_phrase_number_tl -phrase-gender } - \l_@@_translation_tmpa_tl + \@@_culang_one_let_by_gender:NVTF + \l_@@_translation_tmpa_tl \l_@@_phrase_gender_tl + { \l_@@_translation_tmpa_tl } + { + \@@_print_numeral:V #1 + \bool_set_false:N \l_@@_lokal_numeral_bool } - { \exp_args:NV \@@_print_numeral:n #1 } - }{ \@@_print_numerical_input:N #1 } + } + { \@@_print_numeral:V #1 } } +\cs_generate_variant:Nn \@@_cuam_print_numerical_input_aux:Nn { NV } % \end{macrocode} +% \end{macro} % +% \begin{macro} { \@@_cuam_print_correct_unitphrase: } +% THis one is thankfully straightforward. % \begin{macrocode} \cs_new:Npn \@@_cuam_print_correct_unitphrase: { \bool_if:NT \l_@@_lokal_phrase_bool { \l_@@_cuphrase_space_tl - \l_@@_phrase_phrase_tl + \l_@@_phrase_text_tl } } % \end{macrocode} +% \end{macro} +% % % +% \subsection{\mycs{cucomp}} % % +% \begin{macrocode} +%\NewDocumentCommand \cucomp { d<> O{} m m m } +% { +% \group_begin: +% \@@_cucomp:nnnnn {#1} {#2} {#3} {#4} {#5} +% \group_end: +% } +% \end{macrocode} +% \begin{macrocode} +%\cs_new:Npn \@@_cucomp:nnnnn #1#2 #3#4#5 +% { +% \group_begin: +% \@@_set_cmd_type_to:n { cunum } +% \@@_do_the_stuff:nnnnnn {#1} {#2} {#3} { } {#4} { } +% / +% \@@_do_the_stuff:nnnnnn {#1} {#4=#5} {#3} { } {#4} { } +% \group_end: +% } +% \end{macrocode} +% +% \begin{macrocode} +%\cs_new:Npn \@@_do_cucomp_stuff:nnnnn #1#2 #3#4#5 +% { +% \group_begin: +% \@@_set_cmd_to:n { cucomp } +% \@@_do_the_stuff:nnnnnn {#1} {#2} {#3} { } {#4} +% \@@_do_the_stuff:nnnnnn {#1} {#2} {#3} { } {#5} +% \group_end: +% } +% \end{macrocode} +% +% \begin{macrocode} +%\cs_new:Npn \@@_new_process_compare_in_input: +% { +% \tl_set_eq:NN \l_@@_number_tmpb_tl \l_@@_number_tmpa_tl +% \tl_set_eq:NN \l_@@_tmpa_unit_tl \l_@@_option_unit_tl +% \@@_calculate_and_store_in:N \l_@@_number_tmpa_tl +% \@@_calculate_and_store_in:N \l_@@_number_tmpb_tl +% \@@_post_process_accordingly:NN \l_@@_number_tmpa_tl \q_no_value +% } +% \end{macrocode} +% % % % \section {cukeys} % % \subsection {Define Keys} % -% \begin{macro}{ \cudefinekeys } +% \begin{macro}{ } % Defining keys. % \begin{macrocode} + +%% To be deleted. In order to remove error messages. +%\newcommand \cudefinekeys {} +%\newcommand \cudefinesinglekey {} +%\newcommand \cuaddkeys {} +%\newcommand \cuaddsinglekeys {} +%\newcommand \cuaddtokeys {} +% \end{macrocode} +% \end{macro} +% +% +% +% +% \begin{macro}{ \cudefinekeys , \cudefinesinglekey } +% Commands used for defining unit-keys. Their main differences +% is in setting |\l_@@_single_key_bool| to the respective value +% and for single-keys to rescan |#2| as it can contain |#1| in its argument. +% +% The other stuff is imply a intialization using the unit in |#1| as a base +% and parsing the rest. +% \begin{macrocode} \NewDocumentCommand \cudefinekeys { m m } { \bool_set_false:N \l_@@_single_key_bool - \@@_cukeys_define_keys_and_single_keys:nn {#1} {#2} + \@@_initialice_cukeys_define:n {#1} + \@@_cukeys_prepare_parsing_keys:nn {#1} {#2} + } +\NewDocumentCommand \cudefinesinglekey { m m } + { + \bool_set_true:N \l_@@_single_key_bool + \@@_initialice_cukeys_define:n {#1} + \tl_set_rescan:Nno \l_@@_tmpa_tl + { \char_set_catcode_letter:N \# } {#2} + \@@_cukeys_prepare_parsing_keys:nV {#1} \l_@@_tmpa_tl + } +% \end{macrocode} +% \end{macro} +% +% \begin{macro}{ \@@_initialice_cukeys_define:n } +% Using |#1| as the base unit for the following keys we set some variables. +% |\l_@@_tmpa_seq| will contain the parsed units; |\l_@@_tmpb_seq| the values. +% We also make sure the unit |#1| is defined, else create an error. +% Also of importance is to set |\l_@@_new_key_base_tl| to $1$. This variable +% is important while adding keys as it sets the base conversion value so to speak. +% \begin{macrocode} +\cs_new:Npn \@@_initialice_cukeys_define:n #1 + { + \@@_set_state_to:n { normal } + \seq_clear:N \l_@@_tmpa_seq + \seq_clear:N \l_@@_tmpb_seq + \prop_clear:N \l_@@_tmpa_prop + \tl_set:Nn \l_@@_new_key_base_tl { 1 } + \@@_error_if_unit_not_defined:nNT {#1} \l_@@_original_unit_tl + { \@@_set_state_to:n { error } } + } +% \end{macrocode} +% \end{macro} +% +% +% \begin{macro}{\cudefinekeychain} +% The command that is going to replace \mycs{cudefinekeys} and friends +% (but \emph{not} the single key variants). Nothing going on here. +% The biggest difference to \mycs{cudefinekeys} is that we do not know +% the base key by default. Thus we make a short detour to grab the first unit +% we encounter in |#1| (and its value) and the rest proceeeds as before. +% \begin{macrocode} +\NewDocumentCommand \cudefinekeychain { m } + { + \bool_set_false:N \l_@@_single_key_bool + \@@_initialice_cukeychain_define:n {#1} + \@@_cukeys_prepare_parsing_keys:n {#1} + } +% \end{macrocode} +% \end{macro} +% \begin{macro}{\@@_initialice_cukeychain_define:n} +% Initializing the key-chain. First, grab the first unit in |#1|. This needs to +% be done as the old code expects us to already know a base unit. Here the first +% unit that is encountered is taken as the base unit. Its value is stored in |\l_@@_base_tl|. +% This is needed to normalice the values in relation to the base unit. Remember, +% the base unit is defined to be exactly |1|, thus all further values need to be +% changed to reflect that. The normalization factor is stored inside |\l_@@_new_key_base_tl|. +% |\l_@@_curr_unit_tl| is cleared to remind me, that it is not a unit per se +% (as it is not set \emph{via} |\@@_set_unit:Nn|. +% \begin{macrocode} +\cs_new:Npn \@@_initialice_cukeychain_define:n #1 + { + \@@_cukeychain_get_first_unit_aux:nn #1 + \q_recursion_tail \q_recursion_tail \q_recursion_stop + \@@_if_state_equal:nF { error } + { + \exp_args:NV \@@_initialice_cukeys_define:n \l_@@_curr_unit_tl + \@@_tl_eval:Nn \l_@@_new_key_base_tl { 1 / (\l_@@_base_tl) } + \tl_clear:N \l_@@_curr_unit_tl + } + } +% \end{macrocode} +% \end{macro} +% \begin{macro}{\@@_cukeychain_get_first_unit_aux:nn} +% Nothing fancy here. Just grab the first unit and its value. +% \begin{macrocode} +\cs_new:Npn \@@_cukeychain_get_first_unit_aux:nn #1#2 + { + \quark_if_recursion_tail_stop_do:nn {#1} + { \@@_set_state_to:n { error } } + \quark_if_recursion_tail_stop_do:nn {#2} + { + \msg_error:nn { cooking-units } { missing-argument } + \@@_set_state_to:n { error } + } + \tl_set:Nn \l_@@_curr_unit_tl {#1} + \tl_set:Nn \l_@@_base_tl {#2} + \use_none_delimit_by_q_recursion_stop:w + \@@_cukeychain_get_first_unit_aux:nn } % \end{macrocode} % \end{macro} % -% \begin{macro}{ \cudefinesinglekey } -% Again, but with the boolean set to true. +% +% +% +% +% +% +% \begin{macro}{ \cuaddkeys , \cuaddtokeys , \cuaddsinglekeys } +% Thanks to rewriting the code the |add| commands and the |define| +% commands share a lot of code. The difference is the initialicing, which is a bit +% different. % \begin{macrocode} -\NewDocumentCommand \cudefinesinglekey { m m } +\NewDocumentCommand \cuaddkeys { m m } + { + \bool_set_false:N \l_@@_single_key_bool + \@@_initialice_cukeys_add:n {#1} + \@@_cukeys_prepare_parsing_keys:nn {#1} {#2} + } +\NewDocumentCommand \cuaddtokeys { m m m } + { + \bool_set_false:N \l_@@_single_key_bool + \@@_initialice_cukeys_add:n {#1} + \tl_set:Nn \l_@@_tmpa_tl { {#2} { \fp_eval:n { 1.0 / (#3) } } } + \@@_cukeys_prepare_parsing_keys:nV {#1} \l_@@_tmpa_tl + } +\NewDocumentCommand \cuaddsinglekeys { m m } { \bool_set_true:N \l_@@_single_key_bool - \@@_cukeys_define_keys_and_single_keys:nn {#1} {#2} + \@@_initialice_cukeys_add:n {#1} + \tl_set_rescan:Nno \l_@@_tmpa_tl + { \char_set_catcode_letter:N \# } {#2} + \@@_cukeys_prepare_parsing_keys:nV {#1} \l_@@_tmpa_tl + } +% \end{macrocode} +% \end{macro} +% +% \begin{macro}{ \@@_initialice_cukeys_add:n } +% This one is quite different compared to |\@@_initialice_cukeys_define:n| as it +% needs a bit more stuff to do. +% +% The beginning is checking if |#1| exists and later if |#1| is a key at all. +% If it not a key already we cannot add keys, in either case print an error and +% go to the end. +% +% If the checks passed without error we go to the \enquote{retrieving} step. +% As we are adding (potentially) new keys to existing ones we need to retrive +% the values we stored and got during the definition of keys. +% +% First, get the |\l_@@_original_unit_tl|. This one is the unit given in the first argument +% of either |cudefinekeys| or |\cudefinesinglekey|. It is the base unit +% for those keys. Afterwards retrieve the other values. Get the property list +% which stores the unit-value pairs, get the list of units we can transform the unit to +% and -- to make sure -- make sure a single key is only added to a single key and vice versa. +% +% Afterwards, this cs is done. +% \begin{macrocode} +\cs_new:Npn \@@_initialice_cukeys_add:n #1 + { + \seq_clear:N \l_@@_tmpa_seq + \seq_clear:N \l_@@_tmpb_seq + \@@_set_state_to:n { normal } + \@@_error_if_unit_not_defined:nNT {#1} \l_@@_curr_unit_tl + { + \@@_set_state_to:n { error } + \use_none_delimit_by_q_stop:w + } + \@@_if_unit_has_a_key:nF {#1} + { + \msg_error:nnx { cooking-units } { Key-not-defined } \l_@@_curr_unit_tl + \@@_set_state_to:n { error } + \use_none_delimit_by_q_stop:w + } + \tl_set_eq:Nc \l_@@_original_unit_tl { l_@@_base_key_unit_ \l_@@_curr_unit_tl _tl } + \prop_set_eq:Nc \l_@@_tmpa_prop { l_@@_new_cukeys_ \l_@@_original_unit_tl _prop } + \prop_get:NnN \l_@@_tmpa_prop {#1} \l_@@_new_key_base_tl + \prop_get:NnN \l_@@_tmpa_prop { Liste } \l_@@_tmpa_seq + \prop_get:NnN \l_@@_tmpa_prop { single } \l_@@_tmpa_tl + \int_compare:nNnF { \l_@@_single_key_bool } = { \l_@@_tmpa_tl } + { + \msg_error:nn { cooking-units } { Adding-single-to-multi-key-or-vice-verca } + \@@_set_state_to:n { error } + } + \use_none_delimit_by_q_stop:w \q_stop + } +\cs_generate_variant:Nn \@@_initialice_cukeys_add:n { V } +% \end{macrocode} +% \end{macro} +% +% +% \begin{macro}{\cuaddtokeychain} +% This command is going to replace \mycs{cuaddkeys} and \mycs{cuaddtokeys}. +% It is similar to \mycs{cudefinekeychain}. Just with some more hoops before the keys +% can be defined. +% \begin{macrocode} +\NewDocumentCommand \cuaddtokeychain { m } + { + \bool_set_false:N \l_@@_single_key_bool + \@@_initialice_cukeys_keychain_add:n {#1} + \@@_cukeys_prepare_parsing_keys:n {#1} + } +% \end{macrocode} +% \end{macro} +% +% \begin{macro}{\@@_initialice_cukeys_keychain_add:n} +% Initiliazing the key-chain. Like \mycs{cudefinekeychain} we first need to get +% the base unit. Afterwards, the \enquote{normal} initialization command is used +% (with the found base key) and |\l_@@_new_key_base_tl| is normalized. +% \begin{macrocode} +\cs_new:Npn \@@_initialice_cukeys_keychain_add:n #1 + { + \@@_cukeys_keychain_get_first_valid_unit:n {#1} + \@@_if_state_equal:nF { error } + { + \@@_initialice_cukeys_add:V \l_@@_curr_unit_tl + \@@_tl_eval:Nn \l_@@_new_key_base_tl { (\l_@@_new_key_base_tl) / (\l_@@_base_tl) } + } + } +% \end{macrocode} +% \end{macro} +% \begin{macro}{\@@_cukeys_keychain_get_first_valid_unit:n +% , \@@_cukeys_keychain_get_first_valid_unit_aux:nn +% } +% +% Just a wrapper for the loop. +% \begin{macrocode} +\cs_new:Npn \@@_cukeys_keychain_get_first_valid_unit:n #1 + { + \@@_cukeys_keychain_get_first_valid_unit_aux:nn #1 + \q_recursion_tail \q_recursion_tail \q_recursion_stop + } +% \end{macrocode} +% Finding the base unit is a bit more complex than just taking the first +% one found, but not by much. The idea is simple: Loop through the units +% till one is found that has an existing key. This allows the user to set the +% new unit(s) first in the loop and the base unit at last place (or an arbitrary place). +% We set this unit to be the |\l_@@_original_unit_tl| and its value as |\l_@@_base_tl| +% (not evaluated at this place). If a unit is found, break the loop. +% \begin{macrocode} +\cs_new:Npn \@@_cukeys_keychain_get_first_valid_unit_aux:nn #1#2 + { + \quark_if_recursion_tail_stop_do:nn {#1} + { + \msg_error:nn { cooking-units } { Key-chain-unit-not-found } + \@@_set_state_to:n { error } + } + \quark_if_recursion_tail_stop_do:nn {#2} + { + \msg_error:nn { cooking-units } { missing-argument } + \@@_set_state_to:n { error } + } + \@@_if_unit_has_a_key:nT {#1} + { + \@@_error_if_unit_not_defined:nNT {#1} \l_@@_curr_unit_tl + { \@@_set_state_to:n { error } } + \tl_set_eq:NN \l_@@_original_unit_tl \l_@@_curr_unit_tl + \tl_set:Nn \l_@@_base_tl {#2} + \use_none_delimit_by_q_recursion_stop:w + } + \@@_cukeys_keychain_get_first_valid_unit_aux:nn } % \end{macrocode} % \end{macro} % -% \begin{macro}{ \@@_cukeys_define_keys_and_single_keys:nn } -% First checks whetever the unit is defined or not, then clears some macros -% which are needed later. Further procession depends on the boolean. -% If more than one key is created, the value \lstinline|\l_@@_tmpa_fp| is set to one. -% This is important for adding keys where \lstinline|\l_@@_tmpa_fp| is changed accordingly. +% +% +% +% +% \begin{macro}{ \@@_cukeys_prepare_parsing_keys:n +% , \@@_cukeys_prepare_parsing_keys:nn +% } +% Just a wrapper. |#1| is the base unit and thus defined to be |1|. % \begin{macrocode} -\cs_new:Npn \@@_cukeys_define_keys_and_single_keys:nn #1#2 +\cs_new:Npn \@@_cukeys_prepare_parsing_keys:nn #1#2 + { + \@@_cukeys_prepare_parsing_keys:n { {#1} { 1.0 } #2 } + } +% After initialising the variables we go to this command. +% At first it seperates the input in |#1| into unit-value pairs via |\@@_cukeys_parse_keys|. +% If no error happened, we go to the definition of keys. +% +% As we add new keys and potentially change the values of old ones we need +% to globally clear |\g_@@_master_changer_prop|. +\cs_new:Npn \@@_cukeys_prepare_parsing_keys:n #1 { - \@@_error_if_unit_not_defined:nTF {#1} - { \bool_set_true:N } { \bool_set_false:N } - \l_@@_unit_error_bool - \tl_if_blank:nF {#2} + \@@_cukeys_parse_keys:n {#1} + \bool_lazy_or:nnF + { \int_compare_p:nNn \l_@@_nr_of_units_int = 0 } + { \@@_if_state_equal_p:n { error } } { \prop_gclear:N \g_@@_master_changer_prop - \prop_gclear:N \g_@@_convert_to_eV_remember_prop - \seq_clear:N \l_@@_tmpa_seq - \prop_clear:N \l_@@_tmpa_prop - \prop_clear_new:c { l_@@_cukeys_ #1 _prop } + \@@_cukeys_prepare_lists:N \l_@@_original_unit_tl + \@@_new_cukeys_create_keys:V \l_@@_original_unit_tl + } + } +\cs_generate_variant:Nn \@@_cukeys_prepare_parsing_keys:nn { nV } +% \end{macrocode} +% \end{macro} +% +% \begin{macro}{ \@@_cukeys_parse_keys:nn , \@@_cukeys_parse_keys_aux:nn} +% Seperates the input into key-value pairs. This cs doesn't do much as the main +% stuff is done in |\@@_cukeys_parse_keys_aux:nn|. +% \begin{macrocode} +\cs_new:Npn \@@_cukeys_parse_keys:n #1 + { + \int_zero:N \l_@@_nr_of_units_int + \@@_cukeys_parse_keys_aux:nn #1 + \q_recursion_tail \q_recursion_tail \q_recursion_stop + } +% \end{macrocode} +% +% Note for the beginning: +% Keys used for definining (#1) are converted into strings! +% No need to keep catcodes. Just string everything! +% +% This command does a lot. The first is the stopping condition, then two +% checks for error messages. Either a \enquote{missing-argument} or a \enquote{unit +% not defined} thingy. +% +% The value is stored in |\l_@@_tmpb_tl|. Afterwards check if a |##1| is found inside. +% If it is, replace |##1| by |\l_@@_tmpa_fp|. So we do not store a command with an +% argument, but rather a formula with a variable inside, which we can set. +% If on ther other side it contains a |##1|, but is not a single key, we raise an error. +% +% Afterwards -- if nor error -- we calculate the value in |\l_@@_tmpb_tl| if we have no +% single key. Here |\l_@@_new_key_base_tl| comes into play. The idea is the following: +% the base key is \enquote{kg} with \enquote{1}, furthermore we have the key +% \enquote{dag} with value \enquote{100}. Now we add \enquote{g} to \enquote{dag} +% with \enquote{10} ($1$ dag equals 10 g). In order to have the correct relation betwen +% the base key \enquote{kg} and \enquote{g}, we set |\l_@@_new_key_base_tl| during +% the initialization to \enquote{100}. Then the relation between \enquote{kg} and +% \enquote{g} is correct with \enquote{(10)*100=1000}. +% +% Add the unit to the list of units; add the unit-value to the propery-list. +% \begin{macrocode} +\cs_new:Npn \@@_cukeys_parse_keys_aux:nn #1#2 + { + \quark_if_recursion_tail_stop:n {#1} + \quark_if_recursion_tail_stop_do:nn {#2} + { + \msg_error:nn { cooking-units } { missing-argument } + \@@_set_state_to:n { error } + } + \@@_error_if_unit_not_defined:nNT {#1} \l_@@_option_unit_tl + { \@@_set_state_to:n { error } } +% + \tl_set:Nn \l_@@_tmpb_tl {#2} + \tl_if_in:NVT \l_@@_tmpb_tl \g_@@_input_str_hash_one_tl + { \bool_if:NTF \l_@@_single_key_bool + { \tl_replace_all:NVn \l_@@_tmpb_tl \g_@@_input_str_hash_one_tl { \l_@@_tmpa_fp } } { - \@@_cukeys_parse_and_create_single_key:nn {#1} {#2} - }{ - \fp_set:Nn \l_@@_tmpa_fp { 1.0 } - \tl_set:Nn \l_@@_original_unit_tl {#1} - \@@_cukeys_parse_and_create_keys:nn {#1} - { - {#1} { 1.0 } #2 - } + \msg_error:nnx { cooking-units } { formula-in-non-singlekeys } \l_@@_tmpb_tl + \@@_set_state_to:n { error } } } + \@@_if_state_equal:nF { error } + { + \int_incr:N \l_@@_nr_of_units_int + \bool_if:NF \l_@@_single_key_bool + { \@@_tl_eval:Nn \l_@@_tmpb_tl { (\l_@@_tmpb_tl) * (\l_@@_new_key_base_tl) } } + \seq_if_in:NVF \l_@@_tmpa_seq \l_@@_option_unit_tl + { \seq_put_right:NV \l_@@_tmpa_seq \l_@@_option_unit_tl } + \prop_put:NnV \l_@@_tmpa_prop {#1} \l_@@_tmpb_tl + } + \@@_cukeys_parse_keys_aux:nn } % \end{macrocode} % \end{macro} % -% \begin{macro}{ \@@_cukeys_parse_and_create_keys:nn } -% A simple parsing function using quarks (which are pretty handy). -% At first parses the input, then creates the property lists for each key -% (containing all the values) and at last defines the keys. -% \begin{macrocode} -\cs_new:Npn \@@_cukeys_parse_and_create_keys:nn #1#2 - { - \@@_cukeys_parse_input:nn #2 - \q_recursion_tail \q_recursion_tail \q_recursion_stop - \bool_if:NF \l_@@_unit_error_bool +% \begin{macro}{ \@@_cukeys_prepare_lists:N } +% At this point we can assume everything to be correct. +% |#1| the main unit aka.\ the \enquote{original unit} or \enquote{base unit}. +% +% First we clear/create new the property list which will contains the conversion values for +% for each unit. There we will safe the the values we collected in the last step, +% the list of units in this set and if the key is single or not. +% +% For simplification, each unit in the key-list always points to the \enquote{base unit}, +% so \enquote{g}, \enquote{kg}, \enquote{dag}, etc.\ will all show to \enquote{kg}. +% This is not needed if we have a single-key (due to how single-keys work). +% Furhtermore, if no single-key, set the default transformation value to \enquote{1}; +% not sure if the last step is necessary, but eh. +% \begin{macrocode} +\cs_new:Npn \@@_cukeys_prepare_lists:N #1 + { + \prop_clear_new:c { l_@@_new_cukeys_ #1 _prop } + \prop_set_eq:cN { l_@@_new_cukeys_ #1 _prop } \l_@@_tmpa_prop + \prop_put:cnV { l_@@_new_cukeys_ #1 _prop } { Liste } \l_@@_tmpa_seq + \prop_put:cnV { l_@@_new_cukeys_ #1 _prop } { single } \l_@@_single_key_bool + \tl_set:cn { l_@@_unit_change_ #1 _tl } { 1 } + \tl_set_eq:cN { l_@@_base_key_unit_ #1 _tl } #1 + \bool_if:NF \l_@@_single_key_bool { - \@@_cukeys_create_key_prop:n {#1} - \clist_set_from_seq:NN \l_@@_tmpa_clist \l_@@_tmpa_seq - \@@_cukeys_define_keys:V \l_@@_tmpa_clist + \seq_map_inline:Nn \l_@@_tmpa_seq + { + \tl_set_eq:cN { l_@@_base_key_unit_ ##1 _tl } #1 + \tl_set:cn { l_@@_unit_change_ ##1 _tl } { 1 } + } } } -\cs_generate_variant:Nn \@@_cukeys_parse_and_create_keys:nn { Vn } % \end{macrocode} % \end{macro} % -% \begin{macro}{ \@@_cukeys_parse_input:nn } -% Yeah \dots\ \lstinline|\l_@@_tmpa_clist| stores all the used unit-keys, while -% the property list saves the relation to each other. This cycle is repeated until an -% recursion tail is found. If you define a new key, \verb|\l_@@_tmpa_fp| is set to -% 1 and changed later if a new key is added. +% \begin{macro}{ \@@_new_cukeys_create_keys:n , \@@_new_cukeys_create_keys:V } +% Here we start creating the keys. If seperate into two cases: +% Do we have a single-key or not. If yes, just create the key |#1| +% and do what needs to be done. If not, we need to create a bunch of +% keys for each unit in the list. % \begin{macrocode} -\cs_new:Npn \@@_cukeys_parse_input:nn #1#2 +\cs_new:Npn \@@_new_cukeys_create_keys:n #1 { - \quark_if_recursion_tail_stop:n {#1} - \quark_if_recursion_tail_stop_do:nn {#2} - { \msg_error:nn { cooking-units } { missing-argument } } - \@@_error_if_unit_not_defined:nF {#1} - { - \seq_if_in:NnF \l_@@_tmpa_seq {#1} - { \seq_put_right:Nn \l_@@_tmpa_seq {#1} } - \prop_put:Nnx \l_@@_tmpa_prop {#1} { \fp_eval:n { (#2) * \l_@@_tmpa_fp } } +% % #1: original_unit + \clist_set_from_seq:NN \l_@@_tmpa_clist \l_@@_tmpa_seq + \bool_if:NTF \l_@@_single_key_bool + { + \@@_new_cukeys_define_key:nVn + {#1} \l_@@_tmpa_clist {#1} + }{ + \seq_map_inline:Nn \l_@@_tmpa_seq + { + \@@_new_cukeys_define_key:nVn + {##1} \l_@@_tmpa_clist {#1} + } } - \@@_cukeys_parse_input:nn } - +\cs_generate_variant:Nn \@@_new_cukeys_create_keys:n { V } % \end{macrocode} % \end{macro} % -% \begin{macro}{ \@@_cukeys_create_key_prop:n } -% -% \changes {2016/09/22} {1.02f} {Save 'Liste', 'prop' and 'Erstes Ding' to \cs{l_tmpb_prop} and set the unit-prop lists equal to \cs{l_tmpb_prop}.} -% \changes {2016/09/22} {1.02g} {Do not need \cs{tl_clear_new:c} as token list is already defined.} -% -% All linked unit-keys are stored within \lstinline|\l_@@_tmpa_clist| and are mapped -% one after another. At first a property list is created (or cleared), this property list -% stores the units linked to this unit, saves the created property list which contains the -% numerical relation of each unit. \lstinline|Erstes Ding| (firsth thing) stores -% the first unit used for defining the keys, it is needed later for adding keys. -% -% For each unit the other units are added in the cleared or newly created property list -% as keys with their value being the correct numerical relation. For example: -% -% \begin{align*} -% \SI{1}{\kg}&= \SI{1}{\kg} \\ -% \SI{1}{\kg}&= \SI{100}{\deka\gram} \\ -% \SI{1}{\kg}&= \SI{1000}{\g} \\ -% \SI{1}{\kg}&= \SI{35.27399}{oz} -% \end{align*} -% -% Therefore the property list for \lstinline|kg| contains the keys and values: -% \myunit{kg}=\myunit{1} -% \myunit{dag}=\myunit{100}, \myunit{g}=\myunit{1000} and \myunit{oz}= \myunit{35.27399}. -% -% For the next unit (\myunit{dag} in this case) a new property list is created, relation above -% stored inside etc. The condition now is that \myunit{dag}=\texttt{1}, therefore every number -% is divided the the number \texttt{100}: -% -% \begin{align*} -% \SI{1}{\deka\gram}&= \SI{0.01}{\kg} \\ -% \SI{1}{\deka\gram}&= \SI{1}{\deka\gram} \\ -% \SI{1}{\deka\gram}&= \SI{10}{\g} \\ -% \SI{1}{\deka\gram}&= \SI{0.3527399}{\oz} -% \end{align*} -% -% Same for \myunit{g}: -% -% \begin{align*} -% \SI{1}{\g}&= \SI{0.001}{\kg} \\ -% \SI{1}{\g}&= \SI{0.1}{\deka\gram} \\ -% \SI{1}{\g}&= \SI{1}{\g} \\ -% \SI{1}{\g}&= \SI{0.03527399}{oz} -% \end{align*} -% -% and \myunit{oz} -% -% \begin{align*} -% \SI{1}{oz}&= \SI{0.0283495}{\kg} \\ -% \SI{1}{oz}&= \SI{2.83495}{\deka\gram} \\ -% \SI{1}{oz}&= \SI{28.3495}{\g} \\ -% \SI{1}{oz}&= \SI{1}{oz} -% \end{align*} +% \begin{macro}{ \@@_new_cukeys_define_key:nnn , \@@_new_cukeys_define_key:nVn } +% Now we define some key(s). |#1| is the unit and key-to-be-defined. +% As |#1| is not expanded, this can contain control sequences, etc. not need for worry +% here. % -% \begin{macrocode} -\cs_new:Npn \@@_cukeys_create_key_prop:n #1 - { - \prop_set_eq:cN { l_@@_cukeys_ #1 _prop } \l_@@_tmpa_prop - \prop_put:cnV { l_@@_cukeys_ #1 _prop } { Liste } \l_@@_tmpa_seq - \seq_map_inline:Nn \l_@@_tmpa_seq - { - \tl_set_eq:cN { l_@@_base_key_unit_ ##1 _tl } \l_@@_original_unit_tl - \tl_set:cn { l_@@_unit_change_ ##1 _tl } { 1.0 } - } - } -% \end{macrocode} -% \end{macro} +% We define the key |#1| with a list of choices |#2| (which is the list of units +% collected in the parse step). |#3| plays an important role as it is the +% \enquote{base unit}. We mainly need this to do some shortcuts later on. +% So instead of getting the the base unit for \enquote{g} \emph{via} +% |l_@@_base_key_unit_g_tl| (which would be \enquote{kg}), we give \enquote{kg} +% directly as the argument |#3|. It was made sure that |#3| \emph{not} a +% control sequence, but text. % -% \begin{macro}{ \@@_cukeys_define_keys:n , \@@_cukeys_define_keys:V } -% Defining the keys: It maps through the list of unit-keys and creates a -% unit-key respectively. +% In order to remind the user which choices each key have, define an error +% message for unknown keys. % \begin{macrocode} -\cs_new:Npn \@@_cukeys_define_keys:n #1 - { - \seq_map_inline:Nn \l_@@_tmpa_seq - { - \@@_cukeys_keys_define:nn {##1} {#1} - } - } -\cs_new:Npn \@@_cukeys_keys_define:nn #1#2 +\cs_new:Npn \@@_new_cukeys_define_key:nnn #1#2#3 { - \seq_if_in:NnF \l_@@_list_of_defined_keys_seq {#1} + \@@_if_unit_has_a_key:nF {#1} { \seq_put_right:Nn \l_@@_list_of_defined_keys_seq {#1} } \keys_define:nn { cooking-units } { #1 .choices:nn = {#2} - { - \@@_cukeys_define_keys_and_single_key_aux:n {#1} - } , + { \@@_change_unit_from_to:nVn {#1} \l_keys_choice_tl {#3} } , #1 / unknown .code:n= { \seq_set_split:Nnn \l_tmpa_seq { , } {#2} @@ -7499,255 +8920,212 @@ and the derived file cooking-units.sty. #1 .groups:n = { change-unit } } } -\cs_generate_variant:Nn \@@_cukeys_define_keys:n { V } +\cs_generate_variant:Nn \@@_new_cukeys_define_key:nnn { nVn } % \end{macrocode} % \end{macro} % -% \begin{macro}{\@@_cukeys_define_keys_and_single_key_aux:n} -%^^A << -% \begin{macrocode} -\prg_new_conditional:Npnn \@@_prop_get_master:nnN #1#2#3 { F } - { - \prop_get:NnNTF \g_@@_master_changer_prop { #1 ~->~ #2 } #3 - { \prg_return_true: } - { \prg_return_false: } - } -\cs_generate_variant:Nn \@@_prop_get_master:nnNF { nVc } +% \begin{macro}{ \@@_change_unit_from_to:nnn } +% Our main \enquote{get the conversion value} command. +% |#1| is the current unit, |#2| is the unit it is converted into, +% |#3| is the \enquote{base unit}, given in order to make some shortcuts. % -\cs_new:Npn \@@_prop_gput_master:nnn #1#2#3 - { - \prop_gput:Nnn \g_@@_master_changer_prop { #1 ~->~ #2 } {#3} - } -\cs_generate_variant:Nn \@@_prop_gput_master:nnn { nVV, nVv } +% |\l_@@_change_unit_prop| stores which unit should be converted into which by +% a key-value list. If the unit is later used we restore the value from this property list. +% +% Now to the calculation. |\g_@@_master_changer_prop| stores the the conversion values +% globally in a | ~->~ | way. If we already have a conversion +% from |#1| to |#2| we simply restore this value and store it in |l_@@_unit_change_ #1_tl|. % -\cs_new:Npn \@@_cukeys_define_keys_and_single_key_aux:n #1 +% If the unit-change is requested for the first time we need to calculate the +% conversion value first. Afterwards, store it (globally) into |\g_@@_master_changer_prop| +% to not recalculate it in the future. +% \begin{macrocode} +\cs_new:Npn \@@_change_unit_from_to:nnn #1#2#3 { - \@@_prop_get_master:nVcF {#1} \l_keys_choice_tl { l_@@_unit_change_ #1_tl } + \prop_put:Nnn \l_@@_change_unit_prop {#1} {#2} + \prop_get:NncF + \g_@@_master_changer_prop + { #1 ~->~ #2 } + { l_@@_unit_change_ #1_tl } { - \prop_if_exist:cTF { l_@@_cukeys_ #1 _prop } - { - \prop_get:cVc - { l_@@_cukeys_ #1 _prop } - \l_keys_choice_tl - { l_@@_unit_change_ #1_tl } - \@@_prop_gput_master:nVv {#1} \l_keys_choice_tl { l_@@_unit_change_ #1_tl } - }{ - \tl_set_eq:Nc \l_@@_tmpa_tl { l_@@_base_key_unit_ #1 _tl } - \prop_set_eq:Nc \l_@@_tmpa_prop { l_@@_cukeys_ \l_@@_tmpa_tl _prop } - \@@_tl_eval:Nn \l_@@_tmpb_tl - { - (\exp_args:NNV\prop_item:Nn \l_@@_tmpa_prop \l_keys_choice_tl) / - (\prop_item:Nn \l_@@_tmpa_prop {#1}) - } - \@@_prop_gput_master:nVV {#1} \l_keys_choice_tl \l_@@_tmpb_tl - \tl_set:cV { l_@@_unit_change_ #1 _tl } \l_@@_tmpb_tl - } + \@@_cukeys_calculate_change_value:nnn {#1} {#2} {#3} + \prop_gput:Nnv \g_@@_master_changer_prop + { #1 ~->~ #2 } + { l_@@_unit_change_ #1 _tl } } - \prop_put:NnV \l_@@_change_unit_prop {#1} \l_keys_choice_tl } +\cs_generate_variant:Nn \@@_change_unit_from_to:nnn { nVn } % \end{macrocode} % \end{macro} % +% \begin{macro}{ \@@_cukeys_calculate_change_value:nnn } +% Great, an unit-change is requested for the first time, thus calculate +% the conversion value. +% +% First we check if the old unit |#1| is the same as the \enquote{base unit} +% |#3|. This is a nice shortcut, as the property list is stored with |#3| as a base, +% so direct retrival of the value is possible in this case. +% +% If |#1| and |#3| are different, we need to do some work. First, get the list +% of key-values |l_@@_new_cukeys_ #3 _prop| and store it in |\l_@@_tmpa_prop|. +% Now eval. % +% Having unit |a| and wanting unit |b|, we need the value to go from |a| to |b| +% which is done by the realtion $|b|/|a|$. This is checked easily as $|a|*|b|/|a|=|b|$. +% Replace this by |#1| and |#2| and we get: |#2|=|#1|*|#2|/|#1|, which we +% evaluate and store in |l_@@_unit_change_ #1 _tl|. % \begin{macrocode} -\cs_new:Npn \@@_cukeys_parse_and_create_single_key:nn #1#2 +\cs_new:Npn \@@_cukeys_calculate_change_value:nnn #1 #2 #3 { - \tl_set_rescan:Nnn \l_@@_tmpa_tl - { - \char_set_catcode_letter:N \# % - \char_set_catcode_ignore:N\ % - } { {#1} { 1.0 } #2 } - \@@_cusinglekeys_parse_input:V \l_@@_tmpa_tl - \bool_if:NF \l_@@_unit_error_bool + \str_if_eq:nnTF {#1} {#3} { - \@@_cusinglekeys_create_key_prop:n {#1} - \clist_set_from_seq:NN \l_@@_tmpa_clist \l_@@_tmpa_seq - \@@_cukeys_define_singlekey:nV {#1} \l_@@_tmpa_clist + \prop_get:cnc { l_@@_new_cukeys_ #1 _prop } {#2} { l_@@_unit_change_ #1 _tl } + }{ + \prop_set_eq:Nc \l_@@_tmpa_prop { l_@@_new_cukeys_ #3 _prop } + \@@_tl_eval:cn { l_@@_unit_change_ #1 _tl } + { + ( \prop_item:Nn \l_@@_tmpa_prop {#2} ) / + ( \prop_item:Nn \l_@@_tmpa_prop {#1} ) + } } } +\cs_generate_variant:Nn \@@_cukeys_calculate_change_value:nnn { VVV } % \end{macrocode} +% \end{macro} +% % -% \begin{macrocode} -\cs_new:Npn \@@_cusinglekeys_parse_input:n #1 - { - \@@_cusinglekeys_parse_input_aux:nn #1 - \q_recursion_tail \q_recursion_tail \q_recursion_stop - } -\cs_generate_variant:Nn \@@_cusinglekeys_parse_input:n { V } % -\cs_new:Npn \@@_cusinglekeys_parse_input_aux:nn #1#2 - { - \quark_if_recursion_tail_stop:n {#1} - \quark_if_recursion_tail_stop_do:nn {#2} - { \msg_error:nn { cooking-units } { missing-argument } } - \@@_error_if_unit_not_defined:nF {#1} - { - \seq_if_in:NnF \l_@@_tmpa_seq {#1} - { \seq_put_right:Nn \l_@@_tmpa_seq {#1} } - \tl_set:Nn \l_@@_tmpa_tl {#2} - \tl_replace_all:NVn \l_@@_tmpa_tl \g_@@_input_str_hash_one_tl { \l_@@_tmpa_fp } - \prop_put:NnV \l_@@_tmpa_prop {#1} \l_@@_tmpa_tl - } - \@@_cusinglekeys_parse_input_aux:nn - } -% \end{macrocode} % -% \begin{macrocode} -\cs_new:Npn \@@_cusinglekeys_create_key_prop:n #1 - { - \tl_set:cn { l_@@_unit_change_ #1 _tl } { 1.0 } - \tl_set:cn { l_@@_base_key_unit_ #1 _tl } {#1} - \prop_set_eq:cN { l_@@_cukeys_ #1 _prop } \l_@@_tmpa_prop - \prop_put:cnV { l_@@_cukeys_ #1 _prop } { Liste } \l_@@_tmpa_seq - } -% \end{macrocode} % -% \begin{macrocode} -\cs_new:Npn \@@_cukeys_define_singlekey:nn #1#2 - { - \@@_cukeys_keys_define:nn {#1} {#2} - } -\cs_generate_variant:Nn \@@_cukeys_define_singlekey:nn { nV } -% \end{macrocode} % % -% \section {Adding Keys} % -% \begin{macrocode} -\NewDocumentCommand \cuaddkeys { m m } - { - \bool_set_false:N \l_@@_single_key_bool - \@@_cukeys_add_keys_or_single_keys:nn {#1} {#2} - } -% \end{macrocode} % -% \begin{macrocode} -\NewDocumentCommand \cuaddsinglekeys { m m } - { - \bool_set_true:N \l_@@_single_key_bool - \@@_cukeys_add_keys_or_single_keys:nn {#1} {#2} - } -% \end{macrocode} % -% \begin{macrocode} -\NewDocumentCommand \cuaddtokeys { m m m } - { - \bool_set_false:N \l_@@_single_key_bool - \tl_set:Nn \l_@@_tmpb_tl { {#2} { \fp_eval:n { 1.0 / (#3) } } } - \@@_cukeys_add_keys_or_single_keys:nV {#1} \l_@@_tmpb_tl - } -% \end{macrocode} % % % -% \begin{macrocode} -\cs_new:Npn \@@_cukeys_add_keys_or_single_keys:nn #1#2 - { - \@@_error_if_unit_not_defined:nF {#1} - { - \seq_if_in:NnF \l_@@_list_of_defined_keys_seq {#1} - { \msg_error:nnn { cooking-units } { Key-not-defined } {#1} } - \tl_if_blank:nF {#2} - { - \prop_gclear:N \g_@@_master_changer_prop - \@@_cukeys_add_keys_and_single_key_aux:n {#1} - \bool_if:NTF \l_@@_single_key_bool - { \@@_cukeys_parse_and_create_single_key:nn {#1} {#2} } - { \@@_cukeys_parse_and_create_keys:Vn \l_@@_original_unit_tl {#2} } - } - } - } -\cs_generate_variant:Nn \@@_cukeys_add_keys_or_single_keys:nn { nV } -% \end{macrocode} % -%^^A (((( -% Now this does the following: 1) get the \enquote{original unit} (the unit used -% in the first argument of |\cudefinekeys|) 2) Get the list of units already in the -% list (It is important that the units are alway in the same order and one cannot -% rely on the order of the property-lists 3) Get the property list of the -% \enquote{original unit}. In the old code I simply stored the whole property list inside -% another property list, but this shouldn't be done this way. So \dots\ simply -% copy the original one. 4) As there is a unit added the unit it is added to -% might not be the \enquote{original unit}. As such we need the conversion factor. -% \begin{macrocode} -\cs_new:Npn \@@_cukeys_add_keys_and_single_key_aux:n #1 - { - \tl_set_eq:Nc \l_@@_original_unit_tl { l_@@_base_key_unit_ #1 _tl } - \prop_set_eq:Nc \l_@@_tmpa_prop { l_@@_cukeys_ \l_@@_original_unit_tl _prop } - \prop_get:NnN\l_@@_tmpa_prop { Liste } \l_@@_tmpa_seq - \prop_get:NnN \l_@@_tmpa_prop {#1} \l_@@_tmpa_fp - } -% \end{macrocode} % % % \section {Creating New Units} % % %\begin{macro}{ \declarecookingunit , \newcookingunit , \providecookingunit } +% Defining new units. Defining an unit is split into two parts: defining +% the necassary tl's and clist's and seq's; and setting them. Depending on which +% command is used, things are handled differently. +% +% We always make sure that the unit |#1| is first converted into a string. % \begin{macrocode} \NewDocumentCommand \declarecookingunit { o m } { - \seq_if_in:NnTF \g_@@_list_of_defined_units_seq {#2} - { \msg_info:nnn { cooking-units } { redefine-unit } {#2} } - { \@@_new_cooking_unit:nn {#1} {#2} } - \@@_set_cooking_unit:nn {#1} {#2} + \@@_if_unit_defined:nNTF {#2} \l_@@_original_unit_tl + { \msg_info:nnx { cooking-units } { redefine-unit } { \l_@@_original_unit_tl } } + { \@@_new_cooking_unit:V \l_@@_original_unit_tl } + \@@_set_cooking_unit:nnV {#1} {#2} \l_@@_original_unit_tl } \NewDocumentCommand \newcookingunit { o m } { - \@@_new_cooking_unit:nn {#1} {#2} - \@@_set_cooking_unit:nn {#1} {#2} + \@@_if_unit_defined:nNTF {#2} \l_@@_original_unit_tl + { \msg_error:nnV { cooking-units } { unit-already-defined } \l_@@_original_unit_tl } + { + \@@_new_cooking_unit:V \l_@@_original_unit_tl + \@@_set_cooking_unit:nnV {#1} {#2} \l_@@_original_unit_tl + } } \NewDocumentCommand \providecookingunit { o m } { - \seq_if_in:NnF \g_@@_list_of_defined_units_seq {#2} + \@@_if_unit_defined:nNT {#2} \l_@@_original_unit_tl { - \@@_new_cooking_unit:nn {#1} {#2} - \@@_set_cooking_unit:nn {#1} {#2} + \@@_new_cooking_unit:V \l_@@_original_unit_tl + \@@_set_cooking_unit:nnV {#1} {#2} \l_@@_original_unit_tl } } % \end{macrocode} %\end{macro} % +%\begin{macro}{ \@@_new_cooking_unit:n } +% Creates the token and other lists for the unit |#1| (which at this point is a string). +% Nothing really expectional here. % \begin{macrocode} -\cs_new:Npn \@@_new_cooking_unit:nn #1#2 +\cs_new:Npn \@@_new_cooking_unit:n #1 { - \seq_if_in:NnTF \g_@@_list_of_defined_units_seq {#2} - { \msg_error:nnn { cooking-units } { unit-already-defined } {#2} } + \tl_map_inline:nn {#1} { - \tl_map_inline:nn {#2} - { - \tl_if_in:NnT \l_@@_unit_letter_not_allowed_tl {##1} - { \msg_error:nnn { cooking-units } { character-not-allowed } {#2} } - } - \seq_gput_right:Nn \g_@@_list_of_defined_units_seq {#2} - \tl_new:c { l_@@_unit_change_ #2 _tl } - \tl_set:cn { l_@@_unit_change_ #2 _tl } { 1.0 } - \clist_new:c { l_@@_unit_option_ #2 _clist } - \keys_define:nn { cooking-units } - { - set-option-for-#2 .code:n = { \cusetoptionfor {#2} {##1} } , - add-option-for-#2 .code:n = { \cuaddoptionfor {#2} {##1} }, - } - \tl_new:c { l_@@_base_key_unit_ #2 _tl } - \tl_new:c { l_@@_default_unit_ #2 _tl } + \tl_if_in:NnT \l_@@_unit_letter_not_allowed_tl {##1} + { \msg_error:nnn { cooking-units } { character-not-allowed } {#1} } + } + \seq_gput_right:Nn \g_@@_list_of_defined_units_seq {#1} + \tl_new:c { l_@@_unit_change_ #1 _tl } + \tl_new:c { l_@@_base_key_unit_ #1 _tl } + \tl_new:c { l_@@_default_unit_ #1 _tl } + \clist_new:c { l_@@_unit_option_ #1 _clist } + \tl_set:cn { l_@@_unit_change_ #1 _tl } { 1 } + \keys_define:nn { cooking-units } + { + set-unit-hook-#1 .code:n = { \@@_set_options_for:nn {#1} {##1} } , + add-unit-hook-#1 .code:n = { \@@_add_options_for:nn {#1} {##1} }, + set-option-for-#1 .meta:n = { set-unit-hook-#1 = {##1} } , + add-option-for-#1 .meta:n = { add-unit-hook-#1 = {##1} } , } } -\cs_new:Npn \@@_set_cooking_unit:nn #1#2 +\cs_generate_variant:Nn \@@_new_cooking_unit:n { V } +% \end{macrocode} +% \end{macro} +% +%\begin{macro}{ \@@_set_cooking_unit:nnn , \@@_set_cooking_unit:nnV } +% Here we set the in the last step defined lists to their respective value. +% |#3| is the unit-string; |#2| is the unit given by the user (as it can be a command +% like |/%]; |#1| is either the wanted unit-symbol \emph{or} a key-val +% list. Depending on that, we either set the printed symbol to |#1| or parse the +% key-val list. +% +% This is done in a three step procedure (if |#1| is a value): First, check if +% the head of |#1| is a group. This happens if the user embraces |#1| in two +% curly brace pairs (e.g.\ |{{Test}}|). This is only needed if the user really wants +% the symbol to contain |=|. +% +% If |#1| is not protected by braces it is parsed as key(s) +% \begin{macrocode} +\cs_new:Npn \@@_set_cooking_unit:nnn #1#2#3 { - \IfNoValueTF {#1} + \@@_set_cooking_unit_base_translation:n {#3} + \bool_set_false:N \l_@@_symbol_was_set_by_key_bool + \bool_set_false:N \l_@@_contains_valid_key_bool + \IfNoValueF {#1} + { + \tl_if_head_is_group:nF {#1} + { \keys_set:nn { cooking-units / definition } {#1} } + } + \bool_if:NF \l_@@_symbol_was_set_by_key_bool { - \tl_set:cn { l_@@_default_unit_ #2 _tl } {#2} - \@@_deftranslation_base:xVn {#2} \c_@@_postfix_unit_tl {#2} - }{ - \tl_set:cn { l_@@_default_unit_ #2 _tl } {#1} - \@@_deftranslation_base:xVn {#2} \c_@@_postfix_unit_tl {#1} + \IfNoValueTF {#1} + { \tl_set:cn { l_@@_default_unit_ #3 _tl } {#2} } + { + \bool_if:NTF \l_@@_contains_valid_key_bool + { \tl_set:cn { l_@@_default_unit_ #3 _tl } {#2} } + { \tl_set:cn { l_@@_default_unit_ #3 _tl } {#1} } + } } - \@@_deftranslation_base:xVn {#2} \c_@@_postfix_unitname_tl { \q_@@_no_translation } - \@@_deftranslation_base:xVn {#2} \c_@@_postfix_unitname_pl_tl { \q_@@_no_translation } - \@@_deftranslation_base:xVn {#2} \c_@@_postfix_gender_tl { m } + \@@_culang_def_base:nnv { unit-symbol } {#3} { l_@@_default_unit_ #3 _tl } } +\cs_generate_variant:Nn \@@_set_cooking_unit:nnn { nnV } % \end{macrocode} +% \end{macro} % +%\begin{macro}{ \@@_set_cooking_unit_base_translation:n } +% Just an auxilary command. Sets the base translations to their default value. +% \begin{macrocode} +\cs_new:Npn \@@_set_cooking_unit_base_translation:n #1 + { + \@@_culang_def_base:nnn { name } {#1} \q_@@_no_translation + \@@_culang_def_base:nnn { name-pl } {#1} \q_@@_no_translation + \@@_culang_def_base:nnn { gender } {#1} { m } + } +% \end{macrocode} +% \end{macro} +% % % % \begin{macro}{\declarecookingderivatives} @@ -7767,149 +9145,229 @@ and the derived file cooking-units.sty. % \end{macrocode} % \end{macro} % -% The idea is the following. The relation between the units are given as -% |(#1)/(#2)| (e.g.). The idea is the following: -% \begin{enumerate} -% \item The derivative contains two units. -% \item The mathematical relationship is given by |(#1)/(#2)| -% \item Define |\@@_tmp:w| to be |(#1)/(#2)|. -% \item Parse through all values and store them in a list (e.g. |\l_tmpa_t|) as | {value-1}{value-2} | -% \item Use |\exp_after:wN \@@_tmp:w \l_tmpa_t | to expand to |\@@_tmp:w {value-1} {value-2} | -% \item Let |\@@_tmp:w| do its job. -% \end{enumerate} % -% \begin{macro}{\@@_tl_set_list:Nnn, \@@_tl_set_list:NnV, \@@_tl_set_list:NVV, \@@_tl_set_list_aux:Nnnnnnnnn } -% The following argument creates the list. I am a bit lazy here and don't quite know how -% to do it \enquote{correctly}. And I know, there are too many |\q_nil|. -% \begin{macrocode} -\cs_new:Npn \@@_tl_set_list:Nnn #1#2#3 - { - \@@_tl_set_list_aux:Nnnnnnnnn #1 {#2} #3 - \q_nil \q_nil \q_nil \q_nil \q_nil \q_nil \q_nil \q_nil \q_nil - \q_recursion_stop - } -\cs_generate_variant:Nn \@@_tl_set_list:Nnn { NnV, NVV } -\cs_new:Npn \@@_tl_set_list_aux:Nnnnnnnnn #1#2#3#4#5#6#7#8#9 - { - \tl_set:Nf #1 - { - \int_case:nn { \l_@@_curr_depth_int } - { - { 1 } { } - { 2 } { {#3} } - { 3 } { {#3}{#4} } - { 4 } { {#3}{#4}{#5} } - { 5 } { {#3}{#4}{#5}{#6} } - { 6 } { {#3}{#4}{#5}{#6}{#7} } - { 7 } { {#3}{#4}{#5}{#6}{#7}{#8} } - { 8 } { {#3}{#4}{#5}{#6}{#7}{#8}{#9} } - } - {#2} - } - \use_none_delimit_by_q_recursion_stop:w - } -% \end{macrocode} -% \end{macro} % \begin{macro} { \@@_declare_cooking_derivative:nnnn } % This command has the following parts: % \begin{enumerate} -% \item Get list of units in |#1|, count their number and store in |\l_@@_max_depth_int| +% \item Get list of units in |#1|, check if they are defined, +% count their number and store in |\l_@@_nr_of_units_int| % \item Use |\cs_generate_from_arg_count:NNnn| to create the commands -% \item Define lists |l_@@_tmp_ 1 ... \l_@@_max_depth_int |, same for prop. I know -% that there is a better way to do it, but this \emph{is} experimental. In the end, it -% safes a bit of brain-power for me. -% \item The main part: Map trough all units in the |l_@@_cukeys_ _prop| lists. -% \item Create key-porperty and define keys. +% that store the final parsed unit-keys, unit-symbols und unit-formulas inside. +% \item Prepare for the following loop. +% \item The main part: Do the loop. +% \item Declare keys and store their formula relation into a property-list. +% \item Clean up. % \end{enumerate} % \begin{macrocode} \cs_new:Npn \@@_declare_cooking_derivative:nnnn #1#2#3#4 { - \prop_gclear:N \g_@@_master_changer_prop - \seq_set_from_clist:Nn \l_@@_tmpa_seq {#1} - \seq_clear:N \l_@@_number_of_iterations_seq - \seq_clear:N \l_@@_derivative_unit_list_seq - \seq_clear:N \l_@@_derivative_symbol_list_seq - \seq_clear:N \l_@@_derivative_value_list_seq - \int_set:Nn \l_@@_max_depth_int { \seq_count:N \l_@@_tmpa_seq } - \int_set:Nn \l_@@_curr_depth_int { 1 } + \seq_clear:N \l_@@_list_of_units_seq + \@@_set_state_to:n { normal } + \clist_map_inline:nn {#1} + { + \@@_if_unit_defined:nNTF {##1} \l_@@_tmpa_tl + { + \@@_if_unit_has_a_key:VTF \l_@@_tmpa_tl + { \seq_put_right:NV \l_@@_list_of_units_seq \l_@@_tmpa_tl } + { + \tl_show:n { Error-no-key-defined } {##1} + \@@_set_state_to:n { error } + } + } { \@@_set_state_to:n { error } } + } + \@@_if_state_equal:nT { error } + { \use_none_delimit_by_q_recursion_stop:w } + \int_set:Nn \l_@@_nr_of_units_int { \seq_count:N \l_@@_list_of_units_seq } +% \end{macrocode} +% Now we generate the functions. The first takes the unit-keys and plugs it into +% the formula |#2| (unit-key) and |#4| (unit-symbol). +% The second function get's the nummerical values and stores it in a sequcence. +% Example: \\ +% Assuming |kg|, |m| and |s| with unit key |#1*#2-#3|, formula |#1*#2/#3| +% and symbol |#1\,\sfrac{#2}{#3}|. Looping through the units, the first +% function creates |kg*m-s|, |kg*m-min|, \dots, |oz*in-h|; and |kg\,\sfrac{m}{s}|, +% \dots, |oz\,\sfrac{in}{h}|. +% +% The second function creates their nummerical relation: for |kg|, |m| and |s| +% this would be |1*1/86400|. |kg|, |in|, |s| would be |1*(36/0.9144)/86400|. +% If we then transform the first ones |kg*m-s| into the second one |kg*in-s| +% we will later calculate $ \frac{1*(36/0.9144)/86400}{1*1/86400} $ which will get +% us the correct transformation. May explanation my not be very good, +% but it makes sense (later). +% \begin{macrocode} + \cs_generate_from_arg_count:NNnn \@@_create_unit:w \cs_set:Npn + { \l_@@_nr_of_units_int } + { + \seq_gpush:Nn \g_@@_stored_derived_unit_symbol_seq {#2} + \seq_gpush:Nn \g_@@_stored_derived_unit_print_seq {#4} + } + \cs_generate_from_arg_count:NNnn \@@_create_formula:w \cs_set:Npn + { \l_@@_nr_of_units_int } + { + \seq_gpush:Nn \g_@@_stored_derived_formula_seq {#3} + } % \end{macrocode} +% Preparing and startidoingng the loop. % \begin{macrocode} - \cs_generate_from_arg_count:NNnn \@@_tmp_unit_and_symbol_list:w \cs_set:Npn - { \l_@@_max_depth_int } - { - \seq_put_right:Nn \l_@@_derivative_unit_list_seq {#2} - \seq_put_right:Nn \l_@@_derivative_symbol_list_seq {#4} - } - \cs_generate_from_arg_count:NNnn \@@_tmp_value_list:w \cs_set:Npn - { \l_@@_max_depth_int } - { \seq_put_right:Nx \l_@@_derivative_value_list_seq { \fp_eval:n {#3} } } + \@@_prepare_sequence_loop: + \@@_step_loop_start:n { } % \end{macrocode} +% Now we create new cooking-units with the unit-keys and unit-symbols +% we created \emph{via} loop. As we need a \enquote{master unit} we use +% the most right unit in the derived unit list. This is because the most right one +% is created by the other base units. % \begin{macrocode} - \int_step_inline:nn { \l_@@_max_depth_int } - { - \tl_set_eq:Nc \l_@@_original_unit_tl - { l_@@_base_key_unit_ \seq_item:Nn \l_@@_tmpa_seq {##1} _tl } - \prop_set_eq:Nc \l_@@_tmpa_prop { l_@@_cukeys_ \l_@@_original_unit_tl _prop } - \prop_get:NnN \l_@@_tmpa_prop { Liste } \l_@@_tmpb_seq - \int_set:Nn \l_@@_tmpa_int { \seq_count:N \l_@@_tmpb_seq } -% \end{macrocode} -% \begin{macrocode} - \seq_put_right:NV \l_@@_number_of_iterations_seq \l_@@_tmpa_int - \seq_clear_new:c { l_@@_tmp_ ##1 _seq } - \prop_clear_new:c { l_@@_tmp_ ##1 _prop } - \seq_set_eq:cN { l_@@_tmp_ ##1 _seq } \l_@@_tmpb_seq - \prop_set_eq:cN { l_@@_tmp_ ##1 _prop } \l_@@_tmpa_prop - } + \seq_get_right:NN \g_@@_stored_derived_unit_symbol_seq \l_@@_curr_unit_tl + \seq_map_inline:Nn \g_@@_stored_derived_unit_symbol_seq + { + \seq_pop:NN \g_@@_stored_derived_formula_seq \l_@@_tmpb_tl + \prop_put:NnV \l_@@_derived_units_prop {##1} \l_@@_tmpb_tl + \seq_pop:NN \g_@@_stored_derived_unit_print_seq \l_@@_tmpa_tl % \end{macrocode} +% First create the unit, \emph{then} set the reference to the base unit. +% (Else it is not yet defined) % \begin{macrocode} - \seq_map_function:cN - { l_@@_tmp_ \int_use:N \l_@@_curr_depth_int _seq } - \@@_seq_step_function:n + \exp_args:NNx \declarecookingunit [ {symbol={\l_@@_tmpa_tl}} ] {##1} + \tl_set_eq:cN { l_@@_base_key_unit_ ##1 _tl } \l_@@_curr_unit_tl + } % \end{macrocode} +% Clean-up. Do not know if this is necessary, but eh. % \begin{macrocode} - \seq_get_left:NN \l_@@_derivative_unit_list_seq \l_@@_original_unit_tl - \prop_clear_new:c { l_@@_cukeys_ \l_@@_original_unit_tl _prop } + \seq_gclear:N \g_@@_stored_derived_unit_symbol_seq + \seq_gclear:N \g_@@_stored_derived_unit_print_seq + \seq_gclear:N \g_@@_stored_derived_formula_seq + \cs_undefine:N \@@_create_unit:w + \cs_undefine:N \@@_create_formula:w % \end{macrocode} +% If we had an error beforehand, we would jump to this place ignoring everything +% inbetween. % \begin{macrocode} - \int_zero:N \l_@@_tmpa_int - \clist_set_from_seq:NN \l_@@_tmpa_clist \l_@@_derivative_unit_list_seq - \seq_map_inline:Nn \l_@@_derivative_unit_list_seq - { - \int_incr:N \l_@@_tmpa_int - \tl_set:Nx \l_@@_tmpa_tl { \seq_item:Nn \l_@@_derivative_symbol_list_seq { \l_@@_tmpa_int } } - \exp_after:wN \declarecookingunit \exp_after:wN [ \l_@@_tmpa_tl ] {##1} - \prop_put:cnx - { l_@@_cukeys_ \l_@@_original_unit_tl _prop } - {##1} - { \seq_item:Nn \l_@@_derivative_value_list_seq { \l_@@_tmpa_int } } - \tl_clear_new:c { l_@@_base_key_unit_ ##1 _tl } - \tl_set_eq:cN { l_@@_base_key_unit_ ##1 _tl } \l_@@_original_unit_tl - \exp_args:NnV \@@_cukeys_keys_define:nn {##1} \l_@@_tmpa_clist - } + \use_none_delimit_by_q_recursion_stop:w + \q_recursion_stop } % \end{macrocode} % \end{macro} % +% \begin{macro} { \@@_declare_cooking_derivative:nnnn } % \begin{macrocode} -\cs_new:Npn \@@_seq_step_function:n #1 - { - \@@_tl_set_list:NnV \l_@@_list_of_units_tl {#1} \l_@@_list_of_units_tl - \prop_get:cnN { l_@@_tmp_ \int_use:N \l_@@_curr_depth_int _prop } {#1} \l_@@_tmpa_tl - \@@_tl_set_list:NVV \l_@@_list_of_values_tl \l_@@_tmpa_tl \l_@@_list_of_values_tl - \int_compare:nNnTF { \l_@@_curr_depth_int } = { \l_@@_max_depth_int } +\cs_new:Npn \@@_prepare_sequence_loop: + { + \seq_map_indexed_inline:Nn \l_@@_list_of_units_seq { - \exp_after:wN \@@_tmp_unit_and_symbol_list:w \l_@@_list_of_units_tl - \exp_after:wN \@@_tmp_value_list:w \l_@@_list_of_values_tl + \prop_clear_new:c { l_@@_keys_ ##1 _prop } + \seq_clear_new:c { l_@@_list_ ##1 _seq } + \tl_set_eq:Nc \l_@@_curr_unit_tl { l_@@_base_key_unit_ ##2 _tl } + \prop_set_eq:cc { l_@@_keys_ ##1 _prop } + { l_@@_new_cukeys_ \l_@@_curr_unit_tl _prop } + \prop_get:cnc { l_@@_keys_ ##1 _prop } { Liste } { l_@@_list_ ##1 _seq } + } + } +% \end{macrocode} +% \end{macro} +% +% \begin{macro} { \@@_declare_cooking_derivative:nnnn } +% \begin{macrocode} +\cs_new:Npn \@@_step_loop_start:n #1 + { + \tl_clear:N \l_@@_stored_units_tl + \tl_clear:N \l_@@_stored_formula_tl + \int_set:Nn \l_@@_depth_int { 1 } + \seq_map_function:cN + { l_@@_list_ \int_use:N \l_@@_depth_int _seq } \@@_seq_recursive_loop_function:n + } +% \end{macrocode} +% \end{macro} +% +% \begin{macro} { \@@_declare_cooking_derivative:nnnn } +% \begin{macrocode} +\cs_new:Npn \@@_seq_recursive_loop_function:n #1 + { + \group_begin: + \tl_put_right:Nn \l_@@_stored_units_tl { {#1} } + \tl_set_eq:Nc \l_@@_original_unit_tl { l_@@_base_key_unit_ #1 _tl } + \tl_put_right:Nx \l_@@_stored_formula_tl + { { ( + \exp_not:N \prop_item:Nn + \exp_not:c { l_@@_new_cukeys_ \l_@@_original_unit_tl _prop } {#1} + ) } } + \int_compare:nNnTF { \l_@@_depth_int } = { \l_@@_nr_of_units_int } + { + \exp_after:wN \@@_create_unit:w \l_@@_stored_units_tl + \exp_after:wN \@@_create_formula:w \l_@@_stored_formula_tl }{ - \int_incr:N \l_@@_curr_depth_int + \int_incr:N \l_@@_depth_int \seq_map_function:cN - { l_@@_tmp_ \int_use:N \l_@@_curr_depth_int _seq } - \@@_seq_step_function:n - \int_decr:N \l_@@_curr_depth_int + { l_@@_list_ \int_use:N \l_@@_depth_int _seq } \@@_seq_recursive_loop_function:n + } + \group_end: + } +% \end{macrocode} +% \end{macro} +% +% \begin{macro} { \@@_declare_cooking_derivative:nnnn } +% \begin{macrocode} +\keys_define:nn { cooking-units } + { + unknown .code:n = + { + \@@_if_key_ais_derived_unit:VTF \l_keys_key_str + { \@@_convert_derived_unit:Vn \l_keys_key_str {#1} } + { + \msg_error:nnxx { cooking-units } { key-unknown } + { \l_keys_path_str } { cooking-units } + } } } % \end{macrocode} +% \end{macro} +% +% \begin{macro} { \@@_declare_cooking_derivative:nnnn } +% \begin{macrocode} +\prg_new_conditional:Npnn \@@_if_key_ais_derived_unit:n #1 { TF } + { + \tl_if_exist:cTF { l_@@_base_key_unit_ #1 _tl } + { \prg_return_true: } + { \prg_return_false: } + } +\cs_generate_variant:Nn \@@_if_key_ais_derived_unit:nTF { V } +% \end{macrocode} +% \end{macro} % +% \begin{macro} { \@@_declare_cooking_derivative:nnnn } +% The idea is the following. The relation between the units are given as +% |(#1)/(#2)| (e.g.). The idea is the following: +% \begin{enumerate} +% \item The derivative contains two units. +% \item The mathematical relationship is given by |(#1)/(#2)| +% \item Define |\@@_tmp:w| to be |(#1)/(#2)|. +% \item Parse through all values and store them in a list (e.g. |\l_tmpa_t|) as | {value-1}{value-2} | +% \item Use |\exp_after:wN \@@_tmp:w \l_tmpa_t | to expand to |\@@_tmp:w {value-1} {value-2} | +% \item Let |\@@_tmp:w| do its job. +% \end{enumerate} +% \begin{macrocode} +\cs_new:Npn \@@_convert_derived_unit:nn #1#2 + { + \tl_if_eq:ccTF + { l_@@_base_key_unit_ #1 _tl } + { l_@@_base_key_unit_ #2 _tl } + { + \prop_get:NnN \l_@@_derived_units_prop {#1} \l_@@_tmpa_tl + \prop_get:NnN \l_@@_derived_units_prop {#2} \l_@@_tmpb_tl + \prop_put:Nnn \l_@@_change_unit_prop {#1} {#2} + \@@_tl_eval:cn { l_@@_unit_change_ #1 _tl } + { + (\l_@@_tmpb_tl) / (\l_@@_tmpa_tl) + } + \prop_gput:Nnv \g_@@_master_changer_prop + { #1 ~->~ #2 } + { l_@@_unit_change_ #1 _tl } + }{ + \msg_error:nnnn { cooking-units } { key-no-knows-value } {#1} {#2} + } + } +\cs_generate_variant:Nn \@@_convert_derived_unit:nn { V } +% \end{macrocode} +% \end{macro} % % % @@ -7985,116 +9443,159 @@ and the derived file cooking-units.sty. % \end{macrocode} % % +% \begin{macro}{\cudefinename} +% This command allows to (re)define \enquote{names} for units to be used +% in \cCutext\ for given language. We need to sanitize the arrows (|<| and |>|) +% in case they are active. Afterwards, parse through the list. % \begin{macrocode} \NewDocumentCommand \cudefinename { m m } { \tl_set:Nn \l_@@_language_tl {#1} \@@_sanitize_arrows:n {#2} - \exp_last_unbraced:NV - \@@_cuname_parse_input:n \l_@@_sanitise_tl - \q_recursion_tail \q_recursion_tail \q_recursion_stop + \exp_after:wN + \@@_parse_definename_start_cycle: \l_@@_sanitise_tl + \q_recursion_tail \q_recursion_tail \q_recursion_stop } % \end{macrocode} +% \end{macro} % -% +% \begin{macro}{\@@_parse_definename_start_cycle:} +% Initializes the parse cycle. Set state to \enquote{normal} and clear some variables. +% Start by grabbing the first argument which is the unit. +% \begin{macrocode} +\cs_new:Npn \@@_parse_definename_start_cycle: + { + \@@_set_state_to:n { normal } + \tl_clear:N \l_@@_curr_unit_tl + \prop_clear:N \l_@@_tmpa_prop + \bool_set_false:N \l_@@_tmpa_bool + \@@_parse_definename_unit:n + } +% \end{macrocode} +% \end{macro} +% \begin{macro}{ \@@_parse_definename_unit:n } +% Grab the unit. This can be either an actual unit (defined by |\newcookingunit| and Co.) +% or it is one of the allowed \enquote{special-keys} like \enquote{decimal-marker}, +% etc. In case neither of those two is found, issue an error, but continue parsing +% to catch more errors. +% +% The next optional argument is the unit-symbol, which can also be set by this +% command. If it is not found, grab the next mandatory argument, which is the +% unit-name. % \begin{macrocode} -\cs_new:Npn \@@_cuname_parse_input:n #1 +\cs_new:Npn \@@_parse_definename_unit:n #1 { - \peek_meaning_ignore_spaces:NTF [ + \quark_if_recursion_tail_stop:n {#1} + \seq_if_in:NnTF \g_@@_allowed_special_keys_seq {#1} { - \@@_cuname_parse_unit_symbol:nw {#1} - }{ - \seq_if_in:NnTF \g_@@_allowed_special_keys_seq {#1} - { \@@_cuname_parse_input_aux:nn {#1} } - { \@@_cuname_parse_unit_symbol:nw {#1} [ \q_no_value ] } + \@@_set_unit:Nn \l_@@_curr_unit_tl {#1} + \bool_set_true:N \l_@@_tmpa_bool + }{ + \@@_error_if_unit_not_defined:nNT {#1} \l_@@_curr_unit_tl + { \@@_set_state_to:n { error } } } + \peek_meaning_ignore_spaces:NTF [ + { \@@_parse_definename_optional_unitsymbol:w } + { \@@_parse_definename_singular:n } } % \end{macrocode} +% \end{macro} % +% \begin{macro}{ \@@_parse_definename_optional_unitsymbol:w } +% The frst optional argument has be found; it is thus the unit-symbol. +% Changing the unit-symbol is only allowed for actual units, so no \enquote{special-keys} +% allowed. If we have an unit, store it into |\l_@@_tmpa_prop|. % \begin{macrocode} -\cs_new:Npn \@@_cuname_parse_unit_symbol:nw #1 [#2] - { - \quark_if_recursion_tail_stop:n {#1} - \quark_if_recursion_tail_stop_do:nn {#2} - { \msg_error:nn { cooking-units } { missing-argument } } - \@@_error_if_unit_not_defined:nT {#1} - { \use_none_delimit_by_q_recursion_stop:w } - \quark_if_no_value:nTF {#2} +\cs_new:Npn \@@_parse_definename_optional_unitsymbol:w [#1] + { + \bool_if:NTF \l_@@_tmpa_bool { - \@@_deftranslation_to:VxVv - \l_@@_language_tl {#1} - \c_@@_postfix_unit_tl - { l_@@_default_unit_ #1 _tl } - }{ - \@@_deftranslation_to:VxVn - \l_@@_language_tl {#1} - \c_@@_postfix_unit_tl {#2} + \@@_set_state_to:n { error } + \msg_error:nnxn { cooking-units } { symbol-and-special-keys-error } + \l_@@_curr_unit_tl {#1} } - \@@_cuname_parse_input_aux:nn {#1} + { \prop_put:Nnn \l_@@_tmpa_prop { unit-symbol } {#1} } + \@@_parse_definename_singular:n } % \end{macrocode} +% \end{macro} % -% +% \begin{macro}{ \@@_parse_definename_singular:n } +% Parses the \enquote{name} of the unit (or special key). +% Do an error check, store the input in the property list and go to the +% next one, which is the plural form. The next (optional) argument is +% the plural form of the \enquote{name}. If there is none, also use |#1| for plural. % \begin{macrocode} -\cs_new:Npn \@@_cuname_parse_input_aux:nn #1#2 +\cs_new:Npn \@@_parse_definename_singular:n #1 { - \quark_if_recursion_tail_stop:n {#1} - \quark_if_recursion_tail_stop_do:nn {#2} + \quark_if_recursion_tail_stop_do:nn {#1} { \msg_error:nn { cooking-units } { missing-argument } } - \seq_if_in:NnF \g_@@_allowed_special_keys_seq {#1} - { - \@@_error_if_unit_not_defined:nT {#1} - { \use_none_delimit_by_q_recursion_stop:w } - } - \@@_deftranslation_to:VxVn - \l_@@_language_tl {#1} - \c_@@_postfix_unitname_tl {#2} + \prop_put:Nnn \l_@@_tmpa_prop { name } {#1} \peek_meaning_ignore_spaces:NTF [ - { \@@_cuname_parse_bracket:nw {#1} } - { \@@_cuname_parse_bracket:nw {#1} [#2] } + { \@@_parse_definename_optional_plural:w } + { \@@_parse_definename_optional_plural:w [#1] } } % \end{macrocode} +% \end{macro} % +% \begin{macro}{ \@@_parse_definename_optional_plural:w } +% Nothing new here. The next one is the gender. If no gender is found +% I assume it to be male \enquote{m}. % \begin{macrocode} -\cs_new:Npn \@@_cuname_parse_bracket:nw #1 [#2] +\cs_new:Npn \@@_parse_definename_optional_plural:w [#1] { - \seq_if_in:NnF \g_@@_allowed_special_keys_seq {#1} - { - \@@_deftranslation_to:VxVn \l_@@_language_tl {#1} - \c_@@_postfix_unitname_pl_tl {#2} - } + \prop_put:Nnn \l_@@_tmpa_prop { name-pl } {#1} \peek_meaning_ignore_spaces:NTF < - { \@@_cuname_parse_gender:nw {#1} } - { \@@_cuname_parse_gender:nw {#1} } + { \@@_parse_definename_optional_gender:w } + { \@@_parse_definename_optional_gender:w } } % \end{macrocode} +% \end{macro} % +% \begin{macro}{ \@@_parse_definename_optional_plural:w } +% Check if the gender is correct. Then store it in the property-list +% and finish the cycle. % \begin{macrocode} -\cs_new:Npn \@@_cuname_parse_gender:nw #1 <#2> +\cs_new:Npn \@@_parse_definename_optional_gender:w <#1> { -% \@@_check_if_correct_gender_input:n {#2} -% \@@_deftranslation_to:VxVn -% \l_@@_language_tl {#1} -% \c_@@_postfix_gender_tl {#2} - \@@_if_gender_error:nTF {#2} - { - \@@_deftranslation_to:VxVn - \l_@@_language_tl {#1} - \c_@@_postfix_gender_tl { m } - }{ - \@@_deftranslation_to:VxVn - \l_@@_language_tl {#1} - \c_@@_postfix_gender_tl {#2} - } - \@@_cuname_parse_input:n + \@@_if_gender_error:nT {#1} + { \@@_set_state_to:n { error } } + \prop_put:Nnn \l_@@_tmpa_prop { gender } {#1} + \@@_parse_name_finish_cycle_and_start_new:VV + \l_@@_language_tl \l_@@_curr_unit_tl } % \end{macrocode} +% \end{macro} % +% \begin{macro}{ \@@_parse_name_finish_cycle_and_start_new:nn } +% Now it makes sense why we used property list before. +% Each unit has some basic definitions for each language (see |\newcookingunit| and Co.): +% \enquote{unit-symbol}, \enquote{name}, \enquote{name\_pl} and \enquote{gender}. % +% So going through the property list (where we stored the given values) +% we set for the given language and unit those definitions (\enquote{unit-symbol} only +% if found). % -% \subsection {cudefinesymbol} +% Afterwards, start the next cycle. +% \begin{macrocode} +\cs_new:Npn \@@_parse_name_finish_cycle_and_start_new:nn #1#2 + { + \@@_if_state_equal:nT { normal } + { + \prop_map_inline:Nn \l_@@_tmpa_prop + { \@@_culang_def_for:nnnn {#1} {##1} {#2} {##2} } + } + \@@_parse_definename_start_cycle: + } +\cs_generate_variant:Nn \@@_parse_name_finish_cycle_and_start_new:nn { VV } +% \end{macrocode} +% \end{macro} % +% \subsection {cudefinesymbol} % +% \begin{macro}{ \cudefinesymbol } +% A small and rather straightforward command. +% No special sanitizing here, just setting the language and parsing. % \begin{macrocode} \NewDocumentCommand \cudefinesymbol { m m } { @@ -8103,7 +9604,13 @@ and the derived file cooking-units.sty. \q_recursion_tail \q_recursion_tail \q_recursion_stop } % \end{macrocode} +% \end{macro} % +% \begin{macro}{ \@@_cuprint_define_printed_unit:nn } +% Sets the symbol for given units or \enquote{special keys}. +% Nothing extraordinary is done here. We we have an unit we +% set its \enquote{unit-symbol} for given language, for an \enquote{special key} +% we set its name. Rinse and repeat. % \begin{macrocode} \cs_new:Npn \@@_cuprint_define_printed_unit:nn #1#2 { @@ -8111,167 +9618,264 @@ and the derived file cooking-units.sty. \quark_if_recursion_tail_stop_do:nn {#2} { \msg_error:nn { cooking-units } { missing-argument } } \seq_if_in:NnTF \g_@@_allowed_special_keys_seq {#1} + { \@@_culang_def_for:Vnnn \l_@@_language_tl { name } } { - \@@_deftranslation_to:VxVn \l_@@_language_tl {#1} - \c_@@_postfix_unitname_tl {#2} - }{ - \@@_error_if_unit_not_defined:nF {#1} - { - \@@_deftranslation_to:VxVn - \l_@@_language_tl {#1} - \c_@@_postfix_unit_tl {#2} - } + \@@_error_if_unit_not_defined:nTF {#1} + { \use_none:nn } + { \@@_culang_def_for:Vnnn \l_@@_language_tl { unit-symbol } } } + {#1} {#2} \@@_cuprint_define_printed_unit:nn } % \end{macrocode} -% +% \end{macro} % % % \subsection {Phrases} % % -% \begin{macrocode} -\@@_newtranslation_base:nVn { phrase-prop } \c_@@_postfix_phrase_tl { \q_@@_no_translation } -% \end{macrocode} % +% \begin{macro}{ \@@_cuprint_define_printed_unit:nn } +% Defining phrases. Phrases (sadly) depend on the language. +% The idea is going to be: Each language has its own property list +% which is going to be stored for each language. Later, the property +% list is recoverd for the language currently used. If no phrase is defined +% the fallback |\q_@@_no_translation| is returned. % \begin{macrocode} -\prg_new_conditional:Npnn \@@_phrase_list_get_for:NN #1#2 { TF } - { - \@@_translate_let:VNnV #2 #1 { phrase-prop } \c_@@_postfix_phrase_tl - \tl_if_eq:NNTF #1 \q_@@_no_translation - { \prg_return_false: } - { \prg_return_true: } - } -\prg_new_conditional:Npnn \@@_get_phrase_for_current_langauge:NN #1#2 { T } - { - \@@_translate_let:NnV #1 { phrase-prop } \c_@@_postfix_phrase_tl - \tl_if_eq:NNTF #1 \q_@@_no_translation - { \prg_return_false: } - { - \@@_translate_let:NnV #2 { phrase-clist } \c_@@_postfix_phrase_tl - \prg_return_true: - } - } +\@@_culang_def_base:nnn { phrase } { phrase-prop } { \q_@@_no_translation } % \end{macrocode} +% \end{macro} +% +% \begin{macro}{ \cudefinephrase } +% Defining some phrases. This command is just a wrapper for the +% subcommand. % \begin{macrocode} \NewDocumentCommand \cudefinephrase { m m } { - \@@_cuphrase:nn {#1} {#2} + \@@_new_cuphrase_add:nn {#1} {#2} } -\cs_new:Npn \@@_cuphrase:nn #1#2 - { - \tl_set:Nn \l_@@_language_tl {#1} -% \end{macrocode} -% \begin{macrocode} - \@@_phrase_list_get_for:NNTF \l_@@_phrase_prop \l_@@_language_tl - { - \@@_translate_let:VNnV \l_@@_language_tl \l_@@_phrase_numbers_seq - { phrase-clist } \c_@@_postfix_phrase_tl - }{ - \prop_clear:N \l_@@_phrase_prop - \seq_clear:N \l_@@_phrase_numbers_seq - } % \end{macrocode} +% \end{macro} +% +% \begin{macro}{ \@@_new_cuphrase_add:nn } +% |#1| is the language, |#2| is something to be parsed. +% I am also not quite happy with this construction, but it works. +% +% First, check if we already have existing phrases for the language. +% If so, recover it, we add the parsed one to them. Else, clear +% some variables. +% +% Next step, sanitize |<| and |>|. I hate this so much. +% +% Using |\@@_parse_phrase:V| we parse through the argument |#2|. +% The results are added to |\l_@@_phrase_prop| and |\l_@@_phrase_numbers_seq|. +% +% By our rules, we prefer big numbers over small ones. For example, +% 120 can be translated into \enquote{2 Schocks} ($2\times60$) or +% \enquote{10 Dutzend} ($10\times12$). We prefer the bigger number first, +% so we will always get \enquote{2 Schocks}. Thus we sort the numbers in the +% sequence from highest to lowest. We also have negative numbers (phrases only +% used for one specific number). We prefer the negative over the positive ones +% if possible. +% +% Then store the variables and thats it. % \begin{macrocode} +\cs_new:Npn \@@_new_cuphrase_add:nn #1#2 + { + \tl_set:Nn \l_@@_language_tl {#1} + \@@_culang_if_translation_exists_for:VnnTF \l_@@_language_tl + { phrase } { phrase-prop } + { + \@@_culang_let_for:VnnN \l_@@_language_tl { phrase } { phrase-prop } + \l_@@_phrase_prop + \prop_get:NnN \l_@@_phrase_prop { seq } \l_@@_phrase_numbers_seq + }{ + \prop_clear:N \l_@@_phrase_prop + \seq_clear:N \l_@@_phrase_numbers_seq + } \@@_sanitize_arrows:n {#2} - \exp_last_unbraced:NV - \@@_cuphrase_parse:n \l_@@_sanitise_tl - \q_recursion_tail \q_recursion_tail \q_recursion_stop + \@@_parse_phrase:V \l_@@_sanitise_tl + \@@_new_cuphrase_sort_sequence:N \l_@@_phrase_numbers_seq + \prop_put:NnV \l_@@_phrase_prop { seq } \l_@@_phrase_numbers_seq + \@@_culang_def_for:VnnV + \l_@@_language_tl { phrase } { phrase-prop } \l_@@_phrase_prop + } % \end{macrocode} +% \end{macro} +% +% \begin{macro}{ \@@_parse_phrase:n } +% Wrapper around the parsing cycles. Nothing new. % \begin{macrocode} - \seq_sort:Nn \l_@@_phrase_numbers_seq - { - \int_compare:nNnTF { \int_abs:n {##1} } < { \int_abs:n {##2} } - { \sort_return_swapped: } - { - \int_compare:nNnTF { \int_abs:n {##1} } = { \int_abs:n {##2} } - { - \int_compare:nNnTF {##1} < {##2} - { \sort_return_same: } - { \sort_return_swapped: } - }{ \sort_return_same: } - } - } +\cs_new:Npn \@@_parse_phrase:n #1 + { + \@@_parse_phrase_start_cycle: #1 + \q_recursion_tail \q_recursion_tail \q_recursion_stop + } +\cs_generate_variant:Nn \@@_parse_phrase:n { V } % \end{macrocode} +% \end{macro} +% +% \begin{macro}{ \@@_parse_phrase_start_cycle: } +% Starts the parsing cycle. Clear some variables, set state to normal. % \begin{macrocode} - \@@_deftranslation_to:VxVV - \l_@@_language_tl { phrase-prop } - \c_@@_postfix_phrase_tl - \l_@@_phrase_prop - \@@_deftranslation_to:VxVV - \l_@@_language_tl { phrase-clist } - \c_@@_postfix_phrase_tl \l_@@_phrase_numbers_seq - } +\cs_new:Npn \@@_parse_phrase_start_cycle: + { + \@@_set_state_to:n { normal } + \bool_set_false:N \l_@@_tmpa_bool + \tl_clear:N \l_@@_curr_unit_tl + \prop_clear:N \l_@@_tmpa_prop + \@@_parse_stuff_mandatories_plus_star:nn + } % \end{macrocode} +% \end{macro} % +% \begin{macro}{ \@@_parse_stuff_mandatories_plus_star:nn } +% Now. We have two cases: two mandatroy arguments following each other +% (number plus phrase) \emph{or} number plus star plus phrase (so three arguments). +% In order to not need explicetly test for the star I do the following: +% Just grab the first two things. |#1| is always the number. |#2| can either be +% the star |*| \emph{or} a phrase. If it is a star, set a boolean, and restart the command +% with |#1| already given. % +% Then check if |#2| is a number (with a primitve test). Star-numbers are stored +% negatively. This makes defining a property list easier for me. +% +% Note that the key in the first |\l_@@_tmpa_prop| is empty. This is done +% in order to not screw up the later |\prop_map_inline| loop. We also store +% if the phrase is only used for one number (aka.\ if there is a star). +% +% Then, parse the optionals. % \begin{macrocode} -\cs_new:Npn \@@_cuphrase_parse:n #1 +\cs_new:Npn \@@_parse_stuff_mandatories_plus_star:nn #1#2 { \quark_if_recursion_tail_stop:n {#1} - \@@_if_integer:nF {#1} - { \msg_error:nnn { cooking-units} { phrase-unit-not-an-integer } {#1} } - \peek_meaning_remove_ignore_spaces:NTF * + \quark_if_recursion_tail_stop_do:nn {#2} + { \msg_error:nn { cooking-units } { missing-argument } } + \str_if_eq:nnTF {#2} { * } { - \int_set:Nn \l_@@_tmpa_int {-#1} - \@@_cuphrase_parse_normal:Vn \l_@@_tmpa_int + \bool_set_true:N \l_@@_tmpa_bool + \@@_parse_stuff_mandatories_plus_star:nn {#1} }{ - \int_set:Nn \l_@@_tmpa_int {#1} - \@@_cuphrase_parse_normal:Vn \l_@@_tmpa_int + \@@_if_evaluation_is_integer:nTF {#1} + { + \int_set:Nn \l_@@_tmpa_int {#1} + \tl_set:NV \l_@@_curr_unit_tl \l_@@_tmpa_int + \bool_if:NT \l_@@_tmpa_bool + { \tl_put_left:Nn \l_@@_curr_unit_tl { - } } + }{ + \@@_set_state_to:n { error } + \msg_error:nnn { cooking-units} { phrase-unit-not-an-integer } {#1} + } + \prop_put:Nnn \l_@@_tmpa_prop { } {#2} + \prop_put:NnV \l_@@_tmpa_prop { - singlebool } \l_@@_tmpa_bool + \@@_parse_phrase_optionals:n {#2} } } % \end{macrocode} +% \end{macro} % +% \begin{macro}{ \@@_parse_phrase_optionals:n } +% Get the plural form of the phrase. If the next token is an open bracket, +% get the plural form, else set the plural form equal to the singular form. % \begin{macrocode} -\cs_new:Npn \@@_cuphrase_parse_normal:nn #1#2 +\cs_new:Npn \@@_parse_phrase_optionals:n #1 { - \quark_if_recursion_tail_stop_do:nn {#2} - { \msg_error:nn { cooking-units } { missing-argument } } - \prop_put:Nnn \l_@@_phrase_prop {#1} {#2} - \seq_if_in:NnF \l_@@_phrase_numbers_seq {#1} - { \seq_push:Nn \l_@@_phrase_numbers_seq {#1} } \peek_meaning_ignore_spaces:NTF [ - { - \@@_chuphrase_parse_plural:nw {#1} - }{ - \@@_chuphrase_parse_plural:nw {#1} [#2] - } + { \@@_parse_stuff_plural:w } + { \@@_parse_stuff_plural:w [#1] } } -\cs_generate_variant:Nn \@@_cuphrase_parse_normal:nn { V } % \end{macrocode} +% \end{macro} % +% \begin{macro}{ \@@_new_cuphrase_add:nn } +% Store the pluarl form in the property list. +% Next, parse gender. Pretty much the same as before. By default we use +% a male gender. % \begin{macrocode} -\cs_new:Npn \@@_chuphrase_parse_plural:nw #1 [#2] +\cs_new:Npn \@@_parse_stuff_plural:w [#1] { - \prop_put:Nnn \l_@@_phrase_prop { #1-pl } {#2} + \prop_put:Nnn \l_@@_tmpa_prop { -pl } {#1} \peek_meaning_ignore_spaces:NTF < + { \@@_parse_stuff_gender:w } + { \@@_parse_stuff_gender:w } + } +% \end{macrocode} +% \end{macro} +% +% \begin{macro}{ \@@_new_cuphrase_add:nn } +% Check if the gender-input is correct, add it to the property list. +% Then finish the cycle and start a new one. +% \begin{macrocode} +\cs_new:Npn \@@_parse_stuff_gender:w <#1> + { + \@@_if_gender_error:nTF {#1} + { \@@_set_state_to:n { error } } + { \prop_put:Nnn \l_@@_tmpa_prop { -gender } {#1} } + \@@_parse_phrase_finish_cycle_and_start_anew:V \l_@@_curr_unit_tl + } +% \end{macrocode} +% \end{macro} +% +% \begin{macro}{ \@@_parse_phrase_finish_cycle_and_start_anew:n } +% If not errors were found: Add the number to the other numbers (if not already inside). +% Afterwards map through the property list and set the variations for each number. +% +% As an example, if we had \enquote{12}, |\l_@@_phrase_prop| would then contain +% the keys \enquote{12}, \enquote{12-pl}, \enquote{12-gender}, \enquote{12-singlebool}. +% \begin{macrocode} +\cs_new:Npn \@@_parse_phrase_finish_cycle_and_start_anew:n #1 + { + \@@_if_state_equal:nT { normal } { - \@@_chuphrase_parse_gender:nw {#1} - }{ - \@@_chuphrase_parse_gender:nw {#1} < m > + \seq_if_in:NnF \l_@@_phrase_numbers_seq {#1} + { \seq_put_right:Nn \l_@@_phrase_numbers_seq {#1} } + \prop_map_inline:Nn \l_@@_tmpa_prop + { + \prop_put:Nnn \l_@@_phrase_prop { #1 ##1 } {##2} + } } + \@@_parse_phrase_start_cycle: } +\cs_generate_variant:Nn \@@_parse_phrase_finish_cycle_and_start_anew:n { V } % \end{macrocode} +% \end{macro} % +% \begin{macro}{ \@@_new_cuphrase_sort_sequence:N } +% Sorting the sequence of numbers from highest to lowest (in absolute values). +% And if two absolute values are equal, negative numbers are preferred over +% positive ones. % \begin{macrocode} -\cs_new:Npn \@@_chuphrase_parse_gender:nw #1 <#2> +\cs_new:Npn \@@_new_cuphrase_sort_sequence:N #1 { - \@@_if_gender_error:nTF {#2} + \seq_sort:Nn #1 { - \@@_deftranslation_to:VxVn - \l_@@_language_tl { #1-phrase-gender } - \c_@@_postfix_gender_tl { m } - }{ - \@@_deftranslation_to:VxVn - \l_@@_language_tl { #1-phrase-gender } - \c_@@_postfix_gender_tl {#2} - } - \@@_cuphrase_parse:n + \int_set:Nn \l_@@_tmpa_int { \int_abs:n {##1} } + \int_set:Nn \l_@@_tmpb_int { \int_abs:n {##2} } + \int_compare:nNnTF { \l_@@_tmpa_int } < { \l_@@_tmpb_int } + { \sort_return_swapped: } + { + \int_compare:nNnTF { \l_@@_tmpa_int } > { \l_@@_tmpb_int } + { \sort_return_same: } + { + \prop_get:NnN \l_@@_phrase_prop { ##1 - singlebool } \l_@@_tmpa_int + \int_compare:nNnTF { \l_@@_tmpa_int } = { 1 } + { \sort_return_same: } + { \sort_return_swapped: } + } + } + } } % \end{macrocode} +% \end{macro} % -% +% \begin{macro}{ \cudefinephrase } +% \begin{macrocode} +%\NewDocumentCommand \cudefinephrase { m m } +% { +%% \@@_cuphrase:nn {#1} {#2} +% } +% \end{macrocode} +% \end{macro} % % % \subsection{Old stuff} @@ -8293,7 +9897,7 @@ and the derived file cooking-units.sty. % \begin{macrocode} \cs_new:Npn \@@_old_cutext_default:nnn #1#2#3 { - \bool_if:NTF \l_@@_draft_bool + \bool_if:NTF \l_@@_pckopt_draft_bool {#2} { \tl_set:Nn \l_@@_cutext_last_value_tl {#2} @@ -8313,19 +9917,21 @@ and the derived file cooking-units.sty. { \@@_old_cutext_if_numeral_is_int_and_parse_and_smaller_then_print_numerals:NTF #1 { - \@@_int_if_equal_one:nTF {#1} + \int_compare:nNnTF {#1} = { 1 } { - \@@_translate_one_and_check_existance:Nx \l_@@_translation_tmpa_tl {#2} - \bool_if:NTF \l_@@_cutext_uppercase_word_bool + \@@_culang_one_let:NnT \l_@@_translation_tmpa_tl {#2} { - \exp_args:Nx \tl_upper_case:n { \tl_head:V \l_@@_translation_tmpa_tl } - \tl_tail:V \l_@@_translation_tmpa_tl + \bool_if:NT \l_@@_cutext_uppercase_word_bool + { + \text_uppercase:x { \tl_head:V \l_@@_translation_tmpa_tl } + \tl_tail:V + } } - { \l_@@_translation_tmpa_tl } + \l_@@_translation_tmpa_tl }{ \bool_if:NTF \l_@@_cutext_uppercase_word_bool - { \@@_print_Numeral:n {#1} } - { \@@_print_numeral:n {#1} } + { \@@_print_Numeral:V #1 } + { \@@_print_numeral:V #1 } } } { \@@_print_numerical_input:N #1 } @@ -8376,7 +9982,7 @@ and the derived file cooking-units.sty. \char_set_catcode_letter:N \_ % \char_set_catcode_ignore:N\ % } {#1} - \bool_if:NTF \l_@@_draft_bool + \bool_if:NTF \l_@@_pckopt_draft_bool { \l_@@_tmpa_tl } { \@@_cuam_old_parse:V \l_@@_tmpa_tl } } @@ -8487,137 +10093,6 @@ and the derived file cooking-units.sty. % \end{macrocode} % % -% -% -% \begin{macrocode} -\cs_new:Npn \@@_add_forbidden_unit:n #1 - { - \seq_set_from_clist:Nn \l_@@_tmpa_seq {#1} - \seq_map_inline:Nn \l_@@_tmpa_seq - { - \@@_error_if_unit_not_defined:nF {##1} - { - \seq_if_in:NnF \l_@@_curef_do_not_change_seq {##1} - { \seq_put_right:Nn \l_@@_curef_do_not_change_seq {##1} } - } - } - } -\cs_new:Npn \@@_remove_forbidden_unit:n #1 - { - \seq_set_from_clist:Nn \l_@@_tmpa_seq {#1} - \seq_map_inline:Nn \l_@@_tmpa_seq - { - \@@_error_if_unit_not_defined:nF {##1} - { - \seq_if_in:NnTF \l_@@_curef_do_not_change_seq {##1} - { \seq_remove_all:Nn \l_@@_curef_do_not_change_seq {##1} } - { - \msg_warning:nnnn { cooking-units } { curef-not-inside-list } {##1} - { \@@_seq_use_msg:N \l_@@_curef_do_not_change_seq } - } - } - } - } -\cs_new:Npn \@@_clear_forbidden_unit: - { \seq_clear:N \l_@@_curef_do_not_change_seq } -% \end{macrocode} -% -% -% -% -% -% -% \begin{macrocode} -\NewDocumentCommand \cudeclareunitgroup { m m } - { - \@@_define_clear_unit_group:nn {#1} {#2} - \@@_add_to_unit_group:nn {#1} {#2} - } -\NewDocumentCommand \cuaddtounitgroup { m m } - { - \@@_add_to_unit_group:nn {#1} {#2} - } -\NewDocumentCommand \cuclearunitgroup { m } - { - \@@_error_if_group_not_defined:nF {#1} - { \@@_define_clear_unit_group:nn {#1} { } } - } -% \end{macrocode} -% -% -% -% -% -% -% -% -% -% -% -% Works better now. -% \begin{macrocode} -\NewDocumentCommand \cusetoptionfor { m m } - { - \@@_map_trough_valid_unit_options:nnn {#1} {#2} - { \clist_set:cn { l_@@_unit_option_ ##1 _clist } {##2} } - } -\NewDocumentCommand \cuaddoptionfor { m m } - { - \@@_map_trough_valid_unit_options:nnn {#1} {#2} - { \clist_put_right:cn { l_@@_unit_option_ ##1 _clist } {##2} } - } -\NewDocumentCommand \cuclearoptionfor { m } - { - \@@_map_trough_valid_unit_options:nnn {#1} { } - { \clist_clear:c { l_@@_unit_option_ ##1 _clist } } - } -% \end{macrocode} -% The reason I map trough the units twice is simply: I think it makes more -% sense if an \enquote{unknown unit} error is shown before an -% \enquote{unknown option} error (at least for me). -% It is kinda stupid, but this is not really a heavily used function, so \dots\ yeah. -% -% Note: I cannot check if |\l_@@_tmpa_clist| is empty because one could -% use |\cusetoptionfor{F,C,Re,K}{}| to clear the options of the given units. -% \begin{macrocode} -\cs_new:Npn \@@_tmp:w { } -\cs_new:Npn \@@_map_trough_valid_unit_options:nnn #1#2 #3 - { - \seq_clear:N \l_@@_tmpa_seq - \clist_clear:N \l_@@_tmpa_clist - \cs_set:Npn \@@_tmp:w ##1##2 {#3} - \clist_map_inline:nn {#1} - { - \@@_error_if_unit_not_defined:nF {##1} - { \seq_put_right:Nn \l_@@_tmpa_seq {##1} } - } - \tl_if_empty:nF {#2} - { \@@_unit_options_check_validity:n {#2} } - \seq_map_inline:Nn \l_@@_tmpa_seq - { \exp_args:NnV \@@_tmp:w {##1} \l_@@_tmpa_clist } - } -\cs_new:Npn \@@_unit_options_check_validity:n #1 - { - \keyval_parse:NNn - \@@_unit_options_check_validity_aux_i:n - \@@_unit_options_check_validity_aux_ii:nn - {#1} - } -\cs_new:Npn \@@_unit_options_check_validity_aux_i:n #1 - { - \keys_if_exist:nnTF { cooking-units } {#1} - { \clist_put_right:Nn \l_@@_tmpa_clist {#1} } - { \msg_error:nnn { cooking-units } { unknown-option } {#1} } - } -\cs_new:Npn \@@_unit_options_check_validity_aux_ii:nn #1#2 - { - \keys_if_exist:nnTF { cooking-units } {#1} - { \clist_put_right:Nn \l_@@_tmpa_clist { #1={#2} } } - { \msg_error:nnn { cooking-units } { unknown-option } {#1} } - } -% \end{macrocode} -% -% % % % @@ -8646,7 +10121,10 @@ and the derived file cooking-units.sty. \newcookingunit { oz } \newcookingunit { lb } \newcookingunit { stick } -\newcookingunit [ \ensuremath{ \@@_frac:nn { eV } { c^2 } } ] { eVc-2 } +\newcookingunit [ + symbol={\ensuremath{ \@@_frac:nn { eV } { c^2 } } } , + natural-unit + ] { eVc-2 } % \end{macrocode} % % \begin{macrocode} @@ -8661,7 +10139,10 @@ and the derived file cooking-units.sty. \newcookingunit { h } \newcookingunit { min } \newcookingunit { s } -\newcookingunit [ \ensuremath{ \@@_frac:nn { \hbar } { eV } } ] { hbareV-1 } +\newcookingunit [ + symbol={\ensuremath{ \@@_frac:nn { \hbar } { eV } } }, + natural-unit + ] { hbareV-1 } % \end{macrocode} % % \begin{macrocode} @@ -8670,7 +10151,9 @@ and the derived file cooking-units.sty. \newcookingunit { dm } \newcookingunit { mm } \newcookingunit { in } -\newcookingunit [ \ensuremath{ \@@_frac:nn { c\hbar } { eV } } ] { chbareV-1 } +\newcookingunit [ + symbol={ \ensuremath{ \@@_frac:nn { c\hbar } { eV } } } , natural-unit + ] { chbareV-1 } % \end{macrocode} % % \begin{macrocode} @@ -8678,7 +10161,9 @@ and the derived file cooking-units.sty. \newcookingunit { dl } \newcookingunit { cl } \newcookingunit { ml } -\newcookingunit [ \ensuremath { \@@_frac:nn { c^3 \hbar^3 } { eV^3 } } ] { (chbareV-1)3 } +\newcookingunit [ + symbol={ \ensuremath { \@@_frac:nn { c^3 \hbar^3 } { eV^3 } } }, natural-unit + ] { (chbareV-1)3 } % \end{macrocode} % % \begin{macrocode} @@ -8686,7 +10171,7 @@ and the derived file cooking-units.sty. \newcookingunit { kcal } \newcookingunit { J } \newcookingunit { kJ } -\newcookingunit { eV } +\newcookingunit [ natural-unit ] { eV } % \end{macrocode} % % \begin{macrocode} @@ -8905,15 +10390,25 @@ and the derived file cooking-units.sty. % % % \begin{macrocode} -\cudefinekeys { kg } +\cudefinekeychain { + { kg } { 1 } { dag }{ 100 } { g } { 1000 } { lb } { 1/0.45359237 } { oz } { 16/0.45359237 } { stick } { 4/0.45359237 } - { eVc-2 } { 560958865.0e+27 } %% 560958865.0 +- 3.5 e+27 + { eVc-2 } { 560958865.0e+27 } %% (560958865.0 +- 3.5) e+27 } +%\cudefinekeys { kg } +% { +% { dag }{ 100 } +% { g } { 1000 } +% { lb } { 1/0.45359237 } +% { oz } { 16/0.45359237 } +% { stick } { 4/0.45359237 } +% { eVc-2 } { 560958865.0e+27 } %% (560958865.0 +- 3.5) e+27 +% } % \end{macrocode} % \begin{macrocode} \cudefinekeys { d } @@ -8921,7 +10416,7 @@ and the derived file cooking-units.sty. { h } { 24 } { min }{ 1440 } { s } { 86400 } - { hbareV-1 } { 151926746.1e+7 * 86400 } %% 151926746.1 +- 2.1 e+7 + { hbareV-1 } { 151926746.1e+7 * 86400 } %% (151926746.1 +- 2.1) e+7 } %\cuaddtokeys { s } { hbareV-1 } { 6.582119514e-16 } % \end{macrocode} @@ -8951,7 +10446,7 @@ and the derived file cooking-units.sty. { kJ }{ 1e-3 } { cal }{ 0.2388459 } { kcal }{ 0.2388459e-3 } - { eV }{ 624150912.6e+10 } %% 624150912.6 +- 3.9 e+10 + { eV }{ 624150912.6e+10 } %% (624150912.6 +- 3.9) e+10 } %\cuaddtokeys { J } { eV } { 1.6021766208e-19 } % \end{macrocode} @@ -8992,7 +10487,7 @@ and the derived file cooking-units.sty. \cudefinephrase { German } { % { 6 } * { halbes \ Dutzend } < n > -% { 6 } { efkjwefjkl \ Dutzend } < n > +% { 6 } { halbe \ Dutzend } < n > { 12 } { Dutzend } < n > % { 60 } { Schock } < n > % { 1728 } { Gro{\ss}gros } < n > @@ -9023,6 +10518,20 @@ and the derived file cooking-units.sty. } , round-precision = 2 , } + + +% \NewDocumentCommand \cudefinekeys { } { \cudefinekeys } + + + +%\AtBeginDocument{ +%\keys_define:nn { cooking-units } +% { +% unknown .code:n = { \tl_show:N {\l_keys_key_str} } +% } +% \keys_set:nn { cooking-units } {#2} +% +%} % \end{macrocode} % % @@ -9064,8 +10573,8 @@ and the derived file cooking-units.sty. % \bibitem{StickSource} \url{https://cooking.stackexchange.com/questions/784/translating-cooking-terms-between-us-uk-au-ca-nz} % % \end{thebibliography} -% -% +% +% % % \endinput % diff --git a/macros/latex/contrib/cooking-units/cooking-units.ins b/macros/latex/contrib/cooking-units/cooking-units.ins index e20b719ad6..7298eb0e53 100644 --- a/macros/latex/contrib/cooking-units/cooking-units.ins +++ b/macros/latex/contrib/cooking-units/cooking-units.ins @@ -5,7 +5,7 @@ %% The original source files were: %% %% cooking-units.dtx (with options: `install') -%% Copyright (C) 2016--2020 by Ben Vitecek (current Maintainer) +%% Copyright (C) 2016--2021 by Ben Vitecek (current Maintainer) %% %% This file may be distributed and/or modified under the %% conditions of the LaTeX Project Public License, either @@ -25,7 +25,7 @@ \input l3docstrip.tex \askforoverwritefalse \preamble -Copyright (C) 2016--2020 by Ben Vitecek (current Maintainer) +Copyright (C) 2016--2021 by Ben Vitecek (current Maintainer) This file may be distributed and/or modified under the conditions of the LaTeX Project Public License, either diff --git a/macros/latex/contrib/cooking-units/cooking-units.pdf b/macros/latex/contrib/cooking-units/cooking-units.pdf index ef512cc946..e65da308d7 100644 Binary files a/macros/latex/contrib/cooking-units/cooking-units.pdf and b/macros/latex/contrib/cooking-units/cooking-units.pdf differ -- cgit v1.2.3