3

we currently use unique IDs inside our documents that can be extended by adding one or more tags. A tag always starts with an hash character eg. MY.REQ.ID.42#TAG1#TAG2

The following code is part of a macro that we use to generate 'nice' looking requirements:

\textbf{#1}\def\@currentlabel{#1}\label{req:#1}

Together with a list where all requirements are listed, \label has problems with the # character inside. So I'm looking for a way to get rid to the character by replacing it with something other, eg. '..' or 'HASH'.

any idea would be appreciated...

Thanks & bye, aronadaal

\documentclass[a4paper]{scrartcl}
\usepackage[left=2cm,right=2cm,top=2.5cm,bottom=2cm]{geometry}
\setlength\parindent{0pt}

\makeatletter
\newcommand{\req}[2]{%
  \begingroup%
    \textbf{#1}\def\@currentlabel{#1}\label{req:#1}~#2\newline
  \endgroup%
  \addcontentsline{lor}{requirement}{#1}%
} %

\DeclareNewTOC[%
  type=requirement, %
  types=requirements, %
  name=Anforderung, %
  listname={List of Requirements} %
]{lor}
\setuptoc{lor}{chapteratlist}

\begin{document}
\section{Test}
\req{MY.REQ.ID.42}{Lorem ipsum dolor sit amet,...}

\req{MY.REQ.ID.43\#BROKEN}{this requirement is broken,...}

Please have a look at \ref{req:MY.REQ.ID.42} on page~\pageref{req:MY.REQ.ID.42}

\listofrequirements

\end{document}

part of the log file:

(./req_test.aux
! Missing \endcsname inserted.
<to be read again> 
\#
l.5 ...REQ.ID.43\#BROKEN}{{MY.REQ.ID.43\#BROKEN}{1}}

The control sequence marked <to be read again> should
not appear between \csname and \endcsname.


LaTeX Warning: Label `req:MY.REQ.ID.43\#BROKEN' multiply defined.

! Missing \endcsname inserted.
<to be read again> 
\#
l.5 ...REQ.ID.43\#BROKEN}{{MY.REQ.ID.43\#BROKEN}{1}}

The control sequence marked <to be read again> should
not appear between \csname and \endcsname.

)
  • Hi, I'm not sure I follow what you mean. Could you post a minimal example please? – yo' Apr 2 '15 at 10:28
  • sure, here we go. – aronadaal Apr 2 '15 at 10:36
  • Thanks. Now it makes sense to me. I'll post a solution soon I hope. – yo' Apr 2 '15 at 10:38
  • 1
    Follow up to Referencing my own command – Johannes_B Apr 2 '15 at 10:50
  • 1
    Sorry, I think I give up. # is just the worst choice for a char in anything. You can make it working, but it would mean redefining everything in LaTeX. (Or find someone who's a better TeXpert than me). – yo' Apr 2 '15 at 11:10
2

In your example, you used \# in the \req parameter. If this is not an issue, you can simply redefine locally its meaning when you generate the label. For instance, you can replace \label{req:#1} by {\def\#{REPLACEMENT}\xdef\lbl{req:#1}}\label{\lbl}.

Example:

\documentclass[a4paper]{scrartcl}
\usepackage[left=2cm,right=2cm,top=2.5cm,bottom=2cm]{geometry}
\setlength\parindent{0pt}

\makeatletter
\newcommand{\hashtag}{\#}
\newcommand{\req}[2]{%

\begingroup%
\textbf{#1}{\def\@currentlabel{#1}{\def\#{::}\xdef\lbl{req:#1}}\label{\lbl}}~#2\newline%
\endgroup%
\addcontentsline{lor}{requirement}{#1}%
} %

\DeclareNewTOC[%
type=requirement, %
types=requirements, %
name=Anforderung, %
listname={List of Requirements} %
]{lor}
\setuptoc{lor}{chapteratlist}

\begin{document}
\section{Test}
\req{MY.REQ.ID.42}{Lorem ipsum dolor sit amet,...}%
\req{MY.REQ.ID.42\#WORKING}{this requirement is broken,...}

Please have a look at \ref{req:MY.REQ.ID.42} on page~\pageref{req:MY.REQ.ID.42}

Please have a look at \ref{req:MY.REQ.ID.42::WORKING} on page~\pageref{req:MY.REQ.ID.42::WORKING}

\listofrequirements

\end{document}
  • thanks for your answer. Well, I have to use the \# inside the document because there will be errors like (! You can't use `macro parameter character #' in horizontal mode.) instead. Your code looks quite simple and works properly. – aronadaal Apr 2 '15 at 12:20
2

Because the simple solution isn't here till now, I put it:

\protected\edef\#{\string#}
  • 1
    It would be better saying also where one should put this code. – egreg Apr 2 '15 at 13:00
  • IMHO, this is clear: in the area where another definitions are:). For example, before \DeclareNewTOC. – wipet Apr 2 '15 at 13:39
1

Well, this works, but it is a very dirty trick. I hope I'll later manage to comment the code. One thing is sure: it's extremely fragile (and impossible to robustify).

\documentclass[a4paper]{scrartcl}
\usepackage[left=2cm,right=2cm,top=2.5cm,bottom=2cm]{geometry}
\setlength\parindent{0pt}

\makeatletter
\def\req#1#2{%
  \begingroup
    \catcode`\#=13
    \makehashexcl
    \edef\aron@do@label{\noexpand\label{req:\scantokens{#1\noexpand}}}%
    \makehashhash
    {\bfseries\scantokens{#1\noexpand}}%
    \edef\@currentlabel{\scantokens{#1\noexpand}}%
    \aron@do@label
    ~#2\newline
    \edef\aron@do@lor{\noexpand\addcontentsline{lor}{requirement}{\scantokens{#1\noexpand}}}%
    \aron@do@lor
  \endgroup%
}

\def\refreq#1#2{%
  \begingroup
    \catcode`\#=13
    \makehashexcl
    \edef\aron@do@{\noexpand#1{req:\scantokens{#2\noexpand}}}%
    \aron@do@
  \endgroup
}

\catcode`\#=13
\def\makehashexcl{\def##{!}}
\def\makehashhash{\def##{\char35 }}
\makehashhash
\catcode`\#=6

\DeclareRobustCommand\HASH{\char35 }

\makeatother


\DeclareNewTOC[
  type=requirement,
  types=requirements,
  name=Anforderung,
  listname={List of Requirements}
]{lor}
\setuptoc{lor}{chapteratlist}

\begin{document}

\section{Test}

\req{MY.REQ.ID.42}{Lorem ipsum dolor sit amet,...}

\req{MY.REQ.ID.43#BROKEN}{this requirement is broken,...}

Please have a look at \ref{req:MY.REQ.ID.42} on page~\pageref{req:MY.REQ.ID.42}

Please have a look at \refreq\ref{MY.REQ.ID.43#BROKEN} on page~\refreq\pageref{MY.REQ.ID.43#BROKEN}

\listofrequirements

\end{document}
  • thanks for your answer. I think the code of @TonioElGringo will solve my problem. What do you think? – aronadaal Apr 2 '15 at 12:23
1

Here I use the \convertchar macro of the stringstrings package to change all occurances of \# into ?, and use that in the label.

\documentclass[a4paper]{scrartcl}
\usepackage[left=2cm,right=2cm,top=2.5cm,bottom=2cm]{geometry}
\usepackage{stringstrings}
\setlength\parindent{0pt}

\makeatletter
\newcommand{\req}[2]{%
  \convertchar[q]{#1}{\#}{?}%
  \begingroup%
    \textbf{#1}\def\@currentlabel{#1}\label{req:\thestring}~#2\newline
  \endgroup%
  \addcontentsline{lor}{requirement}{#1}%
} %

\DeclareNewTOC[%
  type=requirement, %
  types=requirements, %
  name=Anforderung, %
  listname={List of Requirements} %
]{lor}
\setuptoc{lor}{chapteratlist}

\begin{document}
\section{Test}
\req{MY.REQ.ID.42}{Lorem ipsum dolor sit amet,...}

\req{MY.REQ.ID.43\#BROKEN\#}{this requirement is broken,...}

Please have a look at \ref{req:MY.REQ.ID.42} on page~\pageref{req:MY.REQ.ID.42}

Please have a look at \ref{req:MY.REQ.ID.43?BROKEN?} on 
  page~\pageref{req:MY.REQ.ID.43?BROKEN?}

\listofrequirements

\end{document}

enter image description here

  • the result looks a bit odd. The Req-ID is now duplicated... once with ? and once with #. – aronadaal Apr 2 '15 at 12:37
  • @aronadaal Please see revision. I'm still not quite sure if I've captured your intent. – Steven B. Segletes Apr 2 '15 at 12:50

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.