6

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}{...}

\newif\ifBlackAndWhite  \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}
2

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}

\newif\ifBlackAndWhite  
\BlackAndWhitefalse    

\newcommand\myCommand{\ifBlackAndWhite  
fillstyle=none%
\else
fillstyle=solid,fillcolor=red%
\fi}
\def\ePScircle[#1](#2)#3{\expanded{\noexpand\pscircle[#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{\noexpand\pscircle[\myCommand, linewidth=1mm](1,1){0.5}}
\end{pspicture}

\BlackAndWhitefalse  
\begin{pspicture}(0,0)(2,2)
    \expanded{\noexpand\pscircle[\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

1
  • My problem was not really related with pstrick (I just transposed it in this context to avoid a too technical situation), but your solution using \expanded{\noexpand is exactly what I need. Thanks a lot !
    – J.-E. Pin
    Dec 31 '20 at 20:22
3

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
\def\pst@@object#1[#2]{%
  \edef\pst@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}

\newif\ifBlackAndWhite  \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

1

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

0

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}

\newif\ifBlackAndWhite  
\BlackAndWhitefalse    

\makeatletter
\newcommand\myCommand{%
  \ifBlackAndWhite\expandafter\@firstoftwo\else\expandafter\@secondoftwo\fi
  {fillstyle=none}{fillstyle=solid,fillcolor=red}%
}
\newcommand\ePScircle{\@ifnextchar[{\ePScircleOpt}{\pscircle}}%
\newcommand\ePScircleOpt[1][]{%
  {\protected@edef\@tempa{#1}\expandafter}%
  \expandafter\pscircle\expandafter[\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{\noexpand\pscircle[\myCommand, linewidth=1mm](1,1){0.5}}
\end{pspicture}

\BlackAndWhitefalse  
\begin{pspicture}(0,0)(2,2)
    \expanded{\noexpand\pscircle[\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
\newif\ifBlackAndWhite
\BlackAndWhitefalse

\define@key[psset]{pstricks}{myfill}[]{%
  \ifBlackAndWhite\expandafter\@firstoftwo\else\expandafter\@secondoftwo\fi
  {\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

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.