4

In order to create an assignment sheet, I am using the xsim package and to create subquestions within a question, I use the package tasks. The problem comes while referring to the subquestions. Ideally I would like the subquestions to be referred to as 1.2 or 1.3, instead they gets referred as just 1 as the MWE demonstrates. As you can see the output is really stupid.

I have these concerns

  1. How do I get cref identify the subquestions as "subquestion 1.1".? I would ideally like to issue a directive something like \crefname{subquestion}{subquestion}{subquestions}. The cref invocation should also be able to distinguish between a mere question and a subquestion.
  2. Suppose in future, I change counter-format = tsk[1] to counter-format = tsk[r], would I get consistent output? Something like "subquestion 1.a"?

EDIT by magguu :: please see my half-working answer and corresponding MWE

Please see the MWE::

\documentclass[11pt]{article}
\usepackage{tasks,cleveref,xsim}

\NewTasks[counter-format = tsk[1]),
    label-format = \itshape,%
    item-indent = 0em,%
    label-offset=0.8em,%
    label-align=left,%
    before-skip = 0pt,%
    after-item-skip=0pt%
]{subquestionblock}[\subquestion](2)

\crefname{exercise}{question}{questions}
\crefname{subquestion}{subquestion}{subquestions} % has no effect, obviously

\begin{document}
    \begin{exercise}[points=3]
        Isomers of a coordination compound. \label{iso}
        \begin{subquestionblock}
            \subquestion! Why do we have isomers? \label{why}
            \subquestion! Why did I even ask \cref{iso}? \label{metawhy}
            \subquestion! What do you mean \cref{metawhy}?
        \end{subquestionblock}
    \end{exercise}

    \begin{exercise}[points=3]
        Is there an end to stupid questions? \label{stu}
        \begin{subquestionblock}
            \subquestion! Discuss why \cref{metawhy} is a stupid question but \cref{why} is even stupider? \label{huh}
            \subquestion! Are both \cref{huh} and \cref{metawhy} both stupider that each other?
        \end{subquestionblock}
    \end{exercise}
\end{document}

enter image description here

1

After trying several things, now I have an ugly hack. It does not solve every thing and introduces some other irritants but it does solve the most vexing counter issue. For this I embed exercise in a new environment question which has its own counter called question. Then the formatting code of subquestion has a hack to increment another counter called subquestion.

The end result is that my concern number 2 gets resolved automatically as you can see in the output image attached : the subquestion 3.1 and subquestion 3.3.

However I still cannot resolve concern number 1. I tried to use some other hacks but got embroiled in \expandafter mess. I am not posting those efforts in my MWE here.

Now I have these new concerns:

  1. How do I get rid of the ")" coming after every references?
  2. How do I change several invocations of "question" to "subquestion". To wit, "question" in 1.2 should remain unchanged but other "question"s shd change to "subquestion". I could have changed definition of \refsubq but that would have other problems.

Please see the new MWE::

\documentclass[11pt]{article}
\usepackage{tasks,cleveref,xsim}

\newcommand{\refsubq}[1]{\cref{#1}.\ref{#1}}
\newcounter{question}
\newcounter{subquestion}[question]
\newcommand{\uglyhack}{\refstepcounter{subquestion}\itshape}

\NewTasks[counter-format = tsk[1]),
    label-format = \uglyhack,%
    item-indent = 0em,%
    label-offset=0.8em,%
    label-align=left,%
    before-skip = 0pt,%
    after-item-skip=0pt%
]{subquestionblock}[\subquestion](2)

\NewTasks[counter-format = tsk[a]),
    label-format = \uglyhack,%
    item-indent = 0em,%
    label-offset=0.8em,%
    label-align=left,%
    before-skip = 0pt,%
    after-item-skip=0pt%
]{subquestionblockA}[\subquestion](2)

\newenvironment{question}{\refstepcounter{question}\exercise}{\endexercise}
\crefname{exercise}{question}{questions}

\crefname{subquestion}{subquestion}{subquestions} % has no effect, obviously
\crefname{subquestionblock}{subquestion}{subquestions} % fails
\crefname{subquestionblockA}{subquestion}{subquestions} % fails

\begin{document}
    \begin{question}
        Isomers of a coordination compound. \label{iso}
        \begin{subquestionblock}
            \subquestion! Why do we have isomers? \label{why}
            \subquestion! Why did I even ask \cref{iso}? \label{metawhy}
            \subquestion! What do you mean \refsubq{metawhy}?
        \end{subquestionblock}
    \end{question}

    \begin{question}
        Is there an end to stupid questions? \label{stu}
        \begin{subquestionblockA}
            \subquestion! Discuss why \refsubq{metawhy} is a stupid question but \refsubq{why} is even stupider? \label{huh}
            \subquestion! Are \refsubq{huh} and \refsubq{metawhy} both stupider than each other? \label{huh2}
            \subquestion! Please see \refsubq{goto2} for more info. \label{goto}
        \end{subquestionblockA}
    \end{question}

    \begin{question}
        I am just a question.
        \begin{subquestionblock}
            \subquestion! I am a simple subquestion unlike \refsubq{huh2}.
            \subquestion! I am a subquestion (\refsubq{self}) stupid enough to refer to myself\label{self}.
            \subquestion! Please see \refsubq{goto} for even more info. \label{goto2}
        \end{subquestionblock}
    \end{question}
\end{document}

Image :: screenshot

1

Address your request to the author of the tasks-package and make a bug report:

  1. The code of the tasks package comes without properly commented sources, just as a .sty-file and thus is inscrutable. Same for some of the packages loaded/used by the tasks-package.

  2. It seems that instead of using \refstepcounter, the author of that package does his own counter-thingies, based on expl3 and using yet another one of his packages, called cntformats, which one has to spend hours on studying for finding out what might probably go on. According to my opinion, all this makes things even more inscrutable and, according to my opinion, is definitely not a good idea if one wishes ones own things to properly interact with common LaTeX2e-infrastructure.

  3. Within that inscrutable package, \cs_gset:Npx is used for defining the macro \@currentlabel. Seems this does redefine \@currentlabel globally. The LaTeX2e-kernel does never redefine \@currentlabel globally. If you do so, placing labels after ending one of those tasks-environments will yield wrong numbers when referencing these labels.

    (Well, the hyperref-package does redefine \@currentHref globally, which in my opinion is a similar well-established mis-concept as it may lead to connecting references with hyperlinks to wrong targets.)

    This sort of things does confuse and scare off those LaTeX-beginners who exercise the care of checking the correctness of the result while not being experienced enough for tracking down what is happening when things do not turn out correct. I saw users despairing after spending hours and days on studying inscrutable code instead of learning the relevant basics of their field of study as they were, while not yet knowing anything about these things, urged by teachers, who found another way of living out their profile neurosis, to use LaTeX and specific packages, which altogether they would never ever need again after leaving school/university.

  4. You additionally use the package cleveref. This package does redefine some of the kernel-macros, e.g., \refstepcounter and does rely on people using standard-infrastructure for doing counter-thingies, which the tasks-package does not:

    cleveref does redefine \refstepcounter to also define an additional macro \cref@currentlabel and does redefine \label to write two \newlabel-entries to the .aux-file instead of one: The usual \newlabel-entry whose data stems from \@currentlabel and an additional \newlabel-entry where the label-name has the suffix @cref and whose data stems from \cref@currentlabel and which delivers the data needed additionally by the cleveref-referencing-macros.

    The tasks-package, which does its own counter-thingies and which does redefine \@currentlabel on its own instead of using LaTeX2e-infrastructure/\refstepcounter, does not set \cref@currentlabel and thus breaks, e.g., the cleveref package.


Inspired by your own answer/your hack I just came up with a variant where you get rid of the closing parenthese and which makes \cref possible also and which also works out when using the hyperref package.

Of course my variant does not resolve the tasks package's behavior of redefining \@currentlabel globally but does the same thing for cleveref's \cref@currentlabel.

The gist is:

I added another key "ugly-label-hook" to the tasks-package which lets you specify some tokens that get inserted whenever the tasks-package for one of its items modifies \@currentlabel.

You can use this hook for "refstepping" the "dummy"-counter for your subquestions/subanswers.

"refstepping" the "dummy"-counter makes sure the macros \@currentlabel and \cref@currentlabel are (re)defined correctly.

As the tasks-package does for whatever reason redefine \@currentlabel globally, with the "ugly-label-hook" it must be ensured that both \@currentlabel and \cref@currentlabel are (re)defined globally also.

\documentclass[11pt]{article}
\usepackage{hyperref}
\usepackage{tasks,cleveref,xsim}

% ====Begin of patch of tasks.sty====
\makeatletter
\ExplSyntaxOn

% Allocate another token list for the ugly hack:
\tl_new:N     \l__sillyugly_label_hook_tl

% Add a key "ugly-label-hook" for setting that
% token list:
\keys_define:nn {tasks/list}
  {
    ugly-label-hook    .tl_set:N   =  \l__sillyugly_label_hook_tl ,
  }

% Include the ugly-label-hook-key into the `tasks' object:
%   #1: number of items
%   #2: number of columns
%   #3: label-format
\DeclareObjectType {tasks} {3}
% the `default' template interface:
\DeclareTemplateInterface {tasks} {default} {3}
  {
    enumerate       : boolean   = true    ,
    label           : tokenlist           ,
    indent          : length    = 2.5em   ,
    counter-format  : tokenlist = tsk[a]) ,
    label-format    : tokenlist ,
    %----------------------------------------------------
    ugly-label-hook : tokenlist ,
    %----------------------------------------------------
    label-width     : length    = 1em     ,
    label-offset    : length    = .3333em ,
    item-format     : tokenlist ,
    after-item-skip : skip      = 1ex plus 1ex minus 1ex
  }

% When patching the next macro, the really unlikely marker $ with
% unusual catcode is used in ``$tasks$default$label$'':
\cs_set:Nx \__tasks_restore_dollar:
  { \char_set_catcode:nn {36} { \char_value_catcode:n {36} } }
\char_set_catcode_alignment:N \$

% Include the ugly-label-hook-key into the `default' template code
% and apply the hook when \@currentlabel is changed:
\DeclareTemplateCode {tasks} {default} {3}
  {
    enumerate          = \l__tasks_enumerate_bool           ,
    label              = \l__tasks_label_tl                 ,
    indent             = \l__tasks_item_default_indent_dim  ,
    counter-format     = \l__tasks_label_pattern_tl         ,
    label-format       = \l__tasks_label_format_tl          ,
    %----------------------------------------------------
    ugly-label-hook    = \l__sillyugly_label_hook_tl     ,
    %----------------------------------------------------
    label-width        = \l__tasks_label_default_width_dim  ,
    label-offset       = \l__tasks_label_default_offset_dim ,
    item-format        = \l__tasks_item_format_tl           ,
    after-item-skip    = \l__tasks_after_item_skip
  }
  {
    \AssignTemplateKeys
    \bool_if:NF \l__tasks_label_width_bool
      {
        \dim_set_eq:NN
          \l__tasks_label_width_dim
          \l__tasks_label_default_width_dim
      }
    \bool_if:NF \l__tasks_item_indent_bool
      {
        \dim_set_eq:NN
          \l__tasks_item_indent_dim
          \l__tasks_item_default_indent_dim
      }
    \bool_if:NF \l__tasks_label_offset_bool
      {
        \dim_set_eq:NN
          \l__tasks_label_offset_dim
          \l__tasks_label_default_offset_dim
      }
    % \dim_compare:nNnT
    %   { \l__tasks_item_indent_dim }
    %    <
    %   { \l__tasks_label_offset_dim + \l__tasks_label_width_dim }
    %   {
    %     \dim_set:Nn \l__tasks_item_indent_dim
    %       { \l__tasks_label_offset_dim + \l__tasks_label_width_dim }
    %   }
    \bool_if:NT \l__tasks_custom_after_item_skip_bool
      {
        \skip_set_eq:NN
          \l__tasks_after_item_skip
          \l__tasks_custom_after_item_skip
      }
    \bool_if:NT \l__tasks_custom_label_bool
      {
        \tl_set_eq:NN
          \l__tasks_label_tl
          \l__tasks_custom_label_tl
        \bool_set_false:N \l__tasks_enumerate_bool
      }
    \__tasks_label_align:V \l__tasks_label_align_tl
    % need this for enumerate list:
    \bool_if:nT { !\l__tasks_resume_bool && \l__tasks_enumerate_bool }
      { \int_gzero:N \g__tasks_int }
    \int_set:Nn \l__tasks_columns_int {#2}
    % set all the items in their own coffins and join with the ground:
    \int_gzero:N \g__tasks_current_col_num_int
    \int_set:Nn \g__tasks_current_row_num_int {1}
    \tl_if_blank:VF \l__tasks_custom_label_pattern_tl
      {
        \tl_set_eq:NN
          \l__tasks_label_pattern_tl
          \l__tasks_custom_label_pattern_tl
      }
    \tl_if_blank:VF \l__tasks_custom_label_format_tl
      {
        \tl_set_eq:NN
          \l__tasks_label_format_tl
          \l__tasks_custom_label_format_tl
      }
    \tl_if_blank:VF \l__tasks_custom_item_format_tl
      {
        \tl_set_eq:NN
          \l__tasks_item_format_tl
          \l__tasks_custom_item_format_tl
      }
    \seq_map_inline:Nn \l__tasks_seq
      {
        \__tasks_read_item:www ##1 \q_stop
        \bool_if:NTF \l__tasks_enumerate_bool
          {
            \tl_if_eq:VnT \l__tasks_tmp_label_tl { $tasks$default$label$ }
              {
                \int_gincr:N \g__tasks_int
                \SaveCounterPatternFrom [tasks]
                  \l__tasks_tmpa_tl
                  \l__tasks_label_tl
                  \l__tasks_label_pattern_tl
                %-----------------------------------------------------------
                % This seems to set \@currentlabel globally:
                %-----------------------------------------------------------
                \cs_gset:Npx \@currentlabel { \l__tasks_label_tl }
                %-----------------------------------------------------------
                % Carry out the ugly hook hack after setting \@currentlabel
                % for setting \@currentlabel correctly.
                % Seems with this package this needs to be done globally,
                % thus \uglycounterhack does it globally as well.
                %-----------------------------------------------------------
                \l__sillyugly_label_hook_tl
              }
          }
          {
            \tl_if_blank:VT \l__tasks_label_tl
              { \tl_set_eq:NN \l__tasks_label_tl \labelitemi }
          }
        \tl_put_left:NV \l__tasks_label_tl \l__tasks_label_format_tl
        % \tl_put_left:NV \l__tasks_item_tl \l__tasks_item_format_tl
        \tl_if_eq:VnTF \l__tasks_tmp_label_tl { $tasks$default$label$ }
          {
            \__tasks_task:VVV
              \l__tasks_label_tl
              \l__tasks_item_format_tl
              \l__tasks_item_tl
          }
          {
            \__tasks_task:VVV
              \l__tasks_tmp_label_tl
              \l__tasks_item_format_tl
              \l__tasks_item_tl
            \tl_clear:N \l__tasks_tmp_label_tl
          }
      }
  }

\__tasks_restore_dollar:

\ExplSyntaxOff
\makeatother

% ====End of patch of tasks.sty====

\DeclareExerciseTranslations{answer}{
  Fallback = answer ,
  English = answer ,
  French = r\'eponse ,
  German = Antwort
}


\DeclareExerciseType{question}{
  exercise-env = question ,
  solution-env = answer ,
  exercise-name = \XSIMtranslate{question} ,
  solution-name = \XSIMtranslate{answer} ,
  exercise-template = default ,
  solution-template = default
}

\newcounter{subquestion}[question]
\newcounter{subanswer}[answer]

\renewcommand*\thesubquestion{\thequestion.\arabic{subquestion}}%
\csname @ifpackageloaded\endcsname{hyperref}{%
  \renewcommand*\theHsubquestion{\theHquestion.\arabic{subquestion}}%
}%

\renewcommand*\thesubanswer{\theanswer.\arabic{subanswer}}%
\csname @ifpackageloaded\endcsname{hyperref}{%
  \renewcommand*\theHsubanswer{\theHanswer.\arabic{subanswer}}%
}%


% cleveref-aliases/counter-naming-phrases:
\crefname{question}{question}{questions}
\crefname{subquestion}{subquestion}{subquestions} % has no effect, obviously

\crefname{answer}{answer}{answers}
\crefname{subanswer}{subanswer}{subanswers} % has no effect, obviously

\makeatletter
% Why does the tasks-package its own counter-thingie when
% you have to use a counter anyway for getting things 
% with label..ref done correctly? This does not make sense to me.
\DeclareRobustCommand\uglycounterhack[1]{%
  \refstepcounter{#1}%
  \global\let\@currentlabel=\@currentlabel
  \global\let\cref@currentlabel=\cref@currentlabel
}%
\makeatother

\NewTasks[%
    %% This will not include the value of the question-counter
    %% into the subquestion-items:
    %%   counter-format = tsk[1]),%
    %% This will include the value of the question-counter
    %% into the subquestion-items -- I recommend doing this for making
    %% references to subquestion-items unambiguous:
    counter-format = \thequestion.tsk[1]),%
    label-format = \itshape,%
    ugly-label-hook = \uglycounterhack{subquestion},%
    label-width = 1.75em,%
    item-indent = 2.55em,%
    label-offset=0.8em,%
    label-align=left,%
    before-skip = 0pt,%
    after-item-skip=0pt%
]{subquestionblock}[\subquestion](2)

\NewTasks[%
    %% This will not include the value of the answer-counter
    %% into the subanswer-items:
    %%   counter-format = tsk[1]),%
    %% This will include the value of the answer-counter
    %% into the subanswer-items -- I recommend doing this for making
    %% references to subanswer-items unambiguous:
    counter-format = \theanswer.tsk[1]),%
    label-format = \itshape,%
    ugly-label-hook = \uglycounterhack{subanswer},%
    label-width = 1.75em,%
    item-indent = 2.55em,%
    label-offset=0.8em,%
    label-align=left,%
    before-skip = 0pt,%
    after-item-skip=0pt%
]{subanswerblock}[\subanswer](2)

\begin{document}
    \begin{question}[points=3]
        Isomers of a coordination compound. \label{iso}
        \begin{subquestionblock}
            \subquestion! Why do we have isomers? \label{why}
            \subquestion! Why did I even ask \cref{iso}? \label{metawhy}
            \subquestion! What do you mean \cref{metawhy}?
        \end{subquestionblock}
    \end{question}
    \begin{answer}[print=true]
        \begin{subanswerblock}
            \subanswer! Because isomers are fun. \label{because}
            \subanswer! Because I am funny. \label{metabecause}
            \subanswer! \cref{metabecause} is funny but all in all this is no longer funny. 
        \end{subanswerblock}
    \end{answer}

    \begin{question}[points=3]
        Is there an end to stupid questions? \label{stu}
        \begin{subquestionblock}
            \subquestion! Discuss why \cref{metawhy} is a stupid question but \cref{why} is even stupider? \label{huh}
            \subquestion! Are both \cref{huh} and \cref{metawhy} both stupider that each other?
        \end{subquestionblock}
    \end{question}
\end{document}

enter image description here

  • hmmm ... this was lot more complicated than I thought. I really liked the packages tasks and cleveref. Thanks for all the effort that you put into helping me out @Ulrich .. I have also written a mail to the package authors. – magguu Sep 2 '18 at 12:49

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.