tikzset does not work in foreach loop












3















I tried to use a foreach loop to define a new style. However, the code within the loop seems to have no effect. The following MWE ilustrates my problem:



documentclass[tikz]{standalone}

tikzset{
mystyle/.code=
{
%tikzset{very thick}, % This line has an effect (if uncommented)
foreach pos in {0.1, 0.2, 0.3, 0.4} % **EDIT**: Should be a list of names in the end.
{
% There will be other statements here that actually use the list members

tikzset{very thick}, %This line is an exact copy of the comented line but has no effect.
message{======== Foreach: pos=pos}
}
}
}

begin{document}
begin{tikzpicture}
draw [help lines] (-10,-10) grid (10,10);
draw[mystyle] (0,0) --++ (5,0);
end{tikzpicture}
end{document}


When I compile this document, the console shows the messages




...
======== Foreach: pos=0.1 ======== Foreach: pos=0.2 ======== Foreach: pos=0.3
======== Foreach: pos=0.4 [1] (./mwe.aux))
...




so I believe the tikzset is actually run. There are no error messages.



So, why does the tikzset command not make my line thick? And how can I get this to work?



EDIT:
Context:
This is (of course) part of a bigger thing. In the end, I want to create transistor stick diagrams like shown here: http://www.southampton.ac.uk/~bim/notes/cad/guides/sticks.html
(Summary: Chip-level transistor layouts are sketched using mere lines of different colours. Where a line with the "Polysilicon" colour crosses a line with the "N Diffusion" oder "P Diffusion" colour, there is a transistor gate.
For this I first created some line and node styles, borrowing code from Loop Space and circuitikz (for the node styles). With this, I can draw my diagrams, but it is still rather manual since I have to draw multiple lines to create a transistor: The diffusion and polysilicon lines.
So, I decided to create a new line style, that would allow me to place the transistor gates automatically. Using code borrowed from Casimir, I was able to create the following:



documentclass[tikz]{standalone}

% Code adapted from: https://tex.stackexchange.com/a/393496/69074
usetikzlibrary{decorations.markings}

%{{{ Transistor Stick Diagrams

%{{{ Layer Magic

% Source: Adapted from https://tex.stackexchange.com/a/20426/69074
pgfdeclarelayer{M3L} % Metal 3
pgfdeclarelayer{M2L} % Metal 1
pgfdeclarelayer{M1L} % Metal 1
pgfdeclarelayer{POL} % Poly-Silicon
pgfdeclarelayer{DDL} % Diffusion
pgfdeclarelayer{CONTL} % Contacts
pgfsetlayers{DDL,POL,M1L,M2L,M3L,CONTL,main}

makeatletter
pgfkeys{%
/tikz/on layer/.code={
pgfonlayer{#1}begingroup
aftergroupendpgfonlayer
aftergroupendgroup
},
/tikz/node on layer/.code={
gdefnode@@on@layer{%
setboxtikz@tempbox=hboxbgrouppgfonlayer{#1}unhboxtikz@tempboxendpgfonlayeregroup}
aftergroupnode@on@layer
},
/tikz/end node on layer/.code={
endpgfonlayerendgroupendgroup
}
}

defnode@on@layer{aftergroupnode@@on@layer}

%}}}

%{{{ Declare the Node shapes

% Code stolen (and slightly adapted from Circuitikz:
% Source: /usr/share/texmf-dist/tex/generic/circuitikz/pgfcircshapes.tex
makeatletter
newdimensticknodewidth
sticknodewidth=1cm

%% Left out, boring and too long

makeatother
%}}}

%{{{ Line Styles

tikzstyle{M3} = [draw=green, line width=0.3, on layer=M3L ] % Metal 3 Path
tikzstyle{M2} = [draw=yellow, line width=0.3, on layer=M2L ] % Metal 2 Path
tikzstyle{M1} = [draw=turquoise, line width=0.3, on layer=M1L ] % Metal 1 Path
tikzstyle{PO} = [draw=blue, line width=0.3, on layer=POL ] % Poly-Silicon Path (Gate)
tikzstyle{PD} = [draw=red!50, line width=0.3, on layer=DDL ] % P-Diffusion Path (PMOS)
tikzstyle{ND} = [draw=red, line width=0.3, on layer=DDL ] % N-Diffusion Path (NMOS)
tikzstyle{air} = [draw=black,dashed,line width=0.1, on layer=CONTL] % N-Diffusion Path (NMOS)
%}}}

%{{{ Port Styles

tikzstyle{M3P} = [stickport, color=green, node on layer=M3L ] % Metal 3 Terminal
tikzstyle{M2P} = [stickport, color=yellow, node on layer=M2L ] % Metal 2 Terminal
tikzstyle{M1P} = [stickport, color=turquoise, node on layer=M1L ] % Metal 1 Terminal
tikzstyle{POP} = [stickport, color=blue, node on layer=POL ] % Poly-Silicon Terminal
tikzstyle{PDP} = [stickport, color=red!50, node on layer=DDL ] % P-Diffusion Terminal (PMOS)
tikzstyle{NDP} = [stickport, color=red, node on layer=DDL ] % N-Diffusion Terminal (NMOS)
tikzstyle{CON} = [stickcontact, color=black, node on layer=CONTL] % Via (between touching M3,M2,M1,PO,P-Diff,N-Diff)
tikzstyle{TAP} = [sticktap, color=black, node on layer=CONTL] % Substrate Tap (between touching M1,Diff,N-Diff)
tikzstyle{TAPCON} = [sticktapcon, color=black, node on layer=CONTL] % Merged Tap and Via
%}}}

%{{{ Automatic Transistors

tikzset{
gate/.style 2 args=
{
thick,decoration=
{
markings, mark=at position {#1} with
{
draw[PO] (0,-0.25)coordinate(m#2ga)--(0,0.25)coordinate(m#2gb);
node[inner xsep=0, inner ysep=0.1mm,above left,font=tiny,rotate=pgfdecoratedangle-90](x) {$M_{#2}$};
}
},
postaction={decorate}
},
stick pmos/.style=
{
PD,
gate/.list={#1}
},
pmos/.code=
{
foreach name in {#1}
{
% Calculate pos somehow, I'm not there yet
tikzset{gate={pos}{name}}
}
}
}
%}}}

%}}}

begin{document}
begin{tikzpicture}
draw [help lines] (-10,-10) grid (10,10);

draw[stick pmos={{0.333}{1},{0.666}{2}}] (0,0)--++(0,2);
draw[PO] (m1ga)--++(0.5,0.5);
draw[PO] (m2gb)--++(-0.5,-0.5);

draw[pmos={a,b,c}] (3,0)--++(0,2); % Gates spaced automatically
draw[PO] (maga)--++(0.5,0.5);
draw[PO] (magb)--++(-0.5,-0.5);

end{tikzpicture}
end{document}


This thing is quite near to what I want to get. Yet, the last part is what inspired this question: The gate/.list handler will not allow me to automate the node placement (or I just did not find how to do it), so I wanted to do the looping myself. The manual, section 82.4.6 says, that the /.list handler uses a foreach loop internally, so I tried it and met the problems.
The MWE I created is suboptimal in that it uses a list of numbers for the loop, while the final version should be a loop over names. Sorry for that.










share|improve this question




















  • 1





    Because the contents of foreach are executed inside a group (actually two), so local definitions (tikzset does local definitions) are lost when the loop ends. Depending on what the "statements" you mentioned do you can use different approaches to overcome the grouping of foreach. That or use another looping command.

    – Phelype Oleinik
    Jan 30 at 18:07













  • I am going to add further tikzset commands. I have written a style which takes two parameters and draws a line crossing my line. In the end this is for creating transistor stick diagrams.

    – mox
    Jan 30 at 18:34











  • With other tikzset commands the solution I proposed will work fine. Depending on how you are drawing the diagrams, this can perhaps be achieved with styles. But we'd probably need to see the whole drawing to say for sure.

    – Phelype Oleinik
    Jan 30 at 18:46













  • First: Thank you! (forgot that in my first comment) I added the context and how I want to use the code. It should be compilable if you comment out the last two lines inside the tikzpicture. They cannot work yet. Could you give an example how to make the code work if the list is not numbers, or -- even better -- how the <key>/.list handler works around this problem?

    – mox
    Jan 30 at 19:49











  • In the advanced code you already use all the aftergroup trickery, which you could also use for tikzset. So, to some extent you may benefit from smuggling. Yet I fail to see the purpose of all this here.

    – marmot
    Jan 30 at 20:02
















3















I tried to use a foreach loop to define a new style. However, the code within the loop seems to have no effect. The following MWE ilustrates my problem:



documentclass[tikz]{standalone}

tikzset{
mystyle/.code=
{
%tikzset{very thick}, % This line has an effect (if uncommented)
foreach pos in {0.1, 0.2, 0.3, 0.4} % **EDIT**: Should be a list of names in the end.
{
% There will be other statements here that actually use the list members

tikzset{very thick}, %This line is an exact copy of the comented line but has no effect.
message{======== Foreach: pos=pos}
}
}
}

begin{document}
begin{tikzpicture}
draw [help lines] (-10,-10) grid (10,10);
draw[mystyle] (0,0) --++ (5,0);
end{tikzpicture}
end{document}


When I compile this document, the console shows the messages




...
======== Foreach: pos=0.1 ======== Foreach: pos=0.2 ======== Foreach: pos=0.3
======== Foreach: pos=0.4 [1] (./mwe.aux))
...




so I believe the tikzset is actually run. There are no error messages.



So, why does the tikzset command not make my line thick? And how can I get this to work?



EDIT:
Context:
This is (of course) part of a bigger thing. In the end, I want to create transistor stick diagrams like shown here: http://www.southampton.ac.uk/~bim/notes/cad/guides/sticks.html
(Summary: Chip-level transistor layouts are sketched using mere lines of different colours. Where a line with the "Polysilicon" colour crosses a line with the "N Diffusion" oder "P Diffusion" colour, there is a transistor gate.
For this I first created some line and node styles, borrowing code from Loop Space and circuitikz (for the node styles). With this, I can draw my diagrams, but it is still rather manual since I have to draw multiple lines to create a transistor: The diffusion and polysilicon lines.
So, I decided to create a new line style, that would allow me to place the transistor gates automatically. Using code borrowed from Casimir, I was able to create the following:



documentclass[tikz]{standalone}

% Code adapted from: https://tex.stackexchange.com/a/393496/69074
usetikzlibrary{decorations.markings}

%{{{ Transistor Stick Diagrams

%{{{ Layer Magic

% Source: Adapted from https://tex.stackexchange.com/a/20426/69074
pgfdeclarelayer{M3L} % Metal 3
pgfdeclarelayer{M2L} % Metal 1
pgfdeclarelayer{M1L} % Metal 1
pgfdeclarelayer{POL} % Poly-Silicon
pgfdeclarelayer{DDL} % Diffusion
pgfdeclarelayer{CONTL} % Contacts
pgfsetlayers{DDL,POL,M1L,M2L,M3L,CONTL,main}

makeatletter
pgfkeys{%
/tikz/on layer/.code={
pgfonlayer{#1}begingroup
aftergroupendpgfonlayer
aftergroupendgroup
},
/tikz/node on layer/.code={
gdefnode@@on@layer{%
setboxtikz@tempbox=hboxbgrouppgfonlayer{#1}unhboxtikz@tempboxendpgfonlayeregroup}
aftergroupnode@on@layer
},
/tikz/end node on layer/.code={
endpgfonlayerendgroupendgroup
}
}

defnode@on@layer{aftergroupnode@@on@layer}

%}}}

%{{{ Declare the Node shapes

% Code stolen (and slightly adapted from Circuitikz:
% Source: /usr/share/texmf-dist/tex/generic/circuitikz/pgfcircshapes.tex
makeatletter
newdimensticknodewidth
sticknodewidth=1cm

%% Left out, boring and too long

makeatother
%}}}

%{{{ Line Styles

tikzstyle{M3} = [draw=green, line width=0.3, on layer=M3L ] % Metal 3 Path
tikzstyle{M2} = [draw=yellow, line width=0.3, on layer=M2L ] % Metal 2 Path
tikzstyle{M1} = [draw=turquoise, line width=0.3, on layer=M1L ] % Metal 1 Path
tikzstyle{PO} = [draw=blue, line width=0.3, on layer=POL ] % Poly-Silicon Path (Gate)
tikzstyle{PD} = [draw=red!50, line width=0.3, on layer=DDL ] % P-Diffusion Path (PMOS)
tikzstyle{ND} = [draw=red, line width=0.3, on layer=DDL ] % N-Diffusion Path (NMOS)
tikzstyle{air} = [draw=black,dashed,line width=0.1, on layer=CONTL] % N-Diffusion Path (NMOS)
%}}}

%{{{ Port Styles

tikzstyle{M3P} = [stickport, color=green, node on layer=M3L ] % Metal 3 Terminal
tikzstyle{M2P} = [stickport, color=yellow, node on layer=M2L ] % Metal 2 Terminal
tikzstyle{M1P} = [stickport, color=turquoise, node on layer=M1L ] % Metal 1 Terminal
tikzstyle{POP} = [stickport, color=blue, node on layer=POL ] % Poly-Silicon Terminal
tikzstyle{PDP} = [stickport, color=red!50, node on layer=DDL ] % P-Diffusion Terminal (PMOS)
tikzstyle{NDP} = [stickport, color=red, node on layer=DDL ] % N-Diffusion Terminal (NMOS)
tikzstyle{CON} = [stickcontact, color=black, node on layer=CONTL] % Via (between touching M3,M2,M1,PO,P-Diff,N-Diff)
tikzstyle{TAP} = [sticktap, color=black, node on layer=CONTL] % Substrate Tap (between touching M1,Diff,N-Diff)
tikzstyle{TAPCON} = [sticktapcon, color=black, node on layer=CONTL] % Merged Tap and Via
%}}}

%{{{ Automatic Transistors

tikzset{
gate/.style 2 args=
{
thick,decoration=
{
markings, mark=at position {#1} with
{
draw[PO] (0,-0.25)coordinate(m#2ga)--(0,0.25)coordinate(m#2gb);
node[inner xsep=0, inner ysep=0.1mm,above left,font=tiny,rotate=pgfdecoratedangle-90](x) {$M_{#2}$};
}
},
postaction={decorate}
},
stick pmos/.style=
{
PD,
gate/.list={#1}
},
pmos/.code=
{
foreach name in {#1}
{
% Calculate pos somehow, I'm not there yet
tikzset{gate={pos}{name}}
}
}
}
%}}}

%}}}

begin{document}
begin{tikzpicture}
draw [help lines] (-10,-10) grid (10,10);

draw[stick pmos={{0.333}{1},{0.666}{2}}] (0,0)--++(0,2);
draw[PO] (m1ga)--++(0.5,0.5);
draw[PO] (m2gb)--++(-0.5,-0.5);

draw[pmos={a,b,c}] (3,0)--++(0,2); % Gates spaced automatically
draw[PO] (maga)--++(0.5,0.5);
draw[PO] (magb)--++(-0.5,-0.5);

end{tikzpicture}
end{document}


This thing is quite near to what I want to get. Yet, the last part is what inspired this question: The gate/.list handler will not allow me to automate the node placement (or I just did not find how to do it), so I wanted to do the looping myself. The manual, section 82.4.6 says, that the /.list handler uses a foreach loop internally, so I tried it and met the problems.
The MWE I created is suboptimal in that it uses a list of numbers for the loop, while the final version should be a loop over names. Sorry for that.










share|improve this question




















  • 1





    Because the contents of foreach are executed inside a group (actually two), so local definitions (tikzset does local definitions) are lost when the loop ends. Depending on what the "statements" you mentioned do you can use different approaches to overcome the grouping of foreach. That or use another looping command.

    – Phelype Oleinik
    Jan 30 at 18:07













  • I am going to add further tikzset commands. I have written a style which takes two parameters and draws a line crossing my line. In the end this is for creating transistor stick diagrams.

    – mox
    Jan 30 at 18:34











  • With other tikzset commands the solution I proposed will work fine. Depending on how you are drawing the diagrams, this can perhaps be achieved with styles. But we'd probably need to see the whole drawing to say for sure.

    – Phelype Oleinik
    Jan 30 at 18:46













  • First: Thank you! (forgot that in my first comment) I added the context and how I want to use the code. It should be compilable if you comment out the last two lines inside the tikzpicture. They cannot work yet. Could you give an example how to make the code work if the list is not numbers, or -- even better -- how the <key>/.list handler works around this problem?

    – mox
    Jan 30 at 19:49











  • In the advanced code you already use all the aftergroup trickery, which you could also use for tikzset. So, to some extent you may benefit from smuggling. Yet I fail to see the purpose of all this here.

    – marmot
    Jan 30 at 20:02














3












3








3








I tried to use a foreach loop to define a new style. However, the code within the loop seems to have no effect. The following MWE ilustrates my problem:



documentclass[tikz]{standalone}

tikzset{
mystyle/.code=
{
%tikzset{very thick}, % This line has an effect (if uncommented)
foreach pos in {0.1, 0.2, 0.3, 0.4} % **EDIT**: Should be a list of names in the end.
{
% There will be other statements here that actually use the list members

tikzset{very thick}, %This line is an exact copy of the comented line but has no effect.
message{======== Foreach: pos=pos}
}
}
}

begin{document}
begin{tikzpicture}
draw [help lines] (-10,-10) grid (10,10);
draw[mystyle] (0,0) --++ (5,0);
end{tikzpicture}
end{document}


When I compile this document, the console shows the messages




...
======== Foreach: pos=0.1 ======== Foreach: pos=0.2 ======== Foreach: pos=0.3
======== Foreach: pos=0.4 [1] (./mwe.aux))
...




so I believe the tikzset is actually run. There are no error messages.



So, why does the tikzset command not make my line thick? And how can I get this to work?



EDIT:
Context:
This is (of course) part of a bigger thing. In the end, I want to create transistor stick diagrams like shown here: http://www.southampton.ac.uk/~bim/notes/cad/guides/sticks.html
(Summary: Chip-level transistor layouts are sketched using mere lines of different colours. Where a line with the "Polysilicon" colour crosses a line with the "N Diffusion" oder "P Diffusion" colour, there is a transistor gate.
For this I first created some line and node styles, borrowing code from Loop Space and circuitikz (for the node styles). With this, I can draw my diagrams, but it is still rather manual since I have to draw multiple lines to create a transistor: The diffusion and polysilicon lines.
So, I decided to create a new line style, that would allow me to place the transistor gates automatically. Using code borrowed from Casimir, I was able to create the following:



documentclass[tikz]{standalone}

% Code adapted from: https://tex.stackexchange.com/a/393496/69074
usetikzlibrary{decorations.markings}

%{{{ Transistor Stick Diagrams

%{{{ Layer Magic

% Source: Adapted from https://tex.stackexchange.com/a/20426/69074
pgfdeclarelayer{M3L} % Metal 3
pgfdeclarelayer{M2L} % Metal 1
pgfdeclarelayer{M1L} % Metal 1
pgfdeclarelayer{POL} % Poly-Silicon
pgfdeclarelayer{DDL} % Diffusion
pgfdeclarelayer{CONTL} % Contacts
pgfsetlayers{DDL,POL,M1L,M2L,M3L,CONTL,main}

makeatletter
pgfkeys{%
/tikz/on layer/.code={
pgfonlayer{#1}begingroup
aftergroupendpgfonlayer
aftergroupendgroup
},
/tikz/node on layer/.code={
gdefnode@@on@layer{%
setboxtikz@tempbox=hboxbgrouppgfonlayer{#1}unhboxtikz@tempboxendpgfonlayeregroup}
aftergroupnode@on@layer
},
/tikz/end node on layer/.code={
endpgfonlayerendgroupendgroup
}
}

defnode@on@layer{aftergroupnode@@on@layer}

%}}}

%{{{ Declare the Node shapes

% Code stolen (and slightly adapted from Circuitikz:
% Source: /usr/share/texmf-dist/tex/generic/circuitikz/pgfcircshapes.tex
makeatletter
newdimensticknodewidth
sticknodewidth=1cm

%% Left out, boring and too long

makeatother
%}}}

%{{{ Line Styles

tikzstyle{M3} = [draw=green, line width=0.3, on layer=M3L ] % Metal 3 Path
tikzstyle{M2} = [draw=yellow, line width=0.3, on layer=M2L ] % Metal 2 Path
tikzstyle{M1} = [draw=turquoise, line width=0.3, on layer=M1L ] % Metal 1 Path
tikzstyle{PO} = [draw=blue, line width=0.3, on layer=POL ] % Poly-Silicon Path (Gate)
tikzstyle{PD} = [draw=red!50, line width=0.3, on layer=DDL ] % P-Diffusion Path (PMOS)
tikzstyle{ND} = [draw=red, line width=0.3, on layer=DDL ] % N-Diffusion Path (NMOS)
tikzstyle{air} = [draw=black,dashed,line width=0.1, on layer=CONTL] % N-Diffusion Path (NMOS)
%}}}

%{{{ Port Styles

tikzstyle{M3P} = [stickport, color=green, node on layer=M3L ] % Metal 3 Terminal
tikzstyle{M2P} = [stickport, color=yellow, node on layer=M2L ] % Metal 2 Terminal
tikzstyle{M1P} = [stickport, color=turquoise, node on layer=M1L ] % Metal 1 Terminal
tikzstyle{POP} = [stickport, color=blue, node on layer=POL ] % Poly-Silicon Terminal
tikzstyle{PDP} = [stickport, color=red!50, node on layer=DDL ] % P-Diffusion Terminal (PMOS)
tikzstyle{NDP} = [stickport, color=red, node on layer=DDL ] % N-Diffusion Terminal (NMOS)
tikzstyle{CON} = [stickcontact, color=black, node on layer=CONTL] % Via (between touching M3,M2,M1,PO,P-Diff,N-Diff)
tikzstyle{TAP} = [sticktap, color=black, node on layer=CONTL] % Substrate Tap (between touching M1,Diff,N-Diff)
tikzstyle{TAPCON} = [sticktapcon, color=black, node on layer=CONTL] % Merged Tap and Via
%}}}

%{{{ Automatic Transistors

tikzset{
gate/.style 2 args=
{
thick,decoration=
{
markings, mark=at position {#1} with
{
draw[PO] (0,-0.25)coordinate(m#2ga)--(0,0.25)coordinate(m#2gb);
node[inner xsep=0, inner ysep=0.1mm,above left,font=tiny,rotate=pgfdecoratedangle-90](x) {$M_{#2}$};
}
},
postaction={decorate}
},
stick pmos/.style=
{
PD,
gate/.list={#1}
},
pmos/.code=
{
foreach name in {#1}
{
% Calculate pos somehow, I'm not there yet
tikzset{gate={pos}{name}}
}
}
}
%}}}

%}}}

begin{document}
begin{tikzpicture}
draw [help lines] (-10,-10) grid (10,10);

draw[stick pmos={{0.333}{1},{0.666}{2}}] (0,0)--++(0,2);
draw[PO] (m1ga)--++(0.5,0.5);
draw[PO] (m2gb)--++(-0.5,-0.5);

draw[pmos={a,b,c}] (3,0)--++(0,2); % Gates spaced automatically
draw[PO] (maga)--++(0.5,0.5);
draw[PO] (magb)--++(-0.5,-0.5);

end{tikzpicture}
end{document}


This thing is quite near to what I want to get. Yet, the last part is what inspired this question: The gate/.list handler will not allow me to automate the node placement (or I just did not find how to do it), so I wanted to do the looping myself. The manual, section 82.4.6 says, that the /.list handler uses a foreach loop internally, so I tried it and met the problems.
The MWE I created is suboptimal in that it uses a list of numbers for the loop, while the final version should be a loop over names. Sorry for that.










share|improve this question
















I tried to use a foreach loop to define a new style. However, the code within the loop seems to have no effect. The following MWE ilustrates my problem:



documentclass[tikz]{standalone}

tikzset{
mystyle/.code=
{
%tikzset{very thick}, % This line has an effect (if uncommented)
foreach pos in {0.1, 0.2, 0.3, 0.4} % **EDIT**: Should be a list of names in the end.
{
% There will be other statements here that actually use the list members

tikzset{very thick}, %This line is an exact copy of the comented line but has no effect.
message{======== Foreach: pos=pos}
}
}
}

begin{document}
begin{tikzpicture}
draw [help lines] (-10,-10) grid (10,10);
draw[mystyle] (0,0) --++ (5,0);
end{tikzpicture}
end{document}


When I compile this document, the console shows the messages




...
======== Foreach: pos=0.1 ======== Foreach: pos=0.2 ======== Foreach: pos=0.3
======== Foreach: pos=0.4 [1] (./mwe.aux))
...




so I believe the tikzset is actually run. There are no error messages.



So, why does the tikzset command not make my line thick? And how can I get this to work?



EDIT:
Context:
This is (of course) part of a bigger thing. In the end, I want to create transistor stick diagrams like shown here: http://www.southampton.ac.uk/~bim/notes/cad/guides/sticks.html
(Summary: Chip-level transistor layouts are sketched using mere lines of different colours. Where a line with the "Polysilicon" colour crosses a line with the "N Diffusion" oder "P Diffusion" colour, there is a transistor gate.
For this I first created some line and node styles, borrowing code from Loop Space and circuitikz (for the node styles). With this, I can draw my diagrams, but it is still rather manual since I have to draw multiple lines to create a transistor: The diffusion and polysilicon lines.
So, I decided to create a new line style, that would allow me to place the transistor gates automatically. Using code borrowed from Casimir, I was able to create the following:



documentclass[tikz]{standalone}

% Code adapted from: https://tex.stackexchange.com/a/393496/69074
usetikzlibrary{decorations.markings}

%{{{ Transistor Stick Diagrams

%{{{ Layer Magic

% Source: Adapted from https://tex.stackexchange.com/a/20426/69074
pgfdeclarelayer{M3L} % Metal 3
pgfdeclarelayer{M2L} % Metal 1
pgfdeclarelayer{M1L} % Metal 1
pgfdeclarelayer{POL} % Poly-Silicon
pgfdeclarelayer{DDL} % Diffusion
pgfdeclarelayer{CONTL} % Contacts
pgfsetlayers{DDL,POL,M1L,M2L,M3L,CONTL,main}

makeatletter
pgfkeys{%
/tikz/on layer/.code={
pgfonlayer{#1}begingroup
aftergroupendpgfonlayer
aftergroupendgroup
},
/tikz/node on layer/.code={
gdefnode@@on@layer{%
setboxtikz@tempbox=hboxbgrouppgfonlayer{#1}unhboxtikz@tempboxendpgfonlayeregroup}
aftergroupnode@on@layer
},
/tikz/end node on layer/.code={
endpgfonlayerendgroupendgroup
}
}

defnode@on@layer{aftergroupnode@@on@layer}

%}}}

%{{{ Declare the Node shapes

% Code stolen (and slightly adapted from Circuitikz:
% Source: /usr/share/texmf-dist/tex/generic/circuitikz/pgfcircshapes.tex
makeatletter
newdimensticknodewidth
sticknodewidth=1cm

%% Left out, boring and too long

makeatother
%}}}

%{{{ Line Styles

tikzstyle{M3} = [draw=green, line width=0.3, on layer=M3L ] % Metal 3 Path
tikzstyle{M2} = [draw=yellow, line width=0.3, on layer=M2L ] % Metal 2 Path
tikzstyle{M1} = [draw=turquoise, line width=0.3, on layer=M1L ] % Metal 1 Path
tikzstyle{PO} = [draw=blue, line width=0.3, on layer=POL ] % Poly-Silicon Path (Gate)
tikzstyle{PD} = [draw=red!50, line width=0.3, on layer=DDL ] % P-Diffusion Path (PMOS)
tikzstyle{ND} = [draw=red, line width=0.3, on layer=DDL ] % N-Diffusion Path (NMOS)
tikzstyle{air} = [draw=black,dashed,line width=0.1, on layer=CONTL] % N-Diffusion Path (NMOS)
%}}}

%{{{ Port Styles

tikzstyle{M3P} = [stickport, color=green, node on layer=M3L ] % Metal 3 Terminal
tikzstyle{M2P} = [stickport, color=yellow, node on layer=M2L ] % Metal 2 Terminal
tikzstyle{M1P} = [stickport, color=turquoise, node on layer=M1L ] % Metal 1 Terminal
tikzstyle{POP} = [stickport, color=blue, node on layer=POL ] % Poly-Silicon Terminal
tikzstyle{PDP} = [stickport, color=red!50, node on layer=DDL ] % P-Diffusion Terminal (PMOS)
tikzstyle{NDP} = [stickport, color=red, node on layer=DDL ] % N-Diffusion Terminal (NMOS)
tikzstyle{CON} = [stickcontact, color=black, node on layer=CONTL] % Via (between touching M3,M2,M1,PO,P-Diff,N-Diff)
tikzstyle{TAP} = [sticktap, color=black, node on layer=CONTL] % Substrate Tap (between touching M1,Diff,N-Diff)
tikzstyle{TAPCON} = [sticktapcon, color=black, node on layer=CONTL] % Merged Tap and Via
%}}}

%{{{ Automatic Transistors

tikzset{
gate/.style 2 args=
{
thick,decoration=
{
markings, mark=at position {#1} with
{
draw[PO] (0,-0.25)coordinate(m#2ga)--(0,0.25)coordinate(m#2gb);
node[inner xsep=0, inner ysep=0.1mm,above left,font=tiny,rotate=pgfdecoratedangle-90](x) {$M_{#2}$};
}
},
postaction={decorate}
},
stick pmos/.style=
{
PD,
gate/.list={#1}
},
pmos/.code=
{
foreach name in {#1}
{
% Calculate pos somehow, I'm not there yet
tikzset{gate={pos}{name}}
}
}
}
%}}}

%}}}

begin{document}
begin{tikzpicture}
draw [help lines] (-10,-10) grid (10,10);

draw[stick pmos={{0.333}{1},{0.666}{2}}] (0,0)--++(0,2);
draw[PO] (m1ga)--++(0.5,0.5);
draw[PO] (m2gb)--++(-0.5,-0.5);

draw[pmos={a,b,c}] (3,0)--++(0,2); % Gates spaced automatically
draw[PO] (maga)--++(0.5,0.5);
draw[PO] (magb)--++(-0.5,-0.5);

end{tikzpicture}
end{document}


This thing is quite near to what I want to get. Yet, the last part is what inspired this question: The gate/.list handler will not allow me to automate the node placement (or I just did not find how to do it), so I wanted to do the looping myself. The manual, section 82.4.6 says, that the /.list handler uses a foreach loop internally, so I tried it and met the problems.
The MWE I created is suboptimal in that it uses a list of numbers for the loop, while the final version should be a loop over names. Sorry for that.







tikz-pgf tikz-styles






share|improve this question















share|improve this question













share|improve this question




share|improve this question








edited Jan 30 at 19:42







mox

















asked Jan 30 at 17:59









moxmox

263




263








  • 1





    Because the contents of foreach are executed inside a group (actually two), so local definitions (tikzset does local definitions) are lost when the loop ends. Depending on what the "statements" you mentioned do you can use different approaches to overcome the grouping of foreach. That or use another looping command.

    – Phelype Oleinik
    Jan 30 at 18:07













  • I am going to add further tikzset commands. I have written a style which takes two parameters and draws a line crossing my line. In the end this is for creating transistor stick diagrams.

    – mox
    Jan 30 at 18:34











  • With other tikzset commands the solution I proposed will work fine. Depending on how you are drawing the diagrams, this can perhaps be achieved with styles. But we'd probably need to see the whole drawing to say for sure.

    – Phelype Oleinik
    Jan 30 at 18:46













  • First: Thank you! (forgot that in my first comment) I added the context and how I want to use the code. It should be compilable if you comment out the last two lines inside the tikzpicture. They cannot work yet. Could you give an example how to make the code work if the list is not numbers, or -- even better -- how the <key>/.list handler works around this problem?

    – mox
    Jan 30 at 19:49











  • In the advanced code you already use all the aftergroup trickery, which you could also use for tikzset. So, to some extent you may benefit from smuggling. Yet I fail to see the purpose of all this here.

    – marmot
    Jan 30 at 20:02














  • 1





    Because the contents of foreach are executed inside a group (actually two), so local definitions (tikzset does local definitions) are lost when the loop ends. Depending on what the "statements" you mentioned do you can use different approaches to overcome the grouping of foreach. That or use another looping command.

    – Phelype Oleinik
    Jan 30 at 18:07













  • I am going to add further tikzset commands. I have written a style which takes two parameters and draws a line crossing my line. In the end this is for creating transistor stick diagrams.

    – mox
    Jan 30 at 18:34











  • With other tikzset commands the solution I proposed will work fine. Depending on how you are drawing the diagrams, this can perhaps be achieved with styles. But we'd probably need to see the whole drawing to say for sure.

    – Phelype Oleinik
    Jan 30 at 18:46













  • First: Thank you! (forgot that in my first comment) I added the context and how I want to use the code. It should be compilable if you comment out the last two lines inside the tikzpicture. They cannot work yet. Could you give an example how to make the code work if the list is not numbers, or -- even better -- how the <key>/.list handler works around this problem?

    – mox
    Jan 30 at 19:49











  • In the advanced code you already use all the aftergroup trickery, which you could also use for tikzset. So, to some extent you may benefit from smuggling. Yet I fail to see the purpose of all this here.

    – marmot
    Jan 30 at 20:02








1




1





Because the contents of foreach are executed inside a group (actually two), so local definitions (tikzset does local definitions) are lost when the loop ends. Depending on what the "statements" you mentioned do you can use different approaches to overcome the grouping of foreach. That or use another looping command.

– Phelype Oleinik
Jan 30 at 18:07







Because the contents of foreach are executed inside a group (actually two), so local definitions (tikzset does local definitions) are lost when the loop ends. Depending on what the "statements" you mentioned do you can use different approaches to overcome the grouping of foreach. That or use another looping command.

– Phelype Oleinik
Jan 30 at 18:07















I am going to add further tikzset commands. I have written a style which takes two parameters and draws a line crossing my line. In the end this is for creating transistor stick diagrams.

– mox
Jan 30 at 18:34





I am going to add further tikzset commands. I have written a style which takes two parameters and draws a line crossing my line. In the end this is for creating transistor stick diagrams.

– mox
Jan 30 at 18:34













With other tikzset commands the solution I proposed will work fine. Depending on how you are drawing the diagrams, this can perhaps be achieved with styles. But we'd probably need to see the whole drawing to say for sure.

– Phelype Oleinik
Jan 30 at 18:46







With other tikzset commands the solution I proposed will work fine. Depending on how you are drawing the diagrams, this can perhaps be achieved with styles. But we'd probably need to see the whole drawing to say for sure.

– Phelype Oleinik
Jan 30 at 18:46















First: Thank you! (forgot that in my first comment) I added the context and how I want to use the code. It should be compilable if you comment out the last two lines inside the tikzpicture. They cannot work yet. Could you give an example how to make the code work if the list is not numbers, or -- even better -- how the <key>/.list handler works around this problem?

– mox
Jan 30 at 19:49





First: Thank you! (forgot that in my first comment) I added the context and how I want to use the code. It should be compilable if you comment out the last two lines inside the tikzpicture. They cannot work yet. Could you give an example how to make the code work if the list is not numbers, or -- even better -- how the <key>/.list handler works around this problem?

– mox
Jan 30 at 19:49













In the advanced code you already use all the aftergroup trickery, which you could also use for tikzset. So, to some extent you may benefit from smuggling. Yet I fail to see the purpose of all this here.

– marmot
Jan 30 at 20:02





In the advanced code you already use all the aftergroup trickery, which you could also use for tikzset. So, to some extent you may benefit from smuggling. Yet I fail to see the purpose of all this here.

– marmot
Jan 30 at 20:02










1 Answer
1






active

oldest

votes


















3














As I said in the comment, this happens because the contents of foreach are executed inside a group, so when the group ends, the value of line width (modified by the very thick key) is restored to the previous value. That's why doing it outside the foreach loop works okay.



Solution to the first code



Here's a simple solution by changing the looping command. There are several options, here I used expl3's fp_step_variable:nnnNn.



First I make a copy of fp_step_variable:nnnNn called fpStepVariable. The syntax of fp_step_variable:nnnNn is:



fp_step_variable:nnnNn {<initial value>} {<step>} {<final value>} <tl var> {<code>}


so I replaced:



foreach pos in {0.1, 0.2, 0.3, 0.4}


by



fpStepVariable {0.1} {0.1} {0.4} pos


I also added two typeouts to show the effect. After running the code the console shows:



Line width before: 0.4pt
======== Foreach: pos=0.1 ======== Foreach: pos=0.2 ======== Foreach: pos=0.3 ======== Foreach: pos=0.4
Line width after: 1.2pt


Full code:



documentclass[tikz]{standalone}
usepackage{expl3}

ExplSyntaxOn
cs_set_eq:NN fpStepVariable fp_step_variable:nnnNn
ExplSyntaxOff

tikzset{
mystyle/.code=
{
typeout{Line width before: thepgflinewidth}
fpStepVariable {0.1} {0.1} {0.4} pos
{
tikzset{very thick}, %This line is an exact copy of the comented line but has no effect.
message{======== Foreach: pos=pos}
}
typeout{Line width after: thepgflinewidth}
}
}

begin{document}
begin{tikzpicture}
draw [help lines] (-10,-10) grid (10,10);
draw[mystyle] (0,0) --++ (5,0);
end{tikzpicture}
end{document}




Solution to the second code



The solution I used here is very similar to the previous one except for a few details.



Previously I used fp_step_variable:nnnNn because you had an uniform sequence of numbers. Now you have letters. One way to approach the problem is to use a clist_map_... function to loop through a comma-separated list of things. To keep the usage syntax similar I used clist_map_variable:nNn, whose syntax is:



clist_map_variable:nNn {<comma list>} <tl var> {<code>}


I copied clist_map_variable:nNn into ClistMapVariable and used:



ClistMapVariable{#1}name


where #1 is the list a,b,c, which you passed to the pmos key. One problem you'll face is that the variable name expands to the name (a, b, or c), but it's not the name itself, so you need to expand it first. For that I used:



edeftempa{noexpandtikzset{gate={pos}{name}}}
tempa


after the edef, tempa will be something like tikzset{gate={0.12345}{a}} which does what we want.



Finally, I used



pgfmathparse{rnd}
edefpos{pgfmathresult}


to give a value to pos.



Full code:



documentclass[tikz]{standalone}
usepackage{expl3}
ExplSyntaxOn
cs_set_eq:NN ClistMapVariable clist_map_variable:nNn
ExplSyntaxOff

% Code adapted from: https://tex.stackexchange.com/a/393496/69074
usetikzlibrary{decorations.markings}

%{{{ Transistor Stick Diagrams

%{{{ Layer Magic

% Source: Adapted from https://tex.stackexchange.com/a/20426/69074
pgfdeclarelayer{M3L} % Metal 3
pgfdeclarelayer{M2L} % Metal 1
pgfdeclarelayer{M1L} % Metal 1
pgfdeclarelayer{POL} % Poly-Silicon
pgfdeclarelayer{DDL} % Diffusion
pgfdeclarelayer{CONTL} % Contacts
pgfsetlayers{DDL,POL,M1L,M2L,M3L,CONTL,main}

makeatletter
pgfkeys{%
/tikz/on layer/.code={
pgfonlayer{#1}begingroup
aftergroupendpgfonlayer
aftergroupendgroup
},
/tikz/node on layer/.code={
gdefnode@@on@layer{%
setboxtikz@tempbox=hboxbgrouppgfonlayer{#1}unhboxtikz@tempboxendpgfonlayeregroup}
aftergroupnode@on@layer
},
/tikz/end node on layer/.code={
endpgfonlayerendgroupendgroup
}
}

defnode@on@layer{aftergroupnode@@on@layer}

%}}}

%{{{ Declare the Node shapes

% Code stolen (and slightly adapted from Circuitikz:
% Source: /usr/share/texmf-dist/tex/generic/circuitikz/pgfcircshapes.tex
makeatletter
newdimensticknodewidth
sticknodewidth=1cm

%% Left out, boring and too long

makeatother
%}}}

%{{{ Line Styles

tikzset{
M3/.style = { draw=green, line width=0.3, on layer=M3L }, % Metal 3 Path
M2/.style = { draw=yellow, line width=0.3, on layer=M2L }, % Metal 2 Path
M1/.style = { draw=turquoise, line width=0.3, on layer=M1L }, % Metal 1 Path
PO/.style = { draw=blue, line width=0.3, on layer=POL }, % Poly-Silicon Path (Gate)
PD/.style = { draw=red!50, line width=0.3, on layer=DDL }, % P-Diffusion Path (PMOS)
ND/.style = { draw=red, line width=0.3, on layer=DDL }, % N-Diffusion Path (NMOS)
air/.style = { draw=black,dashed,line width=0.1, on layer=CONTL }, % N-Diffusion Path (NMOS)
}

%}}}

%{{{ Port Styles

tikzset{
M3P/.style = {stickport, color=green, node on layer=M3L }, % Metal 3 Terminal
M2P/.style = {stickport, color=yellow, node on layer=M2L }, % Metal 2 Terminal
M1P/.style = {stickport, color=turquoise, node on layer=M1L }, % Metal 1 Terminal
POP/.style = {stickport, color=blue, node on layer=POL }, % Poly-Silicon Terminal
PDP/.style = {stickport, color=red!50, node on layer=DDL }, % P-Diffusion Terminal (PMOS)
NDP/.style = {stickport, color=red, node on layer=DDL }, % N-Diffusion Terminal (NMOS)
CON/.style = {stickcontact, color=black, node on layer=CONTL}, % Via (between touching M3,M2,M1,PO,P-Diff,N-Diff)
TAP/.style = {sticktap, color=black, node on layer=CONTL}, % Substrate Tap (between touching M1,Diff,N-Diff)
TAPCON/.style = {sticktapcon, color=black, node on layer=CONTL}, % Merged Tap and Via
}
%}}}

%{{{ Automatic Transistors

tikzset{
gate/.style 2 args=
{
thick,decoration=
{
markings, mark=at position {#1} with
{
draw[PO] (0,-0.25)coordinate(m#2ga)--(0,0.25)coordinate(m#2gb);
node[inner xsep=0, inner ysep=0.1mm,above left,font=tiny,rotate=pgfdecoratedangle-90](x) {$M_{#2}$};
}
},
postaction={decorate}
},
stick pmos/.style=
{
PD,
gate/.list={#1}
},
pmos/.code=
{
ClistMapVariable{#1}name
{
pgfmathparse{rnd}
edefpos{pgfmathresult}
edeftempa{noexpandtikzset{gate={pos}{name}}}
tempa
}
}
}
%}}}

%}}}

begin{document}
begin{tikzpicture}
draw [help lines] (-10,-10) grid (10,10);

draw[stick pmos={{0.333}{1},{0.666}{2}}] (0,0)--++(0,2);
draw[PO] (m1ga)--++(0.5,0.5);
draw[PO] (m2gb)--++(-0.5,-0.5);

draw[pmos={a,b,c}] (3,0)--++(0,2); % Gates spaced automatically
draw[PO] (maga)--++(0.5,0.5);
draw[PO] (magb)--++(-0.5,-0.5);

end{tikzpicture}
end{document}




Remarks




  • This is one way to do it. There are many more. You could use Mr. marmot's suggestion to "smuggle" the tikzset outside the groups, or you could use some other looping function, or even do something clever with styles.


  • I used clist_map_variable:nNn to keep the syntax similar to before. You could use clist_map_inline:nn, which would spare you from doing that expansion shenanigan. I'll leave this one for you.


  • The syntax tikzstyle{a}=[b] is deprecated. You should use tikzset{s/.style={b}}. I changed it in your code.







share|improve this answer

























    Your Answer








    StackExchange.ready(function() {
    var channelOptions = {
    tags: "".split(" "),
    id: "85"
    };
    initTagRenderer("".split(" "), "".split(" "), channelOptions);

    StackExchange.using("externalEditor", function() {
    // Have to fire editor after snippets, if snippets enabled
    if (StackExchange.settings.snippets.snippetsEnabled) {
    StackExchange.using("snippets", function() {
    createEditor();
    });
    }
    else {
    createEditor();
    }
    });

    function createEditor() {
    StackExchange.prepareEditor({
    heartbeatType: 'answer',
    autoActivateHeartbeat: false,
    convertImagesToLinks: false,
    noModals: true,
    showLowRepImageUploadWarning: true,
    reputationToPostImages: null,
    bindNavPrevention: true,
    postfix: "",
    imageUploader: {
    brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
    contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
    allowUrls: true
    },
    onDemand: true,
    discardSelector: ".discard-answer"
    ,immediatelyShowMarkdownHelp:true
    });


    }
    });














    draft saved

    draft discarded


















    StackExchange.ready(
    function () {
    StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2ftex.stackexchange.com%2fquestions%2f472607%2ftikzset-does-not-work-in-foreach-loop%23new-answer', 'question_page');
    }
    );

    Post as a guest















    Required, but never shown

























    1 Answer
    1






    active

    oldest

    votes








    1 Answer
    1






    active

    oldest

    votes









    active

    oldest

    votes






    active

    oldest

    votes









    3














    As I said in the comment, this happens because the contents of foreach are executed inside a group, so when the group ends, the value of line width (modified by the very thick key) is restored to the previous value. That's why doing it outside the foreach loop works okay.



    Solution to the first code



    Here's a simple solution by changing the looping command. There are several options, here I used expl3's fp_step_variable:nnnNn.



    First I make a copy of fp_step_variable:nnnNn called fpStepVariable. The syntax of fp_step_variable:nnnNn is:



    fp_step_variable:nnnNn {<initial value>} {<step>} {<final value>} <tl var> {<code>}


    so I replaced:



    foreach pos in {0.1, 0.2, 0.3, 0.4}


    by



    fpStepVariable {0.1} {0.1} {0.4} pos


    I also added two typeouts to show the effect. After running the code the console shows:



    Line width before: 0.4pt
    ======== Foreach: pos=0.1 ======== Foreach: pos=0.2 ======== Foreach: pos=0.3 ======== Foreach: pos=0.4
    Line width after: 1.2pt


    Full code:



    documentclass[tikz]{standalone}
    usepackage{expl3}

    ExplSyntaxOn
    cs_set_eq:NN fpStepVariable fp_step_variable:nnnNn
    ExplSyntaxOff

    tikzset{
    mystyle/.code=
    {
    typeout{Line width before: thepgflinewidth}
    fpStepVariable {0.1} {0.1} {0.4} pos
    {
    tikzset{very thick}, %This line is an exact copy of the comented line but has no effect.
    message{======== Foreach: pos=pos}
    }
    typeout{Line width after: thepgflinewidth}
    }
    }

    begin{document}
    begin{tikzpicture}
    draw [help lines] (-10,-10) grid (10,10);
    draw[mystyle] (0,0) --++ (5,0);
    end{tikzpicture}
    end{document}




    Solution to the second code



    The solution I used here is very similar to the previous one except for a few details.



    Previously I used fp_step_variable:nnnNn because you had an uniform sequence of numbers. Now you have letters. One way to approach the problem is to use a clist_map_... function to loop through a comma-separated list of things. To keep the usage syntax similar I used clist_map_variable:nNn, whose syntax is:



    clist_map_variable:nNn {<comma list>} <tl var> {<code>}


    I copied clist_map_variable:nNn into ClistMapVariable and used:



    ClistMapVariable{#1}name


    where #1 is the list a,b,c, which you passed to the pmos key. One problem you'll face is that the variable name expands to the name (a, b, or c), but it's not the name itself, so you need to expand it first. For that I used:



    edeftempa{noexpandtikzset{gate={pos}{name}}}
    tempa


    after the edef, tempa will be something like tikzset{gate={0.12345}{a}} which does what we want.



    Finally, I used



    pgfmathparse{rnd}
    edefpos{pgfmathresult}


    to give a value to pos.



    Full code:



    documentclass[tikz]{standalone}
    usepackage{expl3}
    ExplSyntaxOn
    cs_set_eq:NN ClistMapVariable clist_map_variable:nNn
    ExplSyntaxOff

    % Code adapted from: https://tex.stackexchange.com/a/393496/69074
    usetikzlibrary{decorations.markings}

    %{{{ Transistor Stick Diagrams

    %{{{ Layer Magic

    % Source: Adapted from https://tex.stackexchange.com/a/20426/69074
    pgfdeclarelayer{M3L} % Metal 3
    pgfdeclarelayer{M2L} % Metal 1
    pgfdeclarelayer{M1L} % Metal 1
    pgfdeclarelayer{POL} % Poly-Silicon
    pgfdeclarelayer{DDL} % Diffusion
    pgfdeclarelayer{CONTL} % Contacts
    pgfsetlayers{DDL,POL,M1L,M2L,M3L,CONTL,main}

    makeatletter
    pgfkeys{%
    /tikz/on layer/.code={
    pgfonlayer{#1}begingroup
    aftergroupendpgfonlayer
    aftergroupendgroup
    },
    /tikz/node on layer/.code={
    gdefnode@@on@layer{%
    setboxtikz@tempbox=hboxbgrouppgfonlayer{#1}unhboxtikz@tempboxendpgfonlayeregroup}
    aftergroupnode@on@layer
    },
    /tikz/end node on layer/.code={
    endpgfonlayerendgroupendgroup
    }
    }

    defnode@on@layer{aftergroupnode@@on@layer}

    %}}}

    %{{{ Declare the Node shapes

    % Code stolen (and slightly adapted from Circuitikz:
    % Source: /usr/share/texmf-dist/tex/generic/circuitikz/pgfcircshapes.tex
    makeatletter
    newdimensticknodewidth
    sticknodewidth=1cm

    %% Left out, boring and too long

    makeatother
    %}}}

    %{{{ Line Styles

    tikzset{
    M3/.style = { draw=green, line width=0.3, on layer=M3L }, % Metal 3 Path
    M2/.style = { draw=yellow, line width=0.3, on layer=M2L }, % Metal 2 Path
    M1/.style = { draw=turquoise, line width=0.3, on layer=M1L }, % Metal 1 Path
    PO/.style = { draw=blue, line width=0.3, on layer=POL }, % Poly-Silicon Path (Gate)
    PD/.style = { draw=red!50, line width=0.3, on layer=DDL }, % P-Diffusion Path (PMOS)
    ND/.style = { draw=red, line width=0.3, on layer=DDL }, % N-Diffusion Path (NMOS)
    air/.style = { draw=black,dashed,line width=0.1, on layer=CONTL }, % N-Diffusion Path (NMOS)
    }

    %}}}

    %{{{ Port Styles

    tikzset{
    M3P/.style = {stickport, color=green, node on layer=M3L }, % Metal 3 Terminal
    M2P/.style = {stickport, color=yellow, node on layer=M2L }, % Metal 2 Terminal
    M1P/.style = {stickport, color=turquoise, node on layer=M1L }, % Metal 1 Terminal
    POP/.style = {stickport, color=blue, node on layer=POL }, % Poly-Silicon Terminal
    PDP/.style = {stickport, color=red!50, node on layer=DDL }, % P-Diffusion Terminal (PMOS)
    NDP/.style = {stickport, color=red, node on layer=DDL }, % N-Diffusion Terminal (NMOS)
    CON/.style = {stickcontact, color=black, node on layer=CONTL}, % Via (between touching M3,M2,M1,PO,P-Diff,N-Diff)
    TAP/.style = {sticktap, color=black, node on layer=CONTL}, % Substrate Tap (between touching M1,Diff,N-Diff)
    TAPCON/.style = {sticktapcon, color=black, node on layer=CONTL}, % Merged Tap and Via
    }
    %}}}

    %{{{ Automatic Transistors

    tikzset{
    gate/.style 2 args=
    {
    thick,decoration=
    {
    markings, mark=at position {#1} with
    {
    draw[PO] (0,-0.25)coordinate(m#2ga)--(0,0.25)coordinate(m#2gb);
    node[inner xsep=0, inner ysep=0.1mm,above left,font=tiny,rotate=pgfdecoratedangle-90](x) {$M_{#2}$};
    }
    },
    postaction={decorate}
    },
    stick pmos/.style=
    {
    PD,
    gate/.list={#1}
    },
    pmos/.code=
    {
    ClistMapVariable{#1}name
    {
    pgfmathparse{rnd}
    edefpos{pgfmathresult}
    edeftempa{noexpandtikzset{gate={pos}{name}}}
    tempa
    }
    }
    }
    %}}}

    %}}}

    begin{document}
    begin{tikzpicture}
    draw [help lines] (-10,-10) grid (10,10);

    draw[stick pmos={{0.333}{1},{0.666}{2}}] (0,0)--++(0,2);
    draw[PO] (m1ga)--++(0.5,0.5);
    draw[PO] (m2gb)--++(-0.5,-0.5);

    draw[pmos={a,b,c}] (3,0)--++(0,2); % Gates spaced automatically
    draw[PO] (maga)--++(0.5,0.5);
    draw[PO] (magb)--++(-0.5,-0.5);

    end{tikzpicture}
    end{document}




    Remarks




    • This is one way to do it. There are many more. You could use Mr. marmot's suggestion to "smuggle" the tikzset outside the groups, or you could use some other looping function, or even do something clever with styles.


    • I used clist_map_variable:nNn to keep the syntax similar to before. You could use clist_map_inline:nn, which would spare you from doing that expansion shenanigan. I'll leave this one for you.


    • The syntax tikzstyle{a}=[b] is deprecated. You should use tikzset{s/.style={b}}. I changed it in your code.







    share|improve this answer






























      3














      As I said in the comment, this happens because the contents of foreach are executed inside a group, so when the group ends, the value of line width (modified by the very thick key) is restored to the previous value. That's why doing it outside the foreach loop works okay.



      Solution to the first code



      Here's a simple solution by changing the looping command. There are several options, here I used expl3's fp_step_variable:nnnNn.



      First I make a copy of fp_step_variable:nnnNn called fpStepVariable. The syntax of fp_step_variable:nnnNn is:



      fp_step_variable:nnnNn {<initial value>} {<step>} {<final value>} <tl var> {<code>}


      so I replaced:



      foreach pos in {0.1, 0.2, 0.3, 0.4}


      by



      fpStepVariable {0.1} {0.1} {0.4} pos


      I also added two typeouts to show the effect. After running the code the console shows:



      Line width before: 0.4pt
      ======== Foreach: pos=0.1 ======== Foreach: pos=0.2 ======== Foreach: pos=0.3 ======== Foreach: pos=0.4
      Line width after: 1.2pt


      Full code:



      documentclass[tikz]{standalone}
      usepackage{expl3}

      ExplSyntaxOn
      cs_set_eq:NN fpStepVariable fp_step_variable:nnnNn
      ExplSyntaxOff

      tikzset{
      mystyle/.code=
      {
      typeout{Line width before: thepgflinewidth}
      fpStepVariable {0.1} {0.1} {0.4} pos
      {
      tikzset{very thick}, %This line is an exact copy of the comented line but has no effect.
      message{======== Foreach: pos=pos}
      }
      typeout{Line width after: thepgflinewidth}
      }
      }

      begin{document}
      begin{tikzpicture}
      draw [help lines] (-10,-10) grid (10,10);
      draw[mystyle] (0,0) --++ (5,0);
      end{tikzpicture}
      end{document}




      Solution to the second code



      The solution I used here is very similar to the previous one except for a few details.



      Previously I used fp_step_variable:nnnNn because you had an uniform sequence of numbers. Now you have letters. One way to approach the problem is to use a clist_map_... function to loop through a comma-separated list of things. To keep the usage syntax similar I used clist_map_variable:nNn, whose syntax is:



      clist_map_variable:nNn {<comma list>} <tl var> {<code>}


      I copied clist_map_variable:nNn into ClistMapVariable and used:



      ClistMapVariable{#1}name


      where #1 is the list a,b,c, which you passed to the pmos key. One problem you'll face is that the variable name expands to the name (a, b, or c), but it's not the name itself, so you need to expand it first. For that I used:



      edeftempa{noexpandtikzset{gate={pos}{name}}}
      tempa


      after the edef, tempa will be something like tikzset{gate={0.12345}{a}} which does what we want.



      Finally, I used



      pgfmathparse{rnd}
      edefpos{pgfmathresult}


      to give a value to pos.



      Full code:



      documentclass[tikz]{standalone}
      usepackage{expl3}
      ExplSyntaxOn
      cs_set_eq:NN ClistMapVariable clist_map_variable:nNn
      ExplSyntaxOff

      % Code adapted from: https://tex.stackexchange.com/a/393496/69074
      usetikzlibrary{decorations.markings}

      %{{{ Transistor Stick Diagrams

      %{{{ Layer Magic

      % Source: Adapted from https://tex.stackexchange.com/a/20426/69074
      pgfdeclarelayer{M3L} % Metal 3
      pgfdeclarelayer{M2L} % Metal 1
      pgfdeclarelayer{M1L} % Metal 1
      pgfdeclarelayer{POL} % Poly-Silicon
      pgfdeclarelayer{DDL} % Diffusion
      pgfdeclarelayer{CONTL} % Contacts
      pgfsetlayers{DDL,POL,M1L,M2L,M3L,CONTL,main}

      makeatletter
      pgfkeys{%
      /tikz/on layer/.code={
      pgfonlayer{#1}begingroup
      aftergroupendpgfonlayer
      aftergroupendgroup
      },
      /tikz/node on layer/.code={
      gdefnode@@on@layer{%
      setboxtikz@tempbox=hboxbgrouppgfonlayer{#1}unhboxtikz@tempboxendpgfonlayeregroup}
      aftergroupnode@on@layer
      },
      /tikz/end node on layer/.code={
      endpgfonlayerendgroupendgroup
      }
      }

      defnode@on@layer{aftergroupnode@@on@layer}

      %}}}

      %{{{ Declare the Node shapes

      % Code stolen (and slightly adapted from Circuitikz:
      % Source: /usr/share/texmf-dist/tex/generic/circuitikz/pgfcircshapes.tex
      makeatletter
      newdimensticknodewidth
      sticknodewidth=1cm

      %% Left out, boring and too long

      makeatother
      %}}}

      %{{{ Line Styles

      tikzset{
      M3/.style = { draw=green, line width=0.3, on layer=M3L }, % Metal 3 Path
      M2/.style = { draw=yellow, line width=0.3, on layer=M2L }, % Metal 2 Path
      M1/.style = { draw=turquoise, line width=0.3, on layer=M1L }, % Metal 1 Path
      PO/.style = { draw=blue, line width=0.3, on layer=POL }, % Poly-Silicon Path (Gate)
      PD/.style = { draw=red!50, line width=0.3, on layer=DDL }, % P-Diffusion Path (PMOS)
      ND/.style = { draw=red, line width=0.3, on layer=DDL }, % N-Diffusion Path (NMOS)
      air/.style = { draw=black,dashed,line width=0.1, on layer=CONTL }, % N-Diffusion Path (NMOS)
      }

      %}}}

      %{{{ Port Styles

      tikzset{
      M3P/.style = {stickport, color=green, node on layer=M3L }, % Metal 3 Terminal
      M2P/.style = {stickport, color=yellow, node on layer=M2L }, % Metal 2 Terminal
      M1P/.style = {stickport, color=turquoise, node on layer=M1L }, % Metal 1 Terminal
      POP/.style = {stickport, color=blue, node on layer=POL }, % Poly-Silicon Terminal
      PDP/.style = {stickport, color=red!50, node on layer=DDL }, % P-Diffusion Terminal (PMOS)
      NDP/.style = {stickport, color=red, node on layer=DDL }, % N-Diffusion Terminal (NMOS)
      CON/.style = {stickcontact, color=black, node on layer=CONTL}, % Via (between touching M3,M2,M1,PO,P-Diff,N-Diff)
      TAP/.style = {sticktap, color=black, node on layer=CONTL}, % Substrate Tap (between touching M1,Diff,N-Diff)
      TAPCON/.style = {sticktapcon, color=black, node on layer=CONTL}, % Merged Tap and Via
      }
      %}}}

      %{{{ Automatic Transistors

      tikzset{
      gate/.style 2 args=
      {
      thick,decoration=
      {
      markings, mark=at position {#1} with
      {
      draw[PO] (0,-0.25)coordinate(m#2ga)--(0,0.25)coordinate(m#2gb);
      node[inner xsep=0, inner ysep=0.1mm,above left,font=tiny,rotate=pgfdecoratedangle-90](x) {$M_{#2}$};
      }
      },
      postaction={decorate}
      },
      stick pmos/.style=
      {
      PD,
      gate/.list={#1}
      },
      pmos/.code=
      {
      ClistMapVariable{#1}name
      {
      pgfmathparse{rnd}
      edefpos{pgfmathresult}
      edeftempa{noexpandtikzset{gate={pos}{name}}}
      tempa
      }
      }
      }
      %}}}

      %}}}

      begin{document}
      begin{tikzpicture}
      draw [help lines] (-10,-10) grid (10,10);

      draw[stick pmos={{0.333}{1},{0.666}{2}}] (0,0)--++(0,2);
      draw[PO] (m1ga)--++(0.5,0.5);
      draw[PO] (m2gb)--++(-0.5,-0.5);

      draw[pmos={a,b,c}] (3,0)--++(0,2); % Gates spaced automatically
      draw[PO] (maga)--++(0.5,0.5);
      draw[PO] (magb)--++(-0.5,-0.5);

      end{tikzpicture}
      end{document}




      Remarks




      • This is one way to do it. There are many more. You could use Mr. marmot's suggestion to "smuggle" the tikzset outside the groups, or you could use some other looping function, or even do something clever with styles.


      • I used clist_map_variable:nNn to keep the syntax similar to before. You could use clist_map_inline:nn, which would spare you from doing that expansion shenanigan. I'll leave this one for you.


      • The syntax tikzstyle{a}=[b] is deprecated. You should use tikzset{s/.style={b}}. I changed it in your code.







      share|improve this answer




























        3












        3








        3







        As I said in the comment, this happens because the contents of foreach are executed inside a group, so when the group ends, the value of line width (modified by the very thick key) is restored to the previous value. That's why doing it outside the foreach loop works okay.



        Solution to the first code



        Here's a simple solution by changing the looping command. There are several options, here I used expl3's fp_step_variable:nnnNn.



        First I make a copy of fp_step_variable:nnnNn called fpStepVariable. The syntax of fp_step_variable:nnnNn is:



        fp_step_variable:nnnNn {<initial value>} {<step>} {<final value>} <tl var> {<code>}


        so I replaced:



        foreach pos in {0.1, 0.2, 0.3, 0.4}


        by



        fpStepVariable {0.1} {0.1} {0.4} pos


        I also added two typeouts to show the effect. After running the code the console shows:



        Line width before: 0.4pt
        ======== Foreach: pos=0.1 ======== Foreach: pos=0.2 ======== Foreach: pos=0.3 ======== Foreach: pos=0.4
        Line width after: 1.2pt


        Full code:



        documentclass[tikz]{standalone}
        usepackage{expl3}

        ExplSyntaxOn
        cs_set_eq:NN fpStepVariable fp_step_variable:nnnNn
        ExplSyntaxOff

        tikzset{
        mystyle/.code=
        {
        typeout{Line width before: thepgflinewidth}
        fpStepVariable {0.1} {0.1} {0.4} pos
        {
        tikzset{very thick}, %This line is an exact copy of the comented line but has no effect.
        message{======== Foreach: pos=pos}
        }
        typeout{Line width after: thepgflinewidth}
        }
        }

        begin{document}
        begin{tikzpicture}
        draw [help lines] (-10,-10) grid (10,10);
        draw[mystyle] (0,0) --++ (5,0);
        end{tikzpicture}
        end{document}




        Solution to the second code



        The solution I used here is very similar to the previous one except for a few details.



        Previously I used fp_step_variable:nnnNn because you had an uniform sequence of numbers. Now you have letters. One way to approach the problem is to use a clist_map_... function to loop through a comma-separated list of things. To keep the usage syntax similar I used clist_map_variable:nNn, whose syntax is:



        clist_map_variable:nNn {<comma list>} <tl var> {<code>}


        I copied clist_map_variable:nNn into ClistMapVariable and used:



        ClistMapVariable{#1}name


        where #1 is the list a,b,c, which you passed to the pmos key. One problem you'll face is that the variable name expands to the name (a, b, or c), but it's not the name itself, so you need to expand it first. For that I used:



        edeftempa{noexpandtikzset{gate={pos}{name}}}
        tempa


        after the edef, tempa will be something like tikzset{gate={0.12345}{a}} which does what we want.



        Finally, I used



        pgfmathparse{rnd}
        edefpos{pgfmathresult}


        to give a value to pos.



        Full code:



        documentclass[tikz]{standalone}
        usepackage{expl3}
        ExplSyntaxOn
        cs_set_eq:NN ClistMapVariable clist_map_variable:nNn
        ExplSyntaxOff

        % Code adapted from: https://tex.stackexchange.com/a/393496/69074
        usetikzlibrary{decorations.markings}

        %{{{ Transistor Stick Diagrams

        %{{{ Layer Magic

        % Source: Adapted from https://tex.stackexchange.com/a/20426/69074
        pgfdeclarelayer{M3L} % Metal 3
        pgfdeclarelayer{M2L} % Metal 1
        pgfdeclarelayer{M1L} % Metal 1
        pgfdeclarelayer{POL} % Poly-Silicon
        pgfdeclarelayer{DDL} % Diffusion
        pgfdeclarelayer{CONTL} % Contacts
        pgfsetlayers{DDL,POL,M1L,M2L,M3L,CONTL,main}

        makeatletter
        pgfkeys{%
        /tikz/on layer/.code={
        pgfonlayer{#1}begingroup
        aftergroupendpgfonlayer
        aftergroupendgroup
        },
        /tikz/node on layer/.code={
        gdefnode@@on@layer{%
        setboxtikz@tempbox=hboxbgrouppgfonlayer{#1}unhboxtikz@tempboxendpgfonlayeregroup}
        aftergroupnode@on@layer
        },
        /tikz/end node on layer/.code={
        endpgfonlayerendgroupendgroup
        }
        }

        defnode@on@layer{aftergroupnode@@on@layer}

        %}}}

        %{{{ Declare the Node shapes

        % Code stolen (and slightly adapted from Circuitikz:
        % Source: /usr/share/texmf-dist/tex/generic/circuitikz/pgfcircshapes.tex
        makeatletter
        newdimensticknodewidth
        sticknodewidth=1cm

        %% Left out, boring and too long

        makeatother
        %}}}

        %{{{ Line Styles

        tikzset{
        M3/.style = { draw=green, line width=0.3, on layer=M3L }, % Metal 3 Path
        M2/.style = { draw=yellow, line width=0.3, on layer=M2L }, % Metal 2 Path
        M1/.style = { draw=turquoise, line width=0.3, on layer=M1L }, % Metal 1 Path
        PO/.style = { draw=blue, line width=0.3, on layer=POL }, % Poly-Silicon Path (Gate)
        PD/.style = { draw=red!50, line width=0.3, on layer=DDL }, % P-Diffusion Path (PMOS)
        ND/.style = { draw=red, line width=0.3, on layer=DDL }, % N-Diffusion Path (NMOS)
        air/.style = { draw=black,dashed,line width=0.1, on layer=CONTL }, % N-Diffusion Path (NMOS)
        }

        %}}}

        %{{{ Port Styles

        tikzset{
        M3P/.style = {stickport, color=green, node on layer=M3L }, % Metal 3 Terminal
        M2P/.style = {stickport, color=yellow, node on layer=M2L }, % Metal 2 Terminal
        M1P/.style = {stickport, color=turquoise, node on layer=M1L }, % Metal 1 Terminal
        POP/.style = {stickport, color=blue, node on layer=POL }, % Poly-Silicon Terminal
        PDP/.style = {stickport, color=red!50, node on layer=DDL }, % P-Diffusion Terminal (PMOS)
        NDP/.style = {stickport, color=red, node on layer=DDL }, % N-Diffusion Terminal (NMOS)
        CON/.style = {stickcontact, color=black, node on layer=CONTL}, % Via (between touching M3,M2,M1,PO,P-Diff,N-Diff)
        TAP/.style = {sticktap, color=black, node on layer=CONTL}, % Substrate Tap (between touching M1,Diff,N-Diff)
        TAPCON/.style = {sticktapcon, color=black, node on layer=CONTL}, % Merged Tap and Via
        }
        %}}}

        %{{{ Automatic Transistors

        tikzset{
        gate/.style 2 args=
        {
        thick,decoration=
        {
        markings, mark=at position {#1} with
        {
        draw[PO] (0,-0.25)coordinate(m#2ga)--(0,0.25)coordinate(m#2gb);
        node[inner xsep=0, inner ysep=0.1mm,above left,font=tiny,rotate=pgfdecoratedangle-90](x) {$M_{#2}$};
        }
        },
        postaction={decorate}
        },
        stick pmos/.style=
        {
        PD,
        gate/.list={#1}
        },
        pmos/.code=
        {
        ClistMapVariable{#1}name
        {
        pgfmathparse{rnd}
        edefpos{pgfmathresult}
        edeftempa{noexpandtikzset{gate={pos}{name}}}
        tempa
        }
        }
        }
        %}}}

        %}}}

        begin{document}
        begin{tikzpicture}
        draw [help lines] (-10,-10) grid (10,10);

        draw[stick pmos={{0.333}{1},{0.666}{2}}] (0,0)--++(0,2);
        draw[PO] (m1ga)--++(0.5,0.5);
        draw[PO] (m2gb)--++(-0.5,-0.5);

        draw[pmos={a,b,c}] (3,0)--++(0,2); % Gates spaced automatically
        draw[PO] (maga)--++(0.5,0.5);
        draw[PO] (magb)--++(-0.5,-0.5);

        end{tikzpicture}
        end{document}




        Remarks




        • This is one way to do it. There are many more. You could use Mr. marmot's suggestion to "smuggle" the tikzset outside the groups, or you could use some other looping function, or even do something clever with styles.


        • I used clist_map_variable:nNn to keep the syntax similar to before. You could use clist_map_inline:nn, which would spare you from doing that expansion shenanigan. I'll leave this one for you.


        • The syntax tikzstyle{a}=[b] is deprecated. You should use tikzset{s/.style={b}}. I changed it in your code.







        share|improve this answer















        As I said in the comment, this happens because the contents of foreach are executed inside a group, so when the group ends, the value of line width (modified by the very thick key) is restored to the previous value. That's why doing it outside the foreach loop works okay.



        Solution to the first code



        Here's a simple solution by changing the looping command. There are several options, here I used expl3's fp_step_variable:nnnNn.



        First I make a copy of fp_step_variable:nnnNn called fpStepVariable. The syntax of fp_step_variable:nnnNn is:



        fp_step_variable:nnnNn {<initial value>} {<step>} {<final value>} <tl var> {<code>}


        so I replaced:



        foreach pos in {0.1, 0.2, 0.3, 0.4}


        by



        fpStepVariable {0.1} {0.1} {0.4} pos


        I also added two typeouts to show the effect. After running the code the console shows:



        Line width before: 0.4pt
        ======== Foreach: pos=0.1 ======== Foreach: pos=0.2 ======== Foreach: pos=0.3 ======== Foreach: pos=0.4
        Line width after: 1.2pt


        Full code:



        documentclass[tikz]{standalone}
        usepackage{expl3}

        ExplSyntaxOn
        cs_set_eq:NN fpStepVariable fp_step_variable:nnnNn
        ExplSyntaxOff

        tikzset{
        mystyle/.code=
        {
        typeout{Line width before: thepgflinewidth}
        fpStepVariable {0.1} {0.1} {0.4} pos
        {
        tikzset{very thick}, %This line is an exact copy of the comented line but has no effect.
        message{======== Foreach: pos=pos}
        }
        typeout{Line width after: thepgflinewidth}
        }
        }

        begin{document}
        begin{tikzpicture}
        draw [help lines] (-10,-10) grid (10,10);
        draw[mystyle] (0,0) --++ (5,0);
        end{tikzpicture}
        end{document}




        Solution to the second code



        The solution I used here is very similar to the previous one except for a few details.



        Previously I used fp_step_variable:nnnNn because you had an uniform sequence of numbers. Now you have letters. One way to approach the problem is to use a clist_map_... function to loop through a comma-separated list of things. To keep the usage syntax similar I used clist_map_variable:nNn, whose syntax is:



        clist_map_variable:nNn {<comma list>} <tl var> {<code>}


        I copied clist_map_variable:nNn into ClistMapVariable and used:



        ClistMapVariable{#1}name


        where #1 is the list a,b,c, which you passed to the pmos key. One problem you'll face is that the variable name expands to the name (a, b, or c), but it's not the name itself, so you need to expand it first. For that I used:



        edeftempa{noexpandtikzset{gate={pos}{name}}}
        tempa


        after the edef, tempa will be something like tikzset{gate={0.12345}{a}} which does what we want.



        Finally, I used



        pgfmathparse{rnd}
        edefpos{pgfmathresult}


        to give a value to pos.



        Full code:



        documentclass[tikz]{standalone}
        usepackage{expl3}
        ExplSyntaxOn
        cs_set_eq:NN ClistMapVariable clist_map_variable:nNn
        ExplSyntaxOff

        % Code adapted from: https://tex.stackexchange.com/a/393496/69074
        usetikzlibrary{decorations.markings}

        %{{{ Transistor Stick Diagrams

        %{{{ Layer Magic

        % Source: Adapted from https://tex.stackexchange.com/a/20426/69074
        pgfdeclarelayer{M3L} % Metal 3
        pgfdeclarelayer{M2L} % Metal 1
        pgfdeclarelayer{M1L} % Metal 1
        pgfdeclarelayer{POL} % Poly-Silicon
        pgfdeclarelayer{DDL} % Diffusion
        pgfdeclarelayer{CONTL} % Contacts
        pgfsetlayers{DDL,POL,M1L,M2L,M3L,CONTL,main}

        makeatletter
        pgfkeys{%
        /tikz/on layer/.code={
        pgfonlayer{#1}begingroup
        aftergroupendpgfonlayer
        aftergroupendgroup
        },
        /tikz/node on layer/.code={
        gdefnode@@on@layer{%
        setboxtikz@tempbox=hboxbgrouppgfonlayer{#1}unhboxtikz@tempboxendpgfonlayeregroup}
        aftergroupnode@on@layer
        },
        /tikz/end node on layer/.code={
        endpgfonlayerendgroupendgroup
        }
        }

        defnode@on@layer{aftergroupnode@@on@layer}

        %}}}

        %{{{ Declare the Node shapes

        % Code stolen (and slightly adapted from Circuitikz:
        % Source: /usr/share/texmf-dist/tex/generic/circuitikz/pgfcircshapes.tex
        makeatletter
        newdimensticknodewidth
        sticknodewidth=1cm

        %% Left out, boring and too long

        makeatother
        %}}}

        %{{{ Line Styles

        tikzset{
        M3/.style = { draw=green, line width=0.3, on layer=M3L }, % Metal 3 Path
        M2/.style = { draw=yellow, line width=0.3, on layer=M2L }, % Metal 2 Path
        M1/.style = { draw=turquoise, line width=0.3, on layer=M1L }, % Metal 1 Path
        PO/.style = { draw=blue, line width=0.3, on layer=POL }, % Poly-Silicon Path (Gate)
        PD/.style = { draw=red!50, line width=0.3, on layer=DDL }, % P-Diffusion Path (PMOS)
        ND/.style = { draw=red, line width=0.3, on layer=DDL }, % N-Diffusion Path (NMOS)
        air/.style = { draw=black,dashed,line width=0.1, on layer=CONTL }, % N-Diffusion Path (NMOS)
        }

        %}}}

        %{{{ Port Styles

        tikzset{
        M3P/.style = {stickport, color=green, node on layer=M3L }, % Metal 3 Terminal
        M2P/.style = {stickport, color=yellow, node on layer=M2L }, % Metal 2 Terminal
        M1P/.style = {stickport, color=turquoise, node on layer=M1L }, % Metal 1 Terminal
        POP/.style = {stickport, color=blue, node on layer=POL }, % Poly-Silicon Terminal
        PDP/.style = {stickport, color=red!50, node on layer=DDL }, % P-Diffusion Terminal (PMOS)
        NDP/.style = {stickport, color=red, node on layer=DDL }, % N-Diffusion Terminal (NMOS)
        CON/.style = {stickcontact, color=black, node on layer=CONTL}, % Via (between touching M3,M2,M1,PO,P-Diff,N-Diff)
        TAP/.style = {sticktap, color=black, node on layer=CONTL}, % Substrate Tap (between touching M1,Diff,N-Diff)
        TAPCON/.style = {sticktapcon, color=black, node on layer=CONTL}, % Merged Tap and Via
        }
        %}}}

        %{{{ Automatic Transistors

        tikzset{
        gate/.style 2 args=
        {
        thick,decoration=
        {
        markings, mark=at position {#1} with
        {
        draw[PO] (0,-0.25)coordinate(m#2ga)--(0,0.25)coordinate(m#2gb);
        node[inner xsep=0, inner ysep=0.1mm,above left,font=tiny,rotate=pgfdecoratedangle-90](x) {$M_{#2}$};
        }
        },
        postaction={decorate}
        },
        stick pmos/.style=
        {
        PD,
        gate/.list={#1}
        },
        pmos/.code=
        {
        ClistMapVariable{#1}name
        {
        pgfmathparse{rnd}
        edefpos{pgfmathresult}
        edeftempa{noexpandtikzset{gate={pos}{name}}}
        tempa
        }
        }
        }
        %}}}

        %}}}

        begin{document}
        begin{tikzpicture}
        draw [help lines] (-10,-10) grid (10,10);

        draw[stick pmos={{0.333}{1},{0.666}{2}}] (0,0)--++(0,2);
        draw[PO] (m1ga)--++(0.5,0.5);
        draw[PO] (m2gb)--++(-0.5,-0.5);

        draw[pmos={a,b,c}] (3,0)--++(0,2); % Gates spaced automatically
        draw[PO] (maga)--++(0.5,0.5);
        draw[PO] (magb)--++(-0.5,-0.5);

        end{tikzpicture}
        end{document}




        Remarks




        • This is one way to do it. There are many more. You could use Mr. marmot's suggestion to "smuggle" the tikzset outside the groups, or you could use some other looping function, or even do something clever with styles.


        • I used clist_map_variable:nNn to keep the syntax similar to before. You could use clist_map_inline:nn, which would spare you from doing that expansion shenanigan. I'll leave this one for you.


        • The syntax tikzstyle{a}=[b] is deprecated. You should use tikzset{s/.style={b}}. I changed it in your code.








        share|improve this answer














        share|improve this answer



        share|improve this answer








        edited Jan 30 at 21:21

























        answered Jan 30 at 18:20









        Phelype OleinikPhelype Oleinik

        22.6k54482




        22.6k54482






























            draft saved

            draft discarded




















































            Thanks for contributing an answer to TeX - LaTeX Stack Exchange!


            • Please be sure to answer the question. Provide details and share your research!

            But avoid



            • Asking for help, clarification, or responding to other answers.

            • Making statements based on opinion; back them up with references or personal experience.


            To learn more, see our tips on writing great answers.




            draft saved


            draft discarded














            StackExchange.ready(
            function () {
            StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2ftex.stackexchange.com%2fquestions%2f472607%2ftikzset-does-not-work-in-foreach-loop%23new-answer', 'question_page');
            }
            );

            Post as a guest















            Required, but never shown





















































            Required, but never shown














            Required, but never shown












            Required, but never shown







            Required, but never shown

































            Required, but never shown














            Required, but never shown












            Required, but never shown







            Required, but never shown







            Popular posts from this blog

            Biblatex bibliography style without URLs when DOI exists (in Overleaf with Zotero bibliography)

            ComboBox Display Member on multiple fields

            Is it possible to collect Nectar points via Trainline?