2

I would like to use an environment to fill a vertical coffin. I find that I can fill the coffin this way, but that the poles get lost, in the sense the top pole (t) is treated as if it lies at the bottom of the coffin (the width also gets lost). I have to set the poles manually.

So, my question is whether there's a way to load the vertical coffin in an environment without losing the poles. In the following MWE, my use of \global is a hack, and so maybe also the cause of the problem.

Notes: a) I need to use an environment for compatibility with other codes...I know that can get the final result directly without setting the coffin inside the environment and without losing the poles; b) I have seen this thread and its replies, but they don't quite address my question.

\documentclass[10pt]{article}    
\usepackage{xcoffins,lipsum,xparse}

\NewCoffin{\CoffinA}
\NewCoffin{\CoffinB}

\DeclareDocumentCommand\SetCoffinB{m}{%
    \SetVerticalCoffin{\CoffinB}{100mm}{#1}
}

\NewDocumentEnvironment{coffinB}{+b}{%
   \global\SetCoffinB{\noindent#1}%
}{}

\begin{document}

\SetVerticalCoffin{\CoffinA}{100mm}{%
    {\Large\bfseries\noindent A Big Heading}%
}

\begin{coffinB}
\lipsum[1]
\end{coffinB}

\SetHorizontalPole \CoffinB {t} {\TotalHeight} % <=== why should this be necessary?
\JoinCoffins\CoffinA[l,b]\CoffinB[l,t](0pt,0pt)

\TypesetCoffin\CoffinA

\end{document} 

Without the \SetHorizontalPole command, I get this result, as if the top pole sits at the bottom of CoffinB:

enter image description here

With the \SetHorizontalPole for the top pole of CoffinB, I get this result, which is basically what I want:

enter image description here

5
  • \global\SetCoffinB is unlikely to do anything useful, you can not put \global before arbitrary tex macros it will just apply arbitrarily to the first non expandable token in the expansion of \SetCoffinB Commented Sep 30, 2019 at 20:10
  • \NewDocumentEnvironment{coffinB}{+b}{\gdef\tmp{\SetCoffinB{\noindent#1}}\aftergroup\tmp}{} runs without error but I am not sure I understand the question well enough to know if that produces the desired effect. Commented Sep 30, 2019 at 20:24
  • @DavidCarlisle -- Thanks, that code definitely fixes my problem. I would be great if you could unpack the ideas around \gdef\tmp{...}\aftergroup\tmp just a bit? What \global did for me originally was to get the coffin to exist outside the environment, and I gather that the expansion issue was responsible for the loss of poles?
    – John
    Commented Sep 30, 2019 at 20:51
  • if you put \global before a macro then you are lucky if anything useful happens, certainly it is by luck not design if it does anything before \SetCoffinB if for example you try to make a global definition with \global\newcommand\foo{..} it just makes some internal temp assignment in the implementation of \newcommand global, it doesn't affect the assignment to \foo at all. Commented Sep 30, 2019 at 20:55
  • Thanks, got it. How does the \gdef\tmp{...}\aftergroup\tmp construction resolve this?
    – John
    Commented Sep 30, 2019 at 20:57

1 Answer 1

3

\global can only be used before a tex primitive assignment. If you use it before a macro then it will perhaps make the first internal assignment in that macros expansion global, or it may do nothing or it may generate an error, depending on the internal implementation of the macro. Certainly for a coffin that requires several linked assignments for the box data itself and all the pole structures, a single \global can not possibly work.

If you use

 \NewDocumentEnvironment{coffinB}{+b}{%
   \gdef\tmp{\SetCoffinB{\noindent#1}}\aftergroup\tmp
}{}

then the body of the environment will be wrapped in the \SetCoffinB call but not executed, instead it is (globally) saved in a macro \tmp which is executed outside the group so essentially after the enviornment has finished.

Like any use of global variables this has some limitations, any nested use will break as the inner use would globally over-write \tmp messing up the outer one. The code could be made more robust to just smuggle the definition past one level of grouping without using a global assignment, but if nested use is not required, this is simpler.

1
  • Many thanks. Nested use is not required--although the smuggling operation does make me curious!
    – John
    Commented Sep 30, 2019 at 21:05

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .