summaryrefslogtreecommitdiff
path: root/macros/latex/contrib/substances/substances.sty
diff options
context:
space:
mode:
authorNorbert Preining <norbert@preining.info>2019-09-02 13:46:59 +0900
committerNorbert Preining <norbert@preining.info>2019-09-02 13:46:59 +0900
commite0c6872cf40896c7be36b11dcc744620f10adf1d (patch)
tree60335e10d2f4354b0674ec22d7b53f0f8abee672 /macros/latex/contrib/substances/substances.sty
Initial commit
Diffstat (limited to 'macros/latex/contrib/substances/substances.sty')
-rw-r--r--macros/latex/contrib/substances/substances.sty590
1 files changed, 590 insertions, 0 deletions
diff --git a/macros/latex/contrib/substances/substances.sty b/macros/latex/contrib/substances/substances.sty
new file mode 100644
index 0000000000..5ef0a4cb68
--- /dev/null
+++ b/macros/latex/contrib/substances/substances.sty
@@ -0,0 +1,590 @@
+% --------------------------------------------------------------------------
+% the SUBSTANCES package
+%
+% A Chemical Database
+%
+% --------------------------------------------------------------------------
+% Clemens Niederberger
+% Web: https://bitbucket.org/cgnieder/substances/
+% E-Mail: contact@mychemistry.eu
+% --------------------------------------------------------------------------
+% Copyright 2012--2016 Clemens Niederberger
+%
+% This work 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.3 or later is part of all distributions of LaTeX
+% version 2005/12/01 or later.
+%
+% This work has the LPPL maintenance status `maintained'.
+%
+% The Current Maintainer of this work is Clemens Niederberger.
+% --------------------------------------------------------------------------
+% The substances package consists of the files
+% - substances.sty, substances-default.def, substances-examples.sub,
+% substances_en.tex, substances_en.pdf, README
+% --------------------------------------------------------------------------
+% If you have any ideas, questions, suggestions or bugs to report, please
+% feel free to contact me.
+% --------------------------------------------------------------------------
+\RequirePackage{ expl3 , xparse , l3keys2e , xtemplate }
+\ProvidesExplPackage
+ {substances}
+ {2016/01/07}
+ {0.2a}
+ {A Chemical Database}
+
+\RequirePackage{chemmacros,chemfig,ghsystem}
+\usechemmodule{nomenclature,units}
+
+% ----------------------------------------------------------------------------
+% variables:
+\tl_new:N \l__substances_tmpa_tl
+\tl_new:N \l__substances_tmpb_tl
+
+\prop_new:N \l__substances_properties_pre_prop
+\prop_new:N \l__substances_properties_post_prop
+
+\seq_new:N \l__substances_required_seq
+\seq_new:N \l_substances_chemicals_seq
+
+\clist_new:N \l_substances_chemicals_clist
+
+\bool_new:N \l__substances_strict_bool
+\bool_new:N \l__substances_index_entry_bool
+\bool_new:N \l__substances_imakeidx_bool
+\bool_new:N \l__substances_multind_bool
+\bool_new:N \l__substances_splitidx_bool
+\bool_new:N \l__substances_single_name_bool
+\bool_new:N \l__substances_single_alt_bool
+\bool_set_true:N \l__substances_single_alt_bool
+
+\tl_new:N \l__substances_style_tl
+\tl_set:Nn \l__substances_style_tl {default}
+
+\cs_generate_variant:Nn \prop_get:NnN { c }
+
+\AtBeginDocument
+ {
+ \@ifpackageloaded {imakeidx}
+ { \bool_set_true:N \l__substances_imakeidx_bool } { }
+ \@ifpackageloaded {splitidx}
+ { \bool_set_true:N \l__substances_splitidx_bool } { }
+ \@ifpackageloaded {multind}
+ { \bool_set_true:N \l__substances_multind_bool } { }
+ }
+
+% ----------------------------------------------------------------------------
+% messages:
+\cs_new_protected:Npn \substances_msg:nnn #1#2#3
+ {
+ \bool_if:NTF \l__substances_strict_bool
+ { \msg_error:nnnn {substances} {#1} {#2} {#3} }
+ { \msg_warning:nnnn {substances} {#1} {#2} {#3} }
+ }
+
+\cs_new_protected:Npn \substances_msg:nn #1#2
+ {
+ \bool_if:NTF \l__substances_strict_bool
+ { \msg_error:nnn {substances} {#1} {#2} }
+ { \msg_warning:nnn {substances} {#1} {#2} }
+ }
+
+\msg_new:nnnn {substances} {property-missing}
+ { Property~`#2'~not~defined~for~substance~`#1'~\msg_line_context:. }
+ {
+ You~called~property~`#2'~for~substance~`#1'.~It~seems~though~that~you~
+ haven't~defined~it,~yet.
+ }
+
+\msg_new:nnnn {substances} {field-missing}
+ { Property~`#2'~is~not~defined~\msg_line_context:. }
+ {
+ You~called~property~`#2'~for~substance~`#1'.~This~property~has~not~been~
+ declared,~though.~Perhaps~you've~mispelled?
+ }
+
+\msg_new:nnnn {substances} {database-missing}
+ {
+ I~ can't~ find~ the~ database~ file~ `\__substances_database:n{#1}'~
+ \msg_line_context: .
+ }
+ {
+ You~ requested~ the~ database~ file~ `\__substances_database:n{#1}',~ but~
+ apparently~ it~ is~ missing.~ Maybe~ you've~ mispelled?
+ }
+
+\msg_new:nnnn {substances} {required-field}
+ { The~field~`#1'~is~missing~for~substance~`#2'~\msg_line_context:. }
+ {
+ You~declared~the~the~substance~`#2'~but~forgot~to~add~the~required~
+ property~`#1'.
+ }
+
+\msg_new:nnnn {substances} {style-missing}
+ { I~can't~find~the~file~`substances_#1.def'. }
+ {
+ You~specified~the~style~`#1'~which~means~you~want~me~to~load~the~file~
+ `substances_#1.def'~but~I~can't~find~it.~Perhaps~you've~mispelled?~
+ Anyway~I'm~loading~the~`default'~style~instead.
+ }
+
+% ----------------------------------------------------------------------------
+% options
+\keys_define:nn { substances / options }
+ {
+ strict .bool_set:N = \l__substances_strict_bool ,
+ draft .code:n = \bool_set_true:N \l__substances_strict_bool ,
+ final .code:n = \bool_set_false:N \l__substances_strict_bool ,
+ index .bool_set:N = \l__substances_index_entry_bool ,
+ style .tl_set:N = \l__substances_style_tl
+ }
+
+\ProcessKeysOptions { substances / options }
+
+% ----------------------------------------------------------------------------
+% define new property fields:
+\cs_new_protected:Npn \substances_define_property_field:nnnn #1#2#3#4
+ {
+ \bool_if:nT {#1}
+ { \seq_put_right:Nn \l__substances_required_seq {#2} }
+ \prop_if_exist:cF { l__substances_#2_prop }
+ { \prop_new:c { l__substances_#2_prop } }
+ \tl_if_blank:nTF {#3}
+ { \prop_put:Nnn \l__substances_properties_pre_prop {#2} { } }
+ { \prop_put:Nnn \l__substances_properties_pre_prop {#2} {#3} }
+ \tl_if_blank:nTF {#4}
+ { \prop_put:Nnn \l__substances_properties_post_prop {#2} { } }
+ { \prop_put:Nnn \l__substances_properties_post_prop {#2} {#4} }
+ }
+
+\NewDocumentCommand \DeclareSubstanceProperty { smO{}O{} }
+ { \substances_define_property_field:nnnn {#1} {#2} {#3} {#4} }
+\@onlypreamble\DeclareSubstanceProperty
+
+% ----------------------------------------------------------------------------
+% declare new substance entry:
+\cs_new_protected:Npn \substances_declare_substance:nn #1#2
+ {
+ \seq_put_right:Nn \l_substances_chemicals_seq {#1}
+ \clist_put_right:Nn \l_substances_chemicals_clist {#1}
+ \prop_map_inline:Nn \l__substances_properties_pre_prop
+ {
+ \tl_set:Nn \l__substances_tmpa_tl {##2}
+ \prop_get:NnN \l__substances_properties_post_prop
+ {##1}
+ \l__substances_tmpb_tl
+ \substances_add_property:nnVV {#1} {##1}
+ \l__substances_tmpa_tl
+ \l__substances_tmpb_tl
+ }
+ \keys_set:nn { substances / #1 } {#2}
+ \seq_map_inline:Nn \l__substances_required_seq
+ {
+ \group_begin:
+ \bool_set_true:N \l__substances_strict_bool
+ \prop_if_in:cnF { l__substances_##1_prop } {#1}
+ { \substances_msg:nnn {required-field} {##1} {#1} }
+ \group_end:
+ }
+ \prop_if_in:NnTF \l__substances_sort_prop {#1}
+ {
+ \substances_remove_braces_set:xN
+ { \prop_item:Nn \l__substances_sort_prop {#1} }
+ \l__substances_tmpa_tl
+ }
+ {
+ \prop_get:NnN \l__substances_properties_pre_prop
+ {name}
+ \l__substances_tmpa_tl
+ \substances_remove_str_unbrace_set:VnnN
+ \l__substances_tmpa_tl
+ {#1}
+ {name}
+ \l__substances_tmpa_tl
+ }
+ \prop_put:NnV \l__substances_sort_prop {#1} \l__substances_tmpa_tl
+ \prop_if_in:NnT \l__substances_alt_prop {#1}
+ {
+ \prop_if_in:NnTF \l__substances_altsort_prop {#1}
+ {
+ \substances_remove_braces_set:xN
+ { \prop_item:Nn \l__substances_altsort_prop {#1} }
+ \l__substances_tmpa_tl
+ }
+ {
+ \prop_get:NnN \l__substances_properties_pre_prop {alt}
+ \l__substances_tmpa_tl
+ \substances_remove_str_unbrace_set:VnnN
+ \l__substances_tmpa_tl
+ {#1}
+ {alt}
+ \l__substances_tmpa_tl
+ }
+ \prop_put:NnV \l__substances_altsort_prop {#1} \l__substances_tmpa_tl
+ }
+ \bool_new:c { g_substances_#1_alt_index_entry_bool }
+ \bool_new:c { g_substances_#1_name_index_entry_bool }
+ }
+
+\cs_new_protected:Npn \substances_add_property:nnnn #1#2#3#4
+ {
+ \keys_define:nn { substances / #1 }
+ {
+ #2 .code:n = \prop_put:cnn
+ { l__substances_#2_prop } {#1} { #3{##1}#4 }
+ }
+ }
+\cs_generate_variant:Nn \substances_add_property:nnnn { nnVV }
+
+\NewDocumentCommand \DeclareSubstance { mm }
+ { \substances_declare_substance:nn {#1} {#2} }
+\@onlypreamble\DeclareSubstance
+
+% ----------------------------------------------------------------------------
+% recover values:
+\cs_new_protected:Npn \substances_get_property:nn #1#2
+ {
+ \IfSubstanceFieldTF {#2}
+ {
+ \IfSubstancePropertyTF {#1} {#2}
+ { \prop_item:cn { l__substances_#2_prop } {#1} }
+ { {??} \substances_msg:nnn {property-missing} {#1} {#2} }
+ }
+ { {??} \substances_msg:nnn {field-missing} {#1} {#2} }
+ }
+
+% ----------------------------------------------------------------------------
+% some commands for creating user macros or whatever:
+\NewDocumentCommand \GetSubstanceProperty { mm }
+ { \substances_get_property:nn {#1} {#2} }
+
+\DeclareExpandableDocumentCommand \RetrieveSubstanceProperty { mm }
+ { \substances_get_property:nn {#1} {#2} }
+
+\DeclareExpandableDocumentCommand \IfSubstanceFieldTF { mmm }
+ { \cs_if_exist:cTF { l__substances_#1_prop } {#2} {#3} }
+
+\DeclareExpandableDocumentCommand \IfSubstanceFieldT { mm }
+ { \cs_if_exist:cT { l__substances_#1_prop } {#2} }
+
+\DeclareExpandableDocumentCommand \IfSubstanceFieldF { mm }
+ { \cs_if_exist:cF { l__substances_#1_prop } {#2} }
+
+\DeclareExpandableDocumentCommand \IfSubstanceExistTF { mmm }
+ { \seq_if_in:NnTF \l_substances_chemicals_seq {#1} {#2} {#3} }
+
+\DeclareExpandableDocumentCommand \IfSubstanceExistT { mm }
+ { \seq_if_in:NnT \l_substances_chemicals_seq {#1} {#2} }
+
+\DeclareExpandableDocumentCommand \IfSubstanceExistF { mm }
+ { \seq_if_in:NnF \l_substances_chemicals_seq {#1} {#2} }
+
+\DeclareExpandableDocumentCommand \IfSubstancePropertyTF { mmmm }
+ {
+ \cs_if_exist:cTF { l__substances_#2_prop }
+ { \prop_if_in:cnTF { l__substances_#2_prop } {#1} {#3} {#4} }
+ {#4}
+ }
+
+\DeclareExpandableDocumentCommand \IfSubstancePropertyT { mmm }
+ {
+ \cs_if_exist:cT { l__substances_#2_prop }
+ { \prop_if_in:cnT { l__substances_#2_prop } {#1} {#3} }
+ }
+
+\DeclareExpandableDocumentCommand \IfSubstancePropertyF { mmm }
+ {
+ \cs_if_exist:cTF { l__substances_#2_prop }
+ { \prop_if_in:cnF { l__substances_#2_prop } {#1} {#3} }
+ {#3}
+ }
+
+\DeclareExpandableDocumentCommand \ForAllSubstancesDo {}
+ { \seq_map_inline:Nn \l_substances_chemicals_seq }
+
+\AtBeginDocument
+ {
+ \tl_new:N \AllSubstancesSequence
+ \seq_map_inline:Nn \l_substances_chemicals_seq
+ { \tl_put_right:Nn \AllSubstancesSequence { {#1} } }
+ \cs_new_eq:NN \AllSubstancesClist \l_substances_chemicals_clist
+ }
+
+% ----------------------------------------------------------------------------
+% user command:
+\NewDocumentCommand \chem { soomo }
+ {
+ \IfNoValueF {#2} {#2}
+ \IfNoValueTF {#5}
+ {
+ \IfBooleanTF {#1}
+ {
+ \IfSubstancePropertyTF {#4} {alt}
+ { \RetrieveSubstanceProperty {#4} {alt} }
+ { \RetrieveSubstanceProperty {#4} {name} }
+ }
+ { \RetrieveSubstanceProperty {#4} {name} }
+ }
+ { \RetrieveSubstanceProperty {#4} {#5} }
+ \IfNoValueF {#3} {#3}
+ \SubstanceIndex {#4}
+ }
+
+% ----------------------------------------------------------------------------
+% index command to add an entry to the chemicals list if the option
+% `index=true' is used:
+\cs_new_protected:Npn \substances_index:nn #1#2
+ {
+ \bool_if:NTF \l__substances_imakeidx_bool
+ { \index [ #1 ] {#2} }
+ {
+ \bool_if:NTF \l__substances_splitidx_bool
+ { \sindex [ #1 ] {#2} }
+ {
+ \bool_if:NTF \l__substances_multind_bool
+ { \index {#1} {#2} }
+ { \index {#2} }
+ }
+ }
+ }
+\cs_generate_variant:Nn \substances_index:nn { no,nx }
+
+\cs_new_protected:Npn \substances_index_entry:nn #1#2
+ { \UseInstance {substances-index} {#1} {#2} }
+
+\NewDocumentCommand \SubstanceIndex {O{default}m}
+ {
+ \bool_if:NT \l__substances_index_entry_bool
+ { \substances_index_entry:nn {#1} {#2} }
+ }
+
+\cs_new_protected:Npn \substances_remove_braces_set:nN #1#2
+ { \tl_set:Nn #2 #1 }
+\cs_generate_variant:Nn \substances_remove_braces_set:nN {x}
+
+\cs_new_protected:Npn \substances_remove_str_unbrace_set:nnnN #1#2#3#4
+ {
+ \prop_get:cnN { l__substances_#3_prop } {#2} #4
+ \tl_remove_all:Nn #4 {#1}
+ \substances_remove_braces_set:xN {#4} #4
+ }
+\cs_generate_variant:Nn \substances_remove_str_unbrace_set:nnnN { V }
+
+% let's use xtemplate's features for possible customization later:
+\DeclareObjectType {substances-index} {1}
+
+\DeclareTemplateInterface {substances-index} {standard} {1}
+ {
+ alternative-entry : boolean = true ,
+ alternative-name : boolean = true
+ }
+
+\DeclareTemplateCode {substances-index} {standard} {1}
+ {
+ alternative-entry = \l__substances_index_alternative_entry_bool ,
+ alternative-name = \l__substances_index_alternative_name_bool ,
+ }
+ {
+ \AssignTemplateKeys
+ \bool_if:nTF
+ {
+ \l__substances_index_alternative_name_bool &&
+ \prop_if_in_p:Nn \l__substances_alt_prop {#1}
+ }
+ {
+ \bool_if:cF { g_substances_#1_name_index_entry_bool }
+ {
+ \substances_index:nx { \c_job_name_tl -chem }
+ {
+ \SubstanceIndexNameAltEntry
+ { \prop_item:Nn \l__substances_sort_prop {#1} }
+ { \GetSubstanceProperty {#1} {name} }
+ { \GetSubstanceProperty {#1} {alt} }
+ }
+ }
+ \bool_if:NT \l__substances_single_name_bool
+ { \bool_gset_true:c { g_substances_#1_name_index_entry_bool } }
+ }
+ {
+ \bool_if:cF { g_substances_#1_name_index_entry_bool }
+ {
+ \substances_index:nx { \c_job_name_tl -chem }
+ {
+ \SubstanceIndexNameEntry
+ { \prop_item:Nn \l__substances_sort_prop {#1} }
+ { \GetSubstanceProperty {#1} {name} }
+ }
+ }
+ \bool_if:NT \l__substances_single_name_bool
+ { \bool_gset_true:c { g_substances_#1_name_index_entry_bool } }
+ }
+ \bool_if:nT
+ {
+ \l__substances_index_alternative_entry_bool &&
+ \l__substances_index_alternative_name_bool &&
+ \prop_if_in_p:Nn \l__substances_alt_prop {#1}
+ }
+ {
+ \bool_if:cF { g_substances_#1_alt_index_entry_bool }
+ {
+ \substances_index:nx { \c_job_name_tl -chem }
+ {
+ \SubstanceIndexAltEntry
+ { \prop_item:Nn \l__substances_altsort_prop {#1} }
+ { \GetSubstanceProperty {#1} {name} }
+ { \GetSubstanceProperty {#1} {alt} }
+ }
+ \substances_contains_see:NT \SubstanceIndexAltEntry
+ { \bool_gset_true:c { g_substances_#1_alt_index_entry_bool } }
+ }
+ }
+ }
+
+\DeclareInstance {substances-index} {default} {standard} { }
+
+\cs_new:Npn \SubstanceIndexNameEntry #1#2 { #1@#2 }
+\cs_new:Npn \SubstanceIndexNameAltEntry #1#2#3 { #1@#2~(#3) }
+\cs_new:Npn \SubstanceIndexAltEntry #1#2#3 { #1@#3|see{#2} }
+
+\cs_new_protected:Npn \substances_contains_see:NT #1#2
+ {
+ \tl_set_rescan:Nnx \l__substances_tmpa_tl {} {\cs_meaning:N #1 }
+ \tl_if_in:VnT \l__substances_tmpa_tl { |see } {#2}
+ }
+
+% ----------------------------------------------------------------------------
+% define some default fields:
+
+\cs_new_nopar:Npn \@CAS #1-#2-#3\relax { \iupac{#1-#2-#3} }
+\NewDocumentCommand \CAS { m } { \@CAS #1 \relax }
+
+\DeclareSubstanceProperty* {name} [\iupac]
+\DeclareSubstanceProperty {sort}
+\DeclareSubstanceProperty {alt} [\iupac]
+\DeclareSubstanceProperty {altsort}
+\DeclareSubstanceProperty {CAS} [\CAS]
+\DeclareSubstanceProperty {PubChem}
+
+% ----------------------------------------------------------------------------
+% load style file
+\tl_const:Nn \c__substances_style_extension_tl {def}
+\tl_const:Nn \c__substances_style_prefix_tl {substances-}
+
+\cs_new:Npn \__substances_style:n #1
+ { \c__substances_style_prefix_tl#1.\c__substances_style_extension_tl }
+
+\cs_new_protected:Npn \substances_load_style:n #1
+ {
+ \tl_set:Nx \l__substances_tmpa_tl { \tl_trim_spaces:n {#1} }
+ \__substances_load_style:V \l__substances_tmpa_tl
+ }
+\cs_generate_variant:Nn \substances_load_style:n { V }
+
+\cs_new_protected:Npn \__substances_load_style:n #1
+ {
+ \substances_if_style_exist:nTF {#1}
+ {
+% \msg_log:nnn {substances} {loading-style} {#1}
+ \@onefilewithoptions
+ {\c__substances_style_prefix_tl#1}[][]
+ \c__substances_style_extension_tl
+ }
+ { \substances_msg:nn {style-missing} {#1} }
+ }
+\cs_generate_variant:Nn \__substances_load_style:n { V }
+
+\prg_new_conditional:Npnn \substances_if_style_exist:n #1 {T,F,TF}
+ {
+ \file_if_exist:nTF
+ { \__substances_style:n {#1} }
+ { \prg_return_true: }
+ { \prg_return_false: }
+ }
+
+\cs_new_protected:Npn \__substances_style:nn #1#2
+ {
+ \ProvidesFile { \__substances_style:n {#2} }
+ \bool_if:nT {#1} { \ExplSyntaxOn }
+ }
+
+\bool_new:N \l__substances_inside_style_file_bool
+
+\NewDocumentCommand \SubstancesStyle {sm}
+ {
+ \__substances_style:nn {#1} {#2}
+ \bool_set_true:N \l__substances_inside_style_file_bool
+ \AtEndOfPackage
+ { \bool_set_false:N \l__substances_inside_style_file_bool }
+ }
+
+\NewDocumentCommand \LoadSubstancesStyle {m}
+ {
+ \bool_if:NTF \l__substances_inside_style_file_bool
+ { \substances_load_style:n {#1} }
+ {}
+ }
+
+\substances_load_style:V \l__substances_style_tl
+
+% ----------------------------------------------------------------------------
+% load database file
+\tl_const:Nn \c__substances_database_extension_tl {sub}
+\tl_const:Nn \c__substances_database_prefix_tl {}
+
+\cs_new:Npn \__substances_database:n #1
+ { \c__substances_database_prefix_tl#1.\c__substances_database_extension_tl }
+
+\prg_new_conditional:Npnn \substances_if_database_exist:n #1 {T,F,TF}
+ {
+ \file_if_exist:nTF
+ { \__substances_database:n {#1} }
+ { \prg_return_true: }
+ { \prg_return_false: }
+ }
+
+\cs_new_protected:Npn \__substances_load_database:n #1
+ {
+ \substances_if_database_exist:nTF {#1}
+ {
+ \@onefilewithoptions
+ {\c__substances_database_prefix_tl#1}[][]
+ \c__substances_database_extension_tl
+ }
+ { \substances_msg:nn {database-missing} {#1} }
+ }
+\cs_generate_variant:Nn \__substances_load_database:n { V }
+
+\cs_new_protected:Npn \substances_load_database:n #1
+ {
+ \tl_set:Nx \l__substances_tmpa_tl { \tl_trim_spaces:n {#1} }
+ \__substances_load_database:V \l__substances_tmpa_tl
+ }
+
+\NewDocumentCommand \LoadSubstances {m}
+ { \substances_load_database:n {#1} }
+\@onlypreamble\LoadSubstances
+
+\cs_new_protected:Npn \__substances_database:nn #1#2
+ {
+ \ProvidesFile { \__substances_database:n {#2} }
+ \bool_if:nF {#1} { }
+ }
+
+\NewDocumentCommand \SubstancesDatabase {sm}
+ { \__substances_database:nn {#1} {#2} }
+
+\tex_endinput:D
+
+% ----------------------------------------------------------------------------
+% HISTORY:
+2012/07/22 v0.1 - first release to CTAN
+2012/09/02 v0.1a - small fix due to updated l3kernel
+2015/10/21 v0.2 - maintenance: minor fixes, adapt to chemmacros v5
+ - change implementation of how style files are loaded
+ - change implementation of how database files are loaded
+2016/01/07 v0.2a - \prop_get:Nn => \prop_item:Nn
+
+% TODO: