% \iffalse meta-comment % % styledcmd Handle multiple versions for user-defined macros in LaTeX % Copyright (C) 2021-2024 Paolo De Donato % % This file is part of Styledcmd. % % Styledcmd is free software: you can redistribute it and/or modify % it under the terms of the GNU General Public License as published by % the Free Software Foundation, either version 3 of the License, or % (at your option) any later version. % % Styledcmd is distributed in the hope that it will be useful, % but WITHOUT ANY WARRANTY; without even the implied warranty of % MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the % GNU General Public License for more details. % % You should have received a copy of the GNU General Public License % along with Styledcmd. If not, see . % % \fi % % \iffalse %<*driver> \ProvidesFile{styledcmd.dtx}[2024/03/07 2.0.1 Command with different styles] % %\NeedsTeXFormat{LaTeX2e} %\RequirePackage{expl3}[2022-04-10] %\ProvidesExplPackage{styledcmd}{2024/03/07}{2.0.1}{Command with different styles} %\RequirePackage{lt3rawobjects}[2023-03-17] %\RequirePackage{xparse} %<*driver> \documentclass[full]{l3doc} \usepackage{styledcmd} \begin{document} \DocInput{styledcmd.dtx} \end{document} % % \fi % %\newstyledcmd{\saluto}{informal}[1]{Hi #1} %\newstyledcmd{\saluto}{formal}[1]{Good morning #1} % %\newcommand{\thpkg}{\pkg{styledcmd}} % %\title{styledcmd} %\author{Paolo De Donato} %\date{2.0.1 2024/03/07} % %\maketitle % %\begin{documentation} % %\thpkg{} is a \LaTeX{} package that allows you to create and manage different versions of your macro in order to be able to choose the better style for every occasion and avoid rewriting code each time. %\section{How can you include it in your project?} %You need only to have the file \verb+styledcmd.sty+ in your current working directory. Otherwise you can manually install it inside your preferred \LaTeX{} compiler (for example \verb+TeXLive+ or \verb+MiKTeX+) in order to make it available for all your projects. Instructions for manually install a package can be found on Internet. % %Then once you've added it you can include in your project with this command: %\begin{verbatim} % \usepackage{styledcmd} %\end{verbatim} % %\section{How do you use it?} %You can create a formatted macro via the following command %\begin{function}{\newstyledcmd, \renewstyledcmd, \providestyledcmd} %\begin{syntax} %\tn{newstyledcmd} \{\tn{\meta{macro name}}\} \marg{style name} \oarg{number of arguments} \marg{code} %\end{syntax} %it has the same syntax of \tn{newcommand} except for the \meta{style name} argument that specify the style. This macro alone creates commands \tn{\meta{macro name}} and \tn{\meta{macro name}}\oarg{style name} that both expand as \meta{code}. %\end{function} % %The most important feature is that you can call \tn{newstyledcmd} multiple times with the same \meta{macro name} but different \meta{style name}, in this way each of \tn{\meta{macro name}}\oarg{style name} expands to \meta{code} associated to specified \meta{style name}. Notice that if you don't specify a style with just calling \tn{meta{macro name}} then it expands as the first created style, that style is the \emph{default} one for such command. % %As an example these commands %\begin{verbatim} % \newstyledcmd{\saluto}{informal}[1]{Hi #1} % \newstyledcmd{\saluto}{formal}[1]{Good morning #1} %\end{verbatim} %define the two formats \verb+informal+ and \verb+formal+ for macro \tn{saluto}. Once you've created these two styles for \tn{saluto} you can use it with or without the style name argument, for example these commands %\begin{verbatim} % \saluto{uncle} % \saluto[informal]{uncle} % \saluto[formal]{uncle} %\end{verbatim} %will be expanded respectively as \saluto{uncle}, \saluto[informal]{uncle}, \saluto[formal]{uncle}. With the same syntax you can use \tn{renewstyledcmd} and \tn{providestyledcmd} with the same meaning of \tn{renewcommand} and \tn{providecommand} respectively. % %\section{How do you change the default style?} %In order to change the default style (the one used when you don't choose explicitily a style) you need to execute the following command %\begin{function}{\SetGlobalStyle} %\begin{syntax} %\tn{SetGlobalStyle} \{\cs{\meta{command name}}\} \marg{new default style name} %\end{syntax} %\end{function} %\SetGlobalStyle{\saluto}{formal} % %For example in order to change the default style of command \tn{saluto} from \verb+informal+ to \verb+formal+ you need to execute command \tn{SetGlobalStyle}\{\cs{saluto}\}\{\verb+formal+\}. With this command the output of preceding commands will instead be \saluto{uncle}, \saluto[informal]{uncle}, \saluto[formal]{uncle}. % %\section{Customize parameters with \pkg{xparse}} %\thpkg{} loads automatically the \pkg{xparse} package for internal reasons. You can also define new styled commands with the same syntax used by \tn{NewDocumentCommand} with the following command % %\begin{function}{\NewDocStyledCMD, \RenewDocStyledCMD, \ProvideDocStyledCMD} %\begin{syntax} %\tn{NewDocStyledCMD} \Arg{\cs{\meta{command name}}} \Arg{format name} \Arg{arguments format} \Arg{code} %\end{syntax} %\end{function} % %\NewDocStyledCMD{\prova}{stylea}{r<>}{Stile 1 #1} %\NewDocStyledCMD{\prova}{styleb}{r<>}{Stile 2 #1} %For example we can create the following two styles %\begin{verbatim} % \NewDocStyledCMD{\prova}{stylea}{r<>}{Stile 1 #1} % \NewDocStyledCMD{\prova}{styleb}{r<>}{Stile 2 #1} %\end{verbatim} %in order to execute %\begin{verbatim} % \prova % \prova[stylea] % \prova[styleb] %\end{verbatim} %which are expanded respectively as \prova; \prova[stylea]; \prova[styleb]. Notice that the first optional argument passed to a command defined via \tn{NewDocStyledCMD} will always be interpreted as a style argument, so you should use another syntax for optional arguments or use a mandatory argument for the first place. % %For example this declaration \verb+\NewDocStyledCMD{\bad}{style}{o m}{Bad declaration}+ should be avoided since for example \verb+\bad[arg1]{arg2}+ will interpret \verb+arg1+ as a style name and not as the first optional argument for \tn{bad}. % %\section{Expandable commands} %Coomands created by \tn{newstyledcmd} doesn't work very well in expansion only context due to the presence of optional style argument. In order to be able to create expandable commands you should instead use % %\begin{function}{\newstyledcmdExp, \renewstyledcmdExp, \providestyledcmdExp} %\begin{syntax} %\tn{newstyledcmdExp} \{\tn{\meta{macro name}}\} \marg{style name} \oarg{number of arguments} \marg{code} %\end{syntax} %\end{function} % Despite commands created with \tn{newstyledcmd} the style name of commands created by \tn{newstyledcmdExp} are always mandatory and must be passed inside curly braces. In order to use the default style just pass an empty string as style name. % % For example this code %\begin{verbatim} % \newstyledcmdExp{\expCMD}{sty1}{Style 1} % \newstyledcmdExp{\expCMD}{sty2}{Style 2} % % \expCMD{} % \expCMD{sty1} % \expCMD{sty2} %\end{verbatim} %expand as \newstyledcmdExp{\expCMD}{sty1}{Style 1}\newstyledcmdExp{\expCMD}{sty2}{Style 2} \expCMD{} \expCMD{sty1} \expCMD{sty2} % %\section{Groups} %The group mechanism is very different from \thpkg\ |1.2| and preceding versions. From |2.0| styled commands can be added to a group in order to change toghether their style. Groups are automatically created when you're tying to add commands to it: %\begin{function}{\AddCMDToGroup} %\begin{syntax} % \tn{AddCMDToGroup} \Arg{group name} \Arg{comma list of commands} %\end{syntax} %\end{function} % You can change the default style for each member of a group with %\begin{function}{\SetGroupStyle} %\begin{syntax} % \tn{SetGroupStyle} \Arg{group name} \Arg{style name} %\end{syntax} %\end{function} % %Suppose you've created the following styled commands: % % \begin{verbatim} % \newstyledcmd{\LenUnit}{SI}{metre} % \newstyledcmd{\MasUnit}{SI}{kilo} % % \newstyledcmd{\LenUnit}{old}{yard} % \newstyledcmd{\MasUnit}{old}{pound} % \end{verbatim} % % \newstyledcmd{\LenUnit}{SI}{metre} % \newstyledcmd{\MasUnit}{SI}{kilo} % % \newstyledcmd{\LenUnit}{old}{yard} % \newstyledcmd{\MasUnit}{old}{pound} % % Commands \tn{LenUnit}, \tn{MasUnit} will expand as \LenUnit, \MasUnit\ respectively since |SI| is the default style. We've used \tn{newstyledcmd} but you could use also \tn{NewDocStyledCMD}, \tn{newstyledcmdExp} or any other command generated as in section \ref{advanced}. To add these two commands to group |Units| run % \begin{verbatim} % \AddCMDToGroup{Units}{\LenUnit, \MasUnit} % \end{verbatim} % \AddCMDToGroup{Units}{\LenUnit}\AddCMDToGroup{Units}{\MasUnit}\SetGroupStyle{Units}{old}If you want to set |old| as the default style for these commands just run % \begin{verbatim} % \SetGroupStyle{Units}{old} % \end{verbatim} % now \tn{LenUnit}, \tn{MasUnit} will expand as \LenUnit, \MasUnit\ respectively. % % Notice that if the specified group already exists then \tn{AddCMDToGroup} just appends the speficied commands to it. In particular this % \begin{verbatim} % \AddCMDToGroup{Units}{\LenUnit} % \AddCMDToGroup{Units}{\MasUnit} % \end{verbatim} % is equivalent to write % \begin{verbatim} % \AddCMDToGroup{Units}{\LenUnit, \MasUnit} % \end{verbatim} % %\section{Advanced usage} %\label{advanced}This section is for advanced users and package mantainers that knows \LaTeX3, It's not needed to use \thpkg\ daily or creating documents. If \tn{newstyledcmd}, \tn{NewDocStyledCMD} and \tn{newstyledcmdExp} aren't suitable for you it's possible to create a custom styled command generator, but we first need to know a bit of the internal structure of \thpkg. % % What you see as a styled command it's instead a collection of different macros: % \begin{itemize} % \item multiple \emph{effective styled commands} (\emph{ES commands}), one for each style; % \item a single \emph{dispatch command} that's called by the user and expands to the specified ES command. % \end{itemize} % % \begin{function}{\stycmd_generate:NNN, \stycmd_generate:NN} % \begin{syntax} % \cs{stycmd_generate:NNN} \meta{generator name} \meta{ES commands generator} \meta{dispatch command generator} % \cs{stycmd_generate:NN} \meta{generator name} \meta{ES commands generator} % \end{syntax} % Creates a generator of styled commands with name \meta{generator name}. Argument \meta{ES commands generator} is used to create ES commands and should accept a macro name as the first argument, but there aren't other restrictions on remaining arguments. Suitable ES commands generators are \tn{newcommand} and \tn{NewDocumentCommand}. % \end{function} % % Argument \meta{dispatch command generator} should generate the dispatch command. Despite \meta{ES commands generator} this command must have only one parameter, a string representing the command to be created. Suitable values for this parameter are: % % \begin{function}{\stycmd_xparsecmd:N} % \begin{syntax} % \cs{stycmd_xparsecmd:N} \meta{command} % \end{syntax} % Creates the dispatch command with \tn{ProvideDocumentCommand} with optional style name parameter (used in \tn{newstyledcmd} and \tn{NewDocStyledCMD}). %\end{function} % %\begin{function}{\stycmd_expcmd:N} % \begin{syntax} % \cs{stycmd_expcmd:N} \meta{command} % \end{syntax} % Creates the dispatch command with \tn{providecommand} with mandatory style name parameter (used in \tn{newstyledcmdExp}). %\end{function} % % If you don't specify the dispatch command generator (by using the |NN| variant) \cs{stycmd_xparsecmd:N} is used implicitly. % % \begin{function}{\stycmd_generate_renew:NN} % \begin{syntax} % \cs{stycmd_generate_renew:NN} \meta{updater name} \meta{ES commands generator} % \end{syntax} % Creates command \tn{\meta{updater name}} that modifies styles of commands already generated, like \tn{renewcommmand} edits commands generated by \tn{newcommand}. % % For example if you have \tn{createA} that creates commands and \tn{editA} that edits commands generated by \tn{createA} then % \begin{verbatim} % \stycmd_generate:NN \createStyledA \createA % \end{verbatim} % creates styled commands by using \tn{createA} and % \begin{verbatim} % \stycmd_generate_renew:NN \editStyledA \editA % \end{verbatim} % modifies commands generated by \tn{createStyledA} (by invoking \tn{editA}). % \end{function} % %\end{documentation} % %\begin{implementation} % %\section{Implementation} % \begin{macrocode} %<*package> % \end{macrocode} % % \begin{macrocode} %<@@=stycmd> % \end{macrocode} % %\begin{variable}{\c_@@_cmdproxy_str} %Proxy used to generate styled commands % \begin{macrocode} \str_const:Nx \c_@@_cmdproxy_str { \object_address:nn { stycmd }{ proxy } } \proxy_create:nn { stycmd }{ proxy } \proxy_push_member:Vnn \c_@@_cmdproxy_str { default }{ tl } % \end{macrocode} %\end{variable} % %\begin{macro}{\@@_cmd:n} % Entity name % \begin{macrocode} \cs_new:Nn \@@_cmd:n { \object_address:nn{ stycmd }{ entity - #1 } } % \end{macrocode} %\end{macro} % %\begin{macro}{\@@_setdef_strip:Nn} %Changes the default style % \begin{macrocode} \cs_new_protected:Nn \@@_setdef_aux:nN { \object_member_set:nnn { \@@_cmd:n{ #1 } } { default } { #2 } } \cs_generate_variant:Nn \@@_setdef_aux:nN { nc } \cs_new_protected:Nn \@@_setdef_style:nn { \@@_setdef_aux:nc{ #1 } { \object_macro_adr:nn { \@@_cmd:n{ #1 } } { style - #2 } } } \cs_generate_variant:Nn \@@_setdef_style:nn { ff } \cs_new_protected:Nn \@@_setdef_strip:Nn { \@@_setdef_style:ff{ \cs_to_str:N #1 } { \tl_trim_spaces:n{ #2 } } } % \end{macrocode} %\end{macro} % %\begin{macro}{\@@_cmd_define_strip:NNn} % Define a macro with the specified command % \begin{macrocode} \cs_new_protected:Nn \@@_cmd_define_aux_aux:NN { #1 { #2 } } \cs_generate_variant:Nn \@@_cmd_define_aux_aux:NN { Nc } \cs_new_protected:Nn \@@_cmd_define_aux:Nnn { \@@_cmd_define_aux_aux:Nc #1 { \object_macro_adr:nn { \@@_cmd:n{ #2 } } { style - #3 } } } \cs_generate_variant:Nn \@@_cmd_define_aux:Nnn { Nff } \cs_new_protected:Nn \@@_cmd_define_strip:NNn { \@@_cmd_define_aux:Nff #1 { \cs_to_str:N #2 }{ \tl_trim_spaces:n { #3 } } } % \end{macrocode} %\end{macro} % %\begin{macro}{\@@_cmd_usedef:N, \@@_cmd_usesty_strip:Nn} %Uses the styled command % \begin{macrocode} \cs_new:Nn \@@_cmd_usedef_aux:n { \object_member_use:nn { \@@_cmd:n{ #1 } } { default } } \cs_generate_variant:Nn \@@_cmd_usedef_aux:n { f } \cs_new:Nn \@@_cmd_usedef:N { \@@_cmd_usedef_aux:f{ \cs_to_str:N #1 } } \cs_new:Nn \@@_cmd_usesty_aux:nn { \object_macro_use:nn { \@@_cmd:n{ #1 } } { style - #2 } } \cs_generate_variant:Nn \@@_cmd_usesty_aux:nn { ff } \cs_new:Nn \@@_cmd_usesty_strip:Nn { \@@_cmd_usesty_aux:ff{ \cs_to_str:N #1 } { \tl_trim_spaces:n{ #2 } } } % \end{macrocode} %\end{macro} % % \begin{macro}{\@@_entity_create_strip:Nnn} % Creates a new entity if it doesn't exists and execute following code % \begin{macrocode} \cs_new_protected:Nn \@@_entity_create_aux:nnn { \object_if_exist:nF { \@@_cmd:n{ #1 } } { \object_create:Vnn \c_@@_cmdproxy_str { stycmd }{ entity - #1 } \@@_setdef_style:nn{ #1 }{ #2 } #3 } } \cs_generate_variant:Nn \@@_entity_create_aux:nnn { ffn } \cs_new_protected:Nn \@@_entity_create_strip:Nnn { \@@_entity_create_aux:ffn { \cs_to_str:N #1 } { \tl_trim_spaces:n{ #2 } } { #3 } } % \end{macrocode} % \end{macro} % %\begin{macro}{\stycmd_xparsecmd:N} % Defines the main macro with \cs{ProvideDocumentCommand}. % \begin{macrocode} \cs_new_protected:Nn \stycmd_xparsecmd:N { \ProvideDocumentCommand { #1 } { o } { \IfNoValueTF {##1} { \@@_cmd_usedef:N #1 } { \@@_cmd_usesty_strip:Nn #1 { ##1 } } } } % \end{macrocode} %\end{macro} % %\begin{macro}{\stycmd_expcmd:N} % Defines the main macro with \tn{providecommand} but the style argument is mandatory in order to make the command expandable. To use default style pass an empty argument as style. % \begin{macrocode} \cs_new_protected:Nn \stycmd_expcmd:N { \providecommand { #1 } [1] { \tl_if_empty:nTF {##1} { \@@_cmd_usedef:N #1 } { \@@_cmd_usesty_strip:Nn #1 { ##1 } } } } % \end{macrocode} %\end{macro} % %\begin{macro}{\SetGlobalStyle} %Change the default style for specified command % \begin{macrocode} \NewDocumentCommand{\SetGlobalStyle}{m m} { \@@_setdef_strip:Nn #1 { #2 } } % \end{macrocode} %\end{macro} % %\begin{macro}{\stycmd_generate:NNN, \stycmd_generate:NN, \stycmd_generate_renew:NN} %Declare the styled version \verb+#1+ of the macro generator command \verb+#2+. the \verb+_renew+ variant requires a preceding declaration % \begin{macrocode} \cs_new_protected:Nn \stycmd_generate:NNN { \cs_new_protected:Npn #1 ##1 ##2 { \@@_entity_create_strip:Nnn ##1 { ##2 } { #3 ##1 } \@@_cmd_define_strip:NNn #2 ##1 { ##2 } } } \cs_new_protected:Nn \stycmd_generate:NN { \stycmd_generate:NNN #1 #2 \stycmd_xparsecmd:N } \cs_new_protected:Nn \stycmd_generate_renew:NN { \cs_new_protected:Npn #1 ##1 ##2 { \@@_cmd_define_strip:NNn #2 ##1 { ##2 } } } % \end{macrocode} %\end{macro} % %\begin{macro}{\newstyledcmd, \renewstyledcmd, \providestyledcmd} %Declare a new macro with the specified style name. % \begin{macrocode} \stycmd_generate:NN \newstyledcmd \newcommand \stycmd_generate_renew:NN \renewstyledcmd \renewcommand \stycmd_generate:NN \providestyledcmd \providecommand % \end{macrocode} %\end{macro} % %\begin{macro}{\NewDocStyledCMD, \RenewDocStyledCMD, \ProvideDocStyledCMD} %Declare a new styled macro with the \tn{NewDocumentCommand} syntax. % \begin{macrocode} \stycmd_generate:NN \NewDocStyledCMD \NewDocumentCommand \stycmd_generate_renew:NN \RenewDocStyledCMD \RenewDocumentCommand \stycmd_generate:NN \ProvideDocStyledCMD \ProvideDocumentCommand % \end{macrocode} %\end{macro} % %\begin{macro}{\newstyledcmdExp, \renewstyledcmdExp, \providestyledcmdExp} %Declare a new macro with the specified style name. % \begin{macrocode} \stycmd_generate:NNN \newstyledcmdExp \newcommand \stycmd_expcmd:N \stycmd_generate_renew:NN \renewstyledcmdExp \renewcommand \stycmd_generate:NNN \providestyledcmdExp \providecommand \stycmd_expcmd:N % \end{macrocode} %\end{macro} % %\begin{macro}{\AddCMDToGroup} %Creates a group of commands % \begin{macrocode} \str_new:N \g_@@_grproxy_str \seq_new:N \g_@@_tmp_seq \seq_new:N \g_@@_tmpb_seq \proxy_create_gset:Nnn \g_@@_grproxy_str { stycmd }{ groups } \proxy_push_member:Vnn \g_@@_grproxy_str { commands }{ seq } \cs_generate_variant:Nn \seq_gconcat:NNN { ccN } \cs_new_protected:Nn \@@_gconcat:nN { \seq_gconcat:ccN { #1 }{ #1 } #2 } \cs_new_protected:Nn \@@_addgroup:nn { \object_if_exist:nF { \object_address:nn{ stycmd }{ group - #1 } } { \object_create:Vnn \g_@@_grproxy_str { stycmd } { group - #1 } } \seq_gset_from_clist:Nn \g_@@_tmp_seq { #2 } \seq_gset_map_x:NNn \g_@@_tmpb_seq \g_@@_tmp_seq { \cs_to_str:N ##1 } \@@_gconcat:nN { \object_member_adr:nnn { \object_address:nn { stycmd } { group - #1 } } { commands } { seq } } \g_@@_tmpb_seq } \cs_generate_variant:Nn \@@_addgroup:nn { fn } \NewDocumentCommand{\AddCMDToGroup}{m m} { \@@_addgroup:fn { \tl_trim_spaces:n{ #1 } } { #2 } } % \end{macrocode} %\end{macro} % %\begin{macro}{\SetGroupStyle} %Change the default style for each command in the group. % \begin{macrocode} \NewDocumentCommand{\SetGroupStyle}{m m} { \seq_map_inline:cn { \object_member_adr:nnn { \object_address:nn { stycmd } { group - #1 } } { commands } { seq } } { \@@_setdef_style:nn{ ##1 }{ #2 } } } % \end{macrocode} %\end{macro} % %Legacy commands % \begin{macrocode} \msg_new:nnnn{ styledcmd }{ stydep }{ Old-fashioned~groups~for~styled~commands~are~deprecated } { From~version~2.0~of~styledcmd~you~should~use~new~group~commands~instea~of~old~ones,~see~official~documentation~on~CTAN. } \str_new:N \g_@@_act_group_str \str_new:N \g_@@_act_style_str \NewDocumentCommand{\styBeginGroup}{ m } { \msg_warning:nn{ styledcmd }{ stydep } \str_gset:Nn \g_@@_act_group_str{ #1 } } \NewDocumentCommand{\styEndGroup}{} { \msg_warning:nn{ styledcmd }{ stydep } \str_gset:Nn \g_@@_act_group_str{} } \NewDocumentCommand{\styBeginStyle}{ m } { \msg_warning:nn{ styledcmd }{ stydep } \str_gset:Nn \g_@@_act_style_str{ #1 } } \NewDocumentCommand{\styEndStyle}{} { \msg_warning:nn{ styledcmd }{ stydep } \str_gset:Nn \g_@@_act_style_str{} } \cs_generate_variant:Nn \@@_addgroup:nn { Vn } \NewDocumentCommand{\newGstyledcmd}{m o m} { \msg_warning:nn{ styledcmd }{ stydep } \@@_addgroup:Vn \g_@@_act_group_str { #1 } \IfNoValueTF{ #2 } { \exp_args:NNV \newstyledcmd #1 \g_@@_act_style_str { #3 } } { \exp_args:NNV \newstyledcmd #1 \g_@@_act_style_str [ #2 ] { #3 } } } \NewDocumentCommand{\NewGDocStyledCMD}{m m m} { \msg_warning:nn{ styledcmd }{ stydep } \@@_addgroup:Vn \g_@@_act_group_str { #1 } \exp_args:NNV \NewDocStyledCMD #1 \g_@@_act_style_str { #2 } { #3 } } \NewDocumentCommand{\setGroupStyle}{m m} { \msg_warning:nn{ styledcmd }{ stydep } \SetGroupStyle{ #1 }{ #2 } } % \end{macrocode} % % \begin{macrocode} % % \end{macrocode} % %\end{implementation} % %\PrintIndex