TeX - LaTeX Asked by haff on April 6, 2021
I’m writing a little exam generation package in R that takes a list of questions, randomizes question order and responses, and creates a .pdf. One issue I have is that questions and their responses may be separated by a page break, which is obviously not ideal. I’ve found a manual workaround in encapsulating each item
within a minipage
, but a manual solution won’t work here.
Is it possible to modify the environment of enumerate
or create a custom command that puts each item
in a minipage
to keep questions from being split across pages? That way, I can include the code in the preamble of the RMarkdown document that generates the exam.
Essentially I want
documentclass{article}
begin{document}
begin{enumerate}
item
Which bear is best?
A. Honey bear
B. Grizzly bear
C. Black bear
D. Teddy bear
E. Polar bear
item
How much snow per year is the preferable amount?
A. 90 inches
B. 120+ inches
C. 30 inches
D. 60 inches
end{enumerate}
end{document}
to become
documentclass{article}
begin{document}
begin{enumerate}
begin{minipage}{linewidth}
item
Which bear is best?
A. Honey bear
B. Grizzly bear
C. Black bear
D. Teddy bear
E. Polar bear
end{minipage}
begin{minipage}{linewidth}
item
How much snow per year is the preferable amount?
A. 90 inches
B. 120+ inches
C. 30 inches
D. 60 inches
end{minipage}
end{enumerate}
end{document}
by putting something in the preamble.
You can do something like
newcommand{question}[1]{
begin{minipage}{linewidth}
item
{#1}
end{minipage}
}
So the full code would be
documentclass{article}
begin{document}
newcommand{question}[1]{
begin{minipage}{linewidth}
item
{#1}
end{minipage}
}
begin{enumerate}
question{Which bear is best?A. Honey bearB. Teddy bearC. Black bearD. Grizzly bearE. Polar bear}
end{enumerate}
end{document}
Answered by haff on April 6, 2021
Here's a LuaLaTeX-based solution. It sets up a Lua function, called add_minipage_wrappers
, that acts as a preprocessor of sorts: It scans all input lines, kicks into high gear when it encounters a begin{enumerate}
instruction, encases item
groups in minipage
environments, and falls back to near-dormancy after it encounters an end{enumerate}
instruction. The Lua function doesn't operate on item
directives contained in itemize
or description
list environments.
The only input requirements are as follows:
begin{enumerate}
and end{enumerate}
occur at the beginning of linesbegin{enumerate}
and an item
instructionitem
instruction on a given lineenumerate
environments aren't nested.I trust that these input requirements aren't too burdensome.
Here's what the output looks like if the Lua function is active. To deactivate the function, just comment out (or delete) the lines
AtBeginDocument{directlua{luatexbase.add_to_callback (
"process_input_buffer" , add_minipage_wrappers , "addminipagewrappers" )}}
% !TEX TS-program = lualatex
documentclass{article}
pagestyle{empty}
usepackage[margin=5mm,textheight=0.5cm,paperheight=4.5cm]{geometry}
usepackage{luacode} %% for 'luacode*' environment
begin{luacode*}
local in_enumerate = false -- define a couple of flags (Boolean variables)
local in_item = false
function add_minipage_wrappers ( s )
if s:find ( "^begin{enumerate}" ) then
in_enumerate = true -- switch 'in_enumerate' to "true"
elseif s:find ( "^end{enumerate}" ) then
s = s:gsub ( "end{enumerate}" , "end{minipage} end{enumerate}" )
in_enumerate = false
in_item = false
elseif s:find ( "item" ) then
if in_enumerate == true then -- do nothing unless in an 'enumerate' env.
if in_item == false then -- first instance of 'item' in the list
s = s:gsub ( "item" , "begin{minipage}{linewidth} item" )
in_item = true -- switch 'in_item' to "true"
else -- 2nd or later instance of 'item'
s = s:gsub ( "item" , "end{minipage} begin{minipage}{linewidth} item" )
end
end
end
return ( s )
end
end{luacode*}
%% Assign the Lua function to LuaTeX's 'process_input_buffer' callback:
AtBeginDocument{directlua{luatexbase.add_to_callback (
"process_input_buffer" , add_minipage_wrappers , "addminipagewrappers" )}}
begin{document}
begin{enumerate}
item
Which bear is best?
A. Honey bear
B. Grizzly bear
C. Black bear
D. Teddy bear
E. Polar bear
item
How much snow per year is the preferable amount?
A. 90 inches
B. 120+ inches
C. 30 inches
D. 60 inches
end{enumerate}
end{document}
Answered by Mico on April 6, 2021
You can capture the item
s and process them using the approach provided by Macro to capture until end-of-line as argument:
documentclass{article}
%usepackage{xparse}% If LaTeX < 2020-10
ExplSyntaxOn
NewDocumentEnvironment{myenumerate}{ O{} +b }
{
% do the setup
keys_set:nn { haff/enumerate } { #1 }
% split the contents at item
seq_set_split:Nnn l_haff_enumerate_input_seq { item } { #2 }
% remove the first (empty) item
seq_pop_left:NN l_haff_enumerate_input_seq l_tmpa_tl
% issue the preamble
tl_use:N l_haff_enumerate_pre_tl
% adorn the items
seq_set_map:NNn
l_haff_enumerate_output_seq
l_haff_enumerate_input_seq
{ exp_not:n { __haff_enumerate_do:n { ##1 } } }
% output the items, separated by the chosen separator
seq_use:NV l_haff_enumerate_output_seq l_haff_enumerate_sep_tl
% issue the postamble
tl_use:N l_haff_enumerate_post_tl
}
{}
seq_new:N l_haff_enumerate_input_seq
seq_new:N l_haff_enumerate_output_seq
cs_generate_variant:Nn seq_use:Nn { NV }
keys_define:nn { haff/enumerate }
{
pre .tl_set:N = l_haff_enumerate_pre_tl,
post .tl_set:N = l_haff_enumerate_post_tl,
sep .tl_set:N = l_haff_enumerate_sep_tl,
action .code:n = cs_set_eq:NN __haff_enumerate_do:n #1,
action .initial:n = use:n,
}
ExplSyntaxOff
NewDocumentCommand{minipageitem}{+m}{%
parnoindent
begin{minipage}{linewidth}
setcounter{option}{0}%
item #1
end{minipage}
}
NewDocumentEnvironment{minipageenumerate}{O{}}{%
begin{myenumerate}[
action=minipageitem,
pre=begin{enumerate},
post=end{enumerate}
]
}{%
end{myenumerate}
}
newcounter{option}
renewcommand{theoption}{Alph{option}}
newcommand{option}{%
parnoindent
refstepcounter{option}%
theoption.~ignorespaces
}
begin{document}
begin{minipageenumerate}
item
Which bear is best?
option Honey bear
option Grizzly bear
option Black bear
option Teddy bear
option Polar bear
item
How much snow per year is the preferable amount?
option 90 inches
option 120+ inches
option 30 inches
option 60 inches
end{minipageenumerate}
end{document}
Answered by Werner on April 6, 2021
You can redefine the existing enumerate
environment using the tasks
package. The latter already puts its items in boxes so the result should suit your needs.
Possible major drawback: enumerate
isn't nestable any more…
documentclass{article}
pagestyle{empty}
usepackage[margin=5mm,paperheight=5cm]{geometry}
usepackage{tasks}
RenewTasksEnvironment[label=arabic*.]{enumerate}[item]
begin{document}
begin{enumerate}
item
Which bear is best?
A. Honey bear
B. Grizzly bear
C. Black bear
D. Teddy bear
E. Polar bear
item
How much snow per year is the preferable amount?
A. 90 inches
B. 120+ inches
C. 30 inches
D. 60 inches
end{enumerate}
end{document}
Answered by cgnieder on April 6, 2021
Get help from others!
Recent Questions
Recent Answers
© 2024 TransWikia.com. All rights reserved. Sites we Love: PCI Database, UKBizDB, Menu Kuliner, Sharing RPP