% \iffalse meta-comment % !TEX encoding = UTF-8 Unicode % !TEX program = pdfLaTeX % % % % %<*internal> \iffalse % %<*readme> cooking-units ============= Overview -------- While writing a cookery book, units and their format can be quite troublesome. This contains not only the question of how to print those units, but also the question of the conversion of units. A cookery book doesn't contain only SI units, it contains a much more colorful range of units (kg, dag, g, oz, ... for example) and it may cause some confusion if too many different units are used, but if you just write a cookery book for fun you don't think about this ... until someone (my mother in my case) tells you that it's too confusing. This package solves both problems: It formats your input and you have the option to convert the units globally or locally using an easy to use key-value system. Please note that this package is not intended to be used to print units (and numbers) physically correct. It should be used for more light-hearted stuff (like a cookery book for example). Requirements ------------ * expl3 & xparse * translator * xfrac * l3keys2e * fmtcount (optional) This file contains ------------------ * README * cooking-units.pdf * cooking-units.dtx * cooking-units.ins Changes ------- See section 'Change History' in the documentation. Supported Languages ------------------- * German * English * French (suboptimal) License ------- This material is subject to the LaTeX Project Public License. See http://www.ctan.org/tex-archive/help/Catalogue/licenses.lppl.html for the details of that license. % %<*internal> \fi \def\nameofplainTeX{plain} \ifx\fmtname\nameofplainTeX\else \expandafter\begingroup \fi % %<*install> \input l3docstrip.tex %\keepsilent \askforoverwritefalse \preamble Copyright (C) 2016 by Ben Vitecek (current Maintainer) This file may be distributed and/or modified under the conditions of the LaTeX Project Public License, either version 1.3 of this license or (at your option) any later version. The latest version of this license is in: http://www.latex-project.org/lppl.txt and version 1.3c or later is part of all distributions of LaTeX version 2008-05-04 or later. This work has the LPPL maintenance status `maintained'. This work consists of the files README.md, cooking-units.dtx and cooking-units.ins and the derived file cooking-units.sty. \endpreamble %\postamble %\endpostamble \usedir{tex/latex/cooking-units} \generate{ \file{\jobname.sty}{\from{\jobname.dtx}{package}} } % %\endbatchfile %<*internal> \usedir{source/latex/cooking-units} \generate{ \file{\jobname.ins}{\from{\jobname.dtx}{install}} } \nopreamble\nopostamble \usedir{doc/latex/cooking-units} \generate{ \file{README.md}{\from{\jobname.dtx}{readme}} } \ifx\fmtname\nameofplainTeX \expandafter\endbatchfile \else \expandafter\endgroup \fi % %<*driver> \documentclass [ english, %french, naustrian onlydoc, % check-declarations, ]{l3doc} \usepackage[utf8]{inputenc} \usepackage{babel} \usepackage[use-numerals=true]{cooking-units} \usepackage{tikzsymbols} \usepackage{listings} \usepackage{environ} \usepackage{nicefrac} \usepackage{varioref} \usepackage{mathtools} \usepackage{siunitx} \DeclareSIUnit{\ounce}{oz} \DeclareSIUnit{\oz}{\ounce} \DeclareSIUnit{\pound}{lb} \DeclareSIUnit{\lb}{\pound} \DeclareSIUnit{\stone}{st} \DeclareSIUnit{\st}{\stone} \cusetup{use-numerals-below=0} %\EnableCrossrefs \labelformat{table}{table~#1} \labelformat{section}{section~#1} \newcommand\mycs[1]{\cs{\textcolor{blue}{#1}}} \newcommand\opt{\texttt} \newcommand\true{\opt{true}} \newcommand\false{\opt{false}} \ExplSyntaxOn \NewDocumentCommand \PrintUnit { m } { \translate{ #1 (cu-unitname) } & #1 & \translate{ #1 ( cu-unit ) } } \NewDocumentCommand \PrintUnitSymbol { m } { #1 & \translate{ #1 ( cu-unit ) } } \NewDocumentCommand \dothewhitespace { O{ 42 } } { \textcolor{white} {#1} \\ } \NewEnviron { cuexamplecode }[1][] { \begin{center} \begin{minipage}{0.4\linewidth} \tl_replace_all:Nnn \BODY { @ } { \dothewhitespace } \tl_replace_all:Nnn \BODY { ! } { } \BODY \end{minipage} #1 \int_zero:N \l_tmpa_int \begin{minipage}{0.5\linewidth} \ttfamily \tl_set_rescan:Nno \l_tmpa_tl { \char_set_catcode_other:N \{ % \char_set_catcode_other:N \} % % \char_set_catcode_other:N \# % } { \BODY } \tl_map_inline:Nn \l_tmpa_tl { \token_if_cs:NTF ##1 { \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_if:nTF { \tl_if_eq_p:NN ##1 @ || \tl_if_eq_p:NN ##1 ! } { \\ } { \token_if_active:NTF ##1 { \string ##1 } { \token_if_parameter:NTF ##1 { \int_compare:nTF { \l_tmpa_int == 0 } { \c_hash_str \int_incr:N \l_tmpa_int } { \int_zero:N \l_tmpa_int } } { ##1 {} } } } } } \end{minipage} \end{center} } \NewDocumentEnvironment { cuexample } { } { \paragraph{Example:} } { } \ExplSyntaxOff \lstset { basicstyle = \ttfamily, basewidth = 0.51em, gobble = 3, keywordstyle = \color{blue}, language = [LaTeX]{TeX}, commentstyle=\color{red!80!black}, moretexcs = { cunum, cutext, Cutext, cuam, newcookingunit, cudefinename, cudefinesymbol, cusetup, cudefinekeys, cudefinesinglekey, cuaddkeys, cuaddsinglekeys, cuaddtokeys, } } \newcookingunit {st} \cuaddkeys {lb} %% adding t to g (could also add to kg, dag and oz) { {st} { 1/14 } %% 1 lb are 1/14 st } \newcookingunit [\ensuremath{ {} ^ { \circ } }\kern-\scriptspace R{\o}] {Ro} \cuaddsinglekeys {C} { {Ro} { #1*21/40 + 7.5} } \cusetup { set-option-for-Ro = { round-to-int = true } } %: \cusetup \cusetup { % convert-to-eV=true , % erase-all-options, % set-option-for-K= {}, % set-unknown-message = error , % check-temperature = true, % round-precision = 30 , } \EnableCrossrefs \CodelineIndex \RecordChanges \AtEndDocument { \PrintChanges \PrintIndex } \begin{document} \DocInput{\jobname.dtx} \end{document} % % \fi % % % % % \CharacterTable % {Upper-case \A\B\C\D\E\F\G\H\I\J\K\L\M\N\O\P\Q\R\S\T\U\V\W\X\Y\Z % Lower-case \a\b\c\d\e\f\g\h\i\j\k\l\m\n\o\p\q\r\s\t\u\v\w\x\y\z % Digits \0\1\2\3\4\5\6\7\8\9 % Exclamation \! Double quote \" Hash (number) \# % Dollar \$ Percent \% Ampersand \& % Acute accent \' Left paren \( Right paren \) % Asterisk \* Plus \+ Comma \, % Minus \- Point \. Solidus \/ % Colon \: Semicolon \; Less than \< % Equals \= Greater than \> Question mark \? % Commercial at \@ Left bracket \[ Backslash \\ % Right bracket \] Circumflex \^ Underscore \_ % Grave accent \` Left brace \{ Vertical bar \| % Right brace \} Tilde \~} % % % \iffalse %: changes % \fi % \changes {2016/06/11} {0.99} {Added the package option to load 'fmtcount'.} % \changes {2016/08/31} {1.00} {Initial version} % \changes {2016/08/31} {1.00a} {Fixed calculation: degree Reamur to eV} % \changes {2016/09/03} {1.01} {Added units 'ssp', 'csp', 'dsp'} % \changes {2016/09/03} {1.01} {English unit: litre (and only litre) uses the curly l \protect\ensuremath{\protect\ell} now } % \changes {2016/09/03} {1.01} {British English: 'pinch' is written in full} % \changes {2016/09/03} {1.01} {Separated Messerpsitze and pinch} % \changes {2016/09/05} {1.02} {Replaced \cs{cufrac} by \cs{cuam}} % \changes {2016/09/05} {1.02} {New message: 'obsolete-command'} % \changes {2016/09/09} {1.02a} {Changed name from \cs{@@_parse_fraction_in_input:www} to \cs{@@_parse_mixed_fraction_in_input:www}} % \changes {2016/09/09} {1.02b} {Changed name from \cs{@@_cunum_parse_range} (and derivatives) to \cs{@@_cutext_parse_range}.} % \changes {2016/09/09} {1.02c} {In \cs{@@_cutext_default:nnn} it is only % checked once if a range is inside.} % \changes {2016/09/09} {1.02d} {\cs{@@_calculate_input_and_store_in:nN} optimiert durch neue property-key: single.} % \changes {2016/09/09} {1.02d} {Add 'single' to property list of singlekeys.} % \changes {2016/09/16} {1.02e} {Only use \cs{phantom} if the argument (for \cs{phantom}) is not empty.} % \changes {2016/09/09} {1.02i} {Delete 'single' from property lists of singlekeys cause it is not as safe as I thought.} % \changes {2016/09/09} {1.02f} {Corrected mistake: 'ELektronenvolt' (note upperacse L) to 'Elektronenvolt' in german.} % \changes {2016/09/26} {1.03} {New option (and needed macros): add-temperature-to-check.} % \changes {2016/09/26} {1.03a} {\cs{cuaddsinglekeys} now tests if the unit exists (it didn't before).} % \changes {2016/09/26} {1.03b} {Replaced \cs{prop_clear_new:c} by \cs{prop_clear:c}.} % \changes {2016/09/26} {1.03b} {Recalculated all electron volt values for conversion (as 'kg' was wrong before). Let's hope they are correct this time.} % % % \GetFileInfo{\jobname.sty} % %\title{The \pkg{\jobname} package^^A %\thanks{This document corresponds to \textsf{Benedikt Vitecek}~\fileversion, dated~\filedate.}} %\author{Ben Vitecek \\ b.vitecek@gmx.at}% % % % \maketitle % % % \begin{documentation} % % % \begin{abstract} % This package enables user to globally format units and to switch % between them. It should be used for light-hearted things like % cookery books (and not e.g. scientific texts).\footnote{I did hide some % grammatical and spelling errors for easter egg hunters \Winkey.} % \end{abstract} % % \tableofcontents % % % \section{Introduction} % % % While writing on a cookery book I used -- for reasons whatsoever -- % three different units for weight: kilogram (kg), gram (g) and % decagram (dag, or older: dkg). Later my mother told me that she doesn't like it if a % cookery book uses more than two different units (for weight in this case). Happily % I hardly used Decagram and therefore didn't have many problems % changing the units. But, well \dots\ I am using \LaTeX\ and changing % those units by hand seemed not very \LaTeX\-like, so I started % writing some code to convert units. I expanded the code, rewrote it % in \LaTeX3 (which is much more pleasant than \LaTeXe) and here it % is. % % \section{Important note} % % This package uses the \pkg{translator} package to be able to switch % between different languages (german, english and french by now). % To do that \pkg{translator} has to know % which languages are used. The (I think) easiest way is to specify % used languages using the optional argument of the documentclass (you % can do this for both \pkg{babel} and \pkg{polyglossia}\footnote{I % know that \pkg{polyglossia} doesn't support the \pkg{babel}-way of % setting the language by optional argument, but it doesn't harm.}): % % \begin{lstlisting} % \documentclass[english,french,ngerman]{class} % \usepackage[main=english]{babel} % \usepackage{cooking-units} % ... % \end{lstlisting} % % or if you are using \pkg{polyglossia} % % \begin{lstlisting} % \documentclass[french,ngerman,english]{class} % % \usepackage{polyglossia} % \setmainlanguage{english} % \setotherlanguages{german,french} % % \usepackage{cooking-units} % ... % \end{lstlisting} % % At least I hope that this works, dealing with languages is a pain in % the ass\footnote{If you excuse me being blunt about this}. % % \subsection{Supported languages} % % \begin{itemize} % \item German % \item English % \item French (currently suboptimal\footnote{You can only get limited information from the internet.}) % \end{itemize} % Have another language to add or a correction of an existing one? % See \vref{sec:bug-feed} for more details. % % \section {The Commands} % % This package offers the following commands for unit printing (and converting): % % \begin{itemize} % \item \mycs{cunum}\oarg{options}\marg{amount}\oarg{space}\marg{unit-key} % \item \mycs{cutext}\oarg{options}\marg{amount}\marg{unit-key} % \item \mycs{Cutext}\oarg{options}\marg{amount}\marg{unit-key} % \item \mycs{cuam}\oarg{options} \marg{amount} % \end{itemize} % % Numbers and units are printed using \mycs{cunum}. The numerical part % can interpret \verb|_| and \texttt{/} as (mixed) fractions and % \verb|--| as a separator for ranges; to convert units use the option % \texttt{\meta{old-unit}=\meta{new-unit}}\footnote{New keys can be % added and defined, see \vref{sec:pred-units} and % \vref{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 checkup\footnote{You can % customize this behavior, see \vref{sec:options}}. \oarg{space} adds % a space between the number and the unit using \lstinline|\phantom|. % % For a list of predefined units have a look at \vref{tab:def-units}. % % % \begin{cuexamplecode} % \cunum{1}{kg} \\ % \cunum{2.3}{kg} \\ % \cunum{2,3}{kg} \\ % \cunum{2--3}{kg} \\ % \cunum{2.5--3.5}{kg} \\ % \cunum[kg=g]{2.5--3.5}{kg} \\ % \cunum[C=F]{200}{C} \\ % \cunum[C=F]{180--200}{C} \\ % \cunum{1/2}{m} \\ % \cunum{1_1/2}{m} \\ % \cunum[m=cm]{1_1/2}{m} \\ % \cunum{?}{l} \\ % \cunum{50}{dag} \\ % \cunum{5}[0]{dag} \\ % \cunum{1.1234}{m} % \end{cuexamplecode} % % Decimal numbers are automatically rounded to 2 digits after the % colon, temperatures (\texttt{C}, \texttt{F}, \texttt{K} and % \texttt{Re}) are automatically rounded to integers.\footnote{You can % -- of course -- change this behavior, see \vref{sec:options}.} % % \lstinline|\cutext| and \lstinline|\Cutext| print the number and the % written name of the unit. Furthermore, if the package option % \opt{use-numerals} is used, integers below a specific integer (by % default 13; see \opt{use-numerals-below}) are also written out with % \lstinline|\Cutext| capitalizing the first letter (using package \pkg{fmtcount}). % Conversion between % units is not supported. Without \opt{use-numerals}: % % \begin{cuexamplecode} % \cutext{1}{l} \\ % \Cutext{1}{l} \\ % \cutext{12}{l} \\ % \Cutext{13}{l} % \end{cuexamplecode} % and using package option \opt{use-numerals=true} % \cusetup{use-numerals-below=13} % \begin{cuexamplecode} % \cutext{1}{l} \\ % \Cutext{1}{l} \\ % \cutext{12}{l} \\ % \Cutext{13}{l} %^^A \cutext{23}{kg} \\ %^^A \Cutext{23}{kg}\\ %^^A \cutext{1}{l}\\ %^^A \Cutext{2}{l}\\ %^^A \cutext{1}{C} \\ %^^A \cutext{180}{C} \\ %^^A \Cutext{1}{C} \\ %^^A \Cutext{180}{C} \\ %^^A \Cutext{1.4}{C} \\ % \end{cuexamplecode} % \cusetup{use-numerals-below=0} % % % \lstinline|\cuam| works like a more primitive version \mycs{cunum} % which doesn't need a unit, but doesn't check the input like \mycs{cunum}. % Like in \lstinline|\cunum| \texttt{\_} and \texttt{/} are used to imply a (mixed) fraction and \texttt{-{}-} is % used to print ranges\footnote{Note that since v1.02 \mycs{myfrac} is obsolete.}: % % \begin{cuexamplecode} % \cuam{3} \\ % \cuam{2--3} \\ % \cuam{2/3} \\ % \cuam{1_2/3} % \end{cuexamplecode} % % % \section{Predefined units \& some notes} % \label{sec:pred-units} % % In \vref{tab:def-units} and \vref{tab:some-more-units} you can find all predefined units. % % I now \emph{did} include a separate key for \enquote{Messerspitze} (Msp.) % and therefore separated \enquote{Pinch} (pn) and \enquote{Messerspitze} (Msp.). % My biggest problems with the units given in \vref{tab:some-more-units} is % that they may only exist in one language (or country) % and therefore do not exist in another language (I think for example that % knife point \enquote{Messerspitze} doesn't exist in english) so translating % them would be difficult. Therefore use units known to you and if there are % unsupported units or languages feel free to write (see \vref{sec:bug-feed} % for more details). %^^A I did not include a separate key for \enquote{Prise} (pinch), but you can use %^^A \texttt{Msp} (Messerspitze) and modify it to fit your %^^A purpose\footnote{See \vref{sec:language}.}. %^^A In other languages the nearest equivalent of \enquote{Messerspitze} is %^^A \enquote{pinch} which I used. % % % \begin{table}[htbp] % \centering % \caption{List of predefined unit-keys. % The \enquote{symbol} column is language dependent. Note that \enquote{electron % volt} exists just for fun.} % \begin{tabular}{ lll } % \toprule % unit name & unit-key & symbol \\ \midrule % \PrintUnit {kg} \\ % \PrintUnit {dag} \\ % \PrintUnit {g} \\ % \PrintUnit {oz} \\ % \PrintUnit {lb} \\ \addlinespace % % \PrintUnit {C} \\ % \PrintUnit {F} \\ % \PrintUnit {Re} \\ % \PrintUnit {K} \\ \addlinespace % % \PrintUnit {d} \\ % \PrintUnit {h} \\ % \PrintUnit {min} \\ % \PrintUnit {s} \\ \addlinespace % % \PrintUnit {m} \\ % \PrintUnit {dm} \\ % \PrintUnit {cm} \\ % \PrintUnit {mm} \\ % \PrintUnit {in} \\ \addlinespace % % \PrintUnit {l} \\ % \PrintUnit {dl} \\ % \PrintUnit {cl} \\ % \PrintUnit {ml} \\ \addlinespace % % \PrintUnit {cal} \\ % \PrintUnit {kcal} \\ % \PrintUnit {J} \\ % \PrintUnit {kJ} \\ % \PrintUnit {eV} \\ \addlinespace % % \bottomrule % \end{tabular} % \label{tab:def-units} % \end{table} % % \begin{table}[htbp] % \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.} % \begin{tabular}{ lll } % \toprule % unit name & unit-key & symbol \\ \midrule % \PrintUnit {pn} \\ \addlinespace % \PrintUnit {EL} \\ % \PrintUnit {TL} \\ % \PrintUnit {dsp} \\ % \PrintUnit {csp} \\ % \PrintUnit {ssp} \\ \addlinespace % \PrintUnit {Msp} \\ % \bottomrule % \end{tabular} % \label{tab:some-more-units} % \end{table} % % \begin{table}[htbp] % \centering % \caption{List of nonsense units (exist just for fun, there will % be no support for those units). } % \begin{tabular}{ ll } % \toprule % unit-key & symbol \\ \midrule % \PrintUnitSymbol {eVc-2} \\ % \PrintUnitSymbol {hbareV-1} \\ % \PrintUnitSymbol {chbareV-1} \\ % \PrintUnitSymbol {(chbareV-1)3} \\ % \bottomrule % \end{tabular} % \label{tab:def-units} % \end{table} % % % % \section{Defining units} % \label{sec:def-units} % % New units can be defined using \lstinline|\newcookingunit|: % % \begin{function}{\newcookingunit} % \begin{syntax} % \lstinline|\newcookingunit|\oarg{symbol}\marg{new-unit-key} % \end{syntax} % This command defines the new unit \meta{new-unit-key}. If the % key is not the same as the printed symbol use \oarg{symbol}. % % Some examples (note: the definition of the printed degree Celsius is % directly copied \& pasted from [a maybe older version of] \pkg{siunitx}): % % \begin{center} % \begin{tabular}{ll} % \lstinline|\newcookingunit{kg}| \\ % \lstinline|\newcookingunit{g}| \\ % \lstinline|\newcookingunit[Msp.] {Msp}| \\ % \lstinline|\newcookingunit[\ensuremath{{}^{\circ}}\kern-\scriptspace C] {C} | % \end{tabular} % \end{center} % % \end{function} % % % \section{Defining options} % \label{sec:defining-opt} % % Options (to change units) can be newly defined or added to already existing keys % using % \begin{itemize} % \item \lstinline|\cudefinekeys| % \item \lstinline|\cudefinesinglekey| % \item \lstinline|\cuaddkeys| % \item \lstinline|\cuaddsinglekeys| % \item \lstinline|\cuaddtokeys| % \end{itemize} % % % % \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} % \ \ \ \ \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} % % If you define new units (see \vref{sec:def-units}) and cannot add % them to already existing keys you can use \lstinline|\cudefinekeys| bzw. % \lstinline|\cudefinesinglekey| to define new keys. % % \lstinline|\cudefinekeys| takes the \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. ^^A Those keys are linked to each other. % % 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 \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}. % % % \end{function} % % \begin{cuexample} % % This example defines following keys with their respective value: % \begin{itemize} % \item the key \texttt{kg} with the values \texttt{kg}, \texttt{dag}, \texttt{g} and \texttt{oz} % \item the key \texttt{dag} with the values \texttt{kg}, \texttt{dag}, \texttt{g} and \texttt{oz} % \item the key \texttt{g} with the values \texttt{kg}, \texttt{dag}, \texttt{g} and \texttt{oz} % \item the key \texttt{oz} with the values \texttt{kg}, \texttt{dag}, \texttt{g} and \texttt{oz} % \item the key \texttt{d} with the values \texttt{d}, \texttt{h}, \texttt{min} and \texttt{s} % \item \dots % \end{itemize} % % % \begin{align*} % \SI{1}{\kg}&= \SI{1}{\kg} & % \SI{1}{\kg}&= \SI{100}{\deka\g} & % \SI{1}{\kg}&= \SI{1000}{\g} \\ % \SI{1}{\kg}&= \SI{35.27399}{\ounce} & % \SI{1}{\kg}&= \SI{2.204 622 6}{\pound} % \end{align*} % % \begin{lstlisting} % \cudefinekeys {kg} % { % {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} % { % {h} { 24 } %% 1 day are 24 hours % {min}{ 1440 } %% 1 day are 1440 minutes % {s} { 86400 } %% 1 day are 86400 seconds % } % \end{lstlisting} % % To convert degree Fahrenheit to degree Celsius, kelvin and degree R\'eamur one % needs the formulas % \begin{align*} % T_C &= ( T_F - 32 ) \cdot \frac{5}{9} \\ % T_K &= ( T_F - 459.67 ) \cdot \frac{5}{9} \\ % T_{Re} &= ( T_F - 32 ) \cdot \frac{4}{9} % \end{align*} % % 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 \texttt{F} and the values \texttt{C}, \texttt{K} and \texttt{Re} % are defined: % % \begin{lstlisting} % \cudefinesinglekey {F} % { % {C} { ( #1 - 32 ) * 5/9 } %% see formulas above % {K} { ( #1 + 459.67 ) * 5/9 } % {Re} { ( #1 - 32 ) * 4/9 } % } % \end{lstlisting} % % This defines the key \texttt{F} with the values \texttt{F}, \texttt{C}, % \texttt{K} and \texttt{Re}. % % \end{cuexample} % % % % \begin{function}{\cuaddkeys,\cuaddsinglekeys} % % \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{cuaddsinglekeys}\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} % % 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}. % % % 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 \texttt{\#1} (see \lstinline|\cudefinesinglekey|). This % command neither defines new keys nor does it add values to other % keys 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, I % was surprised myself that such a unit exists, but it even appears in % a Sherlock-Holmes story). You exactly know that \SI{1}{\st} equals % \SI{14}{\lb}, well \dots\ now you have two % choices. \lstinline|\cuaddkeys| or \lstinline|\cuaddtokeys| (use the % one best fitting). This example uses the first, the next the 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 % } % \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{cuexample} % Now you want to add degree R{\o}mer and convert % Celsius to degree R{\o}mer: % \begin{equation*} % T_{R\o} = T_C * \frac{21}{40} + 7.5 % \end{equation*} % % \begin{lstlisting} % %% defining new unit 'degree R{\o}mer' % \newcookingunit [\ensuremath{ {} ^ { \circ } }\kern-\scriptspace R{\o}] {Ro} % \cuaddsinglekeys {C} %% adds value 'Ro' to 'C'. % { % {Ro} { #1 * 21/40 + 7.5 } % } % \cusetup %% round to integer automatically % { % set-option-for-Ro = { round-to-int = true } % } % \end{lstlisting} % \begin{cuexamplecode} % \cunum{10}{C} \\ % \cunum[C=Ro]{10}{C} \\ % \end{cuexamplecode} % \end{cuexample} % % % % % % % % % % % % \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} \\ % \end{cuexamplecode} % \end{cuexample} % % % % \section{Language support} % \label{sec:language} % % The unit names and symbols depend on the language. To change the % name depending on the language you can use \lstinline|\cudefinename| % and to only change symbols use \lstinline|\cudefinesymbol|. % % \begin{function}{decimal-mark, one(m),one(f),one(n)} % Those are special keys (as they cannot be used as units). Not only % are printed units language depending, but as is the decimal % mark (\enquote{.} or \enquote{,}). To set the decimal mark use % \opt{decimal-mark} (see examples below). % % Furthermore if you are using the package-option \opt{use-numerals} you may % also use the keys \opt{one(m)}, \opt{one(f)} and \opt{one(n)}. If % you use this option, 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 gender of the % following word (e.g. \enquote{ein Baum} (m), % \enquote{eine Pflanze} (f) and \enquote{ein Auto} (n)). To set the % written-out 1 to be correct with the gender of the used unit, use % this key (see also examples below) % \end{function} % % \begin{function}{\cudefinename} % \begin{syntax} % \mycs{cudefinename}\marg{Language} % \ \ \{ % \ \ \ \ \marg{unit-key-1} \oarg{symbol-1} \marg{singular-1} \oarg{plural-1} \meta{gender} % \ \ \ \ \marg{unit-key-2} \oarg{symbol-2} \marg{singular-2} \oarg{plural-2} \meta{gender} % \ \ \ \ \dots % \ \ \} % \end{syntax} % % This command defines the names (and optionally the symbol) of the % commands printed in \lstinline|\cutext| and \lstinline|\Cutext| % (and \lstinline|\cunum| regarding the symbol) for the specific % \meta{Language}. For details regarding \meta{language} see the % \pkg{translator}-documentation. % % If the plural form of the name differs from the singular form use % \oarg{plural} to specify the plural form, if no \oarg{plural} is % given the plural will be set equal to its singular. The singular % is only used if the number in \lstinline|\cutext| and % \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. % \end{function} % % \begin{lstlisting} % \cudefinename {English} % { % {kg} {kilogramme} % {oz} {ounce} % {h} {hour} [hours] % {C} {degree \space Celsius} [degrees \space Celsius] % {decimal-marker} {.} % {one(m)} {one} % {one(f)} {one} % {one(n)} {one} % } % \end{lstlisting} % \begin{lstlisting} % \cudefinename {German} % { % {kg} {Kilogramm} % {oz} {Unze} % {d} {Tag} [Tage] % {h} {Stunde} [Stunden] % {C} {Grad\space Celsius} % {decimal-marker} {,} % {one(m)} {ein} % {one(f)} {eine} % {one(n)} {ein} % } % \end{lstlisting} % % % \begin{function}{\cudefinesymbol} % % \begin{syntax} % \mycs{cudefinesymbol}\marg{Language} % \ \ \{ % \ \ \ \ \marg{unit-key-1} \marg{symbol-1} % \ \ \ \ \marg{unit-key-2} \marg{symbol-2} % \ \ \ \ \dots % \ \ \} % \end{syntax} % % This command defines the symbols of the units printed in % \lstinline|\cunum| for the specific \meta{language}. It works % similar as \lstinline|\cudefinename|, but only the symbols (and no % names) can be set. For details regarding \meta{language} see % the \pkg{translator}-documentation. % %^^A A special key is the \texttt{decimal-mark}. It defines the symbol %^^A printed for the decimal-marker. % \end{function} % % % \begin{lstlisting} % \cudefinesymbol {English} % { % {decimal-mark} {.} % {one(m)} {one} % {one(f)} {one} % {one(n)} {one} % } % \cudefinesymbol {German} % { % {decimal-mark} {,} % {one(m)} {ein} % {one(f)} {eine} % {one(n)} {ein} % } % \cudefinesymbol {French} % { % {l} {L} % {dl} {dL} % {cl} {cL} % {ml} {mL} % {decimal-mark} {.} % {one(m)} {un} % {one(f)} {une} % {one(n)} {un} % } % \end{lstlisting} % % % \section{Options} % \label{sec:options} % % Options in \pkg{cooking-units} can mostly be set globally using % \lstinline|\cusetup| or locally using the optional argument of the % respective command (but \emph{not} as a package option). The only % exception is the option given in \vref{sec:load-time-options} which % needs to be used as a package option. % % \subsection{Load time options} % \label{sec:load-time-options} % % \begin{function}{use-numerals} % \begin{syntax} % \cs{usepackage}[use-numerals=\meta{true/false}]\{cooking-units\} % \end{syntax} % If set to \true\ loads package \pkg{fmtcount} and uses % \mycs{numberstringnum} for \mycs{cutext} % and \mycs{Numberstringnum} for \mycs{Cutext} to write-out numbers below % \opt{use-numerals-below} (13 by default), integers above are % printed as numbers. Please note the keys \opt{one(m)}, \opt{one(f)} % and \opt{one(n)} to change the printed \enquote{one} (as % \enquote{one} is in many languages dependent on the gender of the % following word. E.g in German: Masculine: ein Baum, % Feminin: eine Pflanze, Neutrum: ein Auto). % \end{function} % % \cusetup{use-numerals-below=13} % \begin{cuexamplecode} % \cutext{1}{kg} \\ % \Cutext{1}{kg} \\ % \cutext{2}{kg} \\ % \Cutext{2}{kg} \\ % \cutext{13}{kg} \\ % \Cutext{14}{kg} % \end{cuexamplecode} % \cusetup{use-numerals-below=0} % % \subsection{Normal options} % % This option can only be set as local options or using % \lstinline|\cusetup|, but \emph{not} as load time options. % % \begin{function}{\cusetup} % Options can be set globally using \lstinline|\cusetup|. % \end{function} % % % \begin{function}{unit} % \begin{syntax} % \meta{unit-key-1} = \meta{unit-key-2} % \end{syntax} % Convert units from \meta{unit-key-1} to \meta{unit-key-2} (see % \vref{sec:defining-opt} to define new options). % \end{function} % % \begin{function}{set-option-for-,add-option-for-,erase-all-options} % \begin{syntax} % set-option-for-\meta{unit-key} = \meta{key1=value1,\dots} % add-option-for-\meta{unit-key} = \meta{key1=value1,\dots} % erase-all-options % \end{syntax} % Sets and adds \meta{key1=value1,\dots}, for a specific % \meta{unit-key} % ^^A with % ^^A options being a comma-separated list of \texttt{key=value}. % \texttt{erase-all-options} is used to erase all options for all % \meta{unit-key}s. % % You may want to attach some options to a special % \meta{unit-key}. Those options are automatically activated if (and % only if) the specific \meta{unit-key} is used (or changed into this % unit). Setting options overwrites old options. Adding options, well % \dots\ adds the options to the old ones. % % The following rounds the values to integers for \texttt{F}, \texttt{C}, % \texttt{K} and \texttt{Re}. % % \end{function} % % \begin{lstlisting} % \cusetup % { % set-option-for-F = { round-to-int = true } , % set-option-for-C = { round-to-int = true } , % set-option-for-K = { round-to-int = true } , % set-option-for-Re = { round-to-int = true } % } % \end{lstlisting} % % You can \enquote{delete} the options by setting % an empty value for a specific \meta{unit-key} (or use % \opt{erase-all-options} to erase all options for all \meta{unit-key}s) % % % \begin{function}{eval-fraction} % \begin{syntax} % eval-fraction = \meta{true/false} % \end{syntax} % This option takes \texttt{true} or \texttt{false} as values. % If set to \texttt{true} fractions are evaluated. Please note that divisions % through zero are not allowed. % \end{function} % % \begin{cuexamplecode} % \cusetup{eval-fraction=true} @ % \cunum{1/3}{kg} \\ % \cunum{1/2}{kg} \\ % \cunum[kg=g]{1/2}{kg} \\ % \cunum{1_1/2}{kg} \\ % \cunum[kg=g]{1_1/2}{kg} % \end{cuexamplecode} % % % \begin{function}{round-precision} % \begin{syntax} % round-precision = \meta{integer} % \end{syntax} % Rounds the amount automatically to \meta{integer} digits after the colon. % Note that units like \texttt{C}, \texttt{F}, \texttt{K} and \texttt{Re} are still rounded % to integers due to \texttt{set-option-for-}. % \end{function} % % % \begin{cuexamplecode} % \cusetup{round-precision= 5} @ % \cunum{1.23456789}{kg} \\ % \cunum[g=kg]{12.587}{g} \\ % \cunum{194}{kg} \\ % \cunum[C=F]{200--210}{C} \\ % \cunum[K=C]{0.0012}{K} \\ % \cusetup{round-precision= 1} @ % \cunum{1.23456789}{kg} \\ % \cunum{12.58}{kg} \\ % \cunum[g=kg]{194}{g} \\ % \cunum[C=F]{200--210}{C} \\ % \cunum[K=C]{0.0012}{K} % \end{cuexamplecode} % % % % \begin{function}{round-to-int} % \begin{syntax} % round-to-int = \meta{true/false} % \end{syntax} % Rounds the amount to an integer if set \texttt{true}. % \end{function} % % % \begin{cuexamplecode} % \cusetup{round-to-int=true} @ % \cunum{1.23456789}{kg} \\ % \cunum{12.58}{kg} \\ % \cunum[g=kg]{194--294}{g} \\ % \cunum[kg=g]{1.23456789}{kg} \\ % \end{cuexamplecode} % % % \begin{function}{range-sign} % \begin{syntax} % range-sign = \meta{string} % cunum-range-sign = \meta{string} % cutext-range-sign = \meta{string} % \end{syntax} %^^A Sets the \emph{printed} range-sign equal to \meta{string}. % The second sets the \emph{printed} range-sign used in \mycs{cunum} % (and \mycs{cuam}) to % \meta{string}, the third sets the printed range-sign used in % \mycs{cutext}/\mycs{Cutext} to \meta{string}. % %^^A If you want to change to the same range-sign for all commands %^^A use the first option. % Use the \opt{range-sign} to set the printed range-signs for both % \mycs{cunum} (and \mycs{cuam}) and \mycs{cutext}/\mycs{Cutext} to \meta{string}. % % The default for \meta{string} is \texttt{-{}-} (for both). % \end{function} % % \begin{cuexamplecode} % \cusetup{cunum-range-sign={~to~}} @ % \cunum{1--2}{kg} \\ % \cuam{1--2}{kg} \\ % \cutext{1--2}{kg} \\ % \Cutext{1--2}{kg} \\ % \end{cuexamplecode} % \begin{cuexamplecode} % \cusetup{cutext-range-sign={~to~}} @ % \cunum{1--2}{kg} \\ % \cuam{1--2}{kg} \\ % \cutext{1--2}{kg} \\ % \Cutext{1--2}{kg} \\ % \end{cuexamplecode} % \begin{cuexamplecode} % \cusetup{range-sign={~to~}} @ % \cunum{1--2}{kg} \\ % \cuam{1--2}{kg} \\ % \cutext{1--2}{kg} \\ % \Cutext{1--2}{kg} \\ % \end{cuexamplecode} % % % % \begin{function}{fraction-command} % \begin{syntax} % fraction-command = \meta{\cs{command}} % \end{syntax} % Sets the command used for printing fractions equal to \meta{\cs{command}}. % \meta{\cs{command}} has to take two arguments. By default % it is equal to \lstinline!\sfrac! from \pkg{xfrac}. % % Please note that the amount is \emph{not} printed inside a math % environment by default. % \end{function} % % \begin{cuexamplecode} % \newcommand\myfrac[2]{#1/#2} @ % \cusetup{fraction-command=\myfrac} @ % \cuam{1/8} \\ % \cunum{1/2}{kg} \\ % \cunum{4/5}{C} \\ % \cunum{1_2/3}{kg} \\ % \cusetup{fraction-command=\nicefrac} @ % \cuam{1/8} \\ % \cunum{1/2}{kg} \\ % \cunum{4/5}{C} \\ % \cunum{1_2/3}{kg} % \end{cuexamplecode} % % \begin{function}{fraction-inline} % \begin{syntax} % fraction-inline = \meta{input containing \#1 and \#2} % \end{syntax} % Similar to \texttt{fraction-command} only that you don't have to % define a command to alter the output of the fraction. % \end{function} % % \begin{cuexamplecode} % \cusetup{fraction-inline={#1/#2} } @ % \cuam{1/8} \\ % \cunum{1/2}{kg} \\ % \cunum{4/5}{C} \\ % \cunum{1_2/3}{kg} \\ % \cusetup{fraction-inline={\nicefrac{#2}{#1}} } @ % \cuam{1/8} \\ % \cunum{1/2}{kg} \\ % \cunum{4/5}{C} \\ % \cunum{1_2/3}{kg} % \end{cuexamplecode} % % % \begin{function}{mixed-fraction-space} % \begin{syntax} % mixed-fraction-space = \meta{length} % \end{syntax} % Sets the length between the fraction and the number in a mixed-fraction, % default is \texttt{0.1em}. % \end{function} % % \begin{cuexamplecode} % \cuam{1_2/3}{kg} \\ % \cunum{1_2/3}{kg} \\ % \cunum{10_2/3}{kg} \\ % \cusetup{mixed-fraction-space=1em } @ % \cuam{1_2/3}{kg} \\ % \cunum{1_2/3}{kg} \\ % \cunum{10_2/3}{kg} \\ % \cusetup{mixed-fraction-space=0em } @ % \cuam{1_2/3}{kg} \\ % \cunum{1_2/3}{kg} \\ % \cunum{10_2/3}{kg} \\ % \end{cuexamplecode} % % % \begin{function}{set-special-sign,add-special-sign} % \begin{syntax} % set-special-sign = \meta{character(s)} % add-special-sign = \meta{character(s)} % \end{syntax} % Allows \meta{character(s)} to be used in the first mandatory argument of % \lstinline!\cunum! without raising an error (you can customize this % behavior, see \opt{set-unknown-message}). By default it is set to \texttt{?}. % \end{function} % % \begin{cuexamplecode} % \cunum{?}{kg} \\ % \cunum[g=kg]{10?--20?}{kg} \\ % \cusetup{add-special-sign={xX} } @ % \cunum{x}{kg} \\ % \cunum{X--?}{kg} \\ % \cusetup{set-special-sign={} } @ % \cunum{1}{kg} \\ % \cunum{1--2}{kg} \\ % \end{cuexamplecode} % % % % % % \begin{function}{parse-number} % \begin{syntax} % parse-number = \meta{true/false} % \end{syntax} % If set to \texttt{false} prints the number of \lstinline!\cunum!, % \lstinline!\cutext! and \lstinline!\Cutext! % as they are (after some \dots\ well \dots\ parsing due to \enquote{\lstinline|_|}). It is \texttt{true} by default. % \end{function} % % % \begin{cuexamplecode} % \cusetup{ parse-number=false } @ % \cunum[kg=g]{1}{kg} \\ % \cunum{1--2}{kg} \\ % \cunum{1----------2}{kg} \\ % \cunum{1.2}{kg} \\ % \cunum[kg=g]{1,2}{kg} \\ % \cunum{1/2}{kg} \\ % \cunum{1_2/3}{kg} \\ % \cunum{1/2_3}{kg} \\ % \cunum{qwertzuiop}{kg} \\ % \cutext{1}{kg} \\ % \cutext{100}{kg} \\ % \cutext{gjfak}{kg} \\ % \end{cuexamplecode} % % % % % % \begin{function}{use-numerals-below} % \begin{syntax} % use-numerals-below = \meta{integer} % \end{syntax} % Only usable if the package option \opt{use-numerals} is active. Prints the name of % the numbers for integers used in \mycs{cutext} and \mycs{Cutext} % smaller than \meta{integer}. \meta{integer} it is by default % 13. % \end{function} % % \cusetup{ use-numerals-below=13 } % \begin{cuexamplecode} % \cutext{1}{kg} \\ % \cutext{2}{kg} \\ % \cutext{12}{kg} \\ % \cutext{13}{kg} \\ % \cusetup{ use-numerals-below=10 } @ % \cutext{1}{kg} \\ % \cutext{2}{kg} \\ % \cutext{12}{kg} \\ % \cutext{13}{kg} \\ % \cusetup{ use-numerals-below=0 } @ % \cutext{1}{kg} \\ % \cutext{2}{kg} \\ % \cutext{12}{kg} \\ % \cutext{13}{kg} \\ % \end{cuexamplecode} % \cusetup{ use-numerals-below=0 } % % \begin{function}{set-unknown-message} % \begin{syntax} % set-unknown-message = \meta{error/warning/none} % \end{syntax} % Using a special sign (\texttt{?} by default) causes a warning to % be raised. Set this option to \opt{error} if you want an error % (as an extra emphasis), \opt{warning} if you want a warning % (default) and \opt{none} if you don't want to know anything about it. % \end{function} % % % % \subsection{Weird options} % % \begin{function}{check-temperature} % \begin{syntax} % check-temperature = \meta{true/false} % \end{syntax} % Checks if the used temperature is below the absolute zero point. % Currently \texttt{C}, \texttt{F}, \texttt{K} and \texttt{Re} are supported. % While \lstinline|\cunum{0}{K}| is ok, \lstinline!\cunum{-1}{K}! raises an error, % same for the others. Is set to \texttt{false} by default. To add new units % see \opt{add-temperature-to-check}. % \end{function} % % \begin{function}{add-temperature-to-check} % \begin{syntax} % add-temperature-to-check = % \ \ \{ % \ \ \ \ \meta{unit-key-1} = \meta{minimum-value-1} , % \ \ \ \ \meta{unit-key-2} = \meta{minimum-value-2} , % \ \ \ \ \dots % \ \ \} % \end{syntax} % This option adds \meta{unit-key-1} and so on to the list of units to be checked % if \opt{check-temperature} is active. The argument can be a comma-separated % list of \meta{unit-key} = \meta{minimum-value}. This sets the allowed minimum % value of \meta{unit-key} to \meta{minimum-value}. % % \end{function} % % For example, this package implements the allowed minimum values for the % temperatures \texttt{C}, \texttt{F}, \texttt{K} and \texttt{Re} to be checked if % \opt{check-temperature} is active: % \begin{lstlisting} % \cusetup % { % add-temperature-to-check = % { % K = 0, % C = -273.15 , % F = -459.67 , % Re = -218.52 % } % } % \end{lstlisting} % % If you want to add a new value, for example degree R{\o}mer % (which has be defined in another example) you can write: % \begin{lstlisting} % \cusetup % { % add-temperature-to-check = { Ro = -135.90375 } % } % \end{lstlisting} % % % ^^A \begin{cuexamplecode} % ^^A \cusetup{check-temperature=true} @ % ^^A \cunum{0}{K} \\ % ^^A \cunum[K=C]{0--1}{K} \\ % ^^A \end{cuexamplecode} % % % % \begin{function}{convert-to-eV} % \begin{syntax} % convert-to-eV = \meta{true/false} % \end{syntax} % Converts (nearly) every unit in \vref{tab:def-units} % to electron volt or the respective derivative. Note that this % option is: % 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. % % \end{function} % % \begin{cuexamplecode}[\hfill] % \cusetup{ convert-to-eV=true } @ % \cunum{1}{kg} \\ % \cunum{1}{l} \\ % \cunum{1}{J} \\ % \cunum{1}{m} \\ % \cunum{1}{C} \\ % \cunum{1}{s} \\ % \end{cuexamplecode} % % % % % \section{Bugs \& Feedback} % \label{sec:bug-feed} % % Bug reports are always welcome. If you are sending a bug report % please include a minimal working example showing the bug and a short % description. Furthermore please add \enquote{cooking-units} % to the e-mail header. GMX has the habit of putting e-mails into the % spam account and adding \enquote{cooking-units} to the header makes % it easier to recognize those e-mails. % % Feedback and requests (commands, units) are most welcome. % Please also add (if possible) an example of the % desired output into the minimal example (and also add \enquote{cooking-units} % to the header). % % Furthermore, as you can see I am not able to speak too many languages (german and % english to be precise; I managed to add french with the help of the internet, % which is not optimal) so if you are able to speak a language not yet implemented % and would like to help you can send me a list of the translations of the units given in % \vref{sec:pred-units}. I would need % \begin{itemize} % \item their singular (and plural) form, % \item the gender, % \item the printed symbol (if different), % \item \texttt{decimal-mark} and \texttt{one(m)}, \texttt{one(f)}, \texttt{one(n)} % \end{itemize} % % Oh yeah, if someone has a better idea of how to deal with languages I am happy to know. % % % %^^A \section{Notes and other stuff} %^^A This section contains stuff which might or might not be interesting. %^^A %^^A \subsection{More or less FAQ} %^^A %^^A \num{624150912.6 +- 3.9 e+10} %^^A \num{6.241509126 +- 0.000000039 e+18} %^^A %^^A \num{8.6173303 +- 00000.0000050 e-5} %^^A %^^A \subsection{Calculation} %^^A This subsection deals with some regarding the conversion to certain units. %^^A Mostly to (I like to call them) \enquote{electron volt units} (or natural units). %^^A Let's begin. %^^A %^^A We start with the easiest one: conversion of joule into electron volt. %^^A Easy because Wikipedia and nearly every physics book knows the answer. %^^A And according to Wikipedia %^^A \begin{align} %^^A \SI{1}{\eV} &= \SI{1.6021766208(98)e-19}{\joule} \\ %^^A \SI{1}{\joule} &= \SI{6.241509126 +- 0.000000039 e+18}{\eV} %^^A \end{align} %^^A Adding this is no problem: %^^A \begin{lstlisting} %^^A \cuaddtokeys {J} {eV} { 1.6021766208e-19 } %^^A \end{lstlisting} %^^A %^^A %^^A Great, next Temperature (kelvin) to electron volt. Also no problem at all %^^A because joule and kelvin are related by the boltzmann constant $k_B$ with %^^A \begin{equation} %^^A energy (\si{\joule}) = k_B \cdot temperature (\si{\kelvin}) %^^A \end{equation} %^^A as $[k_B]= \sfrac{\si{\joule}}{\si{\kelvin}}$ and %^^A $k_B= \SI{1.38064852(79)e-23}{\joule\per\kelvin}$. Now using the power %^^A of (more or less basic, but somehow annoying) mathematics we get: %^^A \begin{align} %^^A [k_B] &= \SI{1.38064852(79)e-23}{\joule\per\kelvin} = \\ %^^A &= \num{1.38064852(79)e-23} \cdot \SI{6.241509126 +- 0.000000039 e+18 }{\eV\per\K} = \\ %^^A &= \SI{8.6173303 +- 0.0000050 e-5 }{\eV\per\K} %^^A \end{align} % % %^^A \section{Notes and other stuff} %^^A \subsection{Some details to electron volts} %^^A This section explains how I calculated the values for conversion into electron volt %^^A or the respective derivative. Let's begin with some constants (from Wikipedia), note that %^^A \begin{equation*} %^^A \num{1.23456(78)e-9} = \num[separate-uncertainty = true]{1.23456(78)e-9} %^^A \end{equation*} %^^A just for info. %^^A %^^A \begin{align} %^^A \SI{1}{\eV} &= \SI{1.6021766208(98)e-19}{\J} \\ %^^A \hbar &= \SI{1.054571800(13)e-34}{\J\s} \\ %^^A k_B &= \SI{1.38064852(79)e-23}{\J\per\K} = \SI{8.6173303(50)e-5}{\eV\per\K}\\ %^^A c &= \SI{299792458}{\m\per\s} %^^A \end{align} %^^A %^^A Note that all those and following values are rounded to the second relevant figure of the %^^A uncertainty of the value. %^^A %^^A Well then, next are temperatures. %^^A %^^A Temperatures are fairly easy. Just convert the temperature of your choice to kelvin %^^A and multiplicate it with $k_B$: %^^A \begin{align} %^^A \SI{1}{\K} * k_B &= \SI{8.6173303(50)e-5}{\eV} %^^A \end{align} %^^A %^^A Next is more complicated. To compute the resulting unceartanity I using %^^A \enquote{Gauß'sches Fehlerfortpflanzungsgesetz} (I don't know if this has %^^A a translation). Anyway. We know that %^^A \begin{align*} %^^A \frac{\SI{1}{\eV}}{c^2} &= \frac{\SI{1.6021766208e-19}{\J}}{(\SI{299792458}{\m\per\s})^2} %^^A = \frac{\SI{1.6021766208e-19}{\kg\m\squared\per\s\squared}}{\SI{8,98755178736818E16}{\m\squared\per\s\squared}} = \\ %^^A &\frac{\SI{1.6021766208e-3}{\kg}}{\num{8,98755178736818}} = %^^A \SI{1782661906,94091624922088}{\kg} %^^A \end{align*} %^^A %^^A Great, now we have to calucalte the unceartinity: %^^A \begin{align} %^^A f(\si{\eV},c) &= \frac{\si{\eV}}{c^2} \\ %^^A df(\si\eV,c) &= \sqrt{ (\frac{\partial f}{\partial \si\eV})^2 * (\Delta \si\eV)^2 + (\frac{\partial f}{\partial c})^2 * (\Delta c)^2 } = \\ %^^A &= \sqrt{ (\frac{1}{c^2})^2 * (\Delta \si\eV)^2 + (-2\frac{eV}{c^{-3}})^2 * (\Delta c)^2 } %^^A \end{align} %^^A %^^A Now we know that $\Delta c = 0$: %^^A \begin{align} %^^A df(\si\eV,c) &= \sqrt{ (\frac{1}{c^2})^2 * (\Delta \si\eV)^2 } = %^^A \sqrt{ \frac{1}{(\SI{299792458}{\m\per\s} )^2} * (\SI{0.0000000098e-19}{\J})^2 } \\ %^^A &= %^^A \end{align} % % \end{documentation} % % \begin{implementation} % % \section{Implementation} % % \subsection{Beginning} % % \begin{macrocode} %<@@=cooking_units> % \end{macrocode} % % \begin{macrocode} %<*package> % \end{macrocode} % % % % Na dann, auf gehts! % \begin{macrocode} \@ifpackageloaded {xparse} { } { \RequirePackage {xparse} } \@ifpackageloaded {expl3} { } { \RequirePackage {expl3} } % \end{macrocode} % %: Package % \begin{macrocode} \ProvidesExplPackage {cooking-units} {2016/09/26} {1.03b} {Ein Paket fuer Kocheinheiten} % \end{macrocode} % Chekcing if \pkg{expl3} is uptodate, otherwise abort the loading of the package. % \begin{macrocode} \@ifpackagelater { expl3 } { 2016/05/18 } { } { \PackageError { cooking-units } { Support~package~expl3~too~old } { You~need~to~update~your~installation~of~the~bundles~'l3kernel'~and~ 'l3packages'.\MessageBreak Loading~cooking-units~will~abort! } \tex_endinput:D } % \end{macrocode} % Loading the packages needed. % \begin{macrocode} \@ifpackageloaded { translator } { } { \RequirePackage { translator } } \@ifpackageloaded { xfrac } { } { \RequirePackage { xfrac } } \@ifpackageloaded { l3keys2e } { } { \RequirePackage { l3keys2e } } % \end{macrocode} % % Define the only load-time option for this package. If it is set, % load package \pkg{fmtcount} and redefine the option so that it % displays an error message if used. % \begin{macrocode} \bool_new:N \g_@@_load_if_opt_numeral_bool \keys_define:nn { cooking-units } { use-numerals .bool_gset:N = \g_@@_load_if_opt_numeral_bool , use-numerals .default:n = { false }, } \ProcessKeysOptions { cooking-units } \bool_if:NT \g_@@_load_if_opt_numeral_bool { \@ifpackageloaded { fmtcount } { } { \RequirePackage { fmtcount } } } \keys_define:nn { cooking-units } { use-numerals .code:n = \msg_error:nnn { cooking-units } { load-time-option } { fmtcount } , } % \end{macrocode} % % % % \subsection {Defining Variables} % % \begin{macro} % { % \tl_replace_all:NVn, % \tl_replace_once:NnV , % \tl_replace_once:NVn , % \tl_if_in:nVTF , % \tl_if_in:NVT , % \fp_compare:cNnT , % \fp_eval:c, % } % Some commands we will need later. % \begin{macrocode} \cs_generate_variant:Nn \tl_replace_all:Nnn { NVn } \cs_generate_variant:Nn \tl_replace_once:Nnn { NnV, NVn } \cs_generate_variant:Nn \tl_if_in:nnTF { nVTF } \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 { cNnT } \cs_generate_variant:Nn \fp_eval:n { c } % \end{macrocode} % \end{macro} % % \begin{macro}{\@@_frac:nn} % This command is used to print the fractions and can be changed % accordingly. % \begin{macrocode} \cs_new_eq:NN \@@_frac:nn \sfrac % \end{macrocode} % \end{macro} % % \begin{macro}{ \l_@@_change_unit_prop } % Conversions of units are stored within this property list. % If someone requests that \texttt{kg} should be changed into \texttt{g}, % \texttt{kg} is stored as a key with the value \texttt{g}. If someone % then uses the unit \texttt{kg} the value \texttt{g} is restored and the unit % is changed accordingly. % \begin{macrocode} \prop_new:N \l_@@_change_unit_prop % \end{macrocode} % \end{macro} % % %\begin{macro} % { % \l_@@_tmpa_tl , % \l_@@_tmpb_tl , % \l_@@_mixed_fraction_tl , % \l_@@_tmp_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_@@_decimal_mark_tl, % \l_@@_value_signs_tl, % \c_@@_str_hash_one_tl , % \l_@@_allowed_special_signs_tl , % } % Some token lists needed later. The first two are just basic % temporary safe tokens which are used everywhere. The third % is used to store the numerical input of the mixed-fraction part. % % \verb|tmp_unit_tl| stores the unit-key given in \lstinline|\cunum|, etc, % whereas \verb|option_unit_tl| stores the unit which the former unit % is converted into. % % The others are needed for printing and checking. % \begin{macrocode} \tl_new:N \l_@@_tmpa_tl \tl_new:N \l_@@_tmpb_tl \tl_new:N \l_@@_mixed_fraction_tl \tl_new:N \l_@@_tmp_unit_tl \tl_new:N \l_@@_option_unit_tl \tl_new:N \l_@@_language_tl \tl_new:N \l_@@_cunum_range_sign_tl \tl_new:N \l_@@_cutext_range_sign_tl \tl_new:N \l_@@_value_unit_space_tl \tl_new:N \l_@@_input_digits_tl \tl_new:N \l_@@_decimal_mark_tl \tl_new:N \l_@@_value_signs_tl \tl_new:N \l_@@_allowed_special_signs_tl \tl_new:N \c_@@_str_hash_one_tl \tl_new:N \l_@@_input_range_sign_tl % \end{macrocode} % \end{macro} % % % Setting some token lists to their default value. % \lstinline|str_hash_one_tl| is used for defining single keys. % (You will see, I didn't have a better idea) % \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_@@_input_digits_tl { 0123456789 } \tl_set:Nn \l_@@_decimal_mark_tl { . , } \tl_set:Nn \l_@@_value_signs_tl { + - } \tl_set:Nn \l_@@_input_range_sign_tl { -- } \tl_set:Nn \l_@@_allowed_special_signs_tl { ? } \tl_set_rescan:Nnn \c_@@_str_hash_one_tl { \char_set_catcode_letter:N \# } {#1} % \end{macrocode} % % Flat out stolen from \pkg{siunitx} % \begin{macrocode} \AtBeginDocument { \cs_if_free:cT { T@TS1 } { \DeclareFontEncoding { TS1 } { } { } \DeclareFontSubstitution { TS1 } { cmr } { m } { n } } } % \end{macrocode} % \begin{macrocode} \DeclareTextSymbolDefault \c_@@_minus_tl { TS1 } \DeclareTextSymbol \c_@@_minus_tl { TS1 } { 61 } \AtBeginDocument { \@ifpackageloaded { fontspec } { \@ifpackageloaded { eulervm } { } { \int_const:Nn \c_@@_minus_int { 8722 } \tl_set:Nn \c_@@_minus_tl { \tex_char:D \c_@@_minus_int } } } { } } % \end{macrocode} % % \begin{macro}{ \l_@@_mixed_frac_dim } % The dimension between the fraction and the mixed fraction part is % stored within this macro. There is no real reason why I have % chosen this distance to be 0.1em, I just thought that it looks % best. But if someone has some ideas of how large this distance % should be I am happy to listen. % \begin{macrocode} \dim_new:N \l_@@_mixed_frac_dim \dim_set:Nn \l_@@_mixed_frac_dim { 0.1 em } % \end{macrocode} % \end{macro} % % % \begin{macro}{ \l_@@_significant_figures_plus_one_int } % Stores the round-precision inside. Not sure if 'significant % figures' is the correct therm for this. Also computes the number % plus 1, later I will count the tokens after the colon in a number % (sorry, can't explain. If you have 123.4567, it gets % \enquote{4567}, 4 tokens, larger then the number plus 1, needs to % be rounded). % \begin{macrocode} \int_new:N \l_@@_significant_figures_int \int_new:N \l_@@_significant_figures_plus_one_int \int_set:Nn \l_@@_significant_figures_int { 2 } \int_set:Nn \l_@@_significant_figures_plus_one_int { 2 + 1 } % \end{macrocode} % \end{macro} % % \begin{macro}{ \l_@@_print_numerals_below_int } % Used if option 'use-numerals' is active. Uses numerals for % integers smaller than this number. % \begin{macrocode} \int_new:N \l_@@_print_numerals_below_int \int_set:Nn \l_@@_print_numerals_below_int { 13 } % \end{macrocode} % \end{macro} % % % \begin{macro}{ \l_@@_list_of_defined_keys_clist , \g_@@_list_of_defined_units_clist } % List of defined units and keys. % \begin{macrocode} \clist_new:N \l_@@_list_of_defined_keys_clist \clist_new:N \g_@@_list_of_defined_units_clist % \end{macrocode} %\end{macro} % % % \begin{macro} { \g_@@_allowed_unit_phrases_tl } % \changes {2016/06/12} {New: \cs{g_@@_allowed_unit_phrases_tl}} % Used for the keys 'one(m)', 'one(f)', etc. Those are special keys % which cannot be used as units, but are processed by the commands in % the language section as such. % \begin{macrocode} \clist_new:N \g_@@_allowed_unit_phrases_clist % \end{macrocode} % \end{macro} % % \begin{macro} { \l_@@_temperatures_to_check_clist } % \changes {1.02h} {New.} % Stores units which should be tested if \opt{check-temperature} equals true. % \begin{macrocode} \clist_new:N \l_@@_temperatures_to_check_clist %\clist_set:Nn \l_@@_temperatures_to_check_clist { C , F , K , Re } % \end{macrocode} % \end{macro} % % \begin{macro} % { % \l_@@_error_bool , % \l_@@_eval_fractions_bool, % \l_@@_parse_input_bool, % \l_@@_round_to_int_bool, % \l_@@_special_sign_bool, % \l_@@_decimal_in_input_bool, % \l_@@_single_key_bool, % \l_@@_fraction_in_input_bool, % \l_@@_check_temperature_bool, % \l_@@_convert_to_eV_bool, % \l_@@_cutext_uppercase_word_bool, % \l_@@_error_for_unknown_value_bool, % \l_@@_parse_range_bool % } % Some booleans we need later. % \begin{macrocode} \bool_new:N \l_@@_error_bool \bool_new:N \l_@@_eval_fractions_bool \bool_new:N \l_@@_parse_input_bool \bool_new:N \l_@@_round_to_int_bool \bool_new:N \l_@@_special_sign_bool \bool_new:N \l_@@_decimal_in_input_bool \bool_new:N \l_@@_single_key_bool \bool_new:N \l_@@_fraction_in_input_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_@@_error_for_unknown_value_bool \bool_new:N \l_@@_parse_range_bool %\bool_new:N \l_@@_unit_is_singlekey_bool % \end{macrocode} % \end{macro} % % Setting some of them to \texttt{true}. % \begin{macrocode} \bool_set_true:N \l_@@_parse_input_bool % \end{macrocode} % % % \begin{macro}{ \q_@@_range } % Replacing the sign \enquote{-{}-} with \lstinline|\q_@@_range| for testing. % \begin{macrocode} \quark_new:N \q_@@_range % \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_unit_phrases_clist|. % Furthermore some translations are defined. % \begin{macrocode} \clist_gset:Nn \g_@@_allowed_unit_phrases_clist { decimal-mark , one (m) , one (f) , one (n) } \newtranslation { decimal-mark (cu-unitname) } { . } \newtranslation [ to=German ] { decimal-mark (cu-unitname) } { , } \newtranslation { one (m) (cu-unitname) } { one } \newtranslation { one (f) (cu-unitname) } { one } \newtranslation { one (n) (cu-unitname) } { one } \newtranslation [ to=German ] { one (m) (cu-unitname) } { ein } \newtranslation [ to=German ] { one (f) (cu-unitname) } { eine } \newtranslation [ to=German ] { one (n) (cu-unitname) } { ein } % \end{macrocode} % \end{macro} % % % % % % \subsection {Keys} % % Let's define some keys. % \begin{macrocode} \keys_define:nn { cooking - units } { % \end{macrocode} % %\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 .default:n = { false } , % \end{macrocode} %\end{macro} % %\begin{macro}{ round-precision } % Setting the round-precision. Setting those two at once to % not calculate it every time. % \begin{macrocode} round-precision .code:n = { \int_set:Nn \l_@@_significant_figures_int {#1} \int_set:Nn \l_@@_significant_figures_plus_one_int { #1 + \c_one } } , round-precision .default:n = { 2 } , % \end{macrocode} %\end{macro} % %\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 .default:n = { false } , % \end{macrocode} %\end{macro} % %\begin{macro}{ range-sign } % Setting the printed range sign and make a difference between cunum % and c(C)utext. % \begin{macrocode} range-sign .meta:n = { cunum-range-sign = {#1} , cutext-range-sign = {#1} } , range-sign .default:n = { -- } , cunum-range-sign .tl_set:N = \l_@@_cunum_range_sign_tl , cunum-range-sign .default:n = { -- } , cutext-range-sign .tl_set:N = \l_@@_cutext_range_sign_tl , cutext-range-sign .default:n = { -- } , % \end{macrocode} %\end{macro} % %\begin{macro}{ value-unit-space } % Setting the space between the value and the printed unit. % \begin{macrocode} value-unit-space .tl_set:N = \l_@@_value_unit_space_tl , value-unit-space .default:n = { \thinspace } , % \end{macrocode} %\end{macro} % %\begin{macro}{ fraction-command } % Setting the fraction command % \begin{macrocode} fraction-command .code:n = { \cs_set_eq:NN \@@_frac:nn #1 } , fraction-command .default:n = { \sfrac } , % \end{macrocode} %\end{macro} % %\begin{macro}{ fraction-inline } % Setting the code inline. % \begin{macrocode} fraction-inline .code:n = { \cs_set:Npn \@@_frac:nn ##1##2 {#1} } , fraction-inline .default:n = { \sfrac {#1}{#2} } , % \end{macrocode} %\end{macro} % %\begin{macro}{ mixed-fraction-space } % Setting the space between the mixed fraction part and the fraction. % \begin{macrocode} mixed-fraction-space .dim_set:N = \l_@@_mixed_frac_dim , mixed-fraction-space .default:n = { 0.1 em } , % \end{macrocode} %\end{macro} % %\begin{macro}{ parse-number } % Parse the numbers? If no the input is printed as is (after some safetyparsing). % \begin{macrocode} parse-number .bool_set:N = \l_@@_parse_input_bool , parse-number .default:n= { true } , % \end{macrocode} %\end{macro} % %\begin{macro}{ add-special-sign } % Adding a (some) special sign(s) which is (are) allowed in the input. % \begin{macrocode} add-special-sign .code:n = { \tl_put_right:Nn \l_@@_allowed_special_signs_tl {#1} } , add-special-sign .default:n = { } , % \end{macrocode} %\end{macro} % %\begin{macro}{ set-special-sign } % Doing the same as above but also overrides the old signs. % \begin{macrocode} set-special-sign .tl_set:N = \l_@@_allowed_special_signs_tl , % \end{macrocode} %\end{macro} % % % \begin{macro}{ input-range-sign } % Don't wanna use \verb|--| as a range sperator in \mycs{cunum}? Set % Use this option. % \begin{macrocode} input-range-sign .tl_set:N = \l_@@_input_range_sign_tl , input-range-sign .default:n = { -- } , % \end{macrocode} %\end{macro} % % %\begin{macro}{ check-temperature } % 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 .default:n = { true } , % \end{macrocode} % %\begin{macro}{ add-temperature-to-check } % Adds a temperature to check for \texttt{check-temperature}. % \begin{macrocode} add-temperature-to-check .code:n = { \keyval_parse:NNn \@@_temperature_to_check_print_error:n \@@_temperatures_to_check_define:nn {#1} }, temperature-to-check .value_required:n = { true } , % \end{macrocode} % %\begin{macro}{ convert-to-eV } % Another weird option, converts pretty much any unit defined by this % package to electron volt or the respective derivative. % \begin{macrocode} convert-to-eV .bool_set:N = \l_@@_convert_to_eV_bool , convert-to-eV .default:n = { true } , % \end{macrocode} %\end{macro} % % \begin{macro}{ use-numerals-below } % Use numerals if the intger is below the integer set by this option. % \begin{macrocode} use-numerals-below .int_set:N = \l_@@_print_numerals_below_int , use-numerals-below .default:n = { 13 } , % \end{macrocode} %\end{macro} % % % \begin{macro}{ set-unknown-message } % Sets the message for a special-sign to error, warning or none. % \begin{macrocode} set-unknown-message .choices:nn = { error , warning , none } { \msg_redirect_name:nnn { cooking-units } { amount-not-known } { \l_keys_choice_tl } } , set-unknown-message .default:n = { warning } , % \end{macrocode} %\end{macro} % % %\begin{macro}{ erase-all-options } % Erasing all preset options. % \begin{macrocode} erase-all-options .code:n = { \clist_map_inline:Nn \g_@@_list_of_defined_units_clist { \clist_clear:c { l_@@_predefined_option_##1_clist } } }, % \end{macrocode} % Ending the definiton of keys. % \end{macro} } % \begin{macrocode} % \end{macrocode} % % % % \subsection {Messages} % % Defining messages. % % \begin{macro} {Messages} % I do not allow fractions and ranges in the same input. Maybe I will % change this. % \begin{macrocode} \msg_new:nnnn { cooking-units } { fraction-not-allowed-with-range } { 'You' \ cannot \ use \ '/' \ ( and \ '_' )\ in \ combination \ with \ '\l_@@_input_range_sign_tl' \ in \ '#1'. }{ You \ cannot \ use \ fractions \ with \ a \ range. \msg_see_documentation_text:n { cooking-units } } % \end{macrocode} % % Do not allow a \_ without a /. % \begin{macrocode} \msg_new:nnnn { cooking-units } { missing-slash } { You \ cannot \ use \ '_' \ without \ '/' in '#1'. }{ You \ cannot \ have \ a \ mixed \ fraction \ ('_') \ without \ a \ normal \ fraction \ ('/'). \msg_see_documentation_text:n { cooking-units } } % \end{macrocode} % Error message if unit is not known to this package. % \begin{macrocode} \msg_new:nnnn { cooking-units } { unknown - unit } { The \ unit \ '#1' \ is \ not \ defined. \ Use \ \newcookingunit \ to \ define \ new \ units. }{ Define \ units \ before \ using \ or \ check \ if \ the \ unit-key \ is \ written \ correctly. \msg_see_documentation_text:n { cooking-units } } % \end{macrocode} % Error if unit is already defined. % \begin{macrocode} \msg_new:nnnn { cooking - units } { unit-already-defined } { The\ unit \ '#1' \ is \ already \ defined. } { The \ unit-key \ is \ already \ defined. \ Please \ use \ a \ different \ key \ for \ a \ new \ unit. \msg_see_documentation_text:n {cooking-units} } % \end{macrocode} % % Missing argument in \lstinline|\cudefinesymbols| (et all). % \begin{macrocode} \msg_new:nnnn { cooking - units } { missing-argument } { There \ is \ an \ missing \ argument. } { You \ probably \ have \ forgotten \ a \ curly-brace \ pair. \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 } { Division\ by \ zero \ is \ not \ allowed. } { See \ a \ math \ book \ of \ your \ choice \ or \ for \ example \ Wikipedia. } % \end{macrocode} % Showing the not allowed token in the input. Hope this helps. % \begin{macrocode} \msg_new:nnnn { cooking - units } { Token-not-allowed } { The \ token \ '#1' \ is \ not \ allowed. } { The \ command \ accepts \ only \ a \ fixed \ number \ of \ tokens. \msg_see_documentation_text:n {cooking-units} } % \end{macrocode} % A second decimal sign is not allowed (No na net). % \begin{macrocode} \msg_new:nnnn { cooking - units } { Second - decimal -sign - not - allowed } { A \ second \ decimal \ sign \ is \ not \ allowed. } { Perhaps \ you \ didn't \ type \ it \ correctly. \msg_see_documentation_text:n {cooking-units} } % \end{macrocode} % Error message for an undefined key. % \begin{macrocode} \msg_new:nnnn { cooking - units } { Key - not -defined } { The \ key \ '#1' \ is \ not \ defined. \ Use \ \cudefinekeys or \ \cudefinesinglekey to \ define \ keys. } { This \ key \ is \ not \ defined, \ perhaps \ you \ misspelled \ it. \msg_see_documentation_text:n {cooking-units} } % \end{macrocode} % If the temperature is too low print this error message. % \begin{macrocode} \msg_new:nnnn { cooking - units } { Temperature-to-low } { The \ temperature \ '#1' \ is \ to \ low.\ It \ cannot \ be \ below \ the \ absolute \ zero - point \ of \ '#2'. \ Note \ that \ by \ default \ the \ temperatures \ 'C', \ 'F' , \ 'K' \ and \ 'Re' \ are \ rounded \ to \ integers. \\\\ You \ can \ disable \ the \ option \ 'check-temperature' \ to \ disable \ this \ error. } { See \ for \ example \ Wikipedia. } % \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-choice-unknown } { The \ key \ '#1' \ only \ accepts \ only \ '#3' \ as \ a \ set \ of \ choices \ and \ '#2' \ is \ non \ of \ these. } { The \ key \ accepts \ accepts\ only \ a \ fixed \ set \ of \ choices. \ You \ can \ add \ new \ choices \ via \ \cuaddkeys, \ \cuaddsinglekeys \ and \ \cuaddtokeys. \msg_see_documentation_text:n {cooking-units} } % \end{macrocode} % %\changes {v0.98a} {2016/06/11} {New option: 'value-not-known'.} %\changes {v0.99} {2016/06/12} {Renamed option: 'amount-not-known'.} % An info message that there are unknown values. % \begin{macrocode} \msg_new:nnnn { cooking - units } { amount-not-known } { The \ amount \ of \ #1 \ is \ not \ known \ at \ line \ \msg_line_number: . } { You \ used\ a\ special\ sign\ indicating\ that\ the\ true\ amount\ of\ the\ specific\ ingredient\ is\ (was) not\ known\ to\ you. This\ message\ reminds\ you\ about\ that\ fact. \msg_see_documentation_text:n {cooking-units} } % \end{macrocode} % % If a load time option not used as a package option, but later, this % message is shown. % \begin{macrocode} \msg_new:nnnn { cooking - units } { load-time-option } { The \ option \ '#1' \ is \ only \ avaiable \ as \ a \ load-time-option. \ Please \ set \ it \ as \ a \ package \ option. } { You \ cannot \ set \ this \ option \ using \ \cusetup \ but \ only \ as \ a \ package \ option. \msg_see_documentation_text:n { cooking-units } } % \end{macrocode} % % If a load time option not used as a package option, but later, this % message is shown. % \begin{macrocode} \msg_new:nnnn { cooking - units } { obsolete-command } { Command \ #1 is \ obsolete. \ Please \ use \ #2 instead. } { Don't \ use \ this \ old \ command \ ... \msg_see_documentation_text:n { cooking-units } } % \end{macrocode} % % Error message if a new temperature to check is defined and no % minimal value is given. % \begin{macrocode} \msg_new:nnnn { cooking - units } { No-Value-given } { Please \ input \ a \ number \ to \ check \ for \ 'check-temperature'. } { \msg_see_documentation_text:n { cooking-units } } % \end{macrocode} % % % \begin{macrocode} \msg_new:nnnn { cooking - units } { Minimum-already-defined } { A \ minimum \ for \ '#1' \ has \ already \ been \ defined. } { You \ cannot \ redefine \ it. \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, % \@@_error_if_unit_not_defined:V, % } % A little helper macro. Checks if the unit is defined, if not raise an error. % \begin{macrocode} \cs_new:Npn \@@_error_if_unit_not_defined:n #1 { \clist_if_in:NnF \g_@@_list_of_defined_units_clist {#1} % \tl_if_exist:cF { l_@@_tmpa_ #1 _tl } { \msg_error:nnn { cooking-units } { unknown-unit } {#1} } } \cs_generate_variant:Nn \@@_error_if_unit_not_defined:n { V } % \end{macrocode} %\end{macro} % % % % % % % \begin{macro}{\@@_if_integer_and_parse:n} % Checking if the input consists only of numbers. Furthermore tests if % the input should be parsed at all. % % \begin{macrocode} %\cs_new:Npn \@@_if_number_and_parse_aux: { } \prg_new_protected_conditional:Npnn \@@_if_integer_and_parse:n #1 { TF } { \bool_if:NTF \l_@@_parse_input_bool { \tl_map_inline:nn {#1} { \tl_if_in:NnF \l_@@_input_digits_tl {##1} { \tl_map_break:n { \use_iii:nnn } } } \use_i:nn \prg_return_true: \prg_return_false: } { \prg_return_false: } } \cs_generate_variant:Nn \@@_if_integer_and_parse:nTF { V } % \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). Is the same construct I use % later in \mycs{cunum}. % \begin{macrocode} \cs_new:Npn \@@_convert_to_eV: { \keys_set:nn { cooking-units } { m= chbareV-1, cm= chbareV-1, dm= chbareV-1, mm= chbareV-1, in= chbareV-1, kg= eVc-2, dag= eVc-2, g= eVc-2, oz= eVc-2, lb= eVc-2, d= hbareV-1, h= hbareV-1, min= hbareV-1, s= hbareV-1, cal= eV, kcal= eV, J= eV, kJ= eV, F= eV, K= eV, C= eV, Re= eV, l= (chbareV-1)3 , dl= (chbareV-1)3 , cl= (chbareV-1)3 , ml= (chbareV-1)3 , } \prop_get:NVN \l_@@_change_unit_prop \l_@@_tmp_unit_tl \l_@@_option_unit_tl \quark_if_no_value:NT \l_@@_option_unit_tl { \tl_set_eq:NN \l_@@_option_unit_tl \l_@@_tmp_unit_tl } \keys_set_filter:nnv { cooking-units } { change-unit } { l_@@_predefined_option_ \l_@@_option_unit_tl _clist } } % \end{macrocode} %\end{macro} % % \begin{macro}{\@@_deftranslation:Nnn} % \begin{macrocode} \cs_new:Npn \@@_deftranslation:Nnn #1#2#3 { \deftranslation [ to=#1 ] { #2 } {#3} } \cs_generate_variant:Nn \@@_deftranslation:Nnn { Vnn } % \end{macrocode} % \end{macro} % % \begin{macro}{\@@_deftranslation:Nnn} % Commands used in the option \texttt{temperature-to-check}. % If no value is given (first command) it raises an error. If a value % is given the unit is added to a check-list and a new % constant is defined. % \begin{macrocode} \cs_new:Npn \@@_temperature_to_check_print_error:n #1 { \msg_error:nn { cooking-units } { No-Value-given } } \cs_new:Npn \@@_temperatures_to_check_define:nn #1#2 { \@@_error_if_unit_not_defined:n {#1} \fp_if_exist:cTF { c_@@_ #1 _min_fp } { \msg_error:nnn { cooking-units } { Minimum-already-defined } {#1} } { \clist_put_right:Nn \l_@@_temperatures_to_check_clist {#1} \fp_const:cn { c_@@_ #1 _min_fp } {#2} } } % \end{macrocode} % \end{macro} % % \subsection {Parsing and cheking numbers} % % This section contains macros helping an checking the input. % % \begin{macro}{ \@@_cunum_parse_input:N, \@@_cunum_parse_input:V } % Splits the input into fractions or ranges (\lstinline|q_@@_range|). % Depending on the input on of the four macros are used. % \begin{macrocode} \cs_new:Npn \@@_cunum_parse_input:N #1 { \bool_if:NTF \l_@@_parse_range_bool { \@@_parse_range_in_input:ww #1 \q_stop } { \tl_if_in:nnTF {#1} { / } { \tl_if_in:nnTF {#1} { _ } { \@@_parse_mixed_fraction_in_input:www #1 \q_stop } { \@@_parse_fraction_in_input:ww #1 \q_stop } } { \@@_parse_number_in_input:n {#1} } } } \cs_generate_variant:Nn \@@_cunum_parse_input:N { V } % \end{macrocode} % \end{macro} % % \begin{macro}{\@@_parse_number_in_input:n} % 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 \@@_parse_number_in_input:n #1 { \@@_parse_input_and_safe_in:nN {#1} \l_@@_tmpa_tl \@@_calculate_and_print_input:N \l_@@_tmpa_tl } % \end{macrocode} % \end{macro} % % \begin{macro}{ \@@_parse_range_in_input:ww } % 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). % \begin{macrocode} \cs_new:Npn \@@_parse_range_in_input:ww #1 \q_@@_range #2 \q_stop { \@@_parse_input_and_safe_in:nN {#1} \l_@@_tmpa_tl \@@_parse_input_and_safe_in:nN {#2} \l_@@_tmpb_tl \@@_calculate_and_print_input:N \l_@@_tmpa_tl \tl_use:N \l_@@_cunum_range_sign_tl \@@_calculate_and_print_input:N \l_@@_tmpb_tl } % \end{macrocode} % \end{macro} % % \begin{macro}{ \@@_parse_fraction_in_input:ww } % If a \lstinline|/| (but no \lstinline|_|) is found inside the input. % Well \dots\ does the same as the functions before. % If fractions should be evaluated the input is \dots\ well, % evaluated and printed. Otherwise the input is given to % another function which prints the fractions. Note that the empty % argument in \lstinline|\@@_formatiere_fractions:nnn| indicates a % \enquote{normal} fraction. % \begin{macrocode} \cs_new:Npn \@@_parse_fraction_in_input:ww #1/#2 \q_stop { \@@_parse_input_and_safe_in:nN {#1} \l_@@_tmpa_tl \@@_parse_input_and_safe_in:nN {#2} \l_@@_tmpb_tl \bool_if:NTF \l_@@_eval_fractions_bool { \@@_calculate_and_print_input:n { \l_@@_tmpa_tl / \l_@@_tmpb_tl } }{ \@@_formatiere_fractions:nnn { } { \l_@@_tmpa_tl } { \l_@@_tmpb_tl } } } % \end{macrocode} % \end{macro} % % \begin{macro}{ \@@_parse_mixed_fraction_in_input:www } % The same procedure as last function? The same procedure as every % function! % % If it should be evaluated it is important to check if the mixed-fraction % part is positive or negative. % % \begin{align} % \cuam{1_2/3} &= 1 + 2/3 \\ % \cuam{-1_2/3} &= -1 - 2/3 % \end{align} % % \begin{macrocode} \cs_new:Npn \@@_parse_mixed_fraction_in_input:www #1_#2/#3 \q_stop { \@@_parse_input_and_safe_in:nN {#1} \l_@@_mixed_fraction_tl \@@_parse_input_and_safe_in:nN {#2} \l_@@_tmpa_tl \@@_parse_input_and_safe_in:nN {#3} \l_@@_tmpb_tl \bool_if:NTF \l_@@_eval_fractions_bool { \@@_calculate_and_print_input:n { \l_@@_mixed_fraction_tl \fp_compare:nNnTF { \l_@@_mixed_fraction_tl } < { \c_zero_fp } { - } { + } \l_@@_tmpa_tl / \l_@@_tmpb_tl } }{ \@@_formatiere_fractions:nnn { \l_@@_mixed_fraction_tl } { \l_@@_tmpa_tl } { \l_@@_tmpb_tl } } } % \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|. % \begin{macrocode} \cs_new:Npn \@@_parse_input_and_safe_in:nN #1 #2 { \tl_clear:N \l_tmpa_tl \bool_set_false:N \l_@@_decimal_in_input_bool \@@_parse_vorzeichen_and_rest:Nw #1 \q_stop \bool_if:NTF \l_@@_error_bool { \tl_set:Nn #2 {#1} } { \tl_set_eq:NN #2 \l_tmpa_tl } } % \end{macrocode} % \end{macro} % % \begin{macro}{ \@@_parse_vorzeichen_and_rest:Nw } % This function seperates the input into two parts with the first % part being the first token. This token is checked whetever or 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_for_safety_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 % empty (hopefully). % \begin{macrocode} \cs_new:Npn \@@_parse_vorzeichen_and_rest:Nw #1#2 \q_stop { \tl_if_in:NnTF \l_@@_value_signs_tl {#1} { \tl_put_right:Nn \l_tmpa_tl {#1} } { \tl_map_function:nN {#1} \@@_parse_input_for_safety_aux:N } \bool_if:NF \l_@@_error_bool { \tl_map_function:nN {#2} \@@_parse_input_for_safety_aux:N } } % \end{macrocode} % \end{macro} % % \begin{macro}{ \@@_parse_input_for_safety_aux:N } % Parses the input. It also is more or less 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. % \begin{macrocode} \cs_new:Npn \@@_parse_input_for_safety_aux:N #1 { \tl_if_in:NnTF \l_@@_input_digits_tl {#1} { \tl_put_right:Nn \l_tmpa_tl {#1} } { \tl_if_in:NnTF \l_@@_decimal_mark_tl {#1} { \bool_if:NT \l_@@_decimal_in_input_bool { \msg_error:nn { cooking-units } { Second - decimal -sign - not - allowed } } \bool_set_true:N \l_@@_decimal_in_input_bool \tl_put_right:Nn \l_tmpa_tl { . } }{ \tl_if_in:NnTF \l_@@_allowed_special_signs_tl {#1} { \bool_set_true:N \l_@@_special_sign_bool \tl_put_right:Nn \l_tmpa_tl {#1} }{ \bool_if:NTF \l_@@_parse_range_bool { \tl_if_in:nnTF { / _ } {#1} { \msg_error:nnn { cooking-units } { fraction-not-allowed-with-range } {#1} } { \msg_error:nnn { cooking-units } { Token-not-allowed } {#1} } } { \tl_if_in:nnTF { _ } {#1} { \msg_error:nnn { cooking-units } { missing-slash } {#1} } { \msg_error:nnn { cooking-units } { Token-not-allowed } {#1} } } \bool_set_true:N \l_@@_error_bool \tl_map_break: } } } } % \end{macrocode} % \end{macro} % % \subsection {Formatiere \& Calculiere} % % \begin{macro}{ \@@_calculate_and_print_input:n , \@@_calculate_and_print_input: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. % \begin{macrocode} \cs_new:Npn \@@_calculate_and_print_input:n #1 { \bool_if:NTF \l_@@_error_bool {#1} { \bool_if:NTF \l_@@_special_sign_bool { \tl_set:Nf \l_tmpa_tl {#1} \msg_warning:nnx { cooking-units } { amount-not-known } \l_tmpa_tl } { \@@_calculate_input_and_store_in:nN {#1} \l_tmpa_tl \@@_check_temperature_limit:N \l_tmpa_tl } \@@_print_nummerical_output:N \l_tmpa_tl } } \cs_generate_variant:Nn \@@_calculate_and_print_input:n { N } % \end{macrocode} % \end{macro} % % \begin{macro} % { % \@@_calculate_input_and_store_in:nN , % \@@_calculate_input_and_store_in:VN % } % 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{macrocode} \cs_new:Npn \@@_calculate_input_and_store_in:nN #1#2 { \fp_set:Nn \l_tmpa_fp {#1} % \tl_set:Nf #2 % { % \fp_eval:n % { % \bool_if:NF \l_@@_unit_is_singlekey_bool % { \l_tmpa_fp * } % \tl_use:c { l_@@_tmpa_ \l_@@_tmp_unit_tl _ tl } % } % } \tl_if_in:cnTF { l_@@_tmpa_ \l_@@_tmp_unit_tl _ tl } { \l_tmpa_fp } { \tl_set:Nf #2 { \fp_eval:c { l_@@_tmpa_ \l_@@_tmp_unit_tl _ tl } } }{ \tl_set:Nf #2 { \fp_eval:n { \l_tmpa_fp * \tl_use:c { l_@@_tmpa_ \l_@@_tmp_unit_tl _ tl } } } } \@@_round_calculated_input:NV #2 #2 } \cs_generate_variant:Nn \@@_calculate_input_and_store_in:nN { V } % \end{macrocode} % \end{macro} % % % % \begin{macro}{\@@_get_number_after_dot:n,\@@_get_number_after_dot_aux:w} % Getting the number after the decimal point. If it doesn't exist % the boolean is set to false, otherwise it checks how many tokens % are within the number after the decimal point. If the number of % tokens is greater than significant\_figures\_plus\_one the bool is % set to true (which tells the package later that the number should % be rounded). % \begin{macrocode} \cs_new:Npn \@@_get_number_after_dot:n #1 { \@@_get_number_after_dot_aux:w #1 . \q_recursion_tail . \q_recursion_stop } \cs_new:Npn \@@_get_number_after_dot_aux:w #1. #2 . { \quark_if_recursion_tail_stop:n {#2} \int_compare:nNnF { \tl_count:n {#2} } < { \l_@@_significant_figures_plus_one_int } { \bool_set_true:N \l_tmpa_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). We test at first if % the input needs to be rounded by comparing the number of tokens after the % decimal with the number of significant figures plus one. 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 { \bool_set_false:N \l_tmpa_bool \@@_get_number_after_dot:n {#2} \tl_set:Nf #1 { \bool_if:nTF { \l_tmpa_bool || \l_@@_round_to_int_bool } { \fp_eval:n { \bool_if:NTF \l_@@_round_to_int_bool { round (#2) } { round( #2 , \l_@@_significant_figures_int ) } } } {#2} } } \cs_generate_variant:Nn \@@_round_calculated_input:NN { NV } % \end{macrocode} % \end{macro} % % \begin{macro}{ \@@_formatiere_fractions:nnn } % The name of this function is the name of the game: It prints fractions. % Furthermore it sets the boolean \lstinline|fraction_in_input_bool| to true % so that the correct unit is printed. Instead of \lstinline|\kern| I used the % \lstinline|\hbox_to_wd:nn| command (I don't have a better idea). % \begin{macrocode} \cs_new:Npn \@@_formatiere_fractions:nnn #1#2#3 { \bool_set_true:N \l_@@_fraction_in_input_bool \tl_if_empty:nF {#1} { #1 \hbox_to_wd:nn { \l_@@_mixed_frac_dim } { } } \@@_frac:nn {#2} {#3} } % \end{macrocode} % \end{macro} % % % \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 \texttt{Re}, a \lstinline|\tl_if_in:nVT| would also check for \texttt{R} % and \texttt{e} instead of only \texttt{Re}. % \begin{macrocode} \cs_new:Npn \@@_check_temperature_limit:N #1 { \bool_if:NT \l_@@_check_temperature_bool { \clist_if_in:NVT \l_@@_temperatures_to_check_clist \l_@@_option_unit_tl { \fp_compare:cNnT { c_@@_ \l_@@_option_unit_tl _min_fp } > {#1} { \msg_error:nnxx { cooking-units } { Temperature-to-low } { #1 \space \l_@@_option_unit_tl } { \fp_use:c { c_@@_ \l_@@_option_unit_tl _min_fp } \space \l_@@_option_unit_tl } } } } } % \end{macrocode} % \end{macro} % % \begin{macro}{ \@@_print_nummerical_output:N } % Prints the nummerical ouput (if it is not a fraction). % % \lstinline|\l_@@_tmpa_tl| can be very dangerous because values are also stored % within \lstinline|\l_@@_tmpa_tl|, but as long as the value stored inside % this function is processed first all is fine. % \begin{macrocode} \cs_new_protected:Npn \@@_print_nummerical_output:N #1 { %% \l_@@_tmpa_tl is sehr gefaehrlich hier. \translatelet \l_@@_tmpa_tl { decimal-mark ( cu-unit name ) } \tl_replace_once:NnV #1 { . } \l_@@_tmpa_tl \tl_replace_once:NnV #1 { - } \c_@@_minus_tl #1 } % \end{macrocode} % \end{macro} % % % % \subsection {\mycs{cunum}} % % % \begin{macro}{ \cunum } % The main command of this package. % \begin{macrocode} \NewDocumentCommand \cunum { O{} m O{} m } { \group_begin: \@@_cunum_initialise:nnnn {#1} {#2} {#3} {#4} \bool_if:NTF \l_@@_parse_input_bool { \@@_cunum:nnVV {#2} {#3} \l_@@_option_unit_tl \l_@@_tmp_unit_tl } { \@@_cunum_do_not_parse:nnn {#2} {#3} {#4} } \group_end: } % \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:nnnn #1#2#3#4 { \tl_set:Nn \l_@@_tmp_unit_tl {#4} \@@_error_if_unit_not_defined:V \l_@@_tmp_unit_tl \bool_if:NTF \l_@@_convert_to_eV_bool { \@@_convert_to_eV: } { \keys_set_groups:nnn { cooking-units } { change-unit } {#1} \prop_get:NVN \l_@@_change_unit_prop \l_@@_tmp_unit_tl \l_@@_option_unit_tl \quark_if_no_value:NT \l_@@_option_unit_tl { \tl_set_eq:NN \l_@@_option_unit_tl \l_@@_tmp_unit_tl } \keys_set_filter:nnv { cooking-units } { change-unit } { l_@@_predefined_option_ \l_@@_option_unit_tl _clist } \keys_set_filter:nnn { cooking-units } { change-unit } {#1} } \bool_set_false:N \l_@@_special_sign_bool \bool_set_false:N \l_@@_error_bool \bool_set_false:N \l_@@_parse_range_bool } % \end{macrocode} % \end{macro} % % % \begin{macro}{ \@@_cunum_do_not_parse:nnn } % If the input shoudn't be parsed this function is used to print the % input without error messages (mostly concerning the \_). Spaces are still ignored. % \begin{macrocode} \cs_new:Npn \@@_cunum_do_not_parse:nnn #1#2#3 { \tl_set_rescan:Nnn \l_tmpa_tl { \char_set_catcode_letter:N \_ % \char_set_catcode_ignore:N \ % } {#1} \l_tmpa_tl \@@_cunum_print_correct_unit:nnn {#2} {#3} {#3} } % \end{macrocode} % \end{macro} % % \begin{macro}{ \@@_cunum:nnNN, \@@_cunum:nnVV } % 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{macrocode} \cs_new:Npn \@@_cunum:nnNN #1#2#3#4 { \tl_set_rescan:Nnn \l_tmpa_tl { \char_set_catcode_letter:N \_ % \char_set_catcode_ignore:N \ % \char_set_catcode_other:N ? % } {#1} \tl_if_empty:VF \l_tmpa_tl { \tl_if_in:NVT \l_tmpa_tl \l_@@_input_range_sign_tl { \tl_replace_once:NVn \l_tmpa_tl \l_@@_input_range_sign_tl { \q_@@_range } \bool_set_true:N \l_@@_parse_range_bool } \@@_cunum_parse_input:V \l_tmpa_tl } \@@_cunum_print_correct_unit:nnn {#2} {#3} {#4} } \cs_generate_variant:Nn \@@_cunum:nnNN { nnVV } % \end{macrocode} % \end{macro} % % \begin{macro}{ \@@_cunum_print_correct_unit:nnn } % The invisible space is added by a \lstinline|\phantom|, afterwards % \lstinline|value_unit_space_tl| is used (which is set to % \lstinline|\thinspace| by default) and if either special signs or % fractions are parsed the input-unit is printed else the converted % unit is. % \begin{macrocode} \cs_new:Npn \@@_cunum_print_correct_unit:nnn #1#2#3 { \tl_if_empty:nF {#1} { \phantom {#1} } \tl_use:N \l_@@_value_unit_space_tl \bool_if:nTF { \l_@@_fraction_in_input_bool || \l_@@_special_sign_bool } { \translate { #3 ( cu-unit ) } } { \translate { #2 ( cu-unit ) } } } % \end{macrocode} % \end{macro} % % % % % % \section {cukeys} % % \subsection {Define Keys} % % \begin{macro}{ \cudefinekeys } % Defining keys. % \begin{macrocode} \NewDocumentCommand \cudefinekeys { m m } { \bool_set_false:N \l_@@_single_key_bool \cukeys_define_keys_and_single_keys:nn {#1} {#2} } % \end{macrocode} % \end{macro} % % \begin{macro}{ \cudefinesinglekey } % Again, but with the boolean set to true. % \begin{macrocode} \NewDocumentCommand \cudefinesinglekey { m m } { \bool_set_true:N \l_@@_single_key_bool \cukeys_define_keys_and_single_keys:nn {#1} {#2} } % \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{macrocode} \cs_new:Npn \cukeys_define_keys_and_single_keys:nn #1#2 { \@@_error_if_unit_not_defined:n {#1} \tl_if_blank:nF {#2} { \clist_clear:N \l_tmpa_clist \prop_clear:N \l_tmpa_prop \bool_if:NTF \l_@@_single_key_bool { \@@_cukeys_parse_and_create_single_key:nn {#1} {#2} }{ \fp_set_eq:NN \l_tmpa_fp \c_one_fp \tl_set:Nn \l_@@_tmp_unit_tl {#1} \@@_cukeys_parse_and_create_keys:nn {#1} { {#1} { \c_one_fp } #2 } } } } % \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 \@@_cukeys_create_key_prop:n {#1} \@@_cukeys_define_keys:V \l_tmpa_clist } % \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{macrocode} \cs_new:Npn \@@_cukeys_parse_input: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:n {#1} \clist_put_right:Nn \l_tmpa_clist {#1} \prop_put:Nnx \l_tmpa_prop {#1} { \fp_eval:n { #2 / \l_tmpa_fp } } \@@_cukeys_parse_input:nn } % \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: % \texttt{kg}=\texttt{1} % \texttt{dag}=\texttt{100}, \texttt{g}=\texttt{1000} and \texttt{oz}= \texttt{35.27399}. % % For the next unit (\texttt{dag} in this case) a new property list is created, relation above % stored inside etc. The condition now is that \texttt{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 \texttt{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 \texttt{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{macrocode} \cs_new:Npn \@@_cukeys_create_key_prop:n #1 { \prop_clear:N \l_tmpb_prop \prop_put:NnV \l_tmpb_prop { Liste } \l_tmpa_clist \prop_put:NnV \l_tmpb_prop { prop } \l_tmpa_prop \prop_put:NnV \l_tmpb_prop { Erstes Ding } \l_@@_tmp_unit_tl \clist_map_inline:Nn \l_tmpa_clist { \prop_clear:c { l_@@_cukeys_ ##1 _prop } \prop_set_eq:cN { l_@@_cukeys_ ##1 _prop } \l_tmpb_prop \tl_set_eq:cN { l_@@_tmpa_ ##1 _tl } \c_one_fp \clist_map_inline:Nn \l_tmpa_clist { \prop_put:cnx { l_@@_cukeys_ ##1 _prop } {####1} { \fp_eval:n { \prop_item:Nn \l_tmpa_prop {####1} / \prop_item:Nn \l_tmpa_prop {##1} } } } } } % \end{macrocode} % \end{macro} % % \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. % \begin{macrocode} \cs_new:Npn \@@_cukeys_define_keys:N #1 { \clist_map_inline:Nn \l_tmpa_clist { \clist_put_right:Nn \l_@@_list_of_defined_keys_clist {##1} \keys_define:nn { cooking-units } { ##1 .choices:Vn = \l_tmpa_clist { \@@_cukeys_define_keys_and_single_key_aux:n {##1} } , ##1 / unknown .code:n= { \seq_set_split:Nnn \l_tmpa_seq { , } {#1} \msg_error:nnxxx { cooking-units } { key-choice-unknown } {##1} {####1} { \seq_use:Nnnn \l_tmpa_seq { ',' } { ',' } { ' ~ and ~ ' } } } , ##1 .default:n = {##1} , ##1 .groups:n = { change-unit } } } \clist_remove_duplicates:N \l_@@_list_of_defined_keys_clist } \cs_generate_variant:Nn \@@_cukeys_define_keys:N { V } % \end{macrocode} % \end{macro} % % \begin{macrocode} \cs_new:Npn \@@_cukeys_define_keys_and_single_key_aux:n #1 { \prop_get:cVN { l_@@_cukeys_#1_prop } \l_keys_choice_tl \l_tmpa_tl \tl_set:cV { l_@@_tmpa_ #1_tl } \l_tmpa_tl \prop_put:NnV \l_@@_change_unit_prop {#1} \l_keys_choice_tl } % \end{macrocode} % % % \begin{macrocode} \cs_new:Npn \@@_cukeys_parse_and_create_single_key:nn #1#2 { \tl_set_rescan:Nnn \l_tmpa_tl { \char_set_catcode_letter:N \# % \char_set_catcode_ignore:N\ % } { {#1} { \c_one_fp } #2 } \@@_cusinglekeys_parse_input:V \l_tmpa_tl \@@_cusinglekeys_create_key_prop:n {#1} \@@_cukeys_define_singlekey:nV {#1} \l_tmpa_clist } % \end{macrocode} % % \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:n {#1} \clist_put_right:Nn \l_tmpa_clist {#1} \tl_set:Nn \l_tmpa_tl {#2} \tl_replace_all:NVn \l_tmpa_tl \c_@@_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 { \prop_clear:c { l_@@_cukeys_ #1 _prop } \tl_set_eq:cN { l_@@_tmpa_ #1 _tl } \c_one_fp % \tl_set:cn { l_@@_tmpa_ #1 _tl } { \c_one_fp } \prop_put:cnV { l_@@_cukeys_ #1 _prop } { Liste } \l_tmpa_clist \prop_put:cnV { l_@@_cukeys_ #1 _prop } { prop } \l_tmpa_prop \prop_put:cnn { l_@@_cukeys_ #1 _prop } { Erstes Ding } {#1} \prop_map_inline:Nn \l_tmpa_prop { \prop_put:cnn { l_@@_cukeys_ #1 _prop } {##1} {##2} } } % \end{macrocode} % % \begin{macrocode} \cs_new:Npn \@@_cukeys_define_singlekey:nN #1#2 { \clist_put_right:Nn \l_@@_list_of_defined_keys_clist {#1} \keys_define:nn { cooking-units } { #1 .choices:Vn = \l_tmpa_clist { \@@_cukeys_define_keys_and_single_key_aux:n {#1} } , #1 / unknown .code:n= { \seq_set_split:Nnn \l_tmpa_seq { , } {#2} \msg_error:nnxxx { cooking-units } { key-choice-unknown } {#1} {##1} { \seq_use:Nnnn \l_tmpa_seq { ',' } { ',' } { ' ~ and ~ ' } } } , #1 .default:n = {#1} , #1 .groups:n = { change-unit } , } \clist_remove_duplicates:N \l_@@_list_of_defined_keys_clist } \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 \tl_set:Nn \l_tmpa_tl {#1} \tl_set:Nn \l_tmpb_tl {#2} \@@_cukeys_add_keys_or_single_keys:VV \l_tmpa_tl \l_tmpb_tl } % \end{macrocode} % % \begin{macrocode} \NewDocumentCommand \cuaddsinglekeys { m m } { \bool_set_true:N \l_@@_single_key_bool \tl_set:Nn \l_tmpa_tl {#1} \tl_set:Nn \l_tmpb_tl {#2} \@@_cukeys_add_keys_or_single_keys:VV \l_tmpa_tl \l_tmpb_tl } % \end{macrocode} % % \begin{macrocode} \NewDocumentCommand \cuaddtokeys { m m m } { \bool_set_false:N \l_@@_single_key_bool \tl_set:Nn \l_tmpa_tl {#1} \tl_set:Nn \l_tmpb_tl { {#2} { \fp_eval:n { \c_one_fp / #3 } } } \@@_cukeys_add_keys_or_single_keys:VV \l_tmpa_tl \l_tmpb_tl } % \end{macrocode} % % % % \begin{macrocode} \cs_new:Npn \@@_cukeys_add_keys_or_single_keys:nn #1#2 { \@@_error_if_unit_not_defined:n {#1} \clist_if_in:NnF \l_@@_list_of_defined_keys_clist {#1} { \msg_error:nnn { cooking-units } { Key - not - defined } {#1} } \tl_if_blank:nF {#2} { \@@_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:nn {#1} {#2} } } } \cs_generate_variant:Nn \@@_cukeys_add_keys_or_single_keys:nn { VV } % \end{macrocode} % % % \begin{macrocode} \cs_new:Npn \@@_cukeys_add_keys_and_single_key_aux:n #1 { \prop_get:cnN { l_@@_cukeys_ #1 _prop } { Liste } \l_tmpa_clist \prop_get:cnN { l_@@_cukeys_ #1 _prop } { prop } \l_tmpa_prop \prop_get:cnN { l_@@_cukeys_ #1 _prop } { Erstes Ding } \l_@@_tmp_unit_tl \prop_get:cVN { l_@@_cukeys_ #1 _prop } \l_@@_tmp_unit_tl \l_tmpa_fp } % \end{macrocode} % % % \section {Creating New Units} % % %\begin{macro}{ \newcookingunit } % \begin{macrocode} \NewDocumentCommand \newcookingunit { o m } { \@@_new_cooking_unit:nn {#1} {#2} } % \end{macrocode} %\end{macro} % % \begin{macrocode} \cs_new:Npn \@@_new_cooking_unit:nn #1#2 { \clist_if_in:NnTF \g_@@_list_of_defined_units_clist {#2} { \msg_error:nnn { cooking-units } { unit-already-defined } {#2} } { \clist_put_right:Nn \g_@@_list_of_defined_units_clist {#2} \tl_new:c { l_@@_tmpa_ #2 _tl } % \tl_set:cn { l_@@_tmpa_ #2 _tl } { \c_one_fp } \tl_set_eq:cN { l_@@_tmpa_ #2 _tl } \c_one_fp \clist_new:c { l_@@_predefined_option_#2_clist } \keys_define:nn { cooking - units } { set-option-for-#2 .clist_set:c = { l_@@_predefined_option_#2_clist } , add-option-for-#2 .code:n = { \clist_put_right:cn { l_@@_predefined_option_#2_clist } {##1} }, } \prop_new:c { l_@@_cukeys_ #2 _prop } \IfNoValueTF {#1} { \newtranslation { #2 ( cu-unit ) } {#2} }{ \newtranslation { #2 ( cu-unit ) } {#1} } } } % \end{macrocode} % % % % \section { cutext \& Cutext } % % \end{macro} % % \begin{macrocode} \NewDocumentCommand \cutext { O{} m m } { \group_begin: \@@_cutext_default:nnn {#1} {#2} {#3} \@@_cutext_print_correct_unitname:nn {#2} {#3} \group_end: } % \end{macrocode} % % \begin{macrocode} \NewDocumentCommand \Cutext { O{} m m } { \group_begin: \bool_set_true:N \l_@@_cutext_uppercase_word_bool \@@_cutext_default:nnn {#1} {#2} {#3} \@@_cutext_print_correct_unitname:nn {#2} {#3} \group_end: } % \end{macrocode} % % \begin{macro} { \@@_cutext_default:nnn } % \changes {2016/06/11} {0.98a} { New command } % \begin{macrocode} \cs_new:Npn \@@_cutext_default:nnn #1#2#3 { \@@_error_if_unit_not_defined:n {#3} \keys_set:nn { cooking-units } {#1} \bool_if:NT \l_@@_convert_to_eV_bool { \@@_convert_to_eV: } \bool_if:NTF \l_@@_parse_input_bool { \tl_set:Nn \l_tmpb_tl {#2} \tl_if_in:NVTF \l_tmpb_tl \l_@@_input_range_sign_tl { \tl_replace_once:NVn \l_tmpb_tl \l_@@_input_range_sign_tl { \q_@@_range } \@@_cutext_parse_range:Vn \l_tmpb_tl {#3} % \bool_set_true:N \l_@@_parse_range_bool }{ \@@_cutext_print_nummerical_output:Nn \l_tmpb_tl {#3} } } {#2} } % \end{macrocode} % \end{macro} % % \begin{macrocode} \cs_new:Npn \@@_cutext_parse_range:Nn #1 #2 { \@@_cutext_parse_range_aux:nww {#2} #1 \q_stop } \cs_generate_variant:Nn \@@_cutext_parse_range:Nn { V } \cs_new:Npn \@@_cutext_parse_range_aux:nww #1 #2 \q_@@_range #3 \q_stop { \tl_set:Nn \l_@@_tmpa_tl {#2} \tl_set:Nn \l_@@_tmpb_tl {#3} \@@_cutext_print_nummerical_output:Nn \l_@@_tmpa_tl {#1} \tl_use:N \l_@@_cutext_range_sign_tl \@@_cutext_print_nummerical_output:Nn \l_@@_tmpb_tl {#1} } % \end{macrocode} % % \begin{macrocode} \cs_new:Npn \@@_cutext_just_print_number_correctly:N #1 { \translatelet \l_tmpa_tl { decimal-mark ( cu-unit name ) } \tl_replace_once:NnV #1 { . } \l_tmpa_tl \tl_replace_once:NnV #1 { - } \c_@@_minus_tl #1 } % \end{macrocode} % % \begin{macro} {\@@_cutext_print_nummerical_output:N} % \changes {2016/06/11} {0.99} {New.} % \begin{macrocode} \cs_new_protected:Npn \@@_cutext_print_nummerical_output:Nn #1#2 { \bool_if:NTF \g_@@_load_if_opt_numeral_bool { \@@_if_integer_and_parse:VTF #1 { \fp_compare:nNnTF {#1} < { \l_@@_print_numerals_below_int } { \fp_compare:nNnTF {#1} = { \c_one_fp } { \translatelet \l_tmpa_tl { #2 (cu-unitgender) } \translatelet \l_tmpa_tl { one (\l_tmpa_tl) (cu-unitname) } \bool_if:NTF \l_@@_cutext_uppercase_word_bool { \exp_args:Nf \tl_to_uppercase:n { \tl_head:V \l_tmpa_tl } \tl_tail:V \l_tmpa_tl } { \l_tmpa_tl } }{ \bool_if:NTF \l_@@_cutext_uppercase_word_bool { \Numberstringnum {#1} } { \numberstringnum {#1} } } }{ \@@_cutext_just_print_number_correctly:N #1 } }{ \@@_cutext_just_print_number_correctly:N #1 } } { \@@_cutext_just_print_number_correctly:N #1 } } % \end{macrocode} % \end{macro} % % \begin{macrocode} \cs_new:Npn \@@_cutext_print_correct_unitname:nn #1#2 { \space \@@_if_integer_and_parse:nTF {#1} { \fp_compare:nNnTF {#1} = { \c_one_fp } { \translate { #2 (cu-unitname) } } { \translate { #2 (cu-unitname pl) } } }{ \translate { #2 (cu-unitname pl) } } } % \end{macrocode} % % % % \section {cufrac} % % Obsolete. % \begin{macrocode} \NewDocumentCommand \cufrac { O{} m } { \msg_error:nnnn { cooking-units } { obsolete-command } { \cufrac } { \cuam } \group_begin: \keys_set:nn { cooking-units } {#1} \@@_cufrac:n {#2} \group_end: } % \end{macrocode} % % \begin{macrocode} \cs_new:Npn \@@_cufrac:n #1 { \tl_set_rescan:Nnn \l_tmpa_tl { \char_set_catcode_letter:N \_ % \char_set_catcode_ignore:N\ % } {#1} \@@_cufrac_parse:V \l_tmpa_tl } % \end{macrocode} % % \begin{macrocode} \cs_new:Npn \@@_cufrac_parse:n #1 { \tl_if_in:nnTF {#1} { / } { \tl_if_in:nnTF {#1} { _ } { \@@_cufrac_parse_mixed_frac:www #1 \q_stop } { \@@_cufrac_parse_frac:ww #1 \q_stop } }{ \tl_if_in:nnTF {#1} { _ } { \msg_error:nnn { cooking-units } { missing-slash } {#1} } { \@@_cufrac_parse_scale:n {#1} } } } \cs_generate_variant:Nn \@@_cufrac_parse:n { V } % \end{macrocode} % % \begin{macrocode} \cs_new:Npn \@@_cufrac_parse_scale:n #1 {#1} % \end{macrocode} % % \begin{macrocode} \cs_new:Npn \@@_cufrac_parse_frac:ww #1/#2 \q_stop { \@@_frac:nn {#1} {#2} } % \end{macrocode} % % \begin{macrocode} \cs_new:Npn \@@_cufrac_parse_mixed_frac:www #1_#2/#3 \q_stop { #1 \hbox_to_wd:nn { \l_@@_mixed_frac_dim } { } \@@_frac:nn {#2} {#3} } % \end{macrocode} % % % \section{cuam} % % Replaces and extends \mycs{cufrac}. % \begin{macro}{\cuam} % \begin{macrcode} \NewDocumentCommand \cuam { O{} m } { \group_begin: \keys_set:nn { cooking-units } {#1} \@@_cuam:n {#2} \group_end: } % \end{macrcode} % \end{macro} % % \begin{macro}{\@@_cuam:n} % \begin{macrocode} \cs_new:Npn \@@_cuam:n #1 { \tl_set_rescan:Nnn \l_tmpa_tl { \char_set_catcode_letter:N \_ % \char_set_catcode_ignore:N\ % } {#1} \@@_cuam_parse:V \l_tmpa_tl } % \end{macrocode} % \end{macro} % % \begin{macrocode} \cs_new_protected:Npn \@@_cuam_parse:n #1 { \tl_if_in:nVTF {#1} \l_@@_input_range_sign_tl { \tl_set:Nn \l_tmpa_tl {#1} \tl_replace_once:NVn \l_tmpa_tl \l_@@_input_range_sign_tl { \q_@@_range } \@@_cuam_parse_range:V \l_tmpa_tl }{ \tl_if_in:nnTF {#1} { / } { \tl_if_in:nnTF {#1} { _ } { \@@_cuam_parse_mixed_frac:www #1 \q_stop } { \@@_cuam_parse_frac:ww #1 \q_stop } }{ \tl_if_in:nnTF {#1} { _ } { \msg_error:nnn { cooking-units } { missing-slash } {#1} } { \@@_cuam_parse_scale:n {#1} } } } } \cs_generate_variant:Nn \@@_cuam_parse:n { V } % \end{macrocode} % % \begin{macrocode} \cs_new:Npn \@@_cuam_parse_range:n #1 { \@@_cuam_parse_range_aux:ww #1 \q_nil } \cs_generate_variant:Nn \@@_cuam_parse_range:n { V } \cs_new:Npn \@@_cuam_parse_range_aux:ww #1 \q_@@_range #2 \q_nil { #1 \l_@@_cunum_range_sign_tl #2 } % \end{macrocode} % % % \begin{macrocode} \cs_new:Npn \@@_cuam_parse_scale:n #1 {#1} % \end{macrocode} % % \begin{macrocode} \cs_new:Npn \@@_cuam_parse_frac:ww #1/#2 \q_stop { \@@_frac:nn {#1} {#2} } % \end{macrocode} % % \begin{macrocode} \cs_new:Npn \@@_cuam_parse_mixed_frac:www #1_#2/#3 \q_stop { #1 \hbox_to_wd:nn { \l_@@_mixed_frac_dim } { } \@@_frac:nn {#2} {#3} } % \end{macrocode} % % \section {Names} % % % \begin{macrocode} \NewDocumentCommand \cudefinename { m m } { \tl_set:Nn \l_@@_language_tl {#1} \@@_cuname_parse_input:n #2 \q_recursion_tail \q_recursion_tail \q_recursion_stop } % \end{macrocode} % % % \begin{macrocode} \cs_new:Npn \@@_cuname_parse_input:n #1 { \peek_meaning_ignore_spaces:NTF [ { \@@_cuname_parse_unit_symbol:nw {#1} } { \@@_cuname_parse_input_aux:nn {#1} } } % \end{macrocode} % % \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:n {#1} % \deftranslation [ to=\l_@@_language_tl ] { #1 ( cu-unit ) } {#2} \@@_deftranslation:Vnn \l_@@_language_tl { #1 ( cu-unit ) } {#2} \@@_cuname_parse_input_aux:nn {#1} } % \end{macrocode} % % % \begin{macrocode} \cs_new:Npn \@@_cuname_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 } } \clist_if_in:NnF \g_@@_allowed_unit_phrases_clist {#1} { \@@_error_if_unit_not_defined:n {#1} } % \deftranslation [ to=\l_@@_language_tl ] { #1 (cu-unitname) } {#2} \@@_deftranslation:Vnn \l_@@_language_tl { #1 ( cu-unitname ) } {#2} \peek_meaning_ignore_spaces:NTF [ { \@@_cuname_parse_bracket:nw {#1} } { \@@_cuname_parse_bracket:nw {#1} [#2] } } % \end{macrocode} % % \begin{macrocode} \cs_new:Npn \@@_cuname_parse_bracket:nw #1 [#2] { % \deftranslation [ to=\l_@@_language_tl ] { #1 ( cu-unitname pl ) } {#2} \@@_deftranslation:Vnn \l_@@_language_tl { #1 ( cu-unitname pl ) } {#2} \peek_meaning_ignore_spaces:NTF < { \@@_cuname_parse_arrows:nw {#1} } { \@@_cuname_parse_arrows:nw {#1} } } % \end{macrocode} % % \begin{macrocode} \cs_new:Npn \@@_cuname_parse_arrows:nw #1 <#2> { % \deftranslation [ to=\l_@@_language_tl ] { #1 ( cu-unitgender ) } {#2} \@@_deftranslation:Vnn \l_@@_language_tl { #1 ( cu-unitgender ) } {#2} \@@_cuname_parse_input:n } % \end{macrocode} % % % % \subsection {cudefinesymbol} % % % \begin{macrocode} \NewDocumentCommand \cudefinesymbol { m m } { \tl_set:Nn \l_@@_language_tl {#1} \@@_cuprint_define_printed_unit:nn #2 \q_recursion_tail \q_recursion_tail \q_recursion_stop } % \end{macrocode} % % \begin{macrocode} \cs_new:Npn \@@_cuprint_define_printed_unit: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 } } \clist_if_in:NnF \g_@@_allowed_unit_phrases_clist {#1} { \@@_error_if_unit_not_defined:n {#1} } % \deftranslation [ to=\l_@@_language_tl ] { #1 ( cu-unit ) } {#2} \@@_deftranslation:Vnn \l_@@_language_tl { #1 ( cu-unit ) } {#2} \@@_cuprint_define_printed_unit:nn } % \end{macrocode} % % % % % % \subsection {cusetup} % % \begin{macrocode} \NewDocumentCommand \cusetup { m } { \keys_set:nn { cooking-units } {#1} } % \end{macrocode} % % % \begin{macrocode} \newcookingunit { kg } \newcookingunit { dag } \newcookingunit { g } \newcookingunit { oz } \newcookingunit { lb } \newcookingunit [ \ensuremath{ \@@_frac:nn { eV } { c^2 } } ] { eVc-2 } % \end{macrocode} % % \begin{macrocode} \newcookingunit [ \ensuremath{ {} ^ { \circ } } \kern-\scriptspace C ] { C } \newcookingunit { K } \newcookingunit [ \ensuremath{ {} ^ { \circ } } \kern-\scriptspace F ] { F } \newcookingunit [ \ensuremath{ {} ^ { \circ } } \kern-\scriptspace R\'{e} ] { Re } % \end{macrocode} % % \begin{macrocode} \newcookingunit { d } \newcookingunit { h } \newcookingunit { min } \newcookingunit { s } \newcookingunit [ \ensuremath{ \@@_frac:nn { \hbar } { eV } } ] { hbareV-1 } % \end{macrocode} % % \begin{macrocode} \newcookingunit { m } \newcookingunit { cm } \newcookingunit { dm } \newcookingunit { mm } \newcookingunit { in } \newcookingunit [ \ensuremath{ \@@_frac:nn { c\hbar } { eV } } ] { chbareV-1 } % \end{macrocode} % % \begin{macrocode} \newcookingunit { l } \newcookingunit { dl } \newcookingunit { cl } \newcookingunit { ml } \newcookingunit [ \ensuremath { \@@_frac:nn { c^3 \hbar^3 } { eV^3 } } ] { (chbareV-1)3 } % \end{macrocode} % % \begin{macrocode} \newcookingunit { cal } \newcookingunit { kcal } \newcookingunit { J } \newcookingunit { kJ } \newcookingunit { eV } % \end{macrocode} % % \begin{macrocode} \newcookingunit [ pinch ] { pn } \newcookingunit { EL } \newcookingunit { TL } \newcookingunit [ ssp. ] { ssp } %% saltspoonful \newcookingunit [ csp. ] { csp } %% coffeespoonful \newcookingunit [ dsp. ] { dsp } \newcookingunit [ Msp. ] { Msp } % \end{macrocode} % % % Notiz am mich: ueberall symbol dazugeben. % \begin{macrocode} \cudefinename { German } { { kg } { Kilogramm } < n > { dag } { Dekagramm } < n > { g } { Gramm } < n > { oz } { Unze } < f > { lb } { Pfund } < n > % \end{macrocode} % \begin{macrocode} { d } { Tag } [ Tage ] { h } { Stunde } [ Stunden ] < f > { min } { Minute } [ Minuten ] < f > { s } { Sekunde } [ Sekunden ] < f > % \end{macrocode} % \begin{macrocode} { C } { Grad \space Celsius } { K } { Kelvin } < n > { F } { Grad \space Fahrenheit } { Re } { Grad \space R\'{e}amur } % \end{macrocode} % \begin{macrocode} { m } { Meter } < n > { dm } { Dezimeter } < n > { cm } { Centimeter } < n > { mm } { Millimeter } < n > { in } { Zoll } % \end{macrocode} % \begin{macrocode} { l } [ l ] { Liter } { dl } { Deziliter } { cl } { Centiliter } { ml } { Milliliter } % \end{macrocode} % \begin{macrocode} { cal } { Kalorie } [ Kalorien ] < f > { kcal } { Kilokalorie } [ Kilokalorien ] < f > { J } { Joule } { kJ } { Kilojoule } { eV } { Elektronenvolt } < n > % \end{macrocode} % \begin{macrocode} { Msp } [ Msp. ] { Messerspitze } [ Messerspitzen ] < f > { pn } [ Prise ] { Prise } [ Prisen ] < f > { EL } [ EL ] { Essl{\"o}ffel } { TL } [ TL ] { Teel{\"o}ffel } { csp } [ KL ] { Mokkal{\"o}ffel } % \end{macrocode} % \begin{macrocode} { decimal-mark } { , } { one (m) } { ein } { one (f) } { eine } { one (n) } { ein } } % \end{macrocode} % % % \begin{macrocode} \cudefinename { English } { { kg } { kilogramme } { dag } { decagramme } { g } { gramme } { oz } { ounce } { lb } { pound } [ pounds ] % \end{macrocode} % \begin{macrocode} { d } { day } [ days ] { h } { hour } [ hours ] { min } { minute } [ minutes ] { s } { second } [ seconds ] % \end{macrocode} % \begin{macrocode} { C } { degree \space Celsius } [ degrees \space Celsius ] { F } { degree \space Fahrenheit } [ degrees \space Fahrenheit ] { K } { kelvin } { Re } { degree \space R\'{e}aumur } [ degrees \space R\'{e}aumur ] % \end{macrocode} % \begin{macrocode} { m } { metre } [ metres ] { dm } { decimetre } [ decimetres ] { cm } { centimetre } [ centimetres ] { mm } { millimitre } [ millimitres ] { in } { inch } [ inches ] % \end{macrocode} % \begin{macrocode} { l } [ \ensuremath { \ell } ] { litre } [ litres ] { dl } { decilitre } [ decilitres ] { cl } { centilitre } [ centilitres ] { ml } { millilitre } [ millilitres ] % \end{macrocode} % \begin{macrocode} { cal } { calorie } [ calories ] { kcal } { kilocalorie } [ kilocalories ] { J } { joule } [ joules ] { kJ } { kilojoule } [ kilojoules ] { eV } { electron \space volt } % \end{macrocode} % \begin{macrocode} % { Msp } [ pinch ] { pinch } [ pinches ] { Msp } { Messerspitze } [ Messerspitzen ] { pn } [ pinch ] { pinch } [ pinches ] { EL } [ tsp. ] { tablespoon } [ tablespoons ] { TL } [ tbsp. ] { teaspoon } [ teaspoons ] { dsp } { dessertspoonful } { csp } { coffeespoonful } { ssp } { saltspoonful } % \end{macrocode} % \begin{macrocode} { decimal-mark } { . } { one (m) } { one } { one (f) } { one } { one (n) } { one } } % \end{macrocode} % % \begin{macrocode} \cudefinename { AmericanEnglish } { { kg } { kilogram } { dag } { decagram } { g } { gram } { oz } { ounce } % \end{macrocode} % \begin{macrocode} { m } { meter } [ meters ] { dm } { decimeter } [ decimeters ] { cm } { centimeter } [ centimeters ] { mm } { millimiter } [ millimiters ] { in } { inch } [ inches ] % \end{macrocode} % \begin{macrocode} { l } [ \ensuremath { \ell } ] { liter } [ liters ] { dl } { deciliter } [ deciliters ] { cl } { centiliter } [ centiliters ] { ml } { milliliter } [ milliliters ] % \end{macrocode} % \begin{macrocode} { Msp } { Messerspitze } [ Messerspitzen ] { pn } [ pn. ] { pinch } [ pinches ] } % \end{macrocode} % % % \begin{macrocode} \cudefinename { French } { { kg } { kilogramme } [ kilogrammes ] { dag } { d\'{e}cagramme } [ d\'{e}cagrammes] { g } { gramme } [ gramme ] { oz } { once } < f > { lb } { livre } [ livres ] < f > % \end{macrocode} % \begin{macrocode} { d } { jour } [ jours ] { h } { heure } [ heures ] < f > { min } { minute } [ minutes ] < f > { s } { seconde } [ secondes ] < f > % \end{macrocode} % \begin{macrocode} { C } { degr\'{e} \space Celsius } [ degr\'{e}s \space Celsius ] { K } { degr\'{e} \space Fahrenheit } [ degr\'{e}s \space Fahrenheit ] { F } { kelvin } [ kelvins ] { Re } { \'{e}chelle \space R\'{e}aumur } [ degr\'{e}s \space R\'{e}aumur ] % \end{macrocode} % \begin{macrocode} { m } { m\`{e}tre } [ m\`{e}tres ] { dm } { d\'{e}cim\`{e}tre } [ d\'{e}cim\`{e}tres ] { cm } { centim\`{e}tre } [ centim\`{e}tres ] { mm } { millim\`{e}tre } [ millim\`{e}tre ] % \end{macrocode} % \begin{macrocode} { l } [ L ] { litre } [ litres ] { dl } [ dL ] { d\'{e}cilitre } [ d\'{e}cilitres ] { cl } [ cL ] { centilitre } [ centilitres ] { ml } [ mL ] { millilitre } [ millilitres ] % \end{macrocode} % \begin{macrocode} { cal } { calorie } [ calorie ] { kcal } { kilocalorie } [ kilocalories ] { J } { joule } [ joules ] { kJ } { kilojoule } [ kilojoules ] { eV } { \'{e}lectron-volt } [ \'{e}lectron-volts ] % \end{macrocode} % \begin{macrocode} { pn } { pinc\'{e}e } < f > { EL } { cuill\'{e}re \space \`{a} \space soupe } < f > { TL } { cuill\'{e}re \space \`{a} \space caf\'{e} } < f > % \end{macrocode} % \begin{macrocode} { decimal-mark } { . } { one (m) } { un } { one (f) } { une } { one (n) } { un } } % \end{macrocode} % % % % \begin{macrocode} \cudefinekeys { kg } { { dag }{ 100 } { g } { 1000 } { oz } { 35.27399 } { lb } { 2.204 622 6 } %% 2.204 622 6 { eVc-2 } { 560958865.0e+27 } %% 560958865.0 +- 3.5 e+27 } %\cuaddtokeys { kg } { eVc-2 } { 1.78266173e-16 } % \end{macrocode} % \begin{macrocode} \cudefinekeys { d } { { h } { 24 } { min }{ 1440 } { s } { 86400 } { hbareV-1 } { 151926746.1e+7 * 86400 } %% 151926746.1 +- 2.1 e+7 } %\cuaddtokeys { s } { hbareV-1 } { 6.582119514e-16 } % \end{macrocode} % \begin{macrocode} \cudefinekeys { m } { { dm } { 10 } { cm } { 100 } { mm } { 1000 } { in } { 39.370079 } { chbareV-1 } { 5067730.759 } %% 5067730.759 +- 0.070 } %\cuaddtokeys { m } { chbareV-1 } { 1.97326972e-7 } % \end{macrocode} % \begin{macrocode} \cudefinekeys { l } { { dl } { 10 } { cl } { 100 } { ml }{ 1000 } { (chbareV-1)3 } { 130148929.5e+12 * 1e-3 } %% (130148929.5 +- 5.4 e+12)*1e-3 } % \end{macrocode} % \begin{macrocode} \cudefinekeys { J } { { kJ }{ 1e-3 } { cal }{ 0.2388459 } { kcal }{ 0.2388459e-3 } { eV }{ 624150912.6e+10 } %% 624150912.6 +- 3.9 e+10 } %\cuaddtokeys { J } { eV } { 1.6021766208e-19 } % \end{macrocode} % \begin{macrocode} \fp_const:Nn \c_@@_kb_eV_fp { 8.617 330 3 e-5 } \cudefinesinglekey { C } { { K } { #1 + 273.15 } { F } { #1 * 1.8 + 32 } { Re } { #1 * 0.8 } { eV } { ( #1 + 273.15 ) * \c_@@_kb_eV_fp } } \cudefinesinglekey { F } { { C } { ( #1 - 32 ) * 5/9 } { K } { ( #1 + 459.67 ) * 5/9 } { Re } { ( #1 - 32 ) * 4/9 } { eV } {( #1 + 459.67 ) * 5/9 * \c_@@_kb_eV_fp } } \cudefinesinglekey { K } { { C } { #1 - 273.15 } { F } { #1 * 1.8 - 459.67 } { Re } { ( #1 - 273.15 ) * 0.8 } { eV } { #1 * \c_@@_kb_eV_fp } } \cudefinesinglekey { Re } { { K } { #1 * 1.25 + 273.15 } { C } { #1 * 1.25 } { F } { #1 * 2.25 + 32 } { eV } { ( #1 * 1.25 + 273.15 ) * \c_@@_kb_eV_fp } } % \end{macrocode} % % % \begin{macrocode} %\fp_const:Nn \c_@@_K_min_fp { 0 } %\fp_const:Nn \c_@@_C_min_fp { -273.15 } %\fp_const:Nn \c_@@_F_min_fp { -459.67 } %\fp_const:Nn \c_@@_Re_min_fp { -218.52 } % \end{macrocode} % % % % \subsection{Finish} % % \begin{macrocode} \cusetup { set-option-for-F = { round-to-int = true } , set-option-for-C = { round-to-int = true } , set-option-for-K = { round-to-int = true } , set-option-for-Re = { round-to-int = true } , add-temperature-to-check = { K = 0, C = -273.15 , F = -459.67 , Re = -218.52 } , } % \end{macrocode} % % \begin{macrocode} % % \end{macrocode} % % \end{implementation} % % \endinput % % % % % Local Variables: % mode: doctex % TeX-master: t % End: