From 5cb65e963600d41f6c7dfb5161fa72448479d048 Mon Sep 17 00:00:00 2001 From: Karl Berry Date: Wed, 3 Feb 2016 22:58:23 +0000 Subject: smartunits (3feb16) git-svn-id: svn://tug.org/texlive/trunk@39556 c570f23f-e606-0410-a88d-b1316a301751 --- Master/texmf-dist/doc/latex/smartunits/README.md | 53 +++ .../texmf-dist/doc/latex/smartunits/smartunits.pdf | Bin 0 -> 331493 bytes .../texmf-dist/doc/latex/smartunits/smartunits.tex | 415 +++++++++++++++++++++ .../texmf-dist/tex/latex/smartunits/smartunits.sty | 163 ++++++++ Master/tlpkg/bin/tlpkg-ctan-check | 2 +- Master/tlpkg/tlpsrc/collection-latexextra.tlpsrc | 1 + Master/tlpkg/tlpsrc/smartunits.tlpsrc | 0 7 files changed, 633 insertions(+), 1 deletion(-) create mode 100644 Master/texmf-dist/doc/latex/smartunits/README.md create mode 100644 Master/texmf-dist/doc/latex/smartunits/smartunits.pdf create mode 100644 Master/texmf-dist/doc/latex/smartunits/smartunits.tex create mode 100644 Master/texmf-dist/tex/latex/smartunits/smartunits.sty create mode 100644 Master/tlpkg/tlpsrc/smartunits.tlpsrc (limited to 'Master') diff --git a/Master/texmf-dist/doc/latex/smartunits/README.md b/Master/texmf-dist/doc/latex/smartunits/README.md new file mode 100644 index 00000000000..1942639f661 --- /dev/null +++ b/Master/texmf-dist/doc/latex/smartunits/README.md @@ -0,0 +1,53 @@ +smartunits +========== + +A [LaTeX](http://en.wikipedia.org/wiki/LaTeX) package that implements +automatic conversions between (some) metric and Imperial units. + +Example +------- + +```tex +\documentclass{article} +\usepackage{smartunits} +\begin{document} + \SmartUnitSettings{metric imperial, places=1} + \SmartUnit{cm=10} % 10 cm (4') + \SmartUnit{celsius=20} % 20 C (43 F) + \SmartUnit{miles=5} % 8 km (5 mi) + \SmartUnit{miles=5, precision=1} % 8.0 km (5 mi) + \SmartUnit{miles=5, km=7} % 7 km (5 mi) +\end{document} +``` + +Units supported +--------------- + +Currently smartunits converts between the following five classes of units: + + ============ ============== + Metric Imperial + ------------ -------------- ------------- + kilometers miles (distance) + centimeters feet and inches (length) + Celsius Fahrenheit (temperature) + 24-hour time 12-hour time (time) + litres USA/UK gallons (volume) + kilograms pounds (weight) + ============ ============== ============= + +It is quite easy to extend the code to other units. I am happy to consider new requests. + +Requirements +------------ + +The package requires +[pgfkeys](https://www.ctan.org/pkg/pgfkeys) and +[siunitx](https://www.ctan.org/pkg/siunitx). + +### Author + +Copyright (c) 2016 [Andrew Mathas](mailto:andrew.mathas@gmail.com) + +Released under the [LaTeX Project Public +License](http://www.latex-project.org/lppl.txt) v1.3c or later diff --git a/Master/texmf-dist/doc/latex/smartunits/smartunits.pdf b/Master/texmf-dist/doc/latex/smartunits/smartunits.pdf new file mode 100644 index 00000000000..eb81116ba63 Binary files /dev/null and b/Master/texmf-dist/doc/latex/smartunits/smartunits.pdf differ diff --git a/Master/texmf-dist/doc/latex/smartunits/smartunits.tex b/Master/texmf-dist/doc/latex/smartunits/smartunits.tex new file mode 100644 index 00000000000..78c23ee12a0 --- /dev/null +++ b/Master/texmf-dist/doc/latex/smartunits/smartunits.tex @@ -0,0 +1,415 @@ +\documentclass[svgnames]{report} +\usepackage{smartunits} +\usepackage{manfnt} +\usepackage{enumitem} +\setlist[description]{font=\sffamily\bfseries\color{DodgerBlue},labelwidth=\textwidth} +\usepackage{booktabs} +\usepackage[a4paper,margin=18mm]{geometry} +\synctex=1 + +\usepackage{fixltx2e} % LaTeX patches, \textsubscript +\usepackage{cmap} % fix search and cut-and-paste in Acrobat +\usepackage[T1]{fontenc} +\usepackage[utf8]{inputenc} +\setcounter{secnumdepth}{0} + +\usepackage{listings}\lstset{language=[LaTeX]TeX,framerule=2pt} +\lstset{language=[LaTeX]TeX, + texcsstyle=*\bfseries\color{Blue}, + backgroundcolor=\color{Ivory}, + numbers=none, + breaklines=true, + keywordstyle=\color{Blue}, + commentstyle=\color{Brown}, + tabsize=2, + morekeywords={SmartUnit,SmartUnitSettings,sisetup}, + resetmargins=true, +} +% hyperref links to ctan +\newcommand\ctan[1]{\href{https://www.ctan.org/pkg/#1}{\texttt{#1}}} + +\usepackage{xparse} +\NewDocumentCommand{\Verb}{v}{{\color{blue}#1}} + +\newcommand\Section[1]{\subsection{\textcolor{blue}{#1}}} + +\makeatletter +\author{Andrew Mathas} +\usepackage{tikz} +\usetikzlibrary{shadows.blur} +\tikzset{shadowed/.style={blur shadow={shadow blur steps=5}, + bottom color=LightSkyBlue!30, + draw=MidnightBlue!70,shade, + font=\normalfont\Huge\bfseries\scshape, + rounded corners=8pt, + top color=SkyBlue, + }, + boxes/.style={draw=MidnightBlue, + fill=Cornsilk, + font=\sffamily\small, + inner sep=5pt, + rectangle, + rounded corners=8pt, + text=RoyalBlue, + } +} +\def\SmartTitle{ + \begin{tikzpicture}[remember picture,overlay] + \node[yshift=-3cm] at (current page.north west) + {\begin{tikzpicture}[remember picture, overlay] + \draw[shadowed](30mm,0) rectangle node[white]{Smart Units} (\paperwidth-30mm,16mm); + \node[anchor=west,boxes] at (4cm,0cm) {\@author}; + \node[anchor=east,boxes] at (\paperwidth-4cm,0) {\smart@version}; + \end{tikzpicture} + }; + \end{tikzpicture} + \vspace*{20mm} +} + + +\def\@oddfoot{\textsc{Smart Units} -- \smart@version\hfill\thepage} + +\usepackage[colorlinks=true,linkcolor=blue,urlcolor=blue]{hyperref} +\hypersetup{pdfcreator={ Generated by pdfLaTeX }, + pdfinfo={Author ={ Andrew Mathas }, + Keywords={ units, metric, Imperial }, + License ={ LaTeX Project Public License v1.3c or later }, + Subject ={ Convert between metric and Imperial units }, + Title ={ smartunits - \smart@version } + }, +} +\makeatother + +\begin{document} + + \SmartTitle + + %\Section{Smart units} + This package implements a \Verb|\SmartUnit| macro for + converting between the following metric and Imperial units: + + \begin{center} + \begin{tabular}{@{\color{Grey!50}}ll@{\quad$\longleftrightarrow$\quad}l}\toprule + & Metric & Imperial \\\midrule + \color{LightSkyBlue}distance & kilometers & miles \\ + \color{LightSkyBlue}length & centimeters & feet and inches \\ + \color{LightSkyBlue}temperature & Celsius & Fahrenheit \\ + \color{LightSkyBlue}time & 24-hour time& 12-hour time \\ + \color{LightSkyBlue}volume & litres & USA/UK gallons \\ + \color{LightSkyBlue}weight & kilograms & pounds \\ + \bottomrule + \end{tabular} + \end{center} + Of course, the underlying unit for length and distance is the same + but it makes sense to convert between units of similar ``scale''. + The \Verb|\SmartUnit| macro is designed to print only one unit at a + time, where the quantity is given in terms of either metric or + Imperial units (there is no error checking, however). Depending on + the (global) settings the unit will be printed either as a metric + unit, or as an Imperial unit, or both. If the required unit is not + given as an argument to \Verb|\SmartUnit| then it is computed. The + units are printed using \ctan{siunitx}, so the formatting of the + units can be controlled using \Verb|\sisetup| together with + formatting parameters from \ctan{siunitx}. Some aspects of the + formatting can be controlled ``locally'' using \Verb|\SmartUnit| and + ``globally'' using \Verb|\SmartUnitSettings|. + + The \Verb|\SmartUnit| macro can print units in the following + four different formats: + + \begin{lstlisting} + \SmartUnit{metric} % --> metric + \SmartUnit{imperial} % --> Imperial + \SmartUnit{metric imperial} % --> metric (Imperial) + \SmartUnit{imperial metric} % --> Imperial (metric) + \end{lstlisting} + + For the impatient, here are some examples: + + \bgroup + \sisetup{round-mode=places,round-precision=2} + \small + \begin{lstlisting}[escapeinside=<>] + \documentclass{article} + \usepackage{smartunits} + \begin{document} + \SmartUnitSettings{places=2} % Some global settings < \SmartUnitSettings{places=2} > + \SmartUnit{metric imperial} % Output format: metric (Imperial) < \SmartUnit{metric imperial} > + \SmartUnit{cm=10} % < \SmartUnit{cm=10} > + \SmartUnit{feet=4,inches=3} % < \SmartUnit{feet=4,inches=3} > + \SmartUnit{celsius=20} % < \SmartUnit{celsius=20} > + \SmartUnit{metric} % Output format: metric < \SmartUnit{metric} > + \SmartUnit{miles=5, places=1} % < \SmartUnit{miles=5,places=1} > + \SmartUnit{imperial} % Output format: Imperial < \SmartUnit{imperial} > + \SmartUnit{hours=12, minutes=1} % < \SmartUnit{hours=12, minutes=1} > + \SmartUnit{km=5,places=3} % < \SmartUnit{km=5,places=3} > + \SmartUnit{imperial metric} % Output format: Imperial (metric) < \SmartUnit{imperial metric} > + \SmartUnit{miles=5, km=7} % < \SmartUnit{miles=5,km=7} > + \SmartUnit{l=1.0, places=1} % < \SmartUnit{l=1.0, places=1} > + \SmartUnit{L=1.0, places=1} % < \SmartUnit{L=1.0, places=1} > + \SmartUnit{gal=25.0,uk,places=2} % < \SmartUnit{gal=25.0, places=2,uk} > + \SmartUnit{gal=25.0,usa,places=2} % < \SmartUnit{gal=25.0, places=2,usa} > + \end{document} + \end{lstlisting} + \egroup + + The calculations done by \Verb|\SmartUnit| are reasonably accurate + but LaTeX is not a calculator so rounding and other errors can and + do happen (indeed, see the displayed example below). In addition, even assuming + that the calculations done by \Verb|\SmartUnit| are accurate this + may not be what you want. For example, if the metric unit is given + as \SI{100}{km} then many people will want the Imperial unit to be + written as \SI{60}{\text{mi}}, rather than the more accurate + \SI{62.137119}{\text{mi}}. In fact, \Verb|\SmartUnit| can cater for + these considerations because all units are printed using the + \ctan{siunitx} package, which is really clever. The precision of the + printed units can be controlled using \Verb|\sisetup|, from the + \ctan{siunitx} package or by using the short-hands, \textsf{figures} + and \textsf{places}, provided by \Verb|\SmartUnit|: + \begin{lstlisting}[texcl] + \SmartUnit{km=100.0, figures=1} % \SmartUnit{km=100.0,figures=1} + \SmartUnit{km=100.0, places=5} % \SmartUnit{km=100.0,places=5} + \end{lstlisting} + \noindent (Comparing with the paragraph above, the last calculation + is only accurate to three decimal places!) The values of the + computed units can be overridden, during proof-reading for example, + by specifying both the metric and Imperial units: + \begin{lstlisting}[texcl] + \SmartUnit{km=100,miles=70} % \SmartUnit{km=100,miles=70} + \end{lstlisting} + \noindent \raisebox{3.9mm}{\dbend}\quad Of course, if you specify + units incorrectly like this then incorrect values will be printed. + + Behind the scenes all units are printed using \ctan{siunitx}. Therefore, + the precision and formatting of the units can be changed using the + options to \Verb|\sisetup| described in the \ctan{siunitx}\ manual. In + particular, when the rounding capabilities of~\ctan{siunitx}\ are enabled + any units calculated by \Verb|\SmartUnit| will be rounded. + In this case there is a shorthand for overriding the global + \ctan{siunitx}\ settings for the rounding precision on an individual + ``smart unit'': + + \begin{lstlisting}[escapeinside=<>] + % Locally=\sisetup{round-precision=3, round-mode=places} + \SmartUnit{cm=2, places=3} % < \SmartUnit{cm=2, places=3} > + \end{lstlisting} + + Section~5.5 of the \ctan{siunitx}\ manual should be consulted for all of the + options for controlling ``post-processing'' of numbers. In particular, + units that are given as integers will always be printed as integers. + For example, the metric version of \Verb|\SmartUnit{cm=2, places=3}| + is printed as \SmartUnit{cm=2, places=3, metric} whereas the Imperial version is + \num{0.787}$'$. If, instead, we use + \Verb|\SmartUnit{cm=2.0, places=3}| then the metric unit is + printed as \SmartUnit{cm=2.0, places=3, metric}. + + + \Section{Unit conversions} + For all of these examples we use the following global settings: + \begin{lstlisting}[texcl] + \SmartUnitSettings{places=2, metric imperial} % Global settings + \end{lstlisting} + \SmartUnitSettings{places=2, metric imperial} + \noindent Of course, as in some of the example below, this can always be overridden locally. + + \begin{description} + \item[Distance -- km, miles, mi] + Conversions between kilometers and miles. Miles can be specified + using either \textbf{miles} or \textbf{mi}. + \begin{lstlisting}[texcl] + \SmartUnit{km=100,miles=60} % \SmartUnit{km=100,miles=60} + \SmartUnit{km=100.0,figures=1} % \SmartUnit{km=100,figures=1} + \SmartUnit{miles=62.15,places=1} % \SmartUnit{miles=62.15,places=1} + \end{lstlisting} + + \item[Length -- cm, inches, feet] + \begin{lstlisting}[texcl] + \SmartUnit{feet=7, inches=1} % \SmartUnit{feet=7, inches=1} + \SmartUnit{cm=189, feet=7, inches=1} % \SmartUnit{cm=189, feet=7, inches=1} + \SmartUnit{cm=191, places=1} % \SmartUnit{cm=191, places=1} + \end{lstlisting} + + \item[Temperature -- celsius, fahrenheit] + \begin{lstlisting}[texcl] + \SmartUnit{celsius=32,places=3} % \SmartUnit{celsius=32,places=3} + \SmartUnit{celsius=0} % \SmartUnit{celsius=0} + \SmartUnit{fahrenheit=0} % \SmartUnit{fahrenheit=0,places=2} + \end{lstlisting} + + \item[Time -- hours, minutes, seconds, am, pm] + \begin{lstlisting}[texcl] + \SmartUnit{hours=0, minutes=59} % \SmartUnit{hours=0, minutes=59} + \SmartUnit{hours=12, minutes=12} % \SmartUnit{hours=12, minutes=12} + \SmartUnit{hours=13, minutes=9} % \SmartUnit{hours=13, minutes=9} + \SmartUnit{hours=8, minutes=31, pm} % \SmartUnit{hours=8, minutes=31, pm} + \SmartUnit{hours=9, minutes=3, am} % \SmartUnit{hours=9, minutes=3, am} + \SmartUnit{hours=0, minutes=0,seconds=1} % \SmartUnit{hours=0, minutes=0,seconds=1} + \SmartUnit{hours=12, minutes=0,seconds=1} % \SmartUnit{hours=12, minutes=0,seconds=1} + \end{lstlisting} + + \item[Volume -- L, l, gal, gallons] + Converting between litres and gallons. Liters can be specified + using \textbf{L} or \textbf{l} and gallons can be given with + \textbf{gallons} or \textbf{gal}. Both UK gallons and USA + gallons are supported, with USA gallons being the default. + \begin{lstlisting}[texcl] + \SmartUnit{l=10.0, places=1} % \SmartUnit{l=10.0, places=1} + \SmartUnit{L=10.0, places=1,uk} % \SmartUnit{L=10.0, places=1,uk} + \SmartUnit{gal=10.0, places=2} % \SmartUnit{gal=10.0, places=2} + \end{lstlisting} + + \item[Weight -- kg, pounds, lbs] + \begin{lstlisting}[texcl] + \SmartUnit{kg=10.0, places=1} % \SmartUnit{kg=10.0, places=1} + \SmartUnit{pound=10.0, places=1} % \SmartUnit{pound=10.0, places=1} + \SmartUnit{pound=10.0,figures=1} % \SmartUnit{pound=10.0,figures=1} + \end{lstlisting} + \end{description} + + \Section{Formatting options} + + The following options can either be used inside \Verb|\SmartUnit| to + control the formatting \textit{locally} for just the unit being + printed. They can also be used as arguments to + \Verb|\SmartUnitSettings| to change the formatting of all subsequent + smart units (unless these settings are overridden locally). More + control over the formatting of the units is given by the + \Verb|\sisetup| macro from the \ctan{siunitx} package. + + \begin{description} + \item[figures] This is equivalent to \Verb|\sisetup{round-mode=figures, precision=#1}|. All units are printed + with \#1 significant figures. + \begin{lstlisting}[texcl] + \SmartUnit{miles=60, metric, figures=0} % \SmartUnit{miles=60, metric, figures=0} + \SmartUnit{miles=60, metric, figures=1} % \SmartUnit{miles=60, metric, figures=1} + \SmartUnit{miles=60, metric, figures=2} % \SmartUnit{miles=60, metric, figures=2} + \SmartUnit{miles=60, metric, figures=3} % \SmartUnit{miles=60, metric, figures=3} + \SmartUnit{miles=60, metric, figures=4} % \SmartUnit{miles=60, metric, figures=4} + \end{lstlisting} + + \item[places] + This is equivalent to \Verb|\sisetup{round-mode=figures, precision=#1}|. All units are printed + with \#1 significant figures. + \begin{lstlisting}[texcl] + \SmartUnit{miles=60, metric, places=0} % \SmartUnit{miles=60, metric, places=0} + \SmartUnit{miles=60, metric, places=1} % \SmartUnit{miles=60, metric, places=1} + \SmartUnit{miles=60, metric, places=2} % \SmartUnit{miles=60, metric, places=2} + \SmartUnit{miles=60, metric, places=3} % \SmartUnit{miles=60, metric, places=3} + \SmartUnit{miles=60, metric, places=4} % \SmartUnit{miles=60, metric, places=4} + \end{lstlisting} + + + \item[imperial] + Print only Imperial units. + \begin{lstlisting}[texcl] + \SmartUnit{km=1.0, imperial} % \SmartUnit{km=1.0, imperial, figures=2} + \SmartUnit{miles=1.0, imperial} % \SmartUnit{miles=1.0, imperial, figures=2} + \end{lstlisting} + \item[imperial metric] + Print Imperial units with metric units enclosed in brackets. + \begin{lstlisting}[texcl] + \SmartUnit{km=1.0, imperial metric} % \SmartUnit{km=1.0, imperial metric, figures=2} + \SmartUnit{miles=1.0, imperial metric} % \SmartUnit{miles=1.0, imperial metric, figures=2} + \end{lstlisting} + \item[metric (default)] + Print only metric units. + \begin{lstlisting}[texcl] + \SmartUnit{km=1.0, metric} % \SmartUnit{km=1.0, metric, figures=2} + \SmartUnit{miles=1.0, metric} % \SmartUnit{miles=1.0, metric, figures=2} + \end{lstlisting} + \item[metric imperial] + Print metric units with Imperial units enclosed in brackets. + \begin{lstlisting}[texcl] + \SmartUnit{km=1.0, metric imperial} % \SmartUnit{km=1.0, metric imperial, figures=2} + \SmartUnit{miles=1.0, metric imperial} % \SmartUnit{miles=1.0, metric imperial, figures=2} + \end{lstlisting} + \item[uk] + Selects the UK variants of the Imperial units (currently this + only affects gallons): + \begin{lstlisting}[texcl] + \SmartUnit{l=1.0, imperial metric, figures=2,uk} % \SmartUnit{l=1.0, imperial metric, figures=2,uk} + \SmartUnit{gal=1.0, imperial metric, figures=2,uk} % \SmartUnit{gal=1.0, imperial metric, figures=2,uk} + \end{lstlisting} + \item[usa (default)] + Selects the USA variants of the Imperial units (currently this + only affects gallons): + \begin{lstlisting}[texcl] + \SmartUnit{l=1.0, imperial metric, figures=2,usa} % \SmartUnit{l=1.0, imperial metric, figures=2,usa} + \SmartUnit{gal=1.0, imperial metric, figures=2,usa} % \SmartUnit{gal=1.0, imperial metric, figures=2,usa} + \end{lstlisting} + By default \Verb|\SmartUnit| uses the American Imperial units. + This is a purely democratic choice dictated by the populations + of the two countries. + \end{description} + + \Section{The code} + Behind the scenes, the \Verb|\SmartUnit| macro uses \ctan{pgfkeys} and + \ctan{pgfmath} to convert between the different units. The interface is + surprisingly simple and easy to extend. For example, the following + code takes care of the conversion between kilometers and miles: + \bgroup\footnotesize + \begin{lstlisting} + %%%% convert=distance: km <-> miles %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + km/.style={convert=distance, unit km=#1},% + mi/.style={convert=distance, unit miles=#1},% + miles/.style={convert=distance, unit miles=#1},% + distance/metric/.style={/SmartUnit/conversion={km}{miles}{0}{1.609344}{0}{km}},% + distance/imperial/.style={/SmartUnit/conversion={miles}{km}{0}{0.62137119}{0}{\text{mi}}},% + \end{lstlisting} + \egroup + \noindent + Most of the conversions are done in this way --- the exceptions are + ``length'' and ``time'', which are more complicated. The key + \Verb|/SmartUnit/conversion| is a macro that takes six arguments and + then implements the generic conversion formula: + \[ + \text{New unit}(\Verb|#1|) = \Big(\text{Old unit}(\Verb|#2)|+\text{Pre-offset}(\Verb|#3|)\Big)*\text{Multiplier}(\Verb|#4|) + \text{Post-offset}(\Verb|#5|), + \] + where \Verb|#6| is the metric or Imperial symbol for the unit being + printed. + + \textit{Adding additional conversions is quite straightforward and I am + happy to incorporate suggestions.} + + There is, of course, some trickery driving how the units are printed. + Here is the definition of \Verb|\SmartUnit|: + \begin{lstlisting} + \newcommand\SmartUnit[1]{% + \bgroup%=> changes are local to \SmartUnit => no need to reset + \pgfkeys{/SmartUnit,#1}% Pass the keys to /SmartUnit + \pgfkeys{/SmartUnit,printunit}% Calculate units and print + \egroup% + } + \end{lstlisting} + So \Verb|\SmartUnit| calls \ctan{pgfkeys} twice: the first time to + set the keys and the second time to print them using + \Verb|/SmartUnit/printunit|. In turn, this uses + \Verb|/SmartUnit/convert| to identify the unit being printed, + after which the pgf key + \Verb|/SmartUnit/output| is called. This has subkeys for the four + different \textit{output formats}: + \begin{center} + \texttt{metric}, \texttt{imperial}, + \texttt{metric imperial} and \texttt{imperial metric}. + \end{center} + Finally, \Verb|/SmartUnit/output/| uses + \Verb|/SmartUnit/convert| to perform the required conversion. + This multi-step printing process is necessary for converting between + inputs like time or centimeters, feet and inches, where the + output units depend on more than one input value. It is also used to + print the four different output formats discussed above. + + + \Section{Acknowledgement} + The package was written in response to a + \href{http://tex.stackexchange.com/questions/241169/}{TeX.SX question}, + partly as a proof-of-concept and partly as an exercise to learn how + to use \ctan{pgfkeys}. I thank Mark Adams for asking the question. + + \Section{Author} + \href{mailto:Andrew.Mathas@gmail.com?smartunits}{Andrew Mathas}, \copyright\space February 2016. + + \Section{Licence} + Released under the \href{http://www.latex-project.org/lppl.txt}{LaTeX Project Public License}, v1.3c or later. + +\end{document} diff --git a/Master/texmf-dist/tex/latex/smartunits/smartunits.sty b/Master/texmf-dist/tex/latex/smartunits/smartunits.sty new file mode 100644 index 00000000000..5fd01f609ce --- /dev/null +++ b/Master/texmf-dist/tex/latex/smartunits/smartunits.sty @@ -0,0 +1,163 @@ +%% ---------------------------------------------------------------- +%% smartunits --- A latex package that implements automatic conversions +%% between certain metric and Imperial units. +%% E-mail: andrew.mathas@gmail.com +%% Released under the LaTeX Project Public License v1.3c or later +%% See http://www.latex-project.org/lppl.txt +%% ---------------------------------------------------------------- + +% http://tex.stackexchange.com/questions/241169/is-it-possible-in-latex-to-print-all-numbers-between-imperial-and-metric/241179#241179 +\NeedsTeXFormat{LaTeX2e} +\def\smart@version{Version 1.1} +\ProvidesPackage{smartunits}[2016/02/03 \smart@version\space- Smart conversion between metric and Imperial units] +\RequirePackage{siunitx,pgfmath,pgfkeys} + +% a global pgfkeyssetvalue from Martin Scharrer's answer to http://tex.stackexchange.com/questions/15204 +\newcommand{\pgfkeysgsetvalue}[2]{\pgfkeys@temptoks{#2}\expandafter\xdef\csname pgfk@#1\endcsname{\the\pgfkeys@temptoks}} + +% a shorthand for extracting key values from /SmartUnit +\newcommand\smart@val[1]{\pgfkeysvalueof{/SmartUnit/#1}} + +% the pgfkey family for smart units +\pgfkeys{/SmartUnit/.is family,/SmartUnit,% + %%%% /SmartUnit/unit keys are implicitly initialised through the + %%%% following. As a bonus this allows us to use \pgfkeysifdefined below. + .unknown/.code={\pgfkeyssetvalue{\pgfkeyscurrentpath/\pgfkeyscurrentname}{#1}},% + %%%% /SmartUnit/convert is used to determine which "smart unit" to print + %%%% printunit --> output --> injects the code to print the current + printunit/.code={\pgfkeysifdefined{/SmartUnit/convert}{\pgfkeys{/SmartUnit/output/\smart@val{format}}}{}},% + output/metric/.code={\pgfkeys{/SmartUnit/\smart@val{convert}/metric}},% + output/imperial/.code={\pgfkeys{/SmartUnit/\smart@val{convert}/imperial}},% + output/metric imperial/.code={\pgfkeys{/SmartUnit/\smart@val{convert}/metric}\space(\pgfkeys{/SmartUnit/\smart@val{convert}/imperial})},% + output/imperial metric/.code={\pgfkeys{/SmartUnit/\smart@val{convert}/imperial}\space(\pgfkeys{/SmartUnit/\smart@val{convert}/metric})},% + %%%% global flags for controlling when metric and imperial units are printed + format/.initial=metric,% + metric/.code={\pgfkeysgsetvalue{/SmartUnit/format}{metric}},% + imperial/.code={\pgfkeysgsetvalue{/SmartUnit/format}{imperial}},% + metric imperial/.code={\pgfkeysgsetvalue{/SmartUnit/format}{metric imperial}},% + imperial metric/.code={\pgfkeysgsetvalue{/SmartUnit/format}{imperial metric}},% + %%%% allow for both UK and US Imperial units + system/.initial=usa,% for purely demographic reasons + usa/.style={system=usa},% + uk/.style={system=uk},% + %%% for local changes to the siunitz precision + figures/.code={\sisetup{round-mode=figures, round-precision=#1}}, + places/.code={\sisetup{round-mode=places, round-precision=#1}}, + %%%%%%%%%%%%%%%%%%%% conversion routines %%%%%%%%%%%%%%%%%%%%%%%%%%%% + % Generic case: #1 = (#2+#3)*#4 + #5 where #6 is the name of the unit + conversion/.code n args={6}{%{#1= to, #2= from, #3=pre-offset, #4=multiplier, #5=post-offset, #6= symbol} + \pgfkeysifdefined{/SmartUnit/unit #1}{\SI{\smart@val{unit #1}}{#6}}{\pgfmathparse{(\smart@val{unit #2}+#3)*#4+#5}\SI{\pgfmathresult}{#6}}% + },% + %%%% convert=distance: km <-> miles %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + km/.style={convert=distance, unit km=#1},% + mi/.style={convert=distance, unit miles=#1},% + miles/.style={convert=distance, unit miles=#1},% + distance/metric/.style={/SmartUnit/conversion={km}{miles}{0}{1.609344}{0}{\km}},% + distance/imperial/.style={/SmartUnit/conversion={miles}{km}{0}{0.62137119}{0}{\text{mi}}},% + %%%% convert=volume l <-> US gallons %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + gal/.style={convert=volume, unit gal=#1},% + gal/uk/.initial=0.21996925,% 1L = 0.21996925 gal (UK) + gal/usa/.initial=0.26417205,% 1L = 0.26417205 gal (USA) + gallons/.style={convert=volume, unit gal=#1},% + l/.style={convert=volume, unit L=#1, volume/symbol=l},% + L/.style={convert=volume, unit L=#1, volume/symbol=L},% + L/uk/.initial=4.54609,% 1 gal (UK) = 4.54609 L + L/usa/.initial=3.7854118,% 1 gal (USA) = 3.7854118 L + volume/symbol/.initial=l,% default symbol for litres + volume/metric/.style={/SmartUnit/conversion={L}{gal}{0}{\smart@val{L/\smart@val{system}}}{0}{\smart@val{volume/symbol}}},% + volume/imperial/.style={/SmartUnit/conversion={gal}{L}{0}{\smart@val{gal/\smart@val{system}}}{0}{\text{gal}}},% + %%%% convert=weight: kg <-> lbs %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + kg/.style={convert=weight, unit kg=#1},% 1 lbs = 0.45359237 kg + lbs/.style={convert=weight, unit pound=#1},% 1kg = 2.2046226 lbs (USA) + pound/.style={convert=weight, unit pound=#1},% 1kg = 2.2046226 lbs (USA) + weight/metric/.style={/SmartUnit/conversion={kg}{pound}{0}{0.45359237}{0}{\kg}},% + weight/imperial/.style={/SmartUnit/conversion={pound}{kg}{0}{2.2046226}{0}{\text{lbs}}},% + %%%% convert=temperature: C <-> F %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + celsius/.style={convert=temperature, unit celsius=#1},% + fahrenheit/.style={convert=temperature, unit fahrenheit=#1},% + temperature/metric/.style={/SmartUnit/conversion={celsius}{fahrenheit}{-32}{5/9}{0}{\degreeCelsius}},% + temperature/imperial/.style={/SmartUnit/conversion={fahrenheit}{celsius}{0}{9/5}{32}{\si{\degree}\text{F}}},% + %%%% convert=length: cm <-> feet and inches %%%%%%%%%%%%%%%%%%%%%%%%% + cm/.style={convert=length, unit cm=#1},% + inches/.style={convert=length, unit inches=#1},% + feet/.style={convert=length, unit feet=#1},% + length/metric/.code={% called via /SmartUnit/printunit -> /SmartUnit/output with convert=length + \pgfkeysifdefined{/SmartUnit/unit cm}{\def\pgfmathresult{\smart@val{unit cm}}}% + {\pgfkeysifdefined{/SmartUnit/unit inches}{\pgfmathsetmacro{\smart@tmp}{2.54*\smart@val{unit inches}}}{\def\smart@tmp{0}}% + \pgfkeysifdefined{/SmartUnit/unit feet}{\pgfmathparse{\smart@tmp+30.84*\smart@val{unit feet}}}{\let\pgfmathresult\smart@tmp}% + }% + \SI{\pgfmathresult}{cm}% + }, + %%%% slightly tricker as we have to convert centimeters to feet and inches + length/imperial/.code={% called via /SmartUnit/printunit -> /SmartUnit/output with convert=length + \pgfkeysifdefined{/SmartUnit/unit inches}{\pgfkeysifdefined{/SmartUnit/unit feet}{\SI{\smart@val{unit feet}}{\arcminute}\enspace\SI{\smart@val{unit inches}}{\arcsecond}}% + {\enspace\SI{\smart@val{unit inches}}{\arcsecond}}% + }% + {\pgfkeysifdefined{/SmartUnit/unit feet}{\SI{\smart@val{unit feet}}{\arcminute}}% + {\pgfmathsetmacro{\smart@tmp}{0.39370079*\smart@val{unit cm}}% centimeters -> inches + \pgfmathparse{greater(\smart@tmp,11)}% + \ifnum\pgfmathresult=1% + \pgfmathparse{int(\smart@tmp/12)}\SI{\pgfmathresult}{\arcminute}% + \pgfmathparse{int(\smart@tmp-12*\pgfmathresult)}\enspace\SI{\pgfmathresult}{\arcsecond}% + \else% + \SI{\smart@tmp}{\arcminute}% + \fi% + }% + }% + },% + %%%% convert=time: 24-hour times versus 12-hour time %%%%%%%%%%%%%%%%%%%%%%%%% + am/.style={convert=time, unit am=1},% + pm/.style={convert=time, unit pm=1},% + hours/.style={convert=time, unit hours=#1},% + minutes/.style={convert=time, unit minutes=#1},% + seconds/.style={convert=time, unit seconds=#1},% + time/metric/.code={% + \pgfkeysifdefined{/SmartUnit/unit pm}{\pgfmathparse{\smart@val{unit hours}+12}\num{\pgfmathresult}}{\num{\smart@val{unit hours}}}:\num[minimum-integer-digits=2]{\smart@val{unit minutes}}% + \pgfkeysifdefined{/SmartUnit/unit seconds}{:\num[minimum-integer-digits=2]{\smart@val{unit seconds}}}{}% + },% + time/imperial/.code={% extra cases here to for AM/PM when hours=12 <-> + \pgfkeysifdefined{/SmartUnit/unit am}{\def\smart@tmp{AM}\num{\smart@val{unit hours}}}% + {\pgfkeysifdefined{/SmartUnit/unit pm}{\def\smart@tmp{PM}\num{\smart@val{unit hours}}}% + {\pgfmathparse{greater(\smart@val{unit hours}+\smart@val{unit minutes}/60,12)}% + \ifnum\pgfmathresult=1\def\smart@tmp{PM}\pgfmathparse{\smart@val{unit hours}==12?12:\smart@val{unit hours}-12}\num{\pgfmathresult}% + \else\pgfmathparse{\smart@val{unit hours}==0?12:\smart@val{unit hours}}\num{\pgfmathresult}\def\smart@tmp{AM}% + \fi% + }% + }% + :\num[minimum-integer-digits=2]{\smart@val{unit minutes}}% + \pgfkeysifdefined{/SmartUnit/unit seconds}{\pgfmathparse{greater(\smart@val{unit hours}+\smart@val{unit seconds}/60,12)}\ifnum\pgfmathresult=1\def\smart@tmp{PM}\fi% + :\num[minimum-integer-digits=2]{\smart@val{unit seconds}}}{}% + \enspace{\text{\smart@tmp}}% + },% +} + +\newcommand\SmartUnit[1]{% + \bgroup%=> all pgfkeys changes are local to \SmartUnit => no need to reset + \pgfkeys{/SmartUnit,#1}% Pass the keys to /SmartUnit + \pgfkeys{/SmartUnit,printunit}% Calculate units and print + \egroup% +} + +\newcommand\SmartUnitSettings[1]{\pgfkeys{/SmartUnit,#1}} + +\endinput +%% End of file `printunits.sty'. +%% +%% Copyright (C) 2016 by Andrew Mathas +%% +%% This work may be distributed and/or modified under the +%% conditions of the LaTeX Project Public License (LPPL), either +%% version 1.3c of this license or (at your option) any later +%% version. The latest version of this license is in the file: +%% +%% http://www.latex-project.org/lppl.txt +%% +%% This work is "maintained" (as per LPPL maintenance status) by +%% Andrew Mathas. +%% +%% This work consists of the files smartunits.sty +%% smartunits.tex +%% README.md +%% +%% Copyright (c) 2016 Andrew Mathas +%% end of smartunits.sty diff --git a/Master/tlpkg/bin/tlpkg-ctan-check b/Master/tlpkg/bin/tlpkg-ctan-check index eb06d6f480f..34a046b74a4 100755 --- a/Master/tlpkg/bin/tlpkg-ctan-check +++ b/Master/tlpkg/bin/tlpkg-ctan-check @@ -506,7 +506,7 @@ my @TLP_working = qw( simplecd simplecv simpler-wick simplewick simplified-latex simurgh sitem siunitx skak skaknew skb skdoc skeycommand skeyval skmath skrapport skull - slantsc slideshow smalltableof smartdiagram smartref + slantsc slideshow smalltableof smartdiagram smartref smartunits snapshot snotez songbook songs sort-by-letters soton soul sourcecodepro sourcesanspro sourceserifpro diff --git a/Master/tlpkg/tlpsrc/collection-latexextra.tlpsrc b/Master/tlpkg/tlpsrc/collection-latexextra.tlpsrc index fadf1aa3ca8..a63353a01d2 100644 --- a/Master/tlpkg/tlpsrc/collection-latexextra.tlpsrc +++ b/Master/tlpkg/tlpsrc/collection-latexextra.tlpsrc @@ -876,6 +876,7 @@ depend skeyval depend skrapport depend slantsc depend smalltableof +depend smartunits depend smartref depend snapshot depend snotez diff --git a/Master/tlpkg/tlpsrc/smartunits.tlpsrc b/Master/tlpkg/tlpsrc/smartunits.tlpsrc new file mode 100644 index 00000000000..e69de29bb2d -- cgit v1.2.3