TransWikia.com

Macros inside pstricks parameters

TeX - LaTeX Asked by J.-E. Pin on January 13, 2021

I would like to create a command to pass easily from color to black-and-white pictures. For this purpose, I would like to use a newif ifBlackAndWhite together with a macro myCommand such that if ifBlackAndWhitetrue, then

begin{pspicture}(0,0)(2,2)
    pscircle[myCommand, linewidth=1mm](1,1){0.5}
end{pspicture}

becomes

begin{pspicture}(0,0)(2,2)
    pscircle[fillstyle=none, linewidth=1mm](1,1){0.5}
end{pspicture}

and if ifBlackAndWhitefalse, then it becomes

begin{pspicture}(0,0)(2,2)
    pscircle[fillstyle=solid, fillcolor=red, linewidth=1mm](1,1){0.5}
end{pspicture}

Is it possible to define such a macro? A naive template below…

documentclass{article}
usepackage{pstricks}

newcommand{myCommand}{...}

newififBlackAndWhite  BlackAndWhitefalse    

ifBlackAndWhite
renewcommand{myCommand}{...}
fi
  
begin{document}
    
begin{pspicture}(0,0)(2,2)
    pscircle[fillstyle=none, linewidth=1mm](1,1){0.5}
end{pspicture}

begin{pspicture}(0,0)(2,2)
    pscircle[fillstyle=solid, fillcolor=red, linewidth=1mm](1,1){0.5}
end{pspicture}

begin{pspicture}(0,0)(2,2)
    pscircle[myCommand, linewidth=1mm](1,1){0.5}
end{pspicture}

end{document}

4 Answers

You need to change the expansion order. For simple commands like pscircle you can define variants that do that for you (ePScircle below). For more complicated commands this is not so easy. Which is why you may want to considering switching to TikZ, where styles can do all of this with ease.

documentclass{article}
usepackage{pstricks}

newififBlackAndWhite  
BlackAndWhitefalse    

