Latex - How to refer to the item's TEXT inside enumitem - latex

I'm using enumitem to enumerate my variables list.
I have a variable list like:
\begin{enumerate}
\item My First Cool Variable \label{var:myvar1}
\item My Second not so Cool Variable \label{var:myvar2}
\item My Third so so \label{var:myvar3}
\end{enumerate}
When I cross-reference one of these items, I get the list key. For example,
Let us reference \ref{var:myvar2} and then my other variable \ref{var:myvar3}
Gives:
Let us reference 2 and then my other variable 3
What I'd like is to not only be able to obtain the list key, but also the whole item text, so the output could be like:
Let us reference My Second not so Cool Variable and then my other variable My Third so so
The goal is to be able to write the variable name only once, and not changing everywhere if ever the variable name is modified to something more specific.
Any ideas? I've taken a look into enumitem-zref but I couldn't find what I was looking for :/

Using some ideas from Macro to capture until end-of-line as argument, you can capture the contents following an \item:
\documentclass{article}
\usepackage{environ}
% https://tex.stackexchange.com/q/127005/5764
\makeatletter
\NewEnviron{wordenumerate}{%
\begin{enumerate}
\let\olditem\item
\def\item##1\item{\dosomething{##1}}%
\expandafter\#empty\BODY\item
\end{enumerate}%
}
\let\oldlabel\label
\newcommand{\dosomething}[1]{%
\def\elvitaluz#arg{#1}%
\ifx\elvitaluz#arg\elvitaluz#stop
\end{enumerate}
\expandafter\env#ignore % to end the recursion
\else
\def\label##1{\def\#textlabel{##1}\let\label\relax}% Capture \label
\olditem #1
\ifx\label\relax
\def\label##1{\#bsphack\#esphack}%
\edef\#currentlabel{#1}% % what to do with #1
\expandafter\oldlabel\expandafter{\#textlabel}%
\fi
\expandafter\item % to continue the recursion
\fi}
\edef\elvitaluz#stop{\noexpand\end{enumerate}\noexpand\env#ignore\space}
\makeatother
\begin{document}
\begin{wordenumerate}
\item First
\item Second\label{second}
\item \label{third}Last
\end{wordenumerate}
Item~2 is \ref{second}. Item~3 is \ref{third}.
\end{document}
The use of a new environment wordenumerate is suggested, as an entirely different \label-\ref is at play. I would not suggest nesting this environment in anything else (also because of the use of environ).

Related

embedded commands into environments and environments with parameters

I'm pretty new to latex and I'm trying to create a format for exam questions that would make write as few latex as possible.
For the moment I wrote this code:
\documentclass{article}
%the question environment wrapping every exam questions
\newenvironment{q}[2] {
\newcounter{answerCounter} %used for display of answer number with question
\setcounter{answerCounter}{0}
\newcommand{a}[1] {
\item a\value{answerCounter}: ##1
%I used double hyphen on previous line because i'm within an environment
\addtocounter{answerCounter}{1}
}
\item q#1: #2
%the 1st param of q (the environment) is the question number, 2nd is the question itself
\begin{itemize}
} { \end{itemize} }
\begin{document}
\begin{itemize}
\begin{q}{1}{to be or not to be?}
\a{to be}
\a{not to be}
\end{q}
\begin{q}{2}{are you john doe?:}
\a{No i'm Chuck Norris}
\a{maybe}
\a{yes}
\end{q}
\end{itemize}
\end{document}
and I want it to display this:
but when I do pdflatex exam.tex I get the following first 2 errors (there are more but I don't want to flood you with information):
! Missing control sequence inserted.
<inserted text>
\inaccessible
l.21 \begin{q}{1}{to be or not to be?}
?
(/usr/share/texlive/texmf-dist/tex/latex/base/omscmr.fd)
! LaTeX Error: Command \to be unavailable in encoding OT1.
See the LaTeX manual or LaTeX Companion for explanation.
Type H <return> for immediate help.
...
l.22 \a{to be}
?
Have i called/defined my environments and commands wrongly? Thanks.
Here are some things to consider:
Environments are defined with a name, as in \newenvironment{someenv}, while commands are defined with their control sequence, as in \newcommand{\somecmd}. Note the \. This is the main problem with your code.
LaTeX defines a number of single-character control sequences, typically used for accents on symbols. After correcting your example for (1) above, \a is already defined. Instead, define something more descriptive to increase code readability.
You may have some spurious spaces inserted as part of your code. These are prevented with strategic placements of %. See What is the use of percent signs (%) at the end of lines?
Defining commands within other commands (like a new counter) could lead to problems, or make things unnecessarily slow (in larger documents and usage). Rather define the counter outside an environment - in the global scope - and then just reset the number as needed.
\documentclass{article}
\newcounter{answerCounter} %used for display of answer number with question
%the question environment wrapping every exam questions
\newenvironment{question}[2] {%
\setcounter{answerCounter}{0}%
\newcommand{\ans}[1]{%
\stepcounter{answerCounter}%
\item a\theanswerCounter: ##1
%I used double hyphen on previous line because i'm within an environment
}
\item q#1: #2
%the 1st param of q (the environment) is the question number, 2nd is the question itself
\begin{itemize}
} { \end{itemize} }
\begin{document}
\begin{itemize}
\begin{question}{1}{To be or not to be?}
\ans{to be}
\ans{not to be}
\end{question}
\begin{question}{2}{Are you John Doe?}
\ans{No I'm Chuck Norris}
\ans{maybe}
\ans{yes}
\end{question}
\end{itemize}
\end{document}

inputting all items of a list into an environment

I have a list of names which I would like to input into a given surrounding, e.g. a box. Put in a different way: I'd like LaTex to create a surrounding for every item in a given list.
Here's my list:
Frank, Fred, Fran
Here's my surrounding:
\fbox{\name}
\name does the following: it inputs the first item from the list and creates another \fbox for each successive item in the list until the end of the list, as a result outputting the same as (but saving the typing of)
\fbox{Frank}
\fbox{Fred}
\fbox{Fran}
I am thinking of the list of names as a "count" (redefining 1 as Frank, 2 as Fred...) and this might be the wrong approach.
I realise that a command can probably not do those two things at once.
If there's a simple solution to this: what is it called and where can I find it? searching for 'variables' or 'foreach' didn't help.
Depending on your application, you can either specify the list explicitly, or in a file:
As an explicit list (see How to iterate over a comma separated list?):
\documentclass{article}
\usepackage{etoolbox}
\newcommand{\printlist}[1]{%
\begin{enumerate}
\renewcommand*{\do}[1]{\item \fbox{##1}}%
\docsvlist{#1}%
\end{enumerate}%
}
\begin{document}
\printlist{Frank, Fred, Fran}
\end{document}
As a file in (say) names.csv:
\documentclass{article}
\usepackage{filecontents}
\begin{filecontents*}{names.csv}
Frank
Fred
Fran
\end{filecontents*}
\usepackage{datatool}
\newcommand{\printlist}[1]{%
\DTLloaddb[noheader,keys=name]{namesdb}{#1}% Load names database file
\begin{enumerate}
\DTLforeach{namesdb}{\name=name}{\item \fbox{\name}}
\end{enumerate}
}
\begin{document}
\printlist{names.csv}
\end{document}
In both instances, the output resembles:

Is it possible to ask Latex to evaluate a command

This code:
\begin{enumerate}
\item Item One \def\commandOne{\alph{enumi} : One}
\item Item Two \def\commandTwo{\alph{enumi} : Two}
\item \commandOne, \commandTwo
\end{enumerate}
Gives this output:
Item One
Item Two
c : One, c : Two
I want that Latex evaluate \alph{enumi} when the command is defined instead of when the command is called, is it possible?
Instead of \def, use \edef which expands at the time of definition (see also \gdef and \xdef). This can of course cause problems if you want parts of it not expanded. For those cases you can use \expandafter as shown in this answer.

\sbox from inside an environment

I'm trying to save some text inside an environment for later use. The smallest test case I could come up with is this. The saved text in the sbox isn't available after the environment is closed. How can I work around that? Thanks.
\documentclass{article}
\begin{document}
\newsavebox{\somebox}
\begin{itemize}
\item hello1
\item hello1 \sbox{\somebox}{Some text}
\end{itemize}
This should show something, but does not: "\usebox{\somebox}"
\end{document}
What you're running into here is a scoping issue. In (La)TeX, you can introduce scopes with { ... }, \bgroup ... \egroup, or \begingroup ... \endgroup. The former two are roughly the same, as \bgroup and \egroup are defined by \let\bgroup{ and \let\egroup}; the last one is slightly different. But the scoping property is the same: any commands, boxen, etc., created or modified within those scopes are not visible outside. And in LaTeX, all environments \begin{env} ... \end{env} implicitly wrap their contents in \begingroup ... \endgroup. This means that your\sbox{\somebox}{Some text} modification is only visible until the \end{itemize}; after that, the modification is undone. To get around this, prepend any command like \newcommand, \def, \newsavebox, \sbox, etc., with \global, which forces the definition to take place at the global scope and be visible everywhere.
Also, to use quotes in (La)TeX, write ``double quoted'', ``double quoted", or `single quoted'; the " character is only for closing quotes, not opening quotes. Putting this all together gives you the revised snippet
\documentclass{article}
\begin{document}
\newsavebox{\somebox}
\begin{itemize}
\item hello1
\item hello1 \global\sbox{\somebox}{Some text}
\end{itemize}
This should show something, and in fact does: ``\usebox{\somebox}''
\end{document}
I think I can work around this by using \def. like so:
\documentclass{article}
\begin{document}
\begin{itemize}
\item hello1
\item hello1
\global \def \somebox {Some text}
\end{itemize}
This should show something: \somebox
\end{document}

How to customize references to sublists in LaTeX?

I have a list/sublist structure in my LaTeX document. By default, the sublist is delimited with letters, so you end up with this:
1. Item
(a) sub item
(b) sub item
In my document, I've got more than 26 sub items, so I was running into a Counter overflow error, which I fixed by rewriting the sub item label, so that they now look like this
1. Item
1.1 sub item
1.2 sub item
I've put a label on one of the items so that I can reference the specific step later on. The problem is that when the reference is rendered, it's rendered using a letter, not the number of the sub item.
Here's a sample doc that shows the problem.
\documentclass[11pt]{report}
\begin{document}
\renewcommand{\labelenumii}{\arabic{enumi}.\arabic{enumii}}
\begin{enumerate}
\item Item
\begin{enumerate}
\item \label{lbl} Label here
\end{enumerate}
\end{enumerate}
Ref: \ref{lbl}
\end{document}
This gets rendered like this:
1. Item
1.1 Label here
Ref: 1a
So instead of saying "Ref: 1.1", it's using "Ref: 1.a". Is there a way to make the \ref use the numbering of the source enumeration? If not, is there anyway to generate correct references to items in a sublist with more than 26 items?
I'm looking at my copy of The LaTeX Companion, p.129, and from what I'm seeing I would suggest something like the following:
\renewcommand{\theenumii}{\arabic{enumii}}
\renewcommand{\labelenumii}{\theenumi.\theenumii.}
\makeatletter
\renewcommand{\p#enumii}{\theenumi.}
\makeatother
I don't have access to a working LaTeX environment to test this at the moment, though.
So for 2 nested lists it should be done in the following way:
\begin{enumerate}
\renewcommand{\theenumi}{\arabic{enumi}}
\renewcommand{\theenumii}{\arabic{enumii}}
\renewcommand{\theenumiii}{\arabic{enumiii}}
\renewcommand{\labelenumi}{\theenumi.}
\renewcommand{\labelenumii}{\theenumi.\theenumii.}
\renewcommand{\labelenumiii}{\theenumi.\theenumii.\theenumiii.}
\makeatletter
\renewcommand{\p#enumii}{\theenumi.}
\renewcommand{\p#enumiii}{\theenumi.\theenumii.}
\makeatother
...
\end{enumerate}
It has taken to me too much time to understand it.
I hope this helps as this thread helped me.
Thanks.

Resources