Take the 2-minute tour ×
TeX - LaTeX Stack Exchange is a question and answer site for users of TeX, LaTeX, ConTeXt, and related typesetting systems. It's 100% free, no registration required.

I'm trying to write some code that allows me to reveal in stages the content of a pre-existing file (a pspicture showing a geometric construction). I'm trying to write this using LaTeX3. I've got some working code, but I don't like how I'm implementing it. Currently, the working version is a hobbled together collection of commands. I want to streamline this using l3keys. However, I'm getting stuck.

What's working:

Here's what I've got that's working. There are three files:

File in which I define the expl3 interface: this is put in a file called stages.tex

%% defining stages
\usepackage{xparse}
\usepackage{verbatim}
\ExplSyntaxOn

\tl_new:N    \ace_reveal_tl
\tl_gset:Nn  \ace_reveal_tl {REVEAL}
\tl_new:N    \ace_conceal_tl
\tl_gset:Nn  \ace_conceal_tl {CONCEAL}

\NewDocumentCommand{\revealstage}{ m }{
        \tl_gset:cV { ace__reveal__ #1 __stage__new } \ace_reveal_tl
    }
\NewDocumentCommand{\burystage}{ m }{
        \tl_gset:cV { ace__reveal__ #1 __stage__new } \ace_conceal_tl
}

\NewDocumentCommand{\testforstage}{ m m m }{
            \tl_if_eq:cNTF { ace__reveal__ #1 __stage__new } \ace_reveal_tl
                           {#2}
                           {#3}    
}

\NewDocumentEnvironment{stage}{ m }
        {
            \tl_if_eq:cNF { ace__reveal__ #1 __stage__new } \ace_reveal_tl
                          {\expandafter\comment}
        }
        {
            \tl_if_eq:cNF { ace__reveal__ #1 __stage__new } \ace_reveal_tl
                          {\expandafter\endcomment}
          }

\ExplSyntaxOff  

File in which I define the picture I'm using in which I implement stages: this file is called diagram.tex

\begin{pspicture}[showgrid=false](-20,-13)(20,13)
    %..% compass directions %..% 
    {
        \psset{PointName=none,PointSymbol=none} 
        \pstGeonode(0,0){o}(1,0){r}(0,1){u}
        \pstRotation[RotAngle=20]{o}{r}[r1] 
        \pstGeonode(0,0){Q}
    }
    %% temporarily define midpont of segment(PQ) --> M to control positioning
    \pstGeonode[PointName=none,PointSymbol=none,PosAngle=0](0,0){tM}
    %% point outside the circle and the center of circle
    \pstTranslation[DistCoef=14,PosAngle=80]{o}{r1}{tM}[Q]
    \pstTranslation[DistCoef=10,PosAngle=-100]{r1}{o}{tM}[P]
    %% construct circle centered at P
    \pstCircleOA[Radius=\pstDistVal{9}]{P}{}

    %% construct mid-point between P and Q
    \pstTranslation[DistCoef=9,PointName=none,PointSymbol=none]{o}{r}{P}[B]
    \pstTranslation[DistCoef=0.5,PointName=none,PointSymbol=none]{P}{Q}{P}[M]
    %% show constructions
    \begin{stage}{midpoint}
        \pstLineAB[linecolor=blue,linewidth=0.1pt,linestyle=dashed]{P}{Q}
        \pstGeonode[PointName=M,PosAngle=-90](M){showM}
    \end{stage}

    %% construct circle centered at M passing through P and Q
    \begin{stage}{large circle}
        \pstCircleOA[linecolor=blue,linewidth=0.2pt,linestyle=dashed]{M}{P}
    \end{stage}

    %% construct tangents
    \pstInterCC[PointName=none,PointSymbol=none,RadiusB=\pstDistVal{9}]{M}{P}{P}{}{U}{V}
    \begin{stage}{tangents}
        \testforstage{large circle}{
            \pstGeonode[PointName={U},PosAngle=-90](U){showU}
            \pstGeonode[PointName={V},PosAngle=110](V){showV}
        }{
            \pstGeonode[PointName={U},PosAngle=-50](U){showU}
            \pstGeonode[PointName={V},PosAngle=90](V){showV}
        }
        \pstLineAB[linecolor=red,nodesep=-8]{Q}{V}
        \pstLineAB[linecolor=red,nodesep=-8]{Q}{U}
    \end{stage}

\end{pspicture}

The main document:

\documentclass{article}
\usepackage{pstricks,pst-eucl}
\psset{unit=0.15cm}
\usepackage[margin=1in]{geometry}
\input{stages}
\pagestyle{empty}
\begin{document}

    \input{diagram} 

    \revealstage{midpoint}
    \input{diagram}

    \revealstage{large circle}
    \input{diagram}

    \revealstage{tangents}
    \input{diagram}

    \burystage{midpoint}
    \burystage{large circle}
    \input{diagram}

\end{document}

This creates:

enter image description here

What's not working:

I would really like to be able to write something like the following lines in the main document:

\activatestage[reveal=midpoint,
               conceal={large circle,
                        midpoint}]
              {diagram}

But this above example is a bit more sophisticated than I've currently tried to implement. Currently, I haven't written code to handle passing multiple values to be parse by the key. I've only written something that I believe should be able to handle the following:

\activatestage[reveal=midpoint,
               conceal=large circle]
              {diagram}

And this is the code I use to try to implement this:

%% defining keys
\ExplSyntaxOn
\keys_define:nn { stages }{
    reveal  .code:n = \fnc_reveal_stages:n #1,
    conceal .code:n = \fnc_conceal_stages:n #1
}

\cs_new:Npn \fnc_reveal_stages:n #1 {
        \tl_gset:cV { ace__reveal__ #1 __stage__new } \ace_reveal_tl
}

\cs_new:Npn \fnc_conceal_stages:n #1 {
        \tl_gset:cV { ace__reveal__ #1 __stage__new } \ace_conceal_tl
}

\NewDocumentCommand{\activatestage}{ o m }{
        \tl_set:Nn  \l__no_value_tl         { \NoValue    }
        \tl_set:Nn  \l__keys_present_tl     { #1 }
        \tl_show:N \l__keys_present_tl
        \bool_if:nF {        \tl_if_eq_p:NN \l__keys_present_tl  \l__no_value_tl) }
                {
                    \keys_set:nn{ stages }{#1}
                }
        \input{#2}
}
\ExplSyntaxOff

I've put the above in its own file called additions.tex

Here's the main document where I try to implement the new approach:

\documentclass{article}
\usepackage{pstricks,pst-eucl}
\psset{unit=0.15cm}
\usepackage[margin=1in]{geometry}
\input{stages}
\input{additions}
\pagestyle{empty}
\begin{document}

    \input{diagram} 

    \revealstage{midpoint}
    \input{diagram}

    \revealstage{large circle}
    \input{diagram}

    \revealstage{tangents}
    \input{diagram}

    \activatestage[reveal=midpoint,
                   conceal=large circle]
                  {diagram}

\end{document}

But this results in:

enter image description here

But this isn't doing what I expect (as you can see by comparing to my working example). The key seems to only see the first letter of the value being passed to it. How do I get the key to see the entire value?

share|improve this question
    
At least it should be reveal .code:n = \fnc_reveal_stages:n {#1} Always put braces around an n-type argument. –  egreg Jan 26 '13 at 18:10
    
@egreg. Oh how humiliating! Such a simple mistake. Thank you! –  A.Ellett Jan 26 '13 at 18:12
    
You should use a boolean, instead of comparing token lists for concealing or revealing the environment. –  egreg Jan 26 '13 at 18:13
    
@egreg. I'm not sure how to implement that. The reason is that I would like the user to have the freedom to define the names for the blocks to be revealed/concealed. –  A.Ellett Jan 26 '13 at 18:18
    
You can define "named" conditionals with \bool_new:c, maybe checking first if they are already existent; then you can use \bool_gset_true:c and \bool_gset_false:c for setting them and \bool_if:cTF for using them. –  egreg Jan 26 '13 at 18:22
show 1 more comment

1 Answer

up vote 5 down vote accepted

Enclose n-type arguments in braces: it should be

\keys_define:nn { stages }
 {
  reveal  .code:n = \fnc_reveal_stages:n  { #1 },
  conceal .code:n = \fnc_conceal_stages:n { #1 },
 }

Here's a proposal using booleans and a good deal of simplifications. However, you should also add a command for defining all allowed "stages".

\documentclass{article}
\usepackage{pstricks,pst-eucl}
\psset{unit=0.15cm}

\usepackage[margin=1in]{geometry}

%% defining stages
\usepackage{xparse}
\usepackage{verbatim}
\ExplSyntaxOn

\NewDocumentCommand{\revealstage}{ m }
 {
  \ace_reveal_stage:n { #1 }
 }
\cs_new_protected:Npn \ace_reveal_stage:n #1
 {
  \bool_if_exist:cF { g__ace_reveal_ #1 _stage_bool }
   { \bool_new:c { g__ace_reveal_ #1 _stage_bool } }
  \bool_gset_true:c { g__ace_reveal_ #1 _stage_bool }
 }
\NewDocumentCommand{\burystage}{ m }
 {
  \ace_conceal_stage:n { #1 }
 }
\cs_new_protected:Npn \ace_conceal_stage:n #1
 {
  \bool_if_exist:cF { g__ace_reveal_ #1 _stage_bool }
   { \bool_new:c { g__ace_reveal_ #1 _stage_bool } }
  \bool_gset_false:c { g__ace_reveal_ #1 _stage_bool }
 }

\NewDocumentCommand{\testforstage}{ m m m }
 {
  \bool_if:cTF { g__ace_reveal_ #1 _stage_bool } { #2 } { #3 }
 }

\NewDocumentEnvironment{stage}{ m }
 {
  \bool_if:cF { g__ace_reveal_ #1 _stage_bool } {\comment}
 }
 {
  \bool_if:cF { g__ace_reveal_ #1 _stage_bool } {\endcomment}
 }

%%% Keyval syntax

\keys_define:nn { stages }{
    reveal  .code:n = \ace_reveal_stage:n  { #1 },
    conceal .code:n = \ace_conceal_stage:n { #1 },
}

\NewDocumentCommand{\activatestage}{ O{} m }
 {
  \keys_set:nn { stages } { #1 }
  \input{#2}
 }

\ExplSyntaxOff  

\pagestyle{empty}
\begin{document}

\activatestage[reveal=midpoint,
               conceal=large circle]
              {diagram}

\end{document}

enter image description here

Notes

  1. Comparing token lists is not an efficient way; booleans are surely better.

  2. Please, stick to the naming conventions; variables should start with l_ or g_ (or l__ and g__ if they are "internal").

  3. \keys_set:nn is perfectly happy to process an empty argument, so

    \NewDocumentCommand{\activatestage}{ O{} m }
    

    is much more efficient than your testing of \NoValue. In any case, you should use \IfNoValueTF to test for the presence of an optional argument.

share|improve this answer
    
Other than the accessor commands, your MWE is pretty much exactly how I rewrote my document after your suggestion to use booleans. Thank you for showing the \bool_if_exist. I've also implemented setting multiple values through \clist_set:Nn \l__ace_stages {#1} and then calling \clist_map_inline:Nn \l__ace_stage { \bool_gset_true:c { g__ace_reveal_ ##1 _stage_new } }. And mutatis mutandis, for the conceal side of things. I have some very nice code now. Thank you again. –  A.Ellett Jan 26 '13 at 19:08
add comment

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

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