% \iffalse meta-comment % % Copyright (C) 2023-20** by Romain NOEL % ----------------------------------------------------------- % % This file may be distributed and/or modified under the conditions of % the LaTeX Project Public License, either version 1.3c 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.3c or later is part of all distributions of LaTeX % version 2006/05/20 or later. % % \fi % % \iffalse %<*driver> \ProvidesFile{tensorstyles.dtx} % %<*internal> \input expl3-generic \relax % %\NeedsTeXFormat{LaTeX3e} %\ProvidesExplPackage{tensorstyles}{2026-04-28}{1.0.1.4}{This package provides a generic customable display of tensors.} %Romain NOEL %Romain NOEL %https://gitlab.com/RomainNOEL/tensorstyles % % This package let you display your tensors according to their order in a generic way. This let you choose and change options of display according to the context. % % %<*driver> \documentclass{l3doc} \usepackage[T1]{fontenc} \usepackage{pdfpages} \usepackage{standalone} \usepackage{tensorstyles} % \usepackage{readprov} % \ReadPackageInfos{tensorstyles} \edef\tensorstylesVersion{v1.0.1.4} %{\fileversion} \edef\tensorstylesDate{2026-04-28} %{\filedate} \usepackage{parskip} \usepackage{setspace} \usepackage{xspace} \onehalfspacing \usepackage{xcolor} \definecolor{tPrim}{HTML}{00707F} % Green-Blue \definecolor{tSec}{HTML}{5FA4B0} % Green-Blue light \definecolor{tAccent}{HTML}{F07F3C} % Orange \definecolor{tGrey}{HTML}{E6E6E1} % Grey-Beige % \usepackage{fancyvrb} \usepackage{listings} \lstset{ language=[LaTeX]{TeX}, basicstyle=\ttfamily, keywordstyle=\color{tPrim}\bfseries, commentstyle=\color{tSec}, stringstyle=\color{tSec}, backgroundcolor=\color{white}, numbers=none, numberstyle=\tiny\ttfamily, stepnumber=2, showspaces=false, showstringspaces=false, showtabs=false, frame=none, framerule=1pt, tabsize=2, rulesep=5em, captionpos=b, breaklines=true, breakatwhitespace=false, framexleftmargin=0em, framexrightmargin=0em, xleftmargin=0em, xrightmargin=0em, aboveskip=1em, belowskip=1em, morekeywords={plain,tensorsset}, } \lstMakeShortInline| \usepackage{hyperref} \setlength{\fboxsep}{0pt}% \usepackage{subcaption} % For subfigures \usepackage{cleveref} % for references \providecommand{\defopt}[1]{\underline{#1}}%{default: #1}% \NewDocumentEnvironment{DescribetensorstylesOption}{ o m m m }{ % At beginning of the environment \DescribeOption{#2} % from l3doc \IfNoValueTF{#1}{ % true => left empty intentionally }{ %false \DescribeOption{ % add extra info like added or updated dates to mimic 'function' env. \rule[2.5ex]{\linewidth}{0.3pt} \\[-3.5ex] {\scriptsize #1 \hfill\ } } } \begin{minipage}[t]{\textwidth} \textit{\textbf{\textcolor{tSec}{#3}}}\dotfill\,\defopt{#4}\par \begingroup \vspace{0.5em} }{ % At environment's end \par \endgroup \end{minipage} } %% ===================================================================== \title{\textsc{ tensorstyles }\\ This package provides a generic customable display of tensors. } \author{Romain NOEL \\ \url{romainoel@free.fr}} \date{\tensorstylesVersion~---~\tensorstylesDate} \providecommand{\pkgName}{\textbf{\textsc{tensorstyles}}\xspace} %% ===================================================================== %% l3doc commands \EnableCrossrefs \CodelineIndex \RecordChanges \begin{document} \input{tensorstyles-doc.tex} \clearpage %\section{A simple example} % \includepdf[pages=-, % pagecommand=\section{A simple example}, % width=0.7\textwidth] % {tensorstyles-exampleSimple.pdf} \section{Commands description for users} \EnableDocumentation \DisableImplementation \DocInput{\jobname.dtx} \newpage \section{Package implementation for developers} \EnableImplementation \DisableDocumentation \GetFileInfo{\jobname.sty} \DocInput{\jobname.dtx} \PrintChanges \end{document} % % %<*devImpl> \documentclass{l3doc} \usepackage[T1]{fontenc} \usepackage{pdfpages} \usepackage{standalone} \usepackage{tensorstyles} \providecommand{\defopt}[1]{\underline{#1}} % l3doc commands \EnableCrossrefs \CodelineIndex \RecordChanges \begin{document} \section{Commands description for users} \EnableImplementation \DisableDocumentation \DocInput{tensorstyles.dtx} \end{document} % % % %<*userCmd> \documentclass{l3doc} \usepackage[T1]{fontenc} \usepackage{pdfpages} \usepackage{standalone} %\usepackage{tensorstyles} \providecommand{\defopt}[1]{\underline{#1}} % l3doc commands \EnableCrossrefs \CodelineIndex \RecordChanges \begin{document} \section{Package implementation for developers} \EnableDocumentation \DisableImplementation \DocInput{tensorstyles.dtx} \end{document} % % % \fi % % % \begin{implementation} % \begin{macrocode} %<*package> %\ProvidesExplPackage{tensorstyles}{2026-04-28}{1.0.1.4}{This package provides a generic customable display of tensors.} \RequirePackage{expl3} % \RequirePackage{xparse,l3keys2e}% depreciated now. \RequirePackage{amsmath}% \overrightarrow \RequirePackage{amssymb}% \curvearrowright % \RequirePackage{bm}% recommended for bold math \RequirePackage{mathtools}% for \mathmakebox % \end{macrocode} % \end{implementation} % %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %%%%%%%%%%%% PACKAGE %%%%%%%%%%%%% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % \begin{implementation} % \begin{variable}{\c__tensorstyles_digits_tl} % Constant variables containing the digits. % \changes{v0.1.1.2}{2025-02-17}{original version} % \begin{macrocode} \tl_const:Nn \c__tensorstyles_digits_tl {123456789-0} % \end{macrocode} % \end{variable} % \end{implementation} % \begin{documentation} % \begin{macro}{\usepackage[options]{tensorstyles}} % \begin{syntax} % \cs{usepackage{}}\oarg{option1=value1, ...}\marg{tensorstyles} % \textrm{where the options are (default marked as} \defopt{default}\textrm{):} % \meta{footer template} = \oarg{\defopt{tensorstyles} \textbar ... } % \end{syntax} % Description of |usepackage{tensorstyles}| which loads the package. % \end{macro} % \end{documentation} %%%% % \begin{implementation} % \begin{macro}{\usepackage[options]{tensorstyles} } % \begin{arguments} % \item |no package option| are present for now. % \end{arguments} % Description % \changes{v0.1.1.2}{2025-02-17}{original version} % \UnitTested % \TestFiles{tensorstyles-test-003} % \begin{macrocode} % Define keys/options for the package. \keys_define:nn { tensorstyles / pkg } { % italic .choice:, % italic .usage:n = { load }, % italic .default:n = { true }, % italic / true .code:n = % { % \bool_set_true:N \l__tensorstyles_pkg_italic_bool % \bool_set_false:N \l__tensorstyles_pkg_upright_bool % }, % italic / false .code:n = % { % \bool_set_false:N \l__tensorstyles_pkg_italic_bool % \bool_set_true:N \l__tensorstyles_pkg_upright_bool % }, % italic / unknown .code:n = { \msg_error:nnx { tensorstyles } { boolean-values-only } \l_keys_key_str }, % % % upright .choice:, % upright .usage:n = { load }, % upright .default:n = { true }, % upright / true .code:n = % { % \bool_set_true:N \l__tensorstyles_pkg_upright_bool % \bool_set_false:N \l__tensorstyles_pkg_italic_bool % }, % upright / false .code:n = % { % \bool_set_false:N \l__tensorstyles_pkg_upright_bool % \bool_set_true:N \l__tensorstyles_pkg_italic_bool % }, % upright / unknown .code:n = { \msg_error:nnx { tensorstyles } { boolean-values-only } \l_keys_key_str }, % upright .initial:n = true, } % process the options. \ProcessKeyOptions[ tensorstyles / pkg ] % \end{macrocode} % \end{macro} % \end{implementation} %%%%%% Key-val: tensorstyles %%%%%% % \begin{implementation} % \begin{variable}{\l__tensorstyles_all_all_user_keys_prop, \c__tensorstyles_all_pkg_keys_prop} % Property list containing the default value for options that are share by all command groups; and a list that will receive the values given by users for these options. % \changes{v0.1.1.2}{2025-02-17}{original version} % \TestFiles{tensorstyles-test-003} % \begin{macrocode} \prop_const_from_keyval:Nn \c__tensorstyles_all_pkg_keys_prop {scale-auto = leftright} \prop_new:N \l__tensorstyles_all_all_user_keys_prop % \end{macrocode} % \end{variable} % \end{implementation} % \begin{documentation} % \begin{macro}{\tensorsset{all}[options]} % \begin{syntax} % \cs{nameMacro}\oarg{option1=value1, ...}\marg{tensor-cmd} % \textrm{where the options are (default marked as} \defopt{default}\textrm{):} % \meta{scale-auto} = \oarg{\defopt{leftright} \textbar auto } % \end{syntax} % The option |scale-auto| that can be set for all command groups, can take |leftright| or |mleftmright| values. % This option is controlling the delimiters to use in auto mode (|\left\right| or |\mleft| |\mright| from |mleftright| package). % \end{macro} % \end{documentation} %%%% % \begin{implementation} % \begin{macro}{\tensorsset{all}[options]} % \begin{arguments} % \item |width| Name of the option to add, this name should also correspond to the name of the environment followed by the suffix 'env'. % \end{arguments} % Option available for all command groups controlling the delimiters in automatic scale mode. % \changes{v0.1.1.2}{2025-02-17}{original version} % \UnitTested % \TestFiles{tensorstyles-test-005} % \begin{macrocode} % Define the options for all group commands (package included). \keys_define:nn { tensorstyles / all / all } { scale-auto .choice:, scale-auto / leftright .code:n = { \cs_set_eq:NN \__tensorstyles_auto_left:n \left \cs_set_eq:NN \__tensorstyles_auto_right:n \right }, scale-auto / mleftmright .code:n = { \cs_set_nopar:Npn \__tensorstyles_auto_left:n { \mleft } \cs_set_nopar:Npn \__tensorstyles_auto_right:n { \mright } } } % \end{macrocode} % \end{macro} % \end{implementation} % \begin{implementation} % \begin{variable}{\l__tensorstyles_new_var_seq} % Local sequence storing new variables names to create. % \changes{v0.1.1.2}{2025-02-17}{original version} % \begin{macrocode} \seq_new:N \l__tensorstyles_new_var_seq % \end{macrocode} % \end{variable} % \end{implementation} % \begin{implementation} % \begin{function}[added= 2025-02-17]{\__tensorstyles_new} % \begin{arguments} % \item |variable-type| eg. "tl" (token list), "dim", "seq", etc. % \item |grp-cmd+variant| eg. "$tensor_tensor$" % \item |variable-category| eg. "style" % \item |cs-var-list| comma separated list of variable names to create. % \end{arguments} % This function is creating the local variables |\l__tensorstyles_'type'_'variant'_'cat'_'var'| for all the variable names given in the argument 4 (|cs-var-list|). % \changes{v0.1.1.2}{2025-02-17}{original version} % \TestFiles{tensorstyles-test-005} % \begin{macrocode} \cs_new:Npn \__tensorstyles_new:nnnn #1 #2 #3 #4 { \seq_set_from_clist:Nn \l__tensorstyles_new_var_seq { #4 } \seq_map_inline:Nn \l__tensorstyles_new_var_seq { \cs:w #1_new:c \cs_end: { l__tensorstyles_#2_#3_##1_#1 } } } % \end{macrocode} % \end{function} % \end{implementation} % % %%%%% Setting keys %%%%% % % \begin{implementation} % \begin{function}[added= 2025-02-17]{\__tensorstyles_set_default_from_keyval} % \begin{arguments} % \item |variable-type| eg. tl (token list), dim, seq etc. % \item |preset| eg. preset % \item |keyval| the option given % \item |cs-var-list| comma separated list of variable names to create. % \end{arguments} % This function is setting the default keys/options from a list of keyval. % \changes{v0.1.1.2}{2025-02-17}{original version} % \TestFiles{tensorstyles-test-005} % \begin{macrocode} % \__tensorstyles_set_default_from_keyval: variant, preset, keyval, group command \cs_new_protected:Npn \__tensorstyles_set_default_from_keyval:nnnn #1 #2 #3 #4 { % tensorstyles~set~default~from~keyval % Check if keyvalues have been given. \tl_if_novalue:nTF { #3 } { % no user keys given so _user_keys_prop is taking pkg prop \prop_set_eq:cc { l__tensorstyles_#4_#1_user_keys_prop } { c__tensorstyles_#4_#2_pkg_keys_prop } }{ % user key given and put it in prop \prop_put_from_keyval:cn { l__tensorstyles_#4_#1_user_keys_prop } { #3 } }% end if % % prepare the map of keys \__tensorstyles_set_default_auxi:cnn { l__tensorstyles_#4_#1_user_keys_prop } { #1 } { #4 } % % set this map as default \keys_set:nn { tensorstyles/#4/#1 } { default } } \cs_generate_variant:Nn \__tensorstyles_set_default_from_keyval:nnnn { nVnn } % \end{macrocode} % \end{function} % \end{implementation} % \begin{implementation} % \begin{function}[added= 2025-02-17]{\__tensorstyles_set_default_auxi, \__tensorstyles_set_default_auxii} % \begin{arguments} % \item |prop-key-val| eg. tl (token list), dim, seq etc. % \item |variant| eg. 'options=toto' % \item |grp-cmd| eg. "style" % \end{arguments} % These functions are internally used to set the default keys/options. % \changes{v0.1.1.2}{2025-02-17}{original version} % \TestFiles{tensorstyles-test-005} % \begin{macrocode} \cs_new_protected:Npn \__tensorstyles_set_default_auxi:Nnn #1 #2 #3 { \__tensorstyles_set_default_auxii:fnn { \prop_to_keyval:N #1 } { #2 } { #3 } } \cs_generate_variant:Nn \__tensorstyles_set_default_auxi:Nnn { c } % % key-val, variant, group command \cs_new_protected:Npn \__tensorstyles_set_default_auxii:nnn #1 #2 #3 { \keys_define:nn { tensorstyles/#3/#2 } { default .meta:n = { #1 } } } \cs_generate_variant:Nn \__tensorstyles_set_default_auxii:nnn { f } % \end{macrocode} % \end{function} % \end{implementation} % \begin{implementation} % \begin{function}[added= 2025-02-17]{\tensorsset} % \begin{arguments} % \item |command| for which options will be set or reset. % \item |options| input given as setting options. % \end{arguments} % Function to (re)set keys/options by default for a group of commands. % \changes{v0.1.1.2}{2025-02-17}{original version} % \TestFiles{tensorstyles-test-005} % \begin{macrocode} % \tensorsset m:command:#1 o:options:#2 \DeclareDocumentCommand{\tensorsset}{ m o } { \str_if_eq:nnTF { #1 } { all } { % True: if the 'all' commands have to be set. \__tensorstyles_set_default_from_keyval:nnnn { all } {empty} { #2 } { all } \keys_set:nn { tensorstyles/all/all } { default } }{ %False: if the command name is given then apply to it: % capture the command name. \tl_set:Nx \l__tensorstyles_tensorsset_tl { \cs_to_str:N #1 } % apply option to the command. \tensorstyles_set_keys:Vn \l__tensorstyles_tensorsset_tl { #2 } } } % \end{macrocode} % \end{function} % \end{implementation} % \begin{implementation} % \begin{function}[added= 2025-02-17]{\tensorstyles_local_keys} % \begin{arguments} % \item |keyval| for which options will be set or reset. % \item |grp-cmd| input given as setting options. % \item |command| input given as setting options. % \item |preset| of options. % \end{arguments} % Set options according to the keys-value given by the user locally. % This command is used in the code definition of the 'command'-group, ie., is called every time the 'command' is called. % \changes{v0.1.1.2}{2025-02-17}{original version} % \TestFiles{tensorstyles-test-005} % \begin{macrocode} % tensorstyles_local_keys:nnnn #1=keyval, #2=group-command, #3=command, #4=preset \cs_new_protected:Npn \tensorstyles_local_keys:nnnn #1 #2 #3 #4 { % in tensorstyles~local~keys \tl_set:Ne \l_tmpa_tl { #4 } \tl_if_novalue:nTF { #1 } { % keyval NOT given \bool_if:cT { l__tensorstyles_#2_#3_local_keys_bool } { % True \keys_set:nV { tensorstyles/#2/#3 } \l_tmpa_tl \bool_set_false:c { l__tensorstyles_#2_#3_local_keys_bool } } }{ % keyvalue given \bool_if:cTF { l__tensorstyles_#2_#3_local_keys_bool } { % True \tl_put_right:Nn \l_tmpa_tl { , #1 } % append #1 unexpanded \keys_set:nV { tensorstyles/#2/#3 } \l_tmpa_tl }{ % False \tl_put_right:Nn \l_tmpa_tl { , #1 } % append #1 unexpanded \keys_set:nV { tensorstyles/#2/#3 } \l_tmpa_tl } \bool_set_true:c { l__tensorstyles_#2_#3_local_keys_bool } } } \cs_generate_variant:Nn \keys_set:nn { nV } % \end{macrocode} % \end{function} % \end{implementation} % \begin{implementation} % \begin{function}[added= 2025-02-17]{\tensorstyles_local_preset } % \begin{arguments} % \item |keyval| for which options will be set or reset. % \item |grp-cmd| input given as setting options. % \item |preset| of options. % \item |variant| of options. % \end{arguments} % Set options according to the keys-value given by the user locally. % This command is used in the code definition of the 'command'-group, ie., is called every time the 'command' is called. % \changes{v0.1.1.2}{2025-02-17}{original version} % \TestFiles{tensorstyles-test-005} % \begin{macrocode} % tensorstyles_local_preset:nnn #1=group-command, #2=preset, #3=star-preset #4=variant \cs_new_protected:Npn \tensorstyles_local_preset:nVVnn #1 #2 #3 #4 { \tl_if_eq:NnTF { #2 } { None } { \keys_define:nn { tensorstyles/tensor/#1 } { pres .meta:n = { default }} } { \prop_set_eq:cc { l__tensorstyles_#4_#1_user_keys_prop } { c__tensorstyles_#4_#2_pkg_keys_prop } \keys_define:nn { tensorstyles/tensor/#1 } { pres .code:n = { \prop_map_inline:cn { l__tensorstyles_#4_#1_user_keys_prop } { \keys_set:nn { tensorstyles/tensor/#1 } { ####1 = {####2} } } } } } \tl_if_eq:NnTF { #3 } { None } { \keys_define:nn { tensorstyles/tensor/#1 } { pres* .meta:n = { default }} } { \prop_set_eq:cc { l__tensorstyles_#4_#1*_user_keys_prop } { c__tensorstyles_#4_#3_pkg_keys_prop } \keys_define:nn { tensorstyles/tensor/#1 } { pres* .code:n = { \prop_map_inline:cn { l__tensorstyles_#4_#1*_user_keys_prop } { \keys_set:nn { tensorstyles/tensor/#1 } { ####1* = {####2} } } } } } } % \end{macrocode} % \end{function} % \end{implementation} % \begin{implementation} % \begin{function}[added= 2025-02-17]{\tensorstyles_addto_globalvar_and_setkeys:NNnnn} % \begin{arguments} % \item |tl-tensor| token list used to concatenate the name of the command. % \item |macro| input given as setting options. % \item |command| input given as setting options. % \item |keyval| for which options will be set or reset. % \item |grp-cmd| input given as setting options. % \end{arguments} % Set options according to the keys-value given by the user locally. % This command is used in the code definition of the 'command'-group, ie., is called every time the 'command' is called. % \changes{v0.1.1.2}{2025-02-17}{original version} % \TestFiles{tensorstyles-test-005} % \begin{macrocode} % % \tensorstyles_addto_globalvar_and_setkeys:NNnnn #1=tl-tensor, #2=macro, #3=inf, #4=keyval, #5=group command \cs_new_protected:Npn \tensorstyles_addto_globalvar_and_setkeys:NNnnn #1 #2 #3 #4 #5 { % store \tl_set:Nx #1 { \cs_to_str:N #2 } % Check if the keyval has values. \tl_if_novalue:nTF { #4 } { % if empty then create the variables by default. \__tensorstyles_preamble_aux:Vnnnn #1 { empty } { empty } { } { #5 } }{ % otherwise, create then set the variables. \use:c { __tensorstyles_#5_define_preset_keys:n } { #1 } \keys_set:nn {tensorstyles/preset/#1} { #4 } \tl_set:Nx \l_tmpa_tl { \tl_use:c { l__tensorstyles_tensor_#1_preset } } \tl_set:Nx \l_tmpb_tl { \tl_use:c { l__tensorstyles_tensor_#1*_preset } } \__tensorstyles_preamble_aux:VVVnn #1 \l_tmpa_tl \l_tmpb_tl { #4 } { #5 } % \__tensorstyles_preamble_aux:Veenn #1 { full } { empty } { #4 } { #5 } } } % % \__tensorstyles_preamble_aux:nnnn #1=variant, #2=preset, #3=star-preset, #4=key-value, #5=grp-cmd \cs_new_protected:Npn \__tensorstyles_preamble_aux:nnnnn #1 #2 #3 #4 #5 { % Check if the command is in the global sequence \seq_if_in:cnF { l__tensorstyles_#5_variant_seq } { #1 } { % if not present % add the command to the sequence \seq_put_left:cn { l__tensorstyles_#5_variant_seq } { #1 } % create new variables (tl) for the new command \use:c { __tensorstyles_#5_variables:n } { #1 } \use:c { __tensorstyles_#5_variables:n } { #1* } % define keys for this command \use:c { __tensorstyles_#5_define_keys:n } { #1 } \use:c { __tensorstyles_#5_define_keys:n } { #1* } } % Apply package options \prop_set_eq:cc { l__tensorstyles_#5_#1_user_keys_prop } { c__tensorstyles_#5_#2_pkg_keys_prop } \prop_set_eq:cc { l__tensorstyles_#5_#1*_user_keys_prop } { c__tensorstyles_#5_#3_pkg_keys_prop } % Apply the newly given options by default \__tensorstyles_set_default_from_keyval:nnnn { #1* } { #3 } { } { #5 } \__tensorstyles_set_default_from_keyval:nnnn { #1 } { #2 } { #4 } { #5 } } \cs_generate_variant:Nn \__tensorstyles_preamble_aux:nnnnn { VVVnn } \cs_generate_variant:Nn \__tensorstyles_preamble_aux:nnnnn { V } % \end{macrocode} % \end{function} % \end{implementation} % % %%%%%% 'TENSOR' GROUP COMMAND CODE %%%%%% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % % \begin{implementation} % \begin{variable}[added= 2025-02-17]{\l__tensorstyles_tensor_variant_seq, \l__tensorstyles_tensor_rank_holder_tl, \l__tensorstyles_tensor_rank_counter_int} % |\l__tensorstyles_tensor_variant_seq| is a sequence to store all the command of this type. % |\l__tensorstyles_tensor_rank_holder_tl| is storing the value of the tensor rank given. % |\l__tensorstyles_tensor_rank_counter_int| is storing the local value of the rank counter (as Einstein indices are running for example). % \changes{v0.1.1.2}{2025-02-17}{original version} % \begin{macrocode} \seq_new:N \l__tensorstyles_tensor_variant_seq \tl_new:N \l__tensorstyles_tensor_rank_holder_tl \int_new:N \l__tensorstyles_tensor_rank_counter_int % \end{macrocode} % \end{variable} % \end{implementation} % \begin{implementation} % \begin{function}[added= 2025-02-17]{\__tensorstyles_tensor_variables:n} % \begin{arguments} % \item |variant| for which variables have to be declared. % \end{arguments} % Define variables of the `tensor` command-group, according to the keys-value given by the user locally. % \changes{v0.1.1.2}{2025-02-17}{original version} % \TestFiles{tensorstyles-test-005} % \begin{macrocode} % Define variables for the tensor group. % \__tensorstyles_tensor_variables:n variant \cs_new_protected:Npn \__tensorstyles_tensor_variables:n #1 { %%\__tensorstyles_new:nnnn data-type, grp-cmd+variant, category, cs-var-list % % switch \__tensorstyles_new:nnnn { bool } {tensor_#1} { switch } { star } \__tensorstyles_new:nnnn { bool } {tensor_#1} { switch } { font, einstein, dirac, arrows, recursiveArrows } % % font \__tensorstyles_new:nnnn { prop } {tensor_#1} { font } { cmd } % Einstein \__tensorstyles_new:nnnn { tl } {tensor_#1} { indexstyle } { covariant, contra } % arrows \__tensorstyles_new:nnnn { prop } {tensor_#1} { arrow } { cmd } % recursive arrows \__tensorstyles_new:nnnn { tl } {tensor_#1} { recursive } { arrowCmd } % Dirac bra-ket \__tensorstyles_new:nnnn { tl } {tensor_#1} { scale } { var } \__tensorstyles_new:nnnn { tl } {tensor_#1} { delims } { eval } % keys \__tensorstyles_new:nnnn { prop } {tensor_#1} { user } { keys } \__tensorstyles_new:nnnn { bool } {tensor_#1} { local } { keys } } % \end{macrocode} % \end{function} % \end{implementation} % \begin{implementation} % \begin{macro}[added= 2025-02-17]{\__tensorstyles_tensor_define_keys:n} % \begin{arguments} % \item |variant| for which key corresponding the command associated, have to be declared. % \end{arguments} % Set options for the `tensor` group-command according to the keys-value given by the user locally. % \changes{v0.1.1.2}{2025-02-17}{original version} % \TestFiles{tensorstyles-test-005} % \begin{macrocode} % Define keys/options for tensor group command style. % \__tensorstyles_tensor_define_keys:n variant \cs_new:Npn \__tensorstyles_tensor_define_keys:n #1 { \keys_define:nn { tensorstyles/tensor/#1 } { switch-* .bool_set:c = { l__tensorstyles_tensor_#1_switch_star_bool }, preset .code:n = {}, deduce-var .tl_set:c = { l__tensorstyles_tensor_#1_deduce_var_tl }, % font font .bool_set:c = { l__tensorstyles_tensor_#1_switch_font_bool }, font-cmd .code:n = { \prop_set_from_keyval:cn { l_tensorstyles_tensor_#1_font_cmd_prop } {##1} }, % arrow arrows .bool_set:c = { l__tensorstyles_tensor_#1_switch_arrows_bool }, arrow-cmd .code:n = { \prop_set_from_keyval:cn { l_tensorstyles_tensor_#1_arrow_cmd_prop } {##1} }, recursive-arrows .bool_set:c = { l__tensorstyles_tensor_#1_switch_recursiveArrows_bool }, recurs-arrows-cmd .tl_set:c = { l__tensorstyles_tensor_#1_recursive_arrowCmd_tl }, % bra-ket bra-ket .bool_set:c = { l__tensorstyles_tensor_#1_switch_dirac_bool }, scale-var .choices:nn = { auto, none, big, Big, bigg, Bigg } { \__tensorstyles_set_scale:nnn {tensor_#1} {##1} { var } }, scale-var .default:n = { auto }, scale-var .initial:n = { auto }, delims-var .tl_set:c = { l__tensorstyles_tensor_#1_delims_var_tl }, mix-delims .bool_set:c = { l__tensorstyles_tensor_#1_mix_delimiter_bool }, % Einstein contra-variant .bool_set:c = { l__tensorstyles_tensor_#1_switch_einstein_bool }, % \__tensorstyles_set_index_style:nnn #1= grp-cmd variant, #2= covariant or contra, #3= option selected, covariant-style .choices:nn = { alph, arabic, greek } { \__tensorstyles_set_index_style:nnn {#1} {covariant} {##1} }, covariant-style .default:n = { greek }, covariant-style .initial:n = { greek }, contra-style .choices:nn = { alph, arabic, greek } { \__tensorstyles_set_index_style:nnn {#1} {contra} {##1} }, contra-style .default:n = { alph }, contra-style .initial:n = { alph }, default-indices .choices:nn = { covariant, contra } { \__tensorstyles_set_index_type:nn {#1} { ##1 }}, default-indices .default:n = { covariant }, default-indices .initial:n = { covariant }, index-marker .tl_set:c = { l__tensorstyles_tensor_#1_index_marker_tl }, specific-indices .clist_set:c = { l__tensorstyles_tensor_#1_specific_indices_clist }, collapsed-indices .bool_set:c = { l__tensorstyles_tensor_#1_collapsed_indices }, index-offset .int_set:c = { l__tensorstyles_tensor_#1_index_offset }, %%% Star Version %%%%%%%%%%%%%%%% % switch-** .bool_set:c = { l__tensorstyles_tensor_#1*_switch_star_bool }, switch-** .code:n = { printSwitchStarStar }, preset* .code:n = {}, deduce-var* .tl_set:c = { l__tensorstyles_tensor_#1*_deduce_var_tl }, % font font* .bool_set:c = { l__tensorstyles_tensor_#1*_switch_font_bool }, font-cmd* .code:n = { \prop_set_from_keyval:cn { l_tensorstyles_tensor_#1*_font_cmd_prop } {##1} }, % arrow arrows* .bool_set:c = { l__tensorstyles_tensor_#1*_switch_arrows_bool }, arrow-cmd* .code:n = { \prop_set_from_keyval:cn { l_tensorstyles_tensor_#1*_arrow_cmd_prop } {##1} }, recursive-arrows* .bool_set:c = { l__tensorstyles_tensor_#1*_switch_recursiveArrows_bool }, recurs-arrows-cmd* .tl_set:c = { l__tensorstyles_tensor_#1*_recursive_arrowCmd_tl }, % bra-ket bra-ket* .bool_set:c = { l__tensorstyles_tensor_#1*_switch_dirac_bool }, scale-var* .choices:nn = { auto, none, big, Big, bigg, Bigg } { \__tensorstyles_set_scale:nnn {tensor_#1*} {##1} { var } }, delims-var* .tl_set:c = { l__tensorstyles_tensor_#1*_delims_var_tl }, mix-delims* .bool_set:c = { l__tensorstyles_tensor_#1*_mix_delimiter_bool }, % Einstein contra-variant* .bool_set:c = { l__tensorstyles_tensor_#1*_switch_einstein_bool }, % \__tensorstyles_set_index_style:nnn #1= grp-cmd variant, #2= covariant or contra, #3= option selected, covariant-style* .choices:nn = { alph, arabic, greek } { \__tensorstyles_set_index_style:nnn {#1*} {covariant} {##1} }, contra-style* .choices:nn = { alph, arabic, greek } { \__tensorstyles_set_index_style:nnn {#1*} {contra} {##1} }, default-indices* .choices:nn = { covariant, contra } { \__tensorstyles_set_index_type:nn {#1*} { ##1 }}, index-marker* .tl_set:c = { l__tensorstyles_tensor_#1*_index_marker_tl }, specific-indices* .clist_set:c = { l__tensorstyles_tensor_#1*_specific_indices_clist }, collapsed-indices* .bool_set:c = { l__tensorstyles_tensor_#1*_collapsed_indices }, index-offset* .int_set:c = { l__tensorstyles_tensor_#1*_index_offset }, } } % \end{macrocode} % \end{macro} % \end{implementation} % \begin{implementation} % \begin{function}[added= 2025-02-12, updated= 2025-02-12]{\__tensorstyles_tensor_define_preset_keys:n, \__tensorstyles_tensor_define_local_preset_keys:n} % \begin{arguments} % \item |variant| of the `tensor` group-command. % \end{arguments} % Define the keys and variables for presets. % \changes{v1.0.1}{2025-02-12}{original version} % \TestFiles{tensorstyles-test-005} % \begin{macrocode} \cs_new:Npn \__tensorstyles_tensor_define_preset_keys:n #1 { % Initialize variables to "empty" as baseline \tl_set:cn { l__tensorstyles_tensor_#1_preset } { empty } \tl_set:cn { l__tensorstyles_tensor_#1*_preset } { empty } \keys_define:nn { tensorstyles/preset/#1 } { preset .tl_set:c = { l__tensorstyles_tensor_#1_preset } , preset* .tl_set:c = { l__tensorstyles_tensor_#1*_preset } , unknown .code:n = {} } } \cs_new:Npn \__tensorstyles_tensor_define_local_preset_keys:n #1 { % Initialize variables to "empty" as baseline \tl_set:cn { l__tensorstyles_tensor_#1_local_preset } { None } \tl_set:cn { l__tensorstyles_tensor_#1*_local_preset } { None } \keys_define:nn { tensorstyles/preset/#1 } { preset .tl_set:c = { l__tensorstyles_tensor_#1_local_preset } , preset* .tl_set:c = { l__tensorstyles_tensor_#1*_local_preset } , unknown .code:n = {} } } % \end{macrocode} % \end{function} % \end{implementation} % \begin{implementation} % \begin{variable}[added= 2025-02-17]{\c__tensorstyles_tensor_empty_pkg_keys_prop, \c__tensorstyles_tensor_einstein_pkg_keys_prop, \c__tensorstyles_tensor_math_pkg_keys_prop, \c__tensorstyles_tensor_arrow_pkg_keys_prop, \c__tensorstyles_tensor_engineer_pkg_keys_prop, \c__tensorstyles_tensor_bra_pkg_keys_prop, \c__tensorstyles_tensor_ket_pkg_keys_prop, \c__tensorstyles_tensor_full_pkg_keys_prop} % Define dictionaries of presets. % \changes{v0.1.1.2}{2025-02-17}{original version} % \TestFiles{tensorstyles-test-008} % \begin{macrocode} \prop_const_from_keyval:Nn \c__tensorstyles_tensor_empty_pkg_keys_prop { % Font font = false, % Einstein index notation contra-variant = false, % Arrows arrows = false, recursive-arrows = false, % Dirac bra-ket bra-ket = false, } \prop_const_from_keyval:Nn \c__tensorstyles_tensor_einstein_pkg_keys_prop { % Font font = false, % Einstein index notation contra-variant = true, contra-style = alph, covariant-style = alph, %greek, %, alph, arabic default-indices = covariant, index-marker = \ , collapsed-indices = false, specific-indices = {}, index-offset = 0, % covariant-indices = 1, % indexOffset = 0, % Arrows arrows = false, recursive-arrows = false, % Dirac bra-ket % bra-ket = false, } \prop_const_from_keyval:Nn \c__tensorstyles_tensor_math_pkg_keys_prop { % Font font = true, font-cmd = {0={}, 1=\boldsymbol, 2=\MakeUppercase, 3=\MakeUpperCal, 4=\MakeUpperBB, 5=\MakeBoldUppercase, n=\mathfrak}, % Einstein index notation contra-variant = false, % Arrows arrows = false, recursive-arrows = false, % Dirac bra-ket bra-ket = false, } \prop_const_from_keyval:Nn \c__tensorstyles_tensor_arrow_pkg_keys_prop { % Font font = false, % Einstein index notation contra-variant = false, % Arrows arrows = true, arrow-cmd = {0={}, 1=\overrightarrow, 2=\overleftrightarrow, 3=\overrightleftrightarrow, 4=\overdoubleleftrightarrow, 5=\overrightdoubleleftrightarrow, n=\underleftrightarrow}, recursive-arrows = false, % Dirac bra-ket bra-ket = false, } \prop_const_from_keyval:Nn \c__tensorstyles_tensor_engineer_pkg_keys_prop { % Font font = false, % Einstein index notation contra-variant = false, % Arrows arrows = false, recursive-arrows = true, recurs-arrows-cmd =\underline, % Dirac bra-ket bra-ket = false, } \prop_const_from_keyval:Nn \c__tensorstyles_tensor_bra_pkg_keys_prop { % Font font = false, % Einstein index notation contra-variant = false, % Arrows arrows = false, recursive-arrows = false, % Dirac bra-ket bra-ket = true, scale-var = auto, delims-var = \langle\rvert, mix-delims = true, } \prop_const_from_keyval:Nn \c__tensorstyles_tensor_ket_pkg_keys_prop { % Font font = false, % Einstein index notation contra-variant = false, % Arrows arrows = false, recursive-arrows = false, % Dirac bra-ket bra-ket = true, scale-var = auto, delims-var = \lvert\rangle, mix-delims = true, } \prop_const_from_keyval:Nn \c__tensorstyles_tensor_full_pkg_keys_prop { % style-inf=d, % style-var = \bold, % switch-* = false, deduce-var= xX, % order = 1, % Font font = true, font-cmd = {0={}, 1=\boldsymbol, 2=\MakeUppercase, 3=\MakeUpperCal, 4=\MakeUpperBB, 5=\MakeBoldUppercase, n=\mathfrak}, %6=\mathfrak, n=\MakeUpperFrak}, % Einstein index notation contra-variant = true, contra-style = alph, covariant-style = greek, %greek, %, alph, arabic default-indices = covariant, index-marker = \ , collapsed-indices = false, specific-indices = {}, index-offset = 0, % covariant-indices = 1, % indexOffset = 0, % Arrows arrows = true, arrow-cmd = {0={}, 1=\overrightarrow, 2=\overleftrightarrow, 3=\widetilde, 4=\overdoubleleftrightarrow, 5=\widehat, n=\underline}, recursive-arrows = false, recurs-arrows-cmd = \underline, % Dirac bra-ket bra-ket = true, scale-var = auto, delims-var = \lbrace\rvert, mix-delims = true, % style= Dirac(bra-ket), Einstein-contravariant, engineer (underline), physics (double-curved-arrows), mathematics (bold) } % \end{macrocode} % \end{variable} % \end{implementation} % \begin{implementation} % \begin{function}[added= 2025-02-17]{\tensorstyles_tensor_define:Nnn} % \begin{arguments} % \item |new/declare/renew/provide| corresponding to the type of command declaration desired. % \item |variant| of the command group. % \item |macro| for name (given by the user) the command that will be created. % \end{arguments} % Generic declaration of new function from tensor-type. % \changes{v0.1.1.2}{2025-02-17}{original version} % \TestFiles{tensorstyles-test-005} % \begin{macrocode} % \tensorstyles_tensor_define:Nnn #1=new/declare/renew/provide, #2=variant, #3=macro \cs_new_protected:Npn \tensorstyles_tensor_define:Nnn #1 #2 #3 { % define the tensor-type of command: \declare {\toto}{ o m }{ code } \tl_new:c { l__tensorstyles_tensor_#2_preset_default_tl } \exp_args:Nne #1 { #3 }{ s o m m o !e{\char_generate:nn {`_}{8}^} } { %% ##1: star, ##2: options, ##3: tensor order, ##4 variable, ##5: einstein indices, ##6: subscript, ##7: superscript \group_begin: % capture and treat eventual indices given \tl_if_in:cnTF { l__tensorstyles_tensor_#2_deduce_var_tl } {##3} { % \tl_show:c l__tensorstyles_tensor_#1_deduce_var_tl \tl_if_novalue:nTF {##5} { \int_set:Nn \l__tensorstyles_tensor_rank_counter_int 0} { \tl_set:Nn \l__tensorstyles_indices_tl {##5} \tl_map_inline:Nn \l__tensorstyles_indices_tl { \tl_if_single:nTF { ####1 } { \token_if_eq_meaning:NNTF ####1 ^{ }{ \token_if_eq_charcode:NNTF ####1 _{ }{ \int_incr:N \l__tensorstyles_tensor_rank_counter_int } } } { \int_incr:N \l__tensorstyles_tensor_rank_counter_int } } } \tl_set:Nn \l__tensorstyles_tensor_rank_holder_tl { \int_use:N \l__tensorstyles_tensor_rank_counter_int } }{ \tl_set:Nn \l__tensorstyles_tensor_rank_holder_tl { ##3 } } % Capture and store presets. \tl_if_novalue:nTF { ##2 } { \tl_set:cn { l__tensorstyles_tensor_#2_preset_default_tl } { default } }{ \use:c { __tensorstyles_tensor_define_local_preset_keys:n } { #2 } \keys_set:nn {tensorstyles/preset/#2} { ##2 } \tl_set:Nx \l_tmpa_tl { \tl_use:c { l__tensorstyles_tensor_#2_local_preset } } \tl_set:Nx \l_tmpb_tl { \tl_use:c { l__tensorstyles_tensor_#2*_local_preset } } \tensorstyles_local_preset:nVVnn {#2} \l_tmpa_tl \l_tmpb_tl { tensor } \tl_set:cn { l__tensorstyles_tensor_#2_preset_default_tl } { pres } } %% \__tensorstyles_evaluation_sub_sup grp-cmd_variant, sub, sup, code-for-fraction \__tensorstyles_evaluation_sub_sup:nnnn {#2} {##6} {##7} { % if star is present \bool_if:nTF {##1} { % star only % Capture and apply options from keys. \tl_if_novalue:nTF { ##2 } { \tensorstyles_local_keys:nnnn { } { tensor } { #2 } { \tl_use:c {l__tensorstyles_tensor_#2_preset_default_tl} } }{ \tensorstyles_local_keys:nnnn { ##2 } { tensor } { #2 } { \tl_use:c {l__tensorstyles_tensor_#2_preset_default_tl} * } } \__tensorstyles_tensor_no:nnen {#2*} {##4} {\tl_use:N \l__tensorstyles_tensor_rank_holder_tl} {##5} }{ % treat a first time the option as if no star will be used (ie if switch-*=false) \tl_if_novalue:nTF { ##2 } { \tensorstyles_local_keys:nnnn { } { tensor } { #2 } { \tl_use:c {l__tensorstyles_tensor_#2_preset_default_tl} } }{ \tensorstyles_local_keys:nnnn { ##2 } { tensor } { #2 } { \tl_use:c {l__tensorstyles_tensor_#2_preset_default_tl} } } \bool_if:cTF {l__tensorstyles_tensor_#2_switch_star_bool}{ % star detected => retreat the options \tl_if_novalue:nTF { ##2 } { \tensorstyles_local_keys:nnnn { } { tensor } { #2 } { \tl_use:c {l__tensorstyles_tensor_#2_preset_default_tl} } }{ \tensorstyles_local_keys:nnnn { ##2 } { tensor } { #2 } { \tl_use:c {l__tensorstyles_tensor_#2_preset_default_tl} * } } \__tensorstyles_tensor_no:nnen {#2*} {##4} {\tl_use:N \l__tensorstyles_tensor_rank_holder_tl} {##5} }{ % no star \__tensorstyles_tensor_no:nnen {#2} {##4} {\tl_use:N \l__tensorstyles_tensor_rank_holder_tl} {##5} } } } \group_end: } } \cs_generate_variant:Nn \tensorstyles_tensor_define:Nnn { NV } % \end{macrocode} % \end{function} % \end{implementation} % \begin{implementation} % \begin{function}[added= 2025-02-17]{\__tensorstyles_tensor_no:nnnn} % \begin{arguments} % \item |grp-cmd(tensor)_variant| to which the setting is related to. % \item |variable| to be displayed. % \item |tensor order| (integer) of the variable. % \item |indices| only if it has to be specified. % \end{arguments} % Command to display tensor command, ie apply font, then, arrows, index and delimiters. % \changes{v0.1.1.2}{2025-02-17}{original version} % \TestFiles{tensorstyles-test-005} % \begin{macrocode} % \__tensorstyles_tensor_no:nnn #1= grp-cmd(tensor) variant, #2=variable, #3=tensor order, #4=Indices \cs_new_protected:Npn \__tensorstyles_tensor_no:nnnn #1 #2 #3 #4 { \__tensorstyles_add_delims:nnn {#1} { var } { \__tensorstyles_add_einsteinIndex:nnnn {#1} { % \__tensorstyles_add_fontCmd:nnn #1= grp-cmd(tensor) variant, #2=variable, #3=tensor order \__tensorstyles_add_recursiveCmd:nnn {#1} { \__tensorstyles_add_arrowCmd:nnn {#1} { \__tensorstyles_add_fontCmd:nnn {#1} {#2} {#3} } {#3} } {#3} } {#3} {#4} } } \cs_generate_variant:Nn \__tensorstyles_tensor_no:nnnn { nnen } % \end{macrocode} % \end{function} % \end{implementation} % % %%%%% Command Declaration %%%%% % %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % % \begin{implementation} % \begin{variable}[added= 2025-02-17]{\l__tensorstyles_cs_name_tl} % Local and temporary variable to concatenate the name of the command as a token list. % \changes{v0.1.1.2}{2025-02-17}{original version} % \TestFiles{tensorstyles-test-005} % \begin{macrocode} \tl_new:N \l__tensorstyles_cs_name_tl \seq_new:N \g__tensorstyles_existing_command_seq % \end{macrocode} % \end{variable} % \end{implementation} % \begin{documentation} % \begin{function}[added= 2025-02-17]{\DeclareTensorsCmd} % \begin{arguments} % \item |command name| to be declared. % \item |keyval| (option) to be given to the new command as a first (non-default) setup. % \end{arguments} % Command to declare a new command from a command group, with eventually options to be given to this new option. % Such new definition are useful for users who would like to create their own custom command that will have the same behaviour than the ones furnished by the package. % \end{function} % \end{documentation} %%%% % \begin{implementation} % \begin{function}[added= 2025-02-17]{\DeclareTensorsCmd} % \begin{arguments} % \item |command name| to be defined/declared. % \item |keyval| (option) to be given to the new command as a first (non-default) setup. % \end{arguments} % Command accessible by the users to declare a new command from a command group, with eventually options to be given to this new option. % \changes{v0.1.1.2}{2025-02-17}{original version} % \TestFiles{tensorstyles-test-005} % \begin{macrocode} \DeclareDocumentCommand{\DeclareTensorsCmd}{ m o } { % \tensorstyles_addto_globalvar_and_setkeys:NNnnnnnn tl-tensor, macro, inf, keyval, preset, star-keyval, star-preset group command \tensorstyles_addto_globalvar_and_setkeys:NNnnn \l__tensorstyles_cs_name_tl #1 {d} { #2 } { tensor } % \tensorstyles_tensor_define:NVn declare/renew..., variant, macro % DeclareDocumentCommand #1 { #2 } { #3 } \tensorstyles_tensor_define:NVn \DeclareDocumentCommand \l__tensorstyles_cs_name_tl { #1 } \seq_put_right:Nn \g__tensorstyles_existing_command_seq { #1 } } % \end{macrocode} % \end{function} % \end{implementation} % % %%%%% Rest of the Code (common) %%%%% % %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % % \begin{implementation} % \begin{function}[added= 2025-02-17]{\__tensorstyles_set_scale:nnn} % \begin{arguments} % \item |grp-cmd_variant| for which the scaling will be set. % \item |scale| the desired scale, eg, auto or none or big or Big... % \item |delimiters-name| the name of the category of delimiters to scale. % \end{arguments} % Set the scale of a pair of delimiters. % \changes{v0.1.1.2}{2025-02-17}{original version} % \TestFiles{tensorstyles-test-005} % \begin{macrocode} % \__tensorstyles_set_scale:nnn #1=grp-cmd_variant, #2=scale, #3=delimiter-name \cs_new:Npn \__tensorstyles_set_scale:nnn #1 #2 #3 { \str_case:nnF { #2 }{ % if the scale desired is 'auto' or 'none' { auto } { \tl_set:cn { l__tensorstyles_#1_scale_#3_tl } { \__tensorstyles_scale_auto:nnn } } { none } { \tl_set:cn { l__tensorstyles_#1_scale_#3_tl } { \__tensorstyles_scale_none:nnn } } }{ % otherwise, applied the given scale \tl_set:cn { l__tensorstyles_#1_scale_#3_tl } { \__tensorstyles_scale_big:nnnn { #2 } } } } % \end{macrocode} % \end{function} % \end{implementation} % % %%%%% Scale, delimiters, evaluation %%%%% % % % \begin{implementation} % \begin{variable}[added= 2025-02-12, updated= 2025-02-12]{\g__tensorstyles_last_delim, \g__tensorstyles_follow_up} % |\g__tensorstyles_follow_up| is capturing if the delimiters are followed by another, in order to maybe compress them. % |\g__tensorstyles_last_delim| is capturing the last delimiter seen. % \changes{v1.0.1}{2025-02-12}{original version} % \begin{macrocode} % counters and local variables \bool_new:N \g__tensorstyles_follow_up \tl_new:N \g__tensorstyles_last_delim % \end{macrocode} % \end{variable} % \end{implementation} % \begin{implementation} % \begin{function}[added= 2025-02-17]{\__tensorstyles_add_delims:nnn} % \begin{arguments} % \item |grp-cmd_variant| for which the scaling will be set. % \item |delimiters-name| name of the delimiters to add. % \item |inner-arg| inside value between the delimiters. % \end{arguments} % Apply a pair of delimiters (scaled) around an inner argument. % \changes{v0.1.1.2}{2025-02-17}{original version} % \TestFiles{tensorstyles-test-005} % \begin{macrocode} % \__tensorstyles_add_delims:nnn #1=grp-cmd_variant, #2=delimiter-name, #3=value \cs_new:Npn \__tensorstyles_add_delims:nnn #1 #2 #3 { \bool_if:cTF {l__tensorstyles_tensor_#1_switch_dirac_bool} { \tl_use:c { l__tensorstyles_tensor_#1_scale_#2_tl } { tensor_#1 } { #2 } { #3 } \tl_set:Nx \l_tmpb_tl { \tl_item:cn { l__tensorstyles_#1_delims_#2_tl } { 2 } } \bool_if:cTF {l__tensorstyles_tensor_#1_mix_delimiter_bool} { \seq_map_inline:Nn \g__tensorstyles_existing_command_seq { \bool_gset_false:N \g__tensorstyles_follow_up \token_if_eq_meaning:NNT \l_peek_token ##1 { \bool_gset_true:N \g__tensorstyles_follow_up \tl_gset:Nx \g__tensorstyles_last_delim { \tl_item:cn { l__tensorstyles_tensor_#1_delims_#2_tl } { 2 } } \seq_map_break: } } } { \bool_gset_false:N \g__tensorstyles_follow_up } }{ #3 } } % \end{macrocode} % \end{function} % \end{implementation} % \begin{implementation} % \begin{function}[added= 2025-02-17]{\__tensorstyles_scale_auto:nnn} % \begin{arguments} % \item |grp-cmd_variant| for which the scaling will be set. % \item |delimiters-name| name of the delimiters to add. % \item |inner-code| inside value to be displayed between the delimiters. % \end{arguments} % Command for auto scaling delimiters (mleft and mright). % \changes{v0.1.1.2}{2025-02-17}{original version} % \TestFiles{tensorstyles-test-005} % \begin{macrocode} %\__tensorstyles_scale_auto:nnn #1=grp-cmd_variant, #2=delimiters-name, #3=inner-arg \cs_new:Npn \__tensorstyles_scale_auto:nnn #1 #2 #3 { \tl_set:Nx \l_tmpa_tl { \tl_item:cn { l__tensorstyles_#1_delims_#2_tl } { 1 } } \tl_set:Nx \l_tmpb_tl { \tl_item:cn { l__tensorstyles_#1_delims_#2_tl } { 2 } } \tl_if_empty:NTF \l_tmpa_tl { } { \bool_if:NTF \g__tensorstyles_follow_up { \bool_if:cTF {l__tensorstyles_#1_mix_delimiter_bool} { \tl_if_eq:NNTF \g__tensorstyles_last_delim \l_tmpa_tl { \! \__tensorstyles_auto_left:n . } { \tl_if_eq:NnTF \g__tensorstyles_last_delim { \rvert } { \tl_if_eq:NnTF \l_tmpa_tl { \lvert } { \! \__tensorstyles_auto_left:n . } { \__tensorstyles_auto_left:n \l_tmpa_tl } } { \__tensorstyles_auto_left:n \l_tmpa_tl } } }{ \__tensorstyles_auto_left:n \l_tmpa_tl } } { \__tensorstyles_auto_left:n \l_tmpa_tl } } #3 \tl_if_empty:NTF \l_tmpb_tl { } { \__tensorstyles_auto_right:n \l_tmpb_tl } } % \end{macrocode} % \end{function} % \end{implementation} % \begin{implementation} % \begin{function}[added= 2025-02-17]{\__tensorstyles_scale_none:nnn} % \begin{arguments} % \item |grp-cmd_variant| for which the scaling will be set. % \item |delimiters-name| name of the delimiters to add. % \item |inner-code| inside value to be displayed between the delimiters. % \end{arguments} % Command for intentionally no-scaling delimiters. % \changes{v0.1.1.2}{2025-02-17}{original version} % \TestFiles{tensorstyles-test-005} % \begin{macrocode} %\__tensorstyles_scale_none:nnn #1=grp-cmd_variant, #2=delimiters-name, #3=inner-arg \cs_new:Npn \__tensorstyles_scale_none:nnn #1 #2 #3 { \tl_set:Nx \l_tmpa_tl { \tl_item:cn { l__tensorstyles_#1_delims_#2_tl } { 1 } } \tl_set:Nx \l_tmpb_tl { \tl_item:cn { l__tensorstyles_#1_delims_#2_tl } { 2 } } \tl_if_empty:NTF \l_tmpa_tl { } { \bool_if:NTF \g__tensorstyles_follow_up { \bool_if:cTF {l__tensorstyles_#1_mix_delimiter_bool} { \tl_if_eq:NNTF \g__tensorstyles_last_delim \l_tmpa_tl { } { \tl_if_eq:NnTF \g__tensorstyles_last_delim { \rvert } { \tl_if_eq:NnTF \l_tmpa_tl { \lvert } { } { \__tensorstyles_dont_use_dot:x { \tl_item:cn { l__tensorstyles_#1_delims_#2_tl } { 1 } } } } { \__tensorstyles_dont_use_dot:x { \tl_item:cn { l__tensorstyles_#1_delims_#2_tl } { 1 } } } } } { \__tensorstyles_dont_use_dot:x { \tl_item:cn { l__tensorstyles_#1_delims_#2_tl } { 1 } } } } { \__tensorstyles_dont_use_dot:x { \tl_item:cn { l__tensorstyles_#1_delims_#2_tl } { 1 } } } } #3 \__tensorstyles_dont_use_dot:x { \tl_item:cn { l__tensorstyles_#1_delims_#2_tl } { 2 } } } % \end{macrocode} % \end{function} % \end{implementation} % \begin{implementation} % \begin{function}[added= 2025-02-17]{\__tensorstyles_dont_use_dot:n} % \begin{arguments} % \item |delimiter-symbol| to be not scaled. % \end{arguments} % Command to force no scaling on the given delimiter. % \changes{v0.1.1.2}{2025-02-17}{original version} % \TestFiles{tensorstyles-test-005} % \begin{macrocode} % \__tensorstyles_dont_use_dot:n #1=delimiter-symbol \cs_new:Npn \__tensorstyles_dont_use_dot:n #1 { \str_if_eq:nnF { #1 } { . } { #1 } } \cs_generate_variant:Nn \__tensorstyles_dont_use_dot:n { x } % \end{macrocode} % \end{function} % \end{implementation} % \begin{implementation} % \begin{function}[added= 2025-02-17]{\__tensorstyles_scale_big:nnnn, \__tensorstyles_scale_big_auxi:nNn} % \begin{arguments} % \item |scale| the desired scale, eg, big or Big... % \item |grp-cmd_variant| for which the scaling will be set. % \item |delimiters-name| the name of the category of delimiters to scale. % \item |inner-code| inside value to be displayed between the delimiters. % \end{arguments} % Apply the scale of a pair of delimiters and display what is inside. % \changes{v0.1.1.2}{2025-02-17}{original version} % \TestFiles{tensorstyles-test-005} % \begin{macrocode} %\__tensorstyles_scale_big:nnnn #1 #2=grp-cmd_variant, #3=delimiters-name, #4=inner-code \cs_new:Npn \__tensorstyles_scale_big:nnnn #1 #2 #3 #4 { \__tensorstyles_scale_big_auxi:ncnn { #1 } {l__tensorstyles_#2_delims_#3_tl} { #4 } { #2 } } % % \__tensorstyles_scale_big_auxi:nNn #1=scaling, #2=delimiters, #3=inner-code, #4=grp-cmd \cs_new:Npn \__tensorstyles_scale_big_auxi:nNnn #1 #2 #3 #4 { \tl_set:Nx \l_tmpa_tl { \tl_item:Nn #2 { 1 } } \tl_set:Nx \l_tmpb_tl { \tl_item:Nn #2 { 2 } } \tl_if_empty:NTF \l_tmpa_tl { } { \bool_if:NTF \g__tensorstyles_follow_up { \bool_if:cTF {l__tensorstyles_#4_mix_delimiter_bool} { \tl_if_eq:NNTF \g__tensorstyles_last_delim \l_tmpa_tl { } { \tl_if_eq:NnTF \g__tensorstyles_last_delim { \rvert } { \tl_if_eq:NnTF \l_tmpa_tl { \lvert } { } { \tl_use:c { #1 l } { \tl_item:Nn #2 { 1 } } } }{ \tl_use:c { #1 l } { \tl_item:Nn #2 { 1 } } } } }{ \tl_use:c { #1 l } { \tl_item:Nn #2 { 1 } } } }{ \tl_use:c { #1 l } { \tl_item:Nn #2 { 1 } } } } #3 \tl_use:c { #1 r } { \tl_item:Nn #2 { 2 } } } \cs_generate_variant:Nn \__tensorstyles_scale_big_auxi:nNnn { nc } % \end{macrocode} % \end{function} % \end{implementation} % \begin{implementation} % \begin{function}[added= 2025-02-12, updated= 2025-02-12]{\nam\__tensorstyles_evaluation_sub_sup:nnnn} % \begin{arguments} % \item |variant| Name of the variant grp-cmd % \item |sub| subscript to add to the inner code % \item |sup| superscript to add to the inner code % \item |inner code| on which the sub and sup will be added % \end{arguments} % Function to add sub and superscript to an inner variable. % \changes{v1.0.1}{2025-02-12}{original version} % \TestFiles{tensorstyles-test-005} % \begin{macrocode} % % \__tensorstyles_evaluation_sub_sup:nnnn #1=variant #2=sub #3=sup #4=inner part \cs_new:Npn \__tensorstyles_evaluation_sub_sup:nnnn #1 #2 #3 #4 { \tl_if_novalue:nTF {#2} { % if no value, skip sub-point \tl_if_novalue:nTF {#3} { % if no value skip sup-point, then add only the code-fraction #4 }{ % if value add only sup-point {#4} \sp{ #3 } } }{ % if value, add sub-point {#4} \sb{ #2 } \tl_if_novalue:nTF {#3} { % if no value skip sup-point }{ \sp{ #3 } } } } % \end{macrocode} % \end{function} % \end{implementation} % \begin{implementation} % \begin{variable}[added= 2025-02-12, updated= 2025-02-12]{\l__indice_sub_bool} % |\l__indice_sub_bool| is triggering either indices should be displayed % \changes{v1.0.1}{2025-02-12}{original version} % \begin{macrocode} % counters and local variables \bool_new:N \l__indice_sub_bool % \end{macrocode} % \end{variable} % \end{implementation} % \begin{implementation} % \begin{variable}[added= 2025-02-12, updated= 2025-02-12]{\l__tensorstyles_var_int_tmpa, \g__tensorstyles_offset_int_tmpa} % |\l__tensorstyles_var_int_tmpa| is internal index counter % |\g__tensorstyles_offset_int_tmpa| is the offset to apply on the index counter. % \changes{v1.0.1}{2025-02-12}{original version} % \begin{macrocode} % counters and local variables \int_new:N \l__tensorstyles_var_int_tmpa \int_new:N \g__tensorstyles_offset_int_tmpa \int_gset:Nn \g__tensorstyles_offset_int_tmpa {0} % \end{macrocode} % \end{variable} % \end{implementation} % \begin{implementation} % \begin{variable}[added= 2025-02-12, updated= 2025-02-12]{\l__tensorstyles_covariant_seq_tmpa, \l__tensorstyles_covariant_manual_seq_tmpa, \l__tensorstyles_contra_seq_tmpa, \l__tensorstyles_contra_manual_seq_tmpa, \l__tensorstyles_indices_tl, \l_tmp_covariant_tl, \l_tmp_contra_tl, \l_tmpc_dim} % |\l__tensorstyles_covariant_seq_tmpa| is local sequence of covariant index % |\l__tensorstyles_covariant_manual_seq_tmpa| is the local sequence of covariant index given manually % |\l__tensorstyles_contra_seq_tmpa| is the local sequence of contravariant of index % |\l__tensorstyles_contra_manual_seq_tmpa| is the local sequence of contravariant of index given manually % |\l__tensorstyles_indices_tl| is the token list that will be decoded to create the sequence % |\l_tmp_covariant_tl| % |\l_tmp_contra_tl| % |\l_tmpc_dim| the internal length for collapsed indices % \changes{v1.0.1}{2025-02-12}{original version} % \begin{macrocode} % counters and local variables \seq_new:N \l__tensorstyles_covariant_seq_tmpa \seq_new:N \l__tensorstyles_covariant_manual_seq_tmpa \seq_new:N \l__tensorstyles_contra_seq_tmpa \seq_new:N \l__tensorstyles_contra_manual_seq_tmpa \tl_new:N \l__tensorstyles_indices_tl \tl_new:N \l_tmp_covariant_tl \tl_new:N \l_tmp_contra_tl \dim_new:N \l_tmpc_dim % \end{macrocode} % \end{variable} % \end{implementation} % \begin{implementation} % \begin{function}[added= 2025-02-12, updated= 2025-02-12]{\__tensorstyles_add_manual_indices:nn} % \begin{arguments} % \item |grp-cmd(tensor) variant| variant of the tensor grp-cmd that is used. % \item |index list| to add manually % \end{arguments} % Adds indices manually (since they have been given by the user) without collapse of indices. % \changes{v1.0.1}{2025-02-12}{original version} % \TestFiles{tensorstyles-test-006} % \begin{macrocode} %\__tensorstyles_add_manual_indices:nn #1= grp-cmd(tensor) variant, #2 = index list \cs_new_protected:Npn \__tensorstyles_add_manual_indices:nn #1 #2 { \tl_set:Nn \l__tensorstyles_indices_tl {#2} % browse the list \tl_map_inline:Nn \l__tensorstyles_indices_tl { \tl_if_single:nTF { ##1 } { \token_if_eq_meaning:NNTF ##1 ^{ \bool_set_false:N \l__indice_sub_bool }{ \token_if_eq_charcode:NNTF ##1 _{ \bool_set_true:N \l__indice_sub_bool }{ \settowidth{\l_tmpa_dim}{$##1$} \bool_if:NTF \l__indice_sub_bool{ \seq_put_right:Nx \l__tensorstyles_covariant_seq_tmpa { \exp_not:n { \mathmakebox[} \dim_use:N \l_tmpa_dim \exp_not:n {][c]} { ##1 } } \seq_put_right:Nx \l__tensorstyles_contra_seq_tmpa { \exp_not:n { \mathmakebox[} \dim_use:N \l_tmpa_dim \exp_not:n {][c]} { \exp_not:v { l__tensorstyles_tensor_#1_index_marker_tl } } } }{ \seq_put_right:Nx \l__tensorstyles_contra_seq_tmpa { \exp_not:n { \mathmakebox[} \dim_use:N \l_tmpa_dim \exp_not:n {][c]} { ##1 } } \seq_put_right:Nx \l__tensorstyles_covariant_seq_tmpa { \exp_not:n { \mathmakebox[} \dim_use:N \l_tmpa_dim \exp_not:n {][c]} { \exp_not:v { l__tensorstyles_tensor_#1_index_marker_tl } } } } \int_incr:N \l__tensorstyles_var_int_tmpa } } }{ %Index is a group \settowidth{\l_tmpa_dim}{$##1$} \bool_if:NTF \l__indice_sub_bool{ \seq_put_right:Nx \l__tensorstyles_covariant_seq_tmpa { \exp_not:n { \mathmakebox[} \dim_use:N \l_tmpa_dim \exp_not:n {][c]} { \exp_not:n {##1} } } \seq_put_right:Nx \l__tensorstyles_contra_seq_tmpa { \exp_not:n { \mathmakebox[} \dim_use:N \l_tmpa_dim \exp_not:n {][c]} \exp_not:v { l__tensorstyles_tensor_#1_index_marker_tl } } }{ \seq_put_right:Nx \l__tensorstyles_contra_seq_tmpa { \exp_not:n { \mathmakebox[} \dim_use:N \l_tmpa_dim \exp_not:n {][c]} { \exp_not:n {##1} } } \seq_put_right:Nx \l__tensorstyles_covariant_seq_tmpa { \exp_not:n { \mathmakebox[} \dim_use:N \l_tmpa_dim \exp_not:n {][c]} \exp_not:v { l__tensorstyles_tensor_#1_index_marker_tl } } } \int_incr:N \l__tensorstyles_var_int_tmpa } } } % \end{macrocode} % \end{function} % \end{implementation} % \begin{implementation} % \begin{function}[added= 2025-02-12, updated= 2025-02-12]{\__tensorstyles_add_manual_collapsed_indices:n} % \begin{arguments} % \item |index list| to add manually % \end{arguments} % Adds indices manually (since they have been given by the user) with collapse of indices. % \changes{v1.0.1}{2025-02-12}{original version} % \TestFiles{tensorstyles-test-006} % \begin{macrocode} %\__tensorstyles_add_manual_collapsed_indices:n #1= index list \cs_new_protected:Npn \__tensorstyles_add_manual_collapsed_indices:n #1 { \tl_set:Nn \l__tensorstyles_indices_tl {#1} \tl_map_inline:Nn \l__tensorstyles_indices_tl { \tl_if_single:nTF { ##1 } { \token_if_eq_meaning:NNTF ##1 ^{ \bool_set_false:N \l__indice_sub_bool }{ \token_if_eq_charcode:NNTF ##1 _{ \bool_set_true:N \l__indice_sub_bool }{ \bool_if:NTF \l__indice_sub_bool{ \seq_put_right:Nx \l__tensorstyles_covariant_manual_seq_tmpa { ##1 } }{ \seq_put_right:Nx \l__tensorstyles_contra_manual_seq_tmpa { ##1 } } \int_incr:N \l__tensorstyles_var_int_tmpa } } }{ \bool_if:NTF \l__indice_sub_bool{ \seq_put_right:Nx \l__tensorstyles_covariant_manual_seq_tmpa { ##1 } }{ \seq_put_right:Nx \l__tensorstyles_contra_manual_seq_tmpa { ##1 } } \int_incr:N \l__tensorstyles_var_int_tmpa } } \int_step_inline:nn { \int_max:nn { \seq_count:N \l__tensorstyles_covariant_manual_seq_tmpa } { \seq_count:N \l__tensorstyles_contra_manual_seq_tmpa } }{ \tl_set:Nx \l_tmp_covariant_tl { \seq_item:Nn \l__tensorstyles_covariant_manual_seq_tmpa { ##1 } } \tl_set:Nx \l_tmp_contra_tl { \seq_item:Nn \l__tensorstyles_contra_manual_seq_tmpa { ##1 } } \settowidth{\l_tmpa_dim}{$\l_tmp_covariant_tl$} \settowidth{\l_tmpb_dim}{$\l_tmp_contra_tl$} \dim_compare:nTF { \l_tmpa_dim > \l_tmpb_dim }{ \dim_set_eq:NN \l_tmpc_dim \l_tmpa_dim }{ \dim_set_eq:NN \l_tmpc_dim \l_tmpb_dim } \seq_put_right:Nx \l__tensorstyles_covariant_seq_tmpa { \exp_not:n { \mathmakebox[} \dim_use:N \l_tmpc_dim \exp_not:n {][c]} { \exp_not:V \l_tmp_covariant_tl } } \seq_put_right:Nx \l__tensorstyles_contra_seq_tmpa { \exp_not:n { \mathmakebox[} \dim_use:N \l_tmpc_dim \exp_not:n {][c]} { \exp_not:V \l_tmp_contra_tl } } } } % \end{macrocode} % \end{function} % \end{implementation} % \begin{implementation} % \begin{function}[added= 2025-02-12, updated= 2025-02-12]{\__tensorstyles_add_one_einsteinIndex:nnn} % \begin{arguments} % \item |grp-cmd(tensor) variant| variant of the tensor grp-cmd that is used. % \item |index-style| ie alph, greek or arabic % \item |index-type| ie contra or covariant % \end{arguments} % Adds only one Einstein index. % \changes{v1.0.1}{2025-02-12}{original version} % \TestFiles{tensorstyles-test-006} % \begin{macrocode} % \usepackage{mathtools} % for \mathmakebox % \__tensorstyles_add_one_einsteinIndex:nn #1= grp-cmd(tensor) variant, #2=Indice type #3=Blank Type \cs_new_protected:Npn \__tensorstyles_add_one_einsteinIndex:nnn #1 #2 #3 { \settowidth{\l_tmpa_dim}{$\use:c { l__tensorstyles_tensor_#1_indexstyle_#2_tl }{\int_eval:n{\l__tensorstyles_var_int_tmpa+\g__tensorstyles_offset_int_tmpa}}$} \seq_put_right:cx { l__tensorstyles_#2_seq_tmpa } { \exp_not:n { \mathmakebox[\l_tmpa_dim][c] } { \exp_not:c { l__tensorstyles_tensor_#1_indexstyle_#2_tl } { \int_use:N \l__tensorstyles_var_int_tmpa } } } \bool_if:cTF {l__tensorstyles_tensor_#1_collapsed_indices} { % We do not add any marker }{ \seq_put_right:cx { l__tensorstyles_#3_seq_tmpa } { \exp_not:n { \mathmakebox[\l_tmpa_dim][c] } { \exp_not:v { l__tensorstyles_tensor_#1_index_marker_tl } } } } } % \end{macrocode} % \end{function} % \end{implementation} % \begin{implementation} % \begin{function}[added= 2025-02-12, updated= 2025-02-12]{\__tensorstyles_add_einsteinIndex:nnnn} % \begin{arguments} % \item |grp-cmd(tensor) variant| variant of the tensor grp-cmd that is used. % \item |variable| variable on which the indices will be added % \item |tensor order| to determine the number of indices to add. % \item |indices| if the list has been explicitly defined by the user. % \end{arguments} % Adds multiple Einstein indices % \changes{v1.0.1}{2025-02-12}{original version} % \TestFiles{tensorstyles-test-006} % \begin{macrocode} % \__tensorstyles_add_einsteinIndex:nnnn #1= grp-cmd(tensor) variant, #2=variable, #3=tensor order #4=Indices \cs_new_protected:Npn \__tensorstyles_add_einsteinIndex:nnnn #1 #2 #3 #4 { \bool_if:cTF {l__tensorstyles_tensor_#1_switch_einstein_bool} { % true switch einstein \seq_clear:N \l__tensorstyles_covariant_seq_tmpa \seq_clear:N \l__tensorstyles_contra_seq_tmpa % Do we raise an error if we do not add #3 indices? \tl_if_novalue:nTF {#4} { \tl_if_in:NnTF \c__tensorstyles_digits_tl {#3} { % The order is a number \int_set:Nn \l__tensorstyles_var_int_tmpa { \int_use:c { l__tensorstyles_tensor_#1_index_offset } } \int_step_inline:nn {#3} { % increase the counter \int_incr:N \l__tensorstyles_var_int_tmpa \tl_set:Nx \l_tmpa_tl { \int_eval:n { \l__tensorstyles_var_int_tmpa - \int_use:c { l__tensorstyles_tensor_#1_index_offset } } } \clist_if_in:cVTF { l__tensorstyles_tensor_#1_specific_indices_clist } \l_tmpa_tl { \exp_args:Nne \__tensorstyles_add_one_einsteinIndex:nnn {#1} { \tl_use:c { l__tensorstyles_tensor_#1_opposed_indices_tl }} { \tl_use:c { l__tensorstyles_tensor_#1_default_indices_tl } } } { \exp_args:Nne \__tensorstyles_add_one_einsteinIndex:nnn {#1} { \tl_use:c { l__tensorstyles_tensor_#1_default_indices_tl }} { \tl_use:c { l__tensorstyles_tensor_#1_opposed_indices_tl } } } % add this counter (+ the offset) of the sequence of index } }{ % if the order is not a number then add it as if it a vector. \seq_put_right:Nx \l__tensorstyles_covariant_seq_tmpa { \__tensorstyles_add_fontCmd:nnn {#1} {#3} {1} } } }{ %Indices were given manually \bool_if:cTF {l__tensorstyles_tensor_#1_collapsed_indices} { \__tensorstyles_add_manual_collapsed_indices:n {#4} }{ \__tensorstyles_add_manual_indices:nn {#1} {#4} } \int_compare:nTF { \l__tensorstyles_var_int_tmpa = #3 } { %Rank and number of indices match }{ %User has given too many or not enough indices \msg_error:nnx { tensorstyles } { rank_indices_missmatch } { \msg_line_context: } } } % print #2\sb{ \seq_use:Nn \l__tensorstyles_covariant_seq_tmpa {} }\sp{ \seq_use:Nn \l__tensorstyles_contra_seq_tmpa {} } }{ % false switch font #2 } } % \end{macrocode} % \end{function} % \end{implementation} % \begin{implementation} % \begin{function}[added= 2025-02-12, updated= 2025-02-12]{\__tensorstyles_set_index_style:nnn} % \begin{arguments} % \item |grp-cmd(tensor) variant| variant of the tensor grp-cmd that is used. % \item |index-type| covariant or contra. % \item |index-style| greek, alph or arabic. % \end{arguments} % Turn the index integer into a string according to the index-style to use. % \changes{v1.0.1}{2025-02-12}{original version} % \TestFiles{tensorstyles-test-006} % \begin{macrocode} % \__tensorstyles_set_index_style:nnn #1= grp-cmd variant, #2= index-type, #3= index-style, \cs_new:Npn \__tensorstyles_set_index_style:nnn #1 #2 #3 { \str_case:nnF {#3} { { alph }{ \tl_set:cn { l__tensorstyles_tensor_#1_indexstyle_#2_tl } { \int_to_alph:n } } { arabic }{ \tl_set:cn { l__tensorstyles_tensor_#1_indexstyle_#2_tl } { \int_to_arabic:n } } { greek }{ \tl_set:cn { l__tensorstyles_tensor_#1_indexstyle_#2_tl } { \int_to_greek:n } } }{ \msg_error:nnxx { tensorstyles } { index-style-option-not-defined } {#3} {'#3'} } } % \end{macrocode} % \end{function} % \end{implementation} % \begin{implementation} % \begin{function}[added= 2025-02-12, updated= 2025-02-12]{\__tensorstyles_set_index_style:nnn} % \begin{arguments} % \item |grp-cmd(tensor) variant| variant of the tensor grp-cmd that is used. % \item |index-type| covariant or contra. % \end{arguments} % Set the default index type to use. % \changes{v1.0.1}{2025-02-12}{original version} % \TestFiles{tensorstyles-test-006} % \begin{macrocode} % \__tensorstyles_set_index_type:nnn #1= grp-cmd variant, #2= index-type \cs_new:Npn \__tensorstyles_set_index_type:nn #1 #2 { \tl_set:cn { l__tensorstyles_tensor_#1_default_indices_tl } { #2 } \str_case:nnF {#2} { { covariant }{ \tl_set:cn { l__tensorstyles_tensor_#1_default_indices_tl } { covariant } \tl_set:cn { l__tensorstyles_tensor_#1_opposed_indices_tl } { contra } }{ contra }{ \tl_set:cn { l__tensorstyles_tensor_#1_default_indices_tl } { contra } \tl_set:cn { l__tensorstyles_tensor_#1_opposed_indices_tl } { covariant } } }{ \msg_error:nnxx { tensorstyles } { index-type-option-not-defined } {#2} {'#2'} } } % \end{macrocode} % \end{function} % \end{implementation} % \begin{implementation} % \begin{function}[added= 2025-02-12, updated= 2025-02-12]{\__tensorstyles_add_fontCmd:nnn} % \begin{arguments} % \item |variant| grp-cmd(tensor) variant % \item |variable| on which the font command will be applied % \item |tensor order| to determine which font select. % \end{arguments} % Apply a font on a variable according to the tensor order. % \changes{v1.0.1}{2025-02-12}{original version} % \TestFiles{tensorstyles-test-005} % \begin{macrocode} % \__tensorstyles_add_fontCmd:nnn #1= grp-cmd(tensor) variant, #2=variable, #3=tensor order \cs_new_protected:Npn \__tensorstyles_add_fontCmd:nnn #1 #2 #3 { \bool_if:cTF {l__tensorstyles_tensor_#1_switch_font_bool}{ % true switch font \prop_if_in:cnTF {l_tensorstyles_tensor_#1_font_cmd_prop} {#3} { % true %\exp_args:NNV \prop_item:cn {l_tensorstyles_tensor_#1_font_cmd_prop} {#3} {#2} }{ % false false\ the\ order\ #3\ is\ not\ present\ in\ font\ option! } }{ % false switch font #2 } } % \end{macrocode} % \end{function} % \end{implementation} % \begin{implementation} % \begin{function}[added= 2025-02-12, updated= 2025-02-12]{\int_to_greek:n} % \begin{arguments} % \item |integer| to turn into a symbol (string). % \end{arguments} % Function that returns the greek symbol corresponding to the integer given. % \changes{v1.0.1}{2025-02-12}{original version} % \TestFiles{tensorstyles-test-005} % \begin{macrocode} %% \cs_new:Npn \int_to_greek:n #1 { % \int_to_symbols:nnn {⟨int expr ⟩} {⟨total symbols ⟩} {⟨value to symbol mapping ⟩} \int_to_symbols:nnn {#1} { 23 } { { 1 }{ \alpha } { 2 }{ \beta } { 3 }{ \gamma } { 4 }{ \delta } { 5 }{ \varepsilon } { 6 }{ \zeta } { 7 }{ \eta } { 8 }{ \theta } { 9 }{ \iota } { 10 }{ \kappa } { 11 }{ \lambda } { 12 }{ \mu } { 13 }{ \nu } { 14 }{ \xi } { 15 }{ o } { 16 }{ \pi } { 17 }{ \varrho } { 18 }{ \sigma } { 19 }{ \tau } { 20 }{ \upsilon } { 21 }{ \phi } { 22 }{ \chi } { 23 }{ \psi } { 23 }{ \omega } } } % \end{macrocode} % \end{function} % \end{implementation} % \begin{implementation} % \begin{function}[added= 2025-02-12, updated= 2025-02-12]{\recursive_cmd:nnn} % \begin{arguments} % \item |cmd| to apply recursively % \item |number| of occurrence to apply % \item |variable| on which the recursively command will be applied % \end{arguments} % Apply a given number of times a command on an input variable. % The input command (to apply) can only take one positional argument. % \changes{v1.0.1}{2025-02-12}{original version} % \TestFiles{tensorstyles-test-005} % \begin{macrocode} % internal variable to store the counter of occurrence \int_new:N \g__tensorstyles_int_tmpa % % \recursive_cmd:nnn cmd, number, var \cs_set:Npn \recursive_cmd:nnn #1 #2 #3 { \group_begin: % % all variable assignments will be constrained in this group \int_gset:Nn \g__tensorstyles_int_tmpa {#2} % % while the number of call is higher than 1 \int_compare:nNnTF {#2} > {1} { %true % then apply recursively the command \int_gdecr:N \g__tensorstyles_int_tmpa \exp_args:Nnx \recursive_cmd:nnV {#1} {\int_use:N \g__tensorstyles_int_tmpa} {#1{#3}} }{ % false % \int_compare:nNnTF {#2} = {0} { %true #3 }{ % false % equal 1 #1{#3} } } \group_end: } % variant command for \recursive_cmd:nnn \cs_generate_variant:Nn \recursive_cmd:nnn { nnV, vnn } % \end{macrocode} % \end{function} % \end{implementation} % \begin{implementation} % \begin{function}[added= 2025-02-12, updated= 2025-02-12]{\__tensorstyles_add_recursiveCmd:nnn} % \begin{arguments} % \item |variant| grp-cmd(tensor) variant % \item |variable| on which the recursively command will be applied % \item |tensor order| which will correspond to the number of occurrence to apply recursively % \end{arguments} % Apply (if needed) as many time as the tensor order a command on an input variable. % \changes{v1.0.1}{2025-02-12}{original version} % \TestFiles{tensorstyles-test-005} % \begin{macrocode} % % \__tensorstyles_add_recurseCmd:nnn #1= grp-cmd(tensor) variant, #2=variable, #3=tensor order \cs_new_protected:Npn \__tensorstyles_add_recursiveCmd:nnn #1 #2 #3 { \bool_if:cTF {l__tensorstyles_tensor_#1_switch_recursiveArrows_bool} { % true switch recursive \tl_if_in:NnTF \c__tensorstyles_digits_tl {#3} { % The order is a number \recursive_cmd:vnn {l__tensorstyles_tensor_#1_recursive_arrowCmd_tl} {#3} {#2} }{ % else the order is a letter \__tensorstyles_add_arrowCmd:nnn {#1} {#2} {#3} } }{ % false switch recursive #2 } } % \end{macrocode} % \end{function} % \end{implementation} % \begin{implementation} % \begin{function}[added= 2025-02-12, updated= 2025-02-12]{\__tensorstyles_add_arrowCmd:nnn} % \begin{arguments} % \item |variant| grp-cmd(tensor) variant % \item |variable| on which the arrow command will be applied % \item |tensor order| to determine which arrow command apply % \end{arguments} % Apply an arrow-command according to the tensor-order on an input variable. % \changes{v1.0.1}{2025-02-12}{original version} % \TestFiles{tensorstyles-test-005} % \begin{macrocode} % \__tensorstyles_add_arrowCmd:nnn #1= grp-cmd(tensor) variant, #2=variable, #3=tensor order \cs_new_protected:Npn \__tensorstyles_add_arrowCmd:nnn #1 #2 #3 { \bool_if:cTF {l__tensorstyles_tensor_#1_switch_arrows_bool} { % true switch arrow \prop_if_in:cnTF {l_tensorstyles_tensor_#1_arrow_cmd_prop} {#3} { % true \prop_item:cn {l_tensorstyles_tensor_#1_arrow_cmd_prop} {#3} {#2} }{ % false false\ the\ order\ #3\ is\ not\ present\ in\ arrows\ option! \prop_show:c {l_tensorstyles_tensor_#1_arrow_cmd_prop} } }{ % false switch arrow #2 } } % \end{macrocode} % \end{function} % \end{implementation} % \begin{documentation} % \begin{function}{\MakeBoldUppercase, \MakeUpperBB, \MakeUpperCal, \MakeUpperFrak, \overdoubleleftrightarrow, \overrightleftrightarrow, \overrightdoubleleftrightarrow} % \begin{syntax} % \cs{MakeBoldUppercase, MakeUpperBB, MakeUpperCal, MakeUpperFrak, overdoubleleftrightarrow, overrightleftrightarrow, overrightdoubleleftrightarrow}\marg{variable} % \end{syntax} % Commands applying a combination of font commands or glyph (arrow) commands. % The combinations are quite explicit from the command names. % \end{function} % \end{documentation} %%%% % \begin{implementation} % \begin{function}[added= 2025-02-12, updated= 2025-02-12]{\MakeBoldUppercase, \MakeUpperBB, \MakeUpperCal, \MakeUpperFrak, \overdoubleleftrightarrow, \overrightleftrightarrow, \overrightdoubleleftrightarrow} % \begin{arguments} % \item |cmd| to apply recursively % \item |number| of occurrence to apply % \item |variable| on which the recursively command will be applied % \end{arguments} % Apply a given number of times a command on an input variable. % The input command (to apply) can only take one positional argument. % \changes{v1.0.1}{2025-02-12}{original version} % \TestFiles{tensorstyles-test-005} % \begin{macrocode} % % \RequirePackage{amsmath}% \overrightarrow % \RequirePackage{amssymb}% \curvearrowright % \RequirePackage{bm} % recommended for bold math % \DeclareDocumentCommand{\MakeBoldUppercase}{ m }{ \mathbf{\MakeUppercase{#1}} } \DeclareDocumentCommand{\MakeUpperBB}{ m }{ \mathbb{\MakeUppercase{#1}} } \DeclareDocumentCommand{\MakeUpperCal}{ m }{ \mathcal{\MakeUppercase{#1}} } \DeclareDocumentCommand{\MakeUpperFrak}{ m }{ {\mathfrak{\MakeUppercase{#1}}} } \DeclareDocumentCommand{\overdoubleleftrightarrow}{ m }{ {\overleftrightarrow{\overleftrightarrow{#1}}} } \DeclareDocumentCommand{\overrightleftrightarrow}{ m }{ {\overrightarrow{\overleftrightarrow{#1}}} } \DeclareDocumentCommand{\overrightdoubleleftrightarrow}{ m }{ {\overrightarrow{\overleftrightarrow{\overleftrightarrow{#1}}}} } % \end{macrocode} % \end{function} % \end{implementation} % % % %%%%% Generate variants %%%%% % %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % % % \begin{implementation} % \begin{function}[added= 2025-02-17]{\__tensorstyles_set_scale:nnn} % \begin{arguments} % \item |grp-cmd_variant| for which the scaling will be set. % \item |scale| the desired scale, eg, auto or none or big or Big... % \item |delimiters-name| the name of the category of delimiters to scale. % \end{arguments} % Set the scale of a pair of delimiters . % \changes{v0.1.1.2}{2025-02-17}{original version} % \TestFiles{tensorstyles-test-005} % \begin{macrocode} % \tensorstyles_set_keys:nn #1:tensor, #2:keyval \cs_new_protected:Npn \tensorstyles_set_keys:nn #1 #2 { % \tl_set:Nx \l_tmpa_tl { \tl_use:c { l__tensorstyles_tensor_#1_preset } } \tl_set:Nx \l_tmpb_tl { \tl_use:c { l__tensorstyles_tensor_#1*_preset } } \use:c { __tensorstyles_tensor_define_local_preset_keys:n } { #1 } \keys_set:nn {tensorstyles/preset/#1} { #2 } \tl_if_eq:cnF { l__tensorstyles_tensor_#1_local_preset } { None } { \tl_set:Nx \l_tmpa_tl { \tl_use:c { l__tensorstyles_tensor_#1_local_preset } } \tl_set:cx { l__tensorstyles_tensor_#1_preset } { \tl_use:c { l__tensorstyles_tensor_#1_local_preset } } } \tl_if_eq:cnF { l__tensorstyles_tensor_#1*_local_preset } { None } { \tl_set:Nx \l_tmpb_tl { \tl_use:c { l__tensorstyles_tensor_#1*_local_preset } } \tl_set:cx { l__tensorstyles_tensor_#1*_preset } { \tl_use:c { l__tensorstyles_tensor_#1*_local_preset } } } \seq_if_in:NnTF \l__tensorstyles_tensor_variant_seq { #1 } { % True tensor \prop_set_eq:cc { l__tensorstyles_tensor_#1_user_keys_prop } { c__tensorstyles_tensor_ \tl_use:N \l_tmpa_tl _pkg_keys_prop } \prop_set_eq:cc { l__tensorstyles_tensor_#1*_user_keys_prop } { c__tensorstyles_tensor_ \tl_use:N \l_tmpb_tl _pkg_keys_prop } \__tensorstyles_set_default_from_keyval:nVnn { #1 } \l_tmpa_tl { #2 } { tensor } \__tensorstyles_set_default_from_keyval:nVnn { #1* } \l_tmpb_tl { #2 } { tensor } }{ % False tensor \seq_if_in:NnTF \l__tensorstyles_i_variant_seq { #1 }{ % True I \prop_set_eq:cc { l__tensorstyles_tensor_#1_user_keys_prop } { c__tensorstyles_i_ \tl_use:N \l_tmpa_tl _pkg_keys_prop } \prop_set_eq:cc { l__tensorstyles_tensor_#1*_user_keys_prop } { c__tensorstyles_i_ \tl_use:N \l_tmpb_tl _pkg_keys_prop } \__tensorstyles_set_default_from_keyval:nVnn { #1 } \l_tmpa_tl { #2 } { i } \__tensorstyles_set_default_from_keyval:nVnn { #1* } \l_tmpb_tl { #2 } { i } } { % False I \msg_error:nnxx { tensorstyles } { tensor-not-defined } { \token_to_str:N #1 } { \token_to_str:N \tensorsset } } } } \cs_generate_variant:Nn \tensorstyles_set_keys:nn { V } % \cs_generate_variant:Nn \__tensorstyles_set_rubber_length:Nn { c } % \cs_generate_variant:Nn \__tensorstyles_var_bool_seq:NNN { c } % \end{macrocode} % \end{function} % \end{implementation} % % % %%%%% Messages %%%%% % %%%%%%%%%%%%%%%%%%%%%%%% % % \begin{implementation} % \begin{function}[added= 2025-02-17]{messages} % Set the messages that can be emitted. % \changes{v0.1.1.2}{2025-02-17}{original version} % \begin{macrocode} % \msg_new:nnnn { tensorstyles } { command-already-defined } % { Command~'#1'~already~defined! } % { % You~have~used~#2~with~a~command~that~already~has~a~definition. \\ % The~existing~definition~of~'#1'~will~not~be~altered. % } \msg_new:nnn { tensorstyles } { rank_indices_missmatch } { The~number~of~given~indices~and~rank~do~not~match~(#1) } \msg_new:nnn { tensorstyles } { index-type-option-not-define } { The~default-indices~is~only~accepting~contra~or~covariant~choice } \msg_new:nnn { tensorstyles } { index-style-option-not-defined } { Index~styles~(ie~contra-style~or~covariant-style)~on~accept~greek,~alph~or~arabic~choice } % \end{macrocode} % \end{function} % \end{implementation} % % % %%%%% Declaring \& Generate %%%%% % %%%%% new group of commands %%%%% % %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % % \begin{implementation} % \begin{macro}[added= 2025-02-17]{\tensorsset{all}} % First setup of the options for 'all' commands. % \changes{v0.1.1.2}{2025-02-17}{original version} % \TestFiles{tensorstyles-test-005} % \begin{macrocode} \@ifpackageloaded{mleftright} { \tensorsset{all}[scale-auto = mleftmright] } { \tensorsset{all}[scale-auto = leftright] } % \end{macrocode} % \end{macro} % \end{implementation} % % \begin{implementation} % \begin{macro}[added= 2025-02-17]{\DeclareTensorsCmd{\testCmd}} % Declare the official commands of the package: testCmd % \changes{v0.1.1.2}{2025-02-17}{original version} % \TestFiles{tensorstyles-test-005} % \begin{macrocode} \DeclareTensorsCmd{\tensor}[preset=full] % \end{macrocode} % \end{macro} % \end{implementation} % \begin{implementation} % \begin{macrocode} \endinput % % \end{macrocode} % \end{implementation} % % \Finale