根据我的计划,我想扩展该elements
包以打印化学元素的熔点和沸点。使用elements
包中使用的相同逻辑,我考虑创建如下命令:
% default: unit=kelvin
\DeclareAtomMeltingPoint[unit=kelvin|celsius|fahrenheit]{<atomic number>}{<temperature>}
调用以下命令之一:
% Used before begin document or in packages/classes
\DeclareAtomMeltingPointKelvin{<atomic number}{<temperature in kelvin>}
\DeclareAtomMeltingPointCelsius{<atomic number}{<temperature in celsius>}
\DeclareAtomMeltingPointFahrenheit{<atomic number}{<temperature in fahrenheit>}
要打印文档内的温度,我会使用如下命令:
% Used inside document
\meltingpoint[<unit=kelvin|celsius|fahrenheit>]{<atomic number>|<element symbol>|<element name>}
我该如何实现这个呢?
答案1
我不会使用unit=
,因为这会妨碍可扩展性。
我采用使用属性列表的方法。
\documentclass{article}
\usepackage{xparse,siunitx}
\DeclareSIUnit{\fahrenheit}{\degree F}
\ExplSyntaxOn
\NewDocumentCommand{\DeclareAtomMeltingPoint}{O{kelvin}mm}
{
\group_begin:
\keys_set:nn { grs/meltingpoint } { #1 }
\prop_gput:Nnx \g_grs_meltingpoint_prop { #2 }
{
\__grs_meltingpoint_store:n { #3 }
}
\group_end:
}
\prop_new:N \g_grs_meltingpoint_prop
\keys_define:nn { grs/meltingpoint }
{
kelvin .code:n = \cs_set_eq:NN \__grs_meltingpoint_store:n \__grs_meltingpoint_in_kelvin:n,
K .code:n = \cs_set_eq:NN \__grs_meltingpoint_store:n \__grs_meltingpoint_in_kelvin:n,
celsius .code:n = \cs_set_eq:NN \__grs_meltingpoint_store:n \__grs_meltingpoint_in_celsius:n,
C .code:n = \cs_set_eq:NN \__grs_meltingpoint_store:n \__grs_meltingpoint_in_celsius:n,
fahrenheit .code:n = \cs_set_eq:NN \__grs_meltingpoint_store:n \__grs_meltingpoint_in_fahrenheit:n,
F .code:n = \cs_set_eq:NN \__grs_meltingpoint_store:n \__grs_meltingpoint_i_fahrenheit:n,
}
\cs_new:Nn \__grs_meltingpoint_in_kelvin:n
{
\fp_eval:n { #1 }
}
\cs_new:Nn \__grs_meltingpoint_in_celsius:n
{
\fp_eval:n { #1 + 273.15 }
}
\cs_new:Nn \__grs_meltingpoint_in_fahrenheit:n
{
\fp_eval:n { (#1 + 459.67)*5/9 }
}
\NewExpandableDocumentCommand{\meltingpoint}{sO{kelvin}m}
{
\IfBooleanTF{#1}
{ % we want the unit
\str_case:nn { #2 }
{
{kelvin}{\SI{\__grs_meltingpoint_out_kelvin:n{#3}}{\kelvin}}
{K}{\SI{\__grs_meltingpoint_out_kelvin:n{#3}}{\kelvin}}
{celsius}{\SI{\__grs_meltingpoint_out_celsius:n{#3}}{\celsius}}
{C}{\SI{\__grs_meltingpoint_out_celsius:n{#3}}{\celsius}}
{fahrenheit}{\SI{\__grs_meltingpoint_out_fahrenheit:n{#3}}{\fahrenheit}}
{F}{\SI{\__grs_meltingpoint_out_fahrenheit:n{#3}}{\fahrenheit}}
}
}
{ % no unit
\str_case:nn { #2 }
{
{kelvin}{\__grs_meltingpoint_out_kelvin:n{#3}}
{K}{\__grs_meltingpoint_out_kelvin:n{#3}}
{celsius}{\__grs_meltingpoint_out_celsius:n{#3}}
{C}{\__grs_meltingpoint_out_celsius:n{#3}}
{fahrenheit}{\__grs_meltingpoint_out_fahrenheit:n{#3}}
{F}{\__grs_meltingpoint_out_fahrenheit:n{#3}}
}
}
}
\cs_new:Nn \__grs_meltingpoint_out_kelvin:n
{
\prop_item:Nn \g_grs_meltingpoint_prop { #1 }
}
\cs_new:Nn \__grs_meltingpoint_out_celsius:n
{
\fp_eval:n { \prop_item:Nn \g_grs_meltingpoint_prop { #1 } - 273.15 }
}
\cs_new:Nn \__grs_meltingpoint_out_fahrenheit:n
{
\fp_eval:n { \prop_item:Nn \g_grs_meltingpoint_prop { #1 } * 9/5 - 459.67 }
}
\ExplSyntaxOff
\DeclareAtomMeltingPoint[celsius]{79}{1064}
\begin{document}
\meltingpoint*[kelvin]{79}
\meltingpoint[kelvin]{79}
\meltingpoint*[K]{79}
\meltingpoint[K]{79}
\meltingpoint*[celsius]{79}
\meltingpoint[celsius]{79}
\meltingpoint*[C]{79}
\meltingpoint[C]{79}
\meltingpoint*[fahrenheit]{79}
\meltingpoint[fahrenheit]{79}
\meltingpoint*[F]{79}
\meltingpoint[F]{79}
\end{document}
您可以使用长名称或首字母,以方便输入。*
-version 用于使用\SI
所需单位排版值。
声明可以使用任何单位,值以开尔文为单位存储。
略有不同的版本也支持沸点并避免代码重复。
\documentclass{article}
\usepackage{xparse,siunitx}
\DeclareSIUnit{\fahrenheit}{\degree F}
\ExplSyntaxOn
\NewDocumentCommand{\DeclareAtomMeltingPoint}{O{kelvin}mm}
{
\prop_gput:Nnx \g_grs_meltingpoint_prop { #2 }
{
\use:c { __grs_temperature_in_#1:n } { #3 }
}
}
\NewDocumentCommand{\DeclareAtomBoilingPoint}{O{kelvin}mm}
{
\prop_gput:Nnx \g_grs_boilingpoint_prop { #2 }
{
\use:c { __grs_temperature_in_#1:n } { #3 }
}
}
\NewExpandableDocumentCommand{\meltingpoint}{sO{kelvin}m}
{
\IfBooleanTF{#1}
{ % we want the unit
\grs_point_si:Nnn \g_grs_meltingpoint_prop { #2 } { #3 }
}
{
\grs_point:Nnn \g_grs_meltingpoint_prop { #2 } { #3 }
}
}
\NewExpandableDocumentCommand{\boilingpoint}{sO{kelvin}m}
{
\IfBooleanTF{#1}
{ % we want the unit
\grs_point_si:Nnn \g_grs_boilingpoint_prop { #2 } { #3 }
}
{
\grs_point:Nnn \g_grs_boilingpoint_prop { #2 } { #3 }
}
}
\prop_new:N \g_grs_meltingpoint_prop
\prop_new:N \g_grs_boilingpoint_prop
\cs_new:Nn \__grs_temperature_in_kelvin:n
{
\fp_eval:n { #1 }
}
\cs_set_eq:NN \__grs_temperature_in_K:n \__grs_temperature_in_kelvin:n
\cs_new:Nn \__grs_temperature_in_celsius:n
{
\fp_eval:n { #1 + 273.15 }
}
\cs_set_eq:NN \__grs_temperature_in_C:n \__grs_temperature_in_celsius:n
\cs_new:Nn \__grs_temperature_in_fahrenheit:n
{
\fp_eval:n { (#1 + 459.67)*5/9 }
}
\cs_set_eq:NN \__grs_temperature_in_F:n \__grs_temperature_in_fahrenheit:n
\cs_new:Nn \__grs_temperature_out_kelvin:Nn
{
\prop_item:Nn #1 { #2 }
}
\cs_new:Nn \__grs_temperature_out_celsius:Nn
{
\fp_eval:n { (\prop_item:Nn #1 { #2 }) - 273.15 }
}
\cs_new:Nn \__grs_temperature_out_fahrenheit:Nn
{
\fp_eval:n { (\prop_item:Nn #1 { #2 }) * 9/5 - 459.67 }
}
\cs_new:Nn \grs_point_si:Nnn
{
\str_case:nn { #2 }
{
{kelvin}{\__grs_point_si:NNnn #1 \__grs_temperature_out_kelvin:Nn {#3} {\kelvin}}
{K}{\__grs_point_si:NNnn #1 \__grs_temperature_out_kelvin:Nn {#3} {\kelvin}}
{celsius}{\__grs_point_si:NNnn #1 \__grs_temperature_out_celsius:Nn {#3} {\celsius}}
{C}{\__grs_point_si:NNnn #1 \__grs_temperature_out_celsius:Nn {#3} {\celsius}}
{fahrenheit}{\__grs_point_si:NNnn #1 \__grs_temperature_out_fahrenheit:Nn {#3} {\fahrenheit}}
{F}{\__grs_point_si:NNnn #1 \__grs_temperature_out_fahrenheit:Nn {#3} {\fahrenheit}}
}
}
\cs_new:Nn \grs_point:Nnn
{
\str_case:nn { #2 }
{
{kelvin}{\__grs_point:NNn #1 \__grs_temperature_out_kelvin:Nn {#3}}
{K}{\__grs_point:NNn #1 \__grs_temperature_out_kelvin:Nn {#3}}
{celsius}{\__grs_point:NNn #1 \__grs_temperature_out_celsius:Nn {#3}}
{C}{\__grs_point:NNn #1 \__grs_temperature_out_celsius:Nn {#3}}
{fahrenheit}{\__grs_point:NNn #1 \__grs_temperature_out_fahrenheit:Nn {#3} }
{F}{\__grs_point:NNn #1 \__grs_temperature_out_fahrenheit:Nn {#3} }
}
}
\cs_new_protected:Nn \__grs_point_si:NNnn
{
\SI{#2 #1 {#3}}{#4}
}
\cs_new:Nn \__grs_point:NNn
{
#2 #1 {#3}
}
\ExplSyntaxOff
\DeclareAtomMeltingPoint[celsius]{79}{1064}
\DeclareAtomBoilingPoint[celsius]{1}{-252.9}
\begin{document}
\meltingpoint*[kelvin]{79}
\meltingpoint[kelvin]{79}
\meltingpoint*[K]{79}
\meltingpoint[K]{79}
\meltingpoint*[celsius]{79}
\meltingpoint[celsius]{79}
\meltingpoint*[C]{79}
\meltingpoint[C]{79}
\meltingpoint*[fahrenheit]{79}
\meltingpoint[fahrenheit]{79}
\meltingpoint*[F]{79}
\meltingpoint[F]{79}
\boilingpoint*[kelvin]{1}
\boilingpoint[kelvin]{1}
\boilingpoint*[K]{1}
\boilingpoint[K]{1}
\boilingpoint*[celsius]{1}
\boilingpoint[celsius]{1}
\boilingpoint*[C]{1}
\boilingpoint[C]{1}
\boilingpoint*[fahrenheit]{1}
\boilingpoint[fahrenheit]{1}
\boilingpoint*[F]{1}
\boilingpoint[F]{1}
\end{document}
答案2
就是这样:
键unit
(默认为kelvin
)设置输入单位为\DeclareAtomMeltingPoint
,输出单位为\meltingpoint
。内部温度以开尔文为单位存储。数字打印时无需进一步格式化。
的声明\DeclareAtomMeltingPoint
和使用都\meltingpoint
使用原子序数。元素符号和名称不太容易检索,因此代码变得更加复杂。
\documentclass{article}
\usepackage{elements}
\usepackage{xparse}
\ExplSyntaxOn
\keys_define:nn { grs / elements }
{
, unit .choice:
, unit / kelvin .code:n = { \cs_set_eq:NN \__grs_select_unit:nnn \use_i:nnn }
, unit / celsius .code:n = { \cs_set_eq:NN \__grs_select_unit:nnn \use_ii:nnn }
, unit / fahrenheit .code:n = { \cs_set_eq:NN \__grs_select_unit:nnn \use_iii:nnn }
, unit .initial:n = kelvin
, unit .value_required:n = true
}
\NewDocumentCommand \DeclareAtomMeltingPoint { o m m }
{
\group_begin:
\IfValueT {#1}
{ \keys_set:nn { grs / elements } {#1} }
\cs_gset:cpx { @elements@atom@meltpoint@ \int_to_roman:n {#2} }
{
\__grs_select_unit:nnn
{ \fp_eval:n {#3} } % kelvin
{ \fp_eval:n {#3 + 273.15} } % celsius
{ \fp_eval:n {(#3 + 459.67)*5/9} } % fahrenheit
}
\group_end:
}
\NewDocumentCommand \meltingpoint { o m }
{
\group_begin:
\IfValueT {#1}
{ \keys_set:nn { grs / elements } {#1} }
\exp_args:Nv \__grs_meltingpoint:n
{ @elements@atom@meltpoint@ \int_to_roman:n {#2} }
\group_end:
}
\cs_new:Npn \__grs_meltingpoint:n #1
{
\__grs_select_unit:nnn
{ #1 } % kelvin
{ \fp_eval:n {#1 - 273.15} } % celsius
{ \fp_eval:n {#1 * 9/5 - 459.67} } % fahrenheit
}
\ExplSyntaxOff
\begin{document}
\DeclareAtomMeltingPoint[unit=celsius]{79}{1064}
\meltingpoint[unit=kelvin]{79}
\meltingpoint[unit=celsius]{79}
\meltingpoint[unit=fahrenheit]{79}
\end{document}