这是我的问题:我正在尝试编写一些代码,以给定的样式绘制节点。样式在单独的文件中定义。样式的名称由一个函数定义,该函数将创建多个具有相同根名称和罗马数字的变量以区分它们。这是设计,无法更改。
我想通过名为 xaller 的函数访问样式的名称,该函数检索变量“root+roman number”的内容:当内容用于显示时,它工作正常,但当内容应该用作样式的名称时,它就不行了。我想我需要指出检索到的内容指定了 tikz 的样式,但我不知道该怎么做。
在 MWE 中,您将找到当前正在运行和不运行的开关:我可以访问变量的内容,并在直接访问变量时将其用作样式名称,但通过 xaller 函数访问时无法使用它。我尝试使用函数 SetStyle 来解决此问题,该函数应该将样式的名称归因于 \monStyle ,但它也不起作用。
任何指示都会有所帮助。抱歉,如果代码看起来有点过分,我已尽我所能将其最小化。
\documentclass[10pt,twoside]{article}
\usepackage{xparse}
\usepackage{xstring}
\usepackage[nomessages]{fp}
% graphics and color
\usepackage[usenames]{color}
\usepackage{xcolor}
\usepackage{tikz}
\usetikzlibrary{matrix, shapes, patterns, fit, positioning}
\usepackage{etoolbox}
\begin{document}
%==================================================================================
%==================================================================================
%==================================================================================
% Define the xpl3 functions to attributes the variables
%\include{fonctionsMWE}
\ExplSyntaxOn
\cs_new:Npn \SetStyle #1
{
% clear new car si new seulement, se plaint que la variable existe deja
\tl_clear_new:N \l_my_tl
% convertit l argument en chiffre romain
\tl_set:Nn \l_my_tl { \int_to_Roman:n {#1} }
% concatene variableCouleurMatrice a ma var \l_my_tl par la gauche
\tl_put_left:Nn \l_my_tl { variableStyle }
%show la variable
%\tl_use:N \l_my_tl
% use permet d executer la variable
\use:c { \tl_use:N \l_my_tl }
\let\monStyle\use:c { \tl_use:N \l_my_tl }
%\let\monStyle\variableStyleII
}
\ExplSyntaxOff
% Automation trial 7 : utilise la syntaxe expl3
\ExplSyntaxOn
\NewDocumentCommand{\DefinitionVariablesEnIndividuel}{O{variable}}
{% pass control to an inner function
% #1 is the "name part", default "variable"
\aline_df:n { #1 }
}
% define an integer variable
\int_new:N \l_aline_df_int
\cs_new_protected:Nn \aline_df:n
{
% the integer variable assigns the trailing roman number
\int_zero:N \l_aline_df_int
% start the recursion
\__aline_df_peek:n { #1 }
}
\cs_new_protected:Nn \__aline_df_peek:n
{
% check whether the next token is { (ignoring spaces)
\peek_catcode_ignore_spaces:NT \c_group_begin_token
{
% if it is, increment the counter and call
% \__aline_df_next:nn { #1 } { #2 }, where
% { #2 } is the next braced group
\int_incr:N \l_aline_df_int
\__aline_df_next:nn { #1 }
}
}
\cs_new_protected:Nn \__aline_df_next:nn
{
% if the variable is already defined, clear it
% otherwise create it
\tl_clear_new:c { #1 \int_to_Roman:n { \l_aline_df_int } }
\tl_clear_new:c { #1 ConstanteLongueur }
% set the variable
\tl_set:cn { #1 \int_to_Roman:n { \l_aline_df_int }} { #2 }
\tl_set:cx { #1 ConstanteLongueur } { \int_eval:n { \l_aline_df_int } }
% restart the recursion
\__aline_df_peek:n { #1 }
}
\ExplSyntaxOff
%==================================================================================
%==================================================================================
%==================================================================================
%==================================================================================
%\include{stylesMWE}
\tikzstyle{teteColonneNegatif} = [
text centered,
text=white, font=\bfseries,
minimum height=1em,
text depth=0.5em, text height=1em,
text width = 3cm,
rectangle, fill=none, draw=none, rounded corners,
fill=black!100
]
\tikzset{
teteColonne/.style={
text centered,
text=white, font=\bfseries,
minimum height=1em,
text depth=0.5em, text height=1em,
text width = 5cm,
rectangle, fill=none, draw=none, rounded corners,
fill=red!100
},
teteColonne/.default=white
}
\newcommand{\xaller}[2]{%
\uppercase\expandafter
{\expandafter\def\expandafter\tmp\expandafter{\romannumeral #1}}%
\csname #2\tmp\endcsname%
%\csname variableStyle\tmp\endcsname%
}
%==================================================================================
%==================================================================================
%==================================================================================
% Define all the variables variableStyleN
\DefinitionVariablesEnIndividuel[variableStyle]{teteColonne}{teteColonneNegatif}{teteColonneNegatif}{teteColonne}{teteColonne}{teteColonne}{teteColonneNegatif}{teteColonne}
%==================================================================================
%==================================================================================
%==================================================================================
Wether the code is called from the variable or via the call of xaller, it is the same result :
xaller call : \xaller{1}{variableStyle}
direct variable : \variableStyleI
=======================================================
% Code to switch between what works (Generalization at false) and what doesn't (Generalization at true)
\newif\ifGeneralization
\Generalizationtrue
\Generalizationfalse
% Use monStyle as a tmp variable for the node
\ifGeneralization
\let\monStyle\xaller{1}{variableStyle}
%\SetStyle{1}
\else
\let\monStyle\variableStyleI
\fi
Style used : \monStyle
\newline
\begin{tikzpicture}%
%\node[\variableStyleI](nom) at (1,10){\variableStyleI};
\node[\monStyle](nom) at (1,10){\monStyle};
\end{tikzpicture}
% Use monStyle as a tmp variable for the node
\ifGeneralization
\let\monStyle\xaller{2}{variableStyle}
\else
\let\monStyle\variableStyleII
\fi
\let\monStyle\variableStyleII
Style used : \monStyle
\newline
\begin{tikzpicture}%
%\node[\variableStyleII](nom) at (1,10){\variableStyleII};
\node[\monStyle](nom) at (1,10){\monStyle};
\end{tikzpicture}
\end{document}
答案1
因为\xaller
要在这里使用,它必须是可扩展的。所以它既不能使用\def
也不能使用\uppercase
。
为了制作一个可扩展的版本(在我看来也更具可读性),你可以使用 expl3:
\ExplSyntaxOn
\cs_new:Npn \xaller #1 #2 {
\use:c { #2 \int_to_Roman:n { #1 } }
}
\ExplSyntaxOff
第二个问题是你使用\let
:
\let\monStyle\xaller{2}{variableStyle}
为创建\monStyle
一个别名\xaller
,但\xaller
不会展开,{2}{variableStyle}
只是作为常规文本输出到文档中。稍后,当\monStyle
使用 时,TeX 会尝试读取\xaller
参数并错过数字。可以通过展开\xaller
三次(这需要很多\expandafter
s)或使用\def
以下方法修复此问题:
\def\monStyle{\xaller{2}{variableStyle}}
这产生了工作版本
\documentclass[10pt,twoside]{article}
\usepackage{xparse}
\usepackage{xstring}
\usepackage[nomessages]{fp}
% graphics and color
\usepackage[usenames]{color}
\usepackage{xcolor}
\usepackage{tikz}
\usetikzlibrary{matrix, shapes, patterns, fit, positioning}
\usepackage{etoolbox}
\begin{document}
%==================================================================================
%==================================================================================
%==================================================================================
% Define the xpl3 functions to attributes the variables
%\include{fonctionsMWE}
\ExplSyntaxOn
\cs_new:Npn \SetStyle #1
{
% clear new car si new seulement, se plaint que la variable existe deja
\tl_clear_new:N \l_my_tl
% convertit l argument en chiffre romain
\tl_set:Nn \l_my_tl { \int_to_Roman:n {#1} }
% concatene variableCouleurMatrice a ma var \l_my_tl par la gauche
\tl_put_left:Nn \l_my_tl { variableStyle }
%show la variable
%\tl_use:N \l_my_tl
% use permet d executer la variable
\use:c { \tl_use:N \l_my_tl }
\let\monStyle\use:c { \tl_use:N \l_my_tl }
%\let\monStyle\variableStyleII
}
\ExplSyntaxOff
% Automation trial 7 : utilise la syntaxe expl3
\ExplSyntaxOn
\NewDocumentCommand{\DefinitionVariablesEnIndividuel}{O{variable}}
{% pass control to an inner function
% #1 is the "name part", default "variable"
\aline_df:n { #1 }
}
% define an integer variable
\int_new:N \l_aline_df_int
\cs_new_protected:Nn \aline_df:n
{
% the integer variable assigns the trailing roman number
\int_zero:N \l_aline_df_int
% start the recursion
\__aline_df_peek:n { #1 }
}
\cs_new_protected:Nn \__aline_df_peek:n
{
% check whether the next token is { (ignoring spaces)
\peek_catcode_ignore_spaces:NT \c_group_begin_token
{
% if it is, increment the counter and call
% \__aline_df_next:nn { #1 } { #2 }, where
% { #2 } is the next braced group
\int_incr:N \l_aline_df_int
\__aline_df_next:nn { #1 }
}
}
\cs_new_protected:Nn \__aline_df_next:nn
{
% if the variable is already defined, clear it
% otherwise create it
\tl_clear_new:c { #1 \int_to_Roman:n { \l_aline_df_int } }
\tl_clear_new:c { #1 ConstanteLongueur }
% set the variable
\tl_set:cn { #1 \int_to_Roman:n { \l_aline_df_int }} { #2 }
\tl_set:cx { #1 ConstanteLongueur } { \int_eval:n { \l_aline_df_int } }
% restart the recursion
\__aline_df_peek:n { #1 }
}
\ExplSyntaxOff
%==================================================================================
%==================================================================================
%==================================================================================
%==================================================================================
%\include{stylesMWE}
\tikzstyle{teteColonneNegatif} = [
text centered,
text=white, font=\bfseries,
minimum height=1em,
text depth=0.5em, text height=1em,
text width = 3cm,
rectangle, fill=none, draw=none, rounded corners,
fill=black!100
]
\tikzset{
teteColonne/.style={
text centered,
text=white, font=\bfseries,
minimum height=1em,
text depth=0.5em, text height=1em,
text width = 5cm,
rectangle, fill=none, draw=none, rounded corners,
fill=red!100
},
teteColonne/.default=white
}
\ExplSyntaxOn
\cs_new:Npn \xaller #1 #2 {
\use:c { #2 \int_to_Roman:n { #1 } }
}
\ExplSyntaxOff
%==================================================================================
%==================================================================================
%==================================================================================
% Define all the variables variableStyleN
\DefinitionVariablesEnIndividuel[variableStyle]{teteColonne}{teteColonneNegatif}{teteColonneNegatif}{teteColonne}{teteColonne}{teteColonne}{teteColonneNegatif}{teteColonne}
%==================================================================================
%==================================================================================
%==================================================================================
Wether the code is called from the variable or via the call of xaller, it is the same result :
xaller call : \xaller{1}{variableStyle}
direct variable : \variableStyleI
=======================================================
% Code to switch between what works (Generalization at false) and what doesn't (Generalization at true)
\newif\ifGeneralization
\Generalizationtrue
%\Generalizationfalse
% Use monStyle as a tmp variable for the node
\ifGeneralization
\def\monStyle{\xaller{1}{variableStyle}}
%\SetStyle{1}
\else
\let\monStyle\variableStyleI
\fi
Style used : \monStyle
\newline
\begin{tikzpicture}%
%\node[\variableStyleI](nom) at (1,10){\variableStyleI};
\node[\monStyle](nom) at (1,10){\monStyle};
\end{tikzpicture}
% Use monStyle as a tmp variable for the node
\ifGeneralization
\def\monStyle{\xaller{2}{variableStyle}}
\else
\let\monStyle\variableStyleII
\fi
\let\monStyle\variableStyleII
Style used : \monStyle
\newline
\begin{tikzpicture}%
%\node[\variableStyleII](nom) at (1,10){\variableStyleII};
\node[\monStyle](nom) at (1,10){\monStyle};
\end{tikzpicture}
\end{document}
答案2
问题在于您混合了新旧风格的编程,以及对\let
工作原理的误解。
\documentclass[10pt,twoside]{article}
\usepackage{xparse}
\usepackage[usenames]{xcolor}
\usepackage{tikz}
\usetikzlibrary{matrix, shapes, patterns, fit, positioning}
\begin{document}
\ExplSyntaxOn
\NewExpandableDocumentCommand{\xaller}{mm}
{
\use:c { #2 \int_to_Roman:n { #1 } }
}
\NewDocumentCommand \SetStyle { m }
{
\cs_set:Npx \monStyle { \xaller{#1}{variableStyle} }
}
\NewDocumentCommand{\DefinitionVariablesEnIndividuel}{O{variable}}
{% pass control to an inner function
% #1 is the "name part", default "variable"
\aline_df:n { #1 }
}
% define an integer variable
\int_new:N \l_aline_df_int
\cs_new_protected:Nn \aline_df:n
{
% the integer variable assigns the trailing roman number
\int_zero:N \l_aline_df_int
% start the recursion
\__aline_df_peek:n { #1 }
}
\cs_new_protected:Nn \__aline_df_peek:n
{
% check whether the next token is { (ignoring spaces)
\peek_catcode_ignore_spaces:NT \c_group_begin_token
{
% if it is, increment the counter and call
% \__aline_df_next:nn { #1 } { #2 }, where
% { #2 } is the next braced group
\int_incr:N \l_aline_df_int
\__aline_df_next:nn { #1 }
}
}
\cs_new_protected:Nn \__aline_df_next:nn
{
% if the variable is already defined, clear it
% otherwise create it
\tl_clear_new:c { #1 \int_to_Roman:n { \l_aline_df_int } }
\tl_clear_new:c { #1 ConstanteLongueur }
% set the variable
\tl_set:cn { #1 \int_to_Roman:n { \l_aline_df_int }} { #2 }
\tl_set:cx { #1 ConstanteLongueur } { \int_eval:n { \l_aline_df_int } }
% restart the recursion
\__aline_df_peek:n { #1 }
}
\ExplSyntaxOff
\tikzset{
teteColonneNegatif/.style = {
text centered,
text=white, font=\bfseries,
minimum height=1em,
text depth=0.5em, text height=1em,
text width = 3cm,
rectangle, fill=none, draw=none, rounded corners,
fill=black!100
},
teteColonne/.style={
text centered,
text=white, font=\bfseries,
minimum height=1em,
text depth=0.5em, text height=1em,
text width = 5cm,
rectangle, fill=none, draw=none, rounded corners,
fill=red!100
},
teteColonne/.default=white,
}
% Define all the variables variableStyleN
\DefinitionVariablesEnIndividuel[variableStyle]
{teteColonne}
{teteColonneNegatif}
{teteColonneNegatif}
{teteColonne}
{teteColonne}
{teteColonne}
{teteColonneNegatif}
{teteColonne}
\SetStyle{1}
Style used : \verb|\monStyle|
\begin{tikzpicture}
\node[\monStyle](nom) at (1,10){\monStyle};
\end{tikzpicture}
\bigskip
\begin{tikzpicture}
\foreach \i in {1,...,8} {
\node[\xaller{\i}{variableStyle},text width=9cm](nom) at (1,10+\i){\xaller{\i}{variableStyle}};
}
\end{tikzpicture}
\end{document}