3

The MWE bellow uses exsheets package to print the solutions to questions at the end of a book. The code doesn't work as it should as it seems to be an expansion issue. When, instead of \SetQuestionProperties{section-title= \secName }, I put what \secName variable it's supposed to hold at that point, One in the 1st section and Two in the 2nd, then all is well (i.e. replace "\secName" with "One" for the 1st couple of occurrences and with "Two" for the next couple).
Does anyone know how to make this code work, to properly pass the string values of the \secName variable to \SetQuestionProperties?

The current result is "Section Answers 1). foo 2). bar Section Answers 1). baz 2). foobar" and it should be Section One 1). foo 2). bar Section Two 1). baz 2). foobar.

\documentclass{scrartcl}
\usepackage{exsheets}
\setlength{\parindent}{0pt}

\SetupExSheets{counter-within=section}
\DeclareQuestionProperty{section-title}
\SetupExSheets{counter-within=section ,
         headings=inline-nr ,
         counter-format=qu).}
\SetupExSheets{section-hook = \noindent\bfseries
          Section \GetQuestionProperty{section-title}{\CurrentQuestionID}
          \space}

\newcommand{\secName}{}
\newcommand{\lsection}[1]
           {
           \renewcommand{\secName}{#1}
           \section{#1}
           }



\begin{document}


\lsection{One}

\begin{question}
 \SetQuestionProperties{section-title= \secName } 
  say foo
\end{question}
\begin{solution}
  foo
\end{solution}

\begin{question}
  \SetQuestionProperties{section-title= \secName }
  say bar
\end{question}
\begin{solution}
  bar
\end{solution}

\lsection{Two}

\begin{question}
  \SetQuestionProperties{section-title= \secName }
  say baz
\end{question}
\begin{solution}
  baz
\end{solution}

\begin{question}
\SetQuestionProperties{section-title= \secName }
  say foobar
\end{question}
\begin{solution}
  foobar
\end{solution}

\lsection{Answers}

\printsolutions

\end{document}

2 Answers 2

5

Indeed in \SetQuestionProperties{ section-title = \secName } the macro \secName needs to be expanded once. Otherwise the question property section-title is set to the token \secName it is only expanded when used in \printsolutions where its current definition is Answers (which is what you're seeing in your example).

A usual way to expand a token before is using \expandafter. This is usable here but tedious: we'd need to step over 16 tokens:

\expandafter\SetQuestionProperties\expandafter{\expandafter
  s\expandafter e\expandafter c\expandafter t\expandafter
  i\expandafter o\expandafter n\expandafter-\expandafter
  t\expandafter i\expandafter t\expandafter l\expandafter
  e\expandafter=\secName
}

So a better choice is another usual solution: defining a temporary macro (\x) using \edef which exhaustively expands the replacement text. In order to only expand \secName once we can use \unexpanded\expandafter{\secName}:

\begingroup
\edef\x{\endgroup
  \SetQuestionProperties{
    section-title = \unexpanded\expandafter{\secName}
  }}\x

(\SetQuestionProperties is not expandable so it needs not be worried about.) However, exsheets is written in expl3 and already has a version of \SetQuestionProperties that expands its argument: \exsheets_set_question_properties:x. We just need to make it usable outside expl3 syntax:

\ExplSyntaxOn
\NewDocumentCommand \SetQuestionPropertiesX {m}
  { \exsheets_set_question_properties:x {#1} }
\ExplSyntaxOff

In the following example I also use pre-body-hook so I don't to change the line in the beginning of every question.

\documentclass[parskip=half]{scrartcl}
\usepackage{exsheets}
% \setlength{\parindent}{0pt} please don't use this but rather KOMA-Script's
% `parskip' option

\ExplSyntaxOn
\NewDocumentCommand \SetQuestionPropertiesX {m}
  { \exsheets_set_question_properties:x {#1} }
\ExplSyntaxOff

\DeclareQuestionProperty{section-title}
\SetupExSheets{
  counter-within = section ,
  headings       = inline-nr ,
  counter-format = qu). ,
  section-hook   =
    \noindent\bfseries Section
    \GetQuestionProperty{section-title}{\CurrentQuestionID}\space ,
  question/pre-body-hook =
    \SetQuestionPropertiesX{ section-title = \unexpanded\expandafter{\secName} }
}

\newcommand{\secName}{}
\newcommand{\lsection}[1]{\renewcommand*{\secName}{#1}\section{#1}}

\begin{document}

\lsection{One}

\begin{question}
  say foo
\end{question}
\begin{solution}
  foo
\end{solution}

\begin{question}
  say bar
\end{question}
\begin{solution}
  bar
\end{solution}

\lsection{Two}

\begin{question}
  say baz
\end{question}
\begin{solution}
  baz
\end{solution}

\begin{question}
  say foobar
\end{question}
\begin{solution}
  foobar
\end{solution}

\lsection{Answers}

\printsolutions

\end{document}

enter image description here

6
  • I accepted this answer as it has the clues to solve the expansion issue without "digging" into exsheets internals. But I'll use one of the 2 codes provided in the two answers. Thank you! As for the \setlength{\parindent}{0pt}, does it clash with something in exsheets? If not, this is meant for the entire book - not even one word is outside the question or solution environments and everything is very cramped. Sort of a "save the trees" typesetting for a colection of exercises "book". But I suppose I can use the koma-script classes (using plain old {report} now) if needed.
    – alwaysask
    Oct 16, 2014 at 10:46
  • The parindent thing is a typographical one: if you set \parindent to zero readers might not have any clue when a paragraph ends and a new one starts. So the usual practice is to at least introduce a vertical skip between paragraphs then. Doing this manually (\setlength{\parskip}{\baselineskip}) can lead to unexpected results, though. KOMA-Script's option handles this correctly.
    – cgnieder
    Oct 16, 2014 at 10:50
  • For other classes there is the parskip package. (I assumed you're already using KOMA-Script since your example uses scrartcl instead of article...)
    – cgnieder
    Oct 16, 2014 at 10:52
  • For now I have to mimic the typesetting of an existing book (printed every year for the past 20 years) and there's no indentation whatsoever except chapters/section titles. New paragraph means new exercise. The exercise number typesetting (bold, bigger, whatever) provides the clue as where a new block of text starts. There are no paragraphs within an exercise except lists made with tasks or shortlst. But I will try using packages instead. Thanks
    – alwaysask
    Oct 16, 2014 at 11:02
  • @alwaysask In almost all books I have ever seen there is either a paragraph indent or a paragraph skip. Your example had neither...
    – cgnieder
    Oct 16, 2014 at 11:05
3

This is an “illegal” answer, as the code I propose relies on defining a variant of an internal command. The answer is so mainly aimed to give ideas to the package developer.

I define a command \DeclareQuestionPropertyFixed that takes as arguments a property name and the variable from which the value should be obtained from, in this case

\DeclareQuestionPropertyFixed{section-title}{\secName}

so one has just to do

\SetupExSheets{
  ...
  question/pre-body-hook = \SetQuestionProperties{section-title},
}

Complete code.

\documentclass[parskip=half]{scrartcl}
\usepackage{exsheets}

\ExplSyntaxOn
\NewDocumentCommand \DeclareQuestionPropertyFixed { m m }
 {
  \exsheets_declare_question_property:n {#1--fixed}
  \keys_define:nn { question / meta }
   {
    #1 .code:n = \__exsheets_question_set_property:nV { #1--fixed } #2
   }
 }
\cs_generate_variant:Nn \__exsheets_question_set_property:nn {nV}
\ExplSyntaxOff

\DeclareQuestionPropertyFixed{section-title}{\secName}
\SetupExSheets{
  counter-within = section ,
  headings = inline-nr ,
  counter-format = qu). ,
  section-hook = \noindent\bfseries Section 
                 \GetQuestionProperty{section-title}{\CurrentQuestionID}\space ,
  question/pre-body-hook = \SetQuestionProperties{section-title}
}

\newcommand{\secName}{}
\newcommand{\lsection}[1]{\renewcommand*{\secName}{#1}\section{#1}}

\begin{document}

\lsection{One}

\begin{question}
  say foo
\end{question}
\begin{solution}
  foo
\end{solution}

\begin{question}
  say bar
\end{question}
\begin{solution}
  bar
\end{solution}

\lsection{Two}

\begin{question}
  say baz
\end{question}
\begin{solution}
  baz
\end{solution}

\begin{question}
  say foobar
\end{question}
\begin{solution}
  foobar
\end{solution}

\lsection{Answers}

\printsolutions

\end{document}

enter image description here

1
  • interesting idea!
    – cgnieder
    Oct 16, 2014 at 9:40

You must log in to answer this question.

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