newcommandmyCommand{ifBlackAndWhite  
fillstyle=none%
else
fillstyle=solid,fillcolor=red%
fi}
defePScircle[#1](#2)#3{expanded{noexpandpscircle[#1](#2){#3}}} 
begin{document}
    
begin{pspicture}(0,0)(2,2)
    pscircle[fillstyle=none, linewidth=1mm](1,1){0.5}
end{pspicture}

begin{pspicture}(0,0)(2,2)
    pscircle[fillstyle=solid, fillcolor=red, linewidth=1mm](1,1){0.5}
end{pspicture}

BlackAndWhitetrue  
begin{pspicture}(0,0)(2,2)
    expanded{noexpandpscircle[myCommand, linewidth=1mm](1,1){0.5}}
end{pspicture}

BlackAndWhitefalse  
begin{pspicture}(0,0)(2,2)
    expanded{noexpandpscircle[myCommand, linewidth=1mm](1,1){0.5}}
end{pspicture}


BlackAndWhitetrue  
begin{pspicture}(0,0)(2,2)
    ePScircle[myCommand, linewidth=1mm](1,1){0.5}
end{pspicture}

BlackAndWhitefalse  
begin{pspicture}(0,0)(2,2)
    ePScircle[myCommand, linewidth=1mm](1,1){0.5}
end{pspicture}
end{document}

enter image description here

Correct answer by user232027 on January 13, 2021

The optional parameters passed to any PStricks object is not expanded. You can redefine the macro that captures the optional parameters - pst@@object - to use an edef instead of a regular def:

makeatletter
defpst@@object#1[#2]{%
  edefpst@par{#2}% Changed from def to edef
  @ifnextchar+{@nameuse{#1@i}}{@nameuse{#1@i}}%
}
makeatother

A little more elegant is probably to use an etoolbox patch:

usepackage{etoolbox}

makeatletter
% patchcmd{<cmd>}{<search>}{<replace>}{<success>}{<failure>}
patchcmd{pst@@object}% <cmd>
  {def}% <search>
  {edef}% <replace>
  {}{}% <success><failure>
makeatother

An edef will expand the parameters once, which is probably sufficient in most cases.

enter image description here

documentclass{article}

usepackage{pstricks}
usepackage{etoolbox}

makeatletter
% patchcmd{<cmd>}{<search>}{<replace>}{<success>}{<failure>}
patchcmd{pst@@object}% <cmd>
  {def}% <search>
  {edef}% <replace>
  {}{}% <success><failure>
makeatother

newcommand{myCommand}{fillstyle=solid, fillcolor=red}

newififBlackAndWhite  BlackAndWhitefalse

ifBlackAndWhite
  renewcommand{myCommand}{fillstyle=none}
fi
  
begin{document}
    
begin{pspicture}(0,0)(2,2)
  pscircle[fillstyle=none, linewidth=1mm](1,1){0.5}
end{pspicture}

begin{pspicture}(0,0)(2,2)
  pscircle[fillstyle=solid, fillcolor=red, linewidth=1mm](1,1){0.5}
end{pspicture}

begin{pspicture}(0,0)(2,2)
  pscircle[myCommand, linewidth=1mm](1,1){0.5}
end{pspicture}

end{document}

And here is the output with BlackAndWhitetrue:

enter image description here

Answered by Werner on January 13, 2021

Here is a variant of the solution of user232027 which does with protected@edef@tempa{...} instead of expanded{...}.

I present it only because older TeX-engines don't have expanded.

Nonetheless I definitely prefer the solution of user232027 because a disadvantage of my variant is that you need to double hashes within the optional argument.

(I don't know if the optional argument of pscircle can contasin hashes.)

Unlike the solution of user232027 where all arguments are expanded my variant does only expand the optional argument if present.

documentclass{article}
usepackage{pstricks}

newififBlackAndWhite  
BlackAndWhitefalse    

makeatletter
newcommandmyCommand{%
  ifBlackAndWhiteexpandafter@firstoftwoelseexpandafter@secondoftwofi
  {fillstyle=none}{fillstyle=solid,fillcolor=red}%
}
newcommandePScircle{@ifnextchar[{ePScircleOpt}{pscircle}}%
newcommandePScircleOpt[1][]{%
  {protected@edef@tempa{#1}expandafter}%
  expandafterpscircleexpandafter[expandafter{@tempa}]%
}%
makeatother

begin{document}
    
begin{pspicture}(0,0)(2,2)
    pscircle[fillstyle=none, linewidth=1mm](1,1){0.5}
end{pspicture}

begin{pspicture}(0,0)(2,2)
    pscircle[fillstyle=solid, fillcolor=red, linewidth=1mm](1,1){0.5}
end{pspicture}

BlackAndWhitetrue  
begin{pspicture}(0,0)(2,2)
    expanded{noexpandpscircle[myCommand, linewidth=1mm](1,1){0.5}}
end{pspicture}

BlackAndWhitefalse  
begin{pspicture}(0,0)(2,2)
    expanded{noexpandpscircle[myCommand, linewidth=1mm](1,1){0.5}}
end{pspicture}


BlackAndWhitetrue  
begin{pspicture}(0,0)(2,2)
    ePScircle[myCommand, linewidth=1mm](1,1){0.5}
end{pspicture}

BlackAndWhitefalse  
begin{pspicture}(0,0)(2,2)
    ePScircle[myCommand, linewidth=1mm](1,1){0.5}
end{pspicture}
end{document}

enter image description here



Similar to egreg's approach you can define a key which evaluates the ifBlackAndWhite-switch:

documentclass{article}
usepackage{pstricks}

makeatletter
newififBlackAndWhite
BlackAndWhitefalse

define@key[psset]{pstricks}{myfill}[]{%
  ifBlackAndWhiteexpandafter@firstoftwoelseexpandafter@secondoftwofi
  {setkeys+[psset]{pstricks}{fillstyle=none}}%
  {setkeys+[psset]{pstricks}{fillstyle=solid,fillcolor=red}}%
}%
makeatother

begin{document}

BlackAndWhitefalse

begin{pspicture}(0,0)(2,2)
    pscircle[myfill, linewidth=1mm](1,1){0.5}
end{pspicture}

BlackAndWhitetrue

begin{pspicture}(0,0)(2,2)
    pscircle[myfill, linewidth=1mm](1,1){0.5}
end{pspicture}

end{document}

enter image description here

Answered by Ulrich Diez on January 13, 2021

You could define your own key.

documentclass{article}
usepackage{pstricks}

makeatletter % switch the commented lines for changing the meaning of the key
define@key[psset]{pstricks}{myfill}[]{setkeys+[psset]{pstricks}{fillstyle=none}}
%define@key[psset]{pstricks}{myfill}[]{setkeys+[psset]{pstricks}{fillstyle=solid,fillcolor=red}}
makeatother

begin{document}

begin{pspicture}(0,0)(2,2)
pscircle[fillstyle=none, linewidth=1mm](1,1){0.5}
end{pspicture}

begin{pspicture}(0,0)(2,2)
pscircle[fillstyle=solid, fillcolor=red, linewidth=1mm](1,1){0.5}
end{pspicture}

begin{pspicture}(0,0)(2,2)
pscircle[myfill, linewidth=1mm](1,1){0.5}
end{pspicture}

end{document}

enter image description here

After switching the comments:

enter image description here

Answered by egreg on January 13, 2021

Add your own answers!

Ask a Question

Get help from others!

© 2024 TransWikia.com. All rights reserved. Sites we Love: PCI Database, UKBizDB, Menu Kuliner, Sharing RPP