TeX - LaTeX Asked by piggy on June 24, 2021
I am quite new to Latex and for the past few days I have been struggling to create a macro to insert schemes with labels. I use .eps files for my schemes which include a temporary marker that is then replaced with a number by the chemstyle package. The command is schemeref
and includes the temporary marker and a label (named cmpd…).
My macro works if there is just one item to label:
documentclass{article}
usepackage{chemstyle}
begin{document}
newcommandinsertscheme[5]{%
begin{scheme}
schemeref[#1]{cmpd:#2}
includegraphics{#3}
caption{#4}
label{scheme:#5}
end{scheme}}
insertscheme
{TMP1}{benzene}
{benzene.eps}{Structure of compound{cmpd:benzene}.}{benzene}
end{document}
However, I also have schemes which include more than one structure, usually between 2 and 7. Without the macro I can label all structures like the following example shows:
begin{scheme}
schemeref[TMP1]{cmpd:benzene}
schemeref[TMP2]{cmpd:Brbenzene}
includegraphics{benzene-Brbenzene.eps}
caption{Structure of compound{cmpd:benzene} and compound{cmpd:Brbenzene}.}
label{scheme:benzene-Brbenzene}
end{scheme}
My question now: How do I need to change the macro so that it can be used for schemes with a variable number structures inside?
I am using the LaTeX compiler on Overleaf.
If you want to take this route you can add protect
to make it work. (I would not recommend using macros with such excessive numbers of arguments, it is almost impossible to recall their usage, especially if you have several of them.)
documentclass{article}
usepackage{chemstyle}
begin{document}
newcommandinsertscheme[5]{%
begin{scheme}
schemeref[#1]{cmpd:#2}
includegraphics{#3}
caption{#4}
label{scheme:#5}
end{scheme}}
insertscheme
{TMP1}{benzene}
{benzene.eps}{Structure of protectcompound{cmpd:benzene}.}{benzene}
end{document}
Answered by user232027 on June 24, 2021
If all your calls to insertscheme
are of pattern
insertscheme{⟨IDENTIFIER A⟩}%
{⟨IDENTIFIER B⟩}%
{⟨IDENTIFIER B⟩.eps}%
{Structure of compound{cmpd:⟨IDENTIFIER B⟩}.}%
{⟨IDENTIFIER B⟩}%
, then you can instead define
newcommandinsertscheme[2]{%
begin{scheme}%
schemeref[{#1}]{cmpd:#2}%
includegraphics{#2.eps}%
caption{Structure of compound{cmpd:#2}.}%
label{scheme:#2}%
end{scheme}%
}
and do insertscheme{⟨IDENTIFIER A⟩}{⟨IDENTIFIER B⟩}%
.
Then you can define a macro insertschemes
which processes a list of comma-separated two-argument-tuples which works as follows:
insertschemes{%
{TMP1}{benzene},
...
{TMP2}{Brbenzene},
}%
The macro insertschemes
in the example below, if called as
insertschemes{%
{TMP1}{benzene},
{TMP2}{Brbenzene},
{TMP3}{Fbenzene},
}%
, creates the tokens
begin{scheme}%
schemeref[{TMP1}]{cmpd:benzene}%
schemeref[{TMP2}]{cmpd:Brbenzene}%
schemeref[{TMP3}]{cmpd:Fbenzene}%
includegraphics{benzene-Brbenzene-Fbenzene.eps}%
caption{%
Structure of compound{cmpd:benzene} %
and compound{cmpd:Brbenzene} %
and compound{cmpd:Fbenzene}%
}%
label{scheme:benzene-Brbenzene-Fbenzene}%
end{scheme}%
for you.
documentclass{article}
usepackage{chemstyle}
usepackage{xparse}
ExplSyntaxOn
clist_new:N l__my_insertschemes_clist
tl_new:N l__my_insertschemes_schemerefs_tl
tl_new:N l__my_insertschemes_compounds_tl
tl_new:N l__my_insertschemes_names_tl
bool_new:N __bool_my_insertschemes_names_first_item
cs_new_protected:Nn __my_insertschemes_set_tls:nn {
bool_if:NTF __bool_my_insertschemes_names_first_item {
bool_set_false:N __bool_my_insertschemes_names_first_item
}{
tl_put_right:Nn l__my_insertschemes_compounds_tl {~and~}
tl_put_right:Nn l__my_insertschemes_names_tl {-}
}
tl_put_right:Nn l__my_insertschemes_compounds_tl {compound{cmpd:#2}}
tl_put_right:Nn l__my_insertschemes_names_tl {#2}
tl_put_right:Nn l__my_insertschemes_schemerefs_tl {
schemeref[{#1}]{cmpd:#2}
}
}
cs_new_protected:Nn __my_insertschemes_use_tls:nnnn{
% If you want to see what this does, uncomment the following two comments:
%deftempa{
begin{#1}
#2
includegraphics{#3.eps}
caption{Structure~of~#4}
label{scheme:#3}
end{#1}
%}showtempa
}
cs_generate_variant:Nn __my_insertschemes_use_tls:nnnn {nVVV}
NewDocumentCommand insertschemes {m} {
group_begin:
clist_clear:N l__my_insertschemes_clist
tl_clear:N l__my_insertschemes_schemerefs_tl
tl_clear:N l__my_insertschemes_compounds_tl
tl_clear:N l__my_insertschemes_names_tl
clist_set:Nn l__my_insertschemes_clist {#1}
bool_set_true:N __bool_my_insertschemes_names_first_item
clist_map_inline:Nn l__my_insertschemes_clist {
__my_insertschemes_set_tls:nn ##1
}
__my_insertschemes_use_tls:nVVV {scheme}
{l__my_insertschemes_schemerefs_tl}
{l__my_insertschemes_names_tl}
{l__my_insertschemes_compounds_tl}
group_end:
}
ExplSyntaxOff
begin{document}
insertschemes{%
{TMP1}{benzene},
{TMP2}{Brbenzene},
{TMP3}{Fbenzene},
}%
end{document}
If you need to process more than two arguments per argument-tuple, then all you need to do is to redefine __my_insertschemes_set_tls:nn
to process more than two arguments/identifiers.
Edit 1:
That was one of my first attempts to use expl3/LaTeX3.
To be honest, I like the approach of wipet much better:
His macros are short and are all expandable.
His approach is very resource-efficient, since no temporary assignments are made in any loop, such as defining temporary helper macros and the like.
And with his doscheme
you don't need to type so many curly braces. ;-)
Edit 2:
Now that wipet has started the ball rolling, a variation of his code where in the very edge case of doscheme
's 2nd argument being empty compounds
will not create a compound
-command in the 1st iteration:
documentclass{article}
usepackage{chemstyle}
defdoscheme[#1]#2{%
begin{scheme}%
schemerefs #1--;#2--%
includegraphics{#2.eps}%
caption{Structure of compounds{}#2--.}%
label{scheme:#2}%
end{scheme}%
}
defschemerefs #1-#2;#3-{%
ifx^#1^elseschemeref[{#1}]{cmpd:#3}afterfi{schemerefs#2;}fi
}
defcompounds #1#2-{%
ifx^#2^else#1compound{cmpd:#2}afterfi{compounds{ and }}fi
}
defafterfi#1#2fi{fi#1}
begin{document}
Tests:
doscheme[TMP1]{benzene}
doscheme[TMP1-TMP2]{benzene-Brbenzene}
doscheme[TMP1-TMP2-TMP3]{benzene-Brbenzene-Rkbenzene}
end{document}
If you don't wish the name of the image-file, the text of the caption and the name of the cross-referencing-label to be created automatically but wish them to be passed as arguments, the following code defines a variant of insertschemes
where
insertschemes{%
{TMP1}{benzene},
{TMP2}{Brbenzene},
{TMP3}{Fbenzene},
}{NameOfImageFile}{text of caption}{CrossReferencingLabel}%
delivers the tokens
begin{scheme}%
schemeref[{TMP1}]{cmpd:benzene}%
schemeref[{TMP2}]{cmpd:Brbenzene}%
schemeref[{TMP3}]{cmpd:Fbenzene}%
includegraphics{NameOfImageFile.eps}%
caption{text of caption}%
label{scheme:CrossReferencingLabel}%
end{scheme}%
, i.e., only the sequence of schemeref
-commands is created automatically:
documentclass{article}
usepackage{chemstyle}
usepackage{xparse}
ExplSyntaxOn
clist_new:N l__my_insertschemes_clist
tl_new:N l__my_insertschemes_schemerefs_tl
cs_new_protected:Nn __my_insertschemes_set_tls:nn {
tl_put_right:Nn l__my_insertschemes_schemerefs_tl {
schemeref[{#1}]{cmpd:#2}
}
}
cs_new_protected:Nn __my_insertschemes_use_tls:nnnnn {
% If you want to see what this does, uncomment the following two comments:
%deftempa{
begin{#1}
#2
includegraphics{#4.eps}
caption{#3}
label{scheme:#5}
end{#1}
%}showtempa
}
cs_generate_variant:Nn __my_insertschemes_use_tls:nnnnn {nVnnn}
NewDocumentCommand insertschemes {mmmm} {
group_begin:
clist_clear:N l__my_insertschemes_clist
tl_clear:N l__my_insertschemes_schemerefs_tl
clist_set:Nn l__my_insertschemes_clist {#1}
clist_map_inline:Nn l__my_insertschemes_clist {
__my_insertschemes_set_tls:nn ##1
}
__my_insertschemes_use_tls:nVnnn {scheme}
{l__my_insertschemes_schemerefs_tl}
{#3}
{#2}
{#4}
group_end:
}
ExplSyntaxOff
begin{document}
insertschemes{%
{TMP1}{benzene},
{TMP2}{Brbenzene},
{TMP3}{Fbenzene},
}{NameOfImageFile}{text of caption}{CrossReferencingLabel}%
end{document}
Syntax where optional arguments of schemeref
are optional within the argument-tuples also can be achieved without expl3 - here the loop is carried out inside the scheme-environment:
documentclass{article}
usepackage{chemstyle}
makeatletter
begingroup
% Removespaces removes one leading and one trailing space from its argument if present.
% Be aware that this implementation also removes a leading implicit space token like
% @sptoken but does not remove a trailing implicit space token.
defRemovespaces#1{%
endgroup
newcommandRemovespaces[1]{%
% Let's have romannmeral create a negative number from an alphabetic constant.
% The negative number will not be printed by romannumeral but things get expanded
% while scanning for the <optional space> that is probably trailing the alphabetic
% constant and that is also removed if present. (It will be present if the argument
% of Removespaces has a leading space.)
romannumeral-`AEnsureForbiddenBeforeTrailSpacenoexpand##1UD@Forbidden#1UD@Forbidden
}
}Removespaces{ }%
@ifdefinableEnsureForbiddenBeforeTrailSpace{%
longdefEnsureForbiddenBeforeTrailSpace#1 UD@Forbidden{%
RemoveTrailingForbiddens#1UD@Forbidden
}%
}%
@ifdefinableRemoveTrailingForbiddens{%
longdefRemoveTrailingForbiddens#1UD@Forbidden#2{#1}%
}%
@ifdefinablegobbledot{defgobbledot.{}}%
@ifdefinableschemerefloop{%
longdefschemerefloop#1,{%
if$detokenizeexpandafter{@secondoftwo#1{}}$%
expandafter@firstoftwoelseexpandafter@secondoftwofi
{schemerefloop.}{%
expandafterexpandafter
expandafterexpandafter
expandafterexpandafter
expandafterdoschemeref
expandafterRemovespaces
expandafter{gobbledot#1}%
}%
}%
}%
newcommanddoschemeref{%
@ifnextchar[doschemeref@optdoschemeref@noopt
}%
newcommanddoschemeref@opt[2][]{%
schemeref[{#1}]{cmpd:#2}schemerefloop.%
}%
newcommanddoschemeref@noopt[1]{%
ifxschemerefloop#1expandafter@gobbleelseexpandafter@firstofonefi
{schemeref{cmpd:#1}schemerefloop.}%
}%
@ifdefinableinsertschemes{%
DeclareRobustCommandinsertschemes[4]{%
begin{scheme}%
schemerefloop.#1,{schemerefloop},%
includegraphics{#2.eps}%
caption{#3}%
label{#4}%
end{scheme}%
}%
}%
makeatother
begin{document}
insertschemes{%
[TMP1]{benzene},
{Brbenzene},
[TMP3]{Fbenzene},
}{NameOfImageFile}{text of caption}{CrossReferencingLabel}%
end{document}
Answered by Ulrich Diez on June 24, 2021
You can create a number of key-value options for insertscheme
:
documentclass{article}
usepackage{chemstyle,graphicx,xkeyval}
makeatletter
define@cmdkey{fam}{scheme}[empty@key]{}
define@cmdkey{fam}{schemeopt}[]{}
define@cmdkey{fam}{compoundAref}[]{}
define@cmdkey{fam}{compoundAlabel}[empty@key]{}
define@cmdkey{fam}{compoundBref}[]{}
define@cmdkey{fam}{compoundBlabel}[empty@key]{}
% Add additional compound keys here...
define@cmdkey{fam}{caption}[empty@key]{}
define@cmdkey{fam}{label}[empty@key]{}
newcommand{insertscheme}[1]{{%
setkeys{fam}{%
schemeopt=,
%compoundAref=,
compoundAlabel=,
compoundBref=,
compoundBlabel=,
% Add additional compound key defaults here...
label=,
#1
}%
begin{scheme}
ifxcmdKV@fam@compoundAlabelempty@keyelse
begingroupedefx{endgroupnoexpandschemeref[cmdKV@fam@compoundAref]{cmpd:cmdKV@fam@compoundAlabel}}x
fi
ifxcmdKV@fam@compoundBlabelempty@keyelse
begingroupedefx{endgroupnoexpandschemeref[cmdKV@fam@compoundBref]{cmpd:cmdKV@fam@compoundBlabel}}x
fi
% Add additional compounds here...
ifxcmdKV@fam@schemeempty@keyelse
begingroupedefx{endgroupnoexpandincludegraphics[cmdKV@fam@schemeopt]{cmdKV@fam@scheme}}x
fi
ifxcmdKV@fam@captionempty@keyelse
caption{cmdKV@fam@caption}%
fi
ifxcmdKV@fam@labelempty@keyelse
expandafterlabelexpandafter{scheme:cmdKV@fam@label}%
fi
end{scheme}
}}
makeatother
begin{document}
insertscheme{%
scheme=example-image,
schemeopt={width=5em},
compoundAref=TMP1,
compoundAlabel=benzene,
compoundBref=TMP2,
compoundBlabel=Brbenzene,
caption={Structure of compound{cmpd:benzene} and compound{cmpd:Brbenzene}.}
}
end{document}
You could add additional compound keys compoundCref
, compoundClabel
, ... with additional setting within insertscheme
to suit your needs.
Answered by Werner on June 24, 2021
I suggest to use doscheme
macro wit syntax
doscheme[TMPA-TMPB-etc.]{nameA-nameB-etc.}
which does:
scheme
schemeref[TMPA]{cmpd:nameA}schemeref[TMPB]{cmpd:nameB}
etc. in loop.nameA-nameB-etc.eps
picture.Structure of compound{cmpd:nameA} and cmpound{cmpd:nameB} and
... (in loop)scheme:nameA-nameB-etc
.scheme
.Example:
documentclass{article}
usepackage{chemstyle}
defdoscheme[#1]#2{%
begin{scheme}
schemerefs #1--;#2--;%
includegraphics{#2.eps}
caption{Structure of compounds #2--.}
label{scheme:#2}
end{scheme}
}
defschemerefs #1-#2;#3-#4;{%
ifx^#1^else schemeref[#1]{cmpd:#3}afterfi{schemerefs#2;#4;}fi
}
defcompounds #1-{compound{cmpd:#1}compoundsA}
defcompoundsA #1-{%
ifx^#1^elsespace and compound{cmpd:#1}expandaftercompoundsAfi
}
defafterfi#1#2fi{fi#1}
begin{document}
Tests:
doscheme[TMP1]{benzene}
doscheme[TMP1-TMP2]{benzene-Brbenzene}
doscheme[TMP1-TMP2-TMP3]{benzene-Brbenzene-Rkbenzene}
end{document}
Answered by wipet on June 24, 2021
Get help from others!
Recent Answers
Recent Questions
© 2024 TransWikia.com. All rights reserved. Sites we Love: PCI Database, UKBizDB, Menu Kuliner, Sharing RPP