0

This is another chapter of the story "how to use a moodle database for my purposes". The accepted answer to this question gives a very effective way to retrieve informations from an exercise database structured as follows

\begin{multi}{}
  Text
  \item first answer
  \item* correct anser
  ...
 \end{multi}

Now, the object retrieved as "nth answer" contains all kind of spacing, for instance

  \item

  first answer

will store the \par.

I would like to erase all kind of "blank" spaces before the start of the actual aswer, for editing purpose.


An example for the Wipet answer which does not fit in a comment. If I set

  \documentclass{article}
  \usepackage{getitems}
  \begin{document}

  \def\item{\futurelet\next \itemA}
  \def\itemA{\ifx\next\par \expandafter\itemB \fi}
  \long\def\itemB#1{\item}

  \def\A{


  A}

  \def\B{%


  B}

  X\expandafter\item\A X

  X\expandafter\item\B X
 \end{document}

The output is

 X
 AX
 XBX

So \expandafter\item\A does not work (it includes a linebreak before A) while \expandafter\item\B works (it does not include a linebreak before B)

12
  • \tl_head, \tl_tail and \tl_if_eq etc. should be sufficient
    – user202729
    May 15, 2022 at 8:57
  • @user202729 what is the usage of such?
    – user126154
    May 16, 2022 at 8:38
  • by the way: I need also to remove empty lines AFTER my object
    – user126154
    May 16, 2022 at 11:05
  • @user202729 I tried something like \NewDocumentCommand{\HEAD}{ m }{\tl_head:N { #1 }} and ` \NewDocumentCommand{\TAIL}{ m }{\tl_tail:N { #1 }}` and then \HEAD\A\TAIL\A, with \A as in the question, and does not work (whil it works with \B)
    – user126154
    May 16, 2022 at 21:39
  • Sorry, it is not full example. In what context is used \def\A{...}\def\B{...}, i.e. what is around them? How the \item is defined? Full example means that it can be used without adding another context which I don't know. Full example is full document.
    – wipet
    May 17, 2022 at 4:33

2 Answers 2

3

The \item control sequence consumes all space after it at during tokenization. So, you want to remove only blank lines tokenized as \par. If you don't asking for expandable macro, the solution can look like this:

\def\item{\futurelet\next \itemA}
\def\itemA{\ifx\next\par \expandafter\itemB \fi}
\long\def\itemB#1{\item}

test:

aaa%
\item 


bbb

\bye

Another approach: Suppose we have defined something like this:

\def\TEXT{
\item 


a b c
\item
d e f

g h i
}

and we want to create a new macro \TEXT where all \par immediately followed by \item are removed. It means that the two \pars after first \item are removed in our example but the \par between d e f and g h i is kept. We can do this by

\rempars\TEXT

This macro changes the body of the \TEXT as mentioned above. This macro can be defined by:

\long\def\addto#1#2{\expandafter\def\expandafter#1\expandafter{#1#2}}
\long\def\afterfi#1#2\fi{\fi#1}
\def\rempars #1{%
   \let\orig=#1%
   \def\tmp{}%
   \expandafter\remparsA #1\item\par\endrempars
   \expandafter\def\expandafter#1\expandafter{\tmp}%
   \ifx#1\orig\else \afterfi{\rempars#1}\fi
}
\long\def\remparsA #1\item\par#2\endrempars{%
   \if\relax\detokenize{#2}\relax \addto\tmp{#1}%
   \else \addto\tmp{#1\item}\afterfi{\remparsA #2\endrempars}\fi
}
11
  • maybe I was not so clear. Everything is part of macros that I use for producing some Exams shet from moodle database, as in here tex.stackexchange.com/questions/644183/… . So getitems already parses \item occurrences, than therefore disappear. All text between \items is stored in a macro \gathereditem{n} and I would like to extract the information as \def\mymacro{content of \gathereditem with spaces removed}
    – user126154
    May 15, 2022 at 10:06
  • Before the text is gathered (it is separated by what?) then you can set the TeX register \endlinechar to -1. It suppresses the conversion of blank lines to \par. I don't know the whole context, so I cannot say more.
    – wipet
    May 15, 2022 at 10:34
  • before the text is gathered it is in the form \begin{multi}{} text of exercise \item first answer \item another answer \item* correct answer ... \end{multi} and getitems.sty package parses it.
    – user126154
    May 15, 2022 at 12:28
  • could you explain what exactly does your code? it seems looping
    – user126154
    May 16, 2022 at 11:33
  • also I tried to turn your code in a macro but it does not work. basically because \def\TEST{\par \par \par test} and then \item\TEST don'e see the \par (because the braces are there?)
    – user126154
    May 16, 2022 at 15:04
1

Add something to the code I suggested last time.

\documentclass{article}
\usepackage{amsthm}
\usepackage{enumitem}

\newcounter{exercise}

\ExplSyntaxOn

\NewDocumentEnvironment{multi}{m +b}
 {
  \par\addvspace{\topsep}\setlength{\parindent}{0pt}
  \stepcounter{exercise}
  \textbf{Exercise~\theexercise}~--~#1\par\nobreak
  \moodle_multi:n { #2 }
  \par\addvspace{\topsep}
 }
 {}

\NewDocumentCommand{\showcorrect}{}
 {
  \bool_gset_true:N \g_moodle_multi_correct_bool
 }
\NewDocumentCommand{\hidecorrect}{}
 {
  \bool_gset_falsee:N \g_moodle_multi_correct_bool
 }

\bool_new:N \g_moodle_multi_correct_bool
\seq_new:N \l__moodle_multi_text_seq
\tl_new:N \l__moodle_multi_text_tl
\tl_new:N \l__moodle_multi_moretext_tl
\tl_new:N \l__moodle_multi_answers_tl

\cs_new_protected:Nn \moodle_multi:n
 {
  \regex_split:nnN { \{(enumerate|itemize)\} } { #1 } \l__moodle_multi_text_seq
  \tl_set:Nx \l__moodle_multi_answers_tl { \seq_item:Nn \l__moodle_multi_text_seq { -1 } }
  \tl_set:Nn \l__moodle_multi_text_tl { #1 }
  \regex_replace_once:nnN { (.*)\u{l__moodle_multi_answers_tl} } { \1 } \l__moodle_multi_text_tl
  \seq_set_split:NnV \l__moodle_multi_text_seq { \item } \l__moodle_multi_answers_tl
  % the first item will contain the question text
  \seq_pop_left:NN \l__moodle_multi_text_seq \l__moodle_multi_moretext_tl
  \tl_use:N \l__moodle_multi_text_tl
  \tl_use:N \l__moodle_multi_moretext_tl
  % now we rebuild the answers
  \begin{enumerate}[label=(\Alph*),nosep,labelsep=0.75em]
  \use:e
   {% add the first \item and put it also between the other items
    \__moodle_multi_item: \seq_use:Nn \l__moodle_multi_text_seq { \__moodle_multi_item: }
   }
  \end{enumerate}
 }

\cs_new_protected:Nn \__moodle_multi_item:
 {
  \item 
  \peek_charcode_remove:NT *
   {% there is an asterisk
    \bool_if:NT \g_moodle_multi_correct_bool { \__moodle_multi_correct: }
    \__moodle_multi_ignore:
   }
 }

\cs_new_protected:Nn \__moodle_multi_correct:
 {
  \makebox[0pt][r]{\makebox[0pt][l]{$^{\scriptscriptstyle*}$}\hspace{\labelsep}}
 }

\cs_new_protected:Nn \__moodle_multi_ignore:
 {% remove blank spaces and \par
  \peek_regex_remove_once:nTF { [\s\c{par}]* } {} {}
 }

\ExplSyntaxOff

\begin{document}

\begin{multi}{Name of the question}
  Text of the question
  \begin{itemize}
  \item a
  \item b
  \end{itemize}
  More text
  \begin{enumerate}
  \item a
  \item b
  \end{enumerate}
  More text
  \item first answer
  \item 

second answer
  \item* the starred is the correct answer
\end{multi}

\showcorrect

\begin{multi}{Name of the question}
  Text of the question
  \item first answer
  \item second answer
  \item*

the starred is the correct answer
\end{multi}

\end{document}

enter image description here

12
  • my LaTeX is not up to date: I have no` \peek_regex_remove_once`
    – user126154
    May 16, 2022 at 15:06
  • @user126154 Update.
    – egreg
    May 16, 2022 at 15:26
  • by the way: your code is much cleaner than all other solutions I found/build without expl3. It's clear that expl3 is the right solution for "programming" with latex.
    – user126154
    May 18, 2022 at 9:39
  • @greg I don't know exacly how your code works, but it seems that it searches for all instances of \item, and this is probably the problem with itemize environment inside questions/answers. This seems the same way listofitems package do (and in fact it has the same problem). On the other hand getitems has not this problem. I don't know if one could take inspiration from that and use the same receipt with expl3. Probably yes, but I don't know.
    – user126154
    May 18, 2022 at 9:39
  • @user126154 Not with the latest version.
    – egreg
    May 18, 2022 at 9:44

You must log in to answer this question.

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