2

I use LaTeX for technical documentation of test-scenarios of a software system. The idea is as follows:

  • I write a test scenario in LaTeX. In this test-scenario, I use pieces of data that are configurable and which are defined in a LaTeX environment.
  • Upon compilation of the LaTeX document I want a nice PDF with the test descriptions, but also a .properties file, which simply lists all data items as a key value pair and which is directly used by the test-suite. This way, updating the test documentation will automatically update the executable tests.

I have create an environment to achieve this as follows:

\edef\althashchar{\string#\space}%
\newcounter{datasnippets}
\newcommand{\datasnippet}[4]{%
    \immediate\write\tempfile{\unexpanded{#1=#4}}
  \refstepcounter{datasnippets}\label{data:#1}%
  \global\expandafter\def\csname #1\endcsname{#2}%
  \global\expandafter\def\csname #1lc\endcsname{\MakeLowercase{#2}}%    
  \global\expandafter\def\csname #1Description\endcsname{#3}%
  \global\expandafter\def\csname #1Value\endcsname{\code{#4}}%
  \global\expandafter\def\csname #1Full\endcsname{#3 (value: \code{#4})}%
  \thedatasnippets. & #2 & \code{#4} & #3 \\
    \addlinespace
}
\newenvironment{datasnippets}
 {
    \immediate\openout\tempfile=scenarios.properties
    \immediate\write\tempfile{\althashchar This is a generated file, *DO NOT EDIT* directly.}
    \immediate\write\tempfile{\althashchar Instead, update the data snippets inside the data.tex file of the scenarios documentation and regenerate.}

    \par
        \small
        \begin{longtable}{
            p{0.4cm}
            p{4cm}
            p{3cm}
            >{\raggedright\arraybackslash}p{\dimexpr\textwidth-8\tabcolsep-0.4cm-4cm-3cm\relax}
        }
        \toprule
        & \textbf{Name} & \textbf{Value} & \textbf{Description} \\
        \midrule
        \endhead
 }
 {%
    \bottomrule
  \end{longtable}
    \immediate\closeout\tempfile
 }

Then, I simply do the following:

\begin{datasnippets}
    \datasnippet{carName}{Car name}{The name (full brand and type) of the car used in the crash-test}{Bugatti Veyron}
\end{datasnippets}

Now, I can simply refer to \carName , \carNameValue , \carNameDescription depending on what I want to use in my document and I get a nice export of the variable and the value in my .properties file at the end.

The problem is that I can't get it to work properly with things such as URLs. Those need to be escaped for LaTeX, but they should NOT be escaped when writing out to the file.

How do I create a datasnippet where the value is a URL? So ideally, I just want to do something like:

\begin{datasnippets}
    \datasnippet{shop}{Online store}{The online store used for the order.}{http://www.mycoolstore.com/}
\end{datasnippets}

It should be in the .properties file as follows:

shop=http://www.mycoolstore.com/

EDIT:

My question is actually more general than just URLs, it is about everything that LaTeX requires escaping for. For example, if I have a variable of the form A_B, I can not simply type that in my \datasnippet command as I need to escape the _, but the output to the properties file also exports those escape characters. So If I have following code:

\begin{datasnippets}
    \datasnippet{someCode}{A secret code}{Just some difficult to typeset thing.}{A\_B14879/C\_D}
\end{datasnippets}

That will be exported as:

someCode=A\_B14879/C\_D

But I would like to see:

someCode=A_B14879/C_D

Here is a full working example:

\documentclass[11pt, a4paper]{article}
\usepackage{booktabs}
\usepackage{framed}
\usepackage{longtable}
\usepackage{hyperref}
\usepackage{array}
\usepackage{fancyhdr}
\date{}
\pagestyle{fancy}
\newcommand{\code}[1]{\texttt{#1}}
\newwrite\tempfile


\edef\althashchar{\string#\space}%
\newcounter{datasnippets}
\newcommand{\datasnippet}[4]{%
    \immediate\write\tempfile{\unexpanded{#1=#4}}
  \refstepcounter{datasnippets}\label{data:#1}%
  \global\expandafter\def\csname #1\endcsname{#2}%
  \global\expandafter\def\csname #1lc\endcsname{\MakeLowercase{#2}}%    
  \global\expandafter\def\csname #1Description\endcsname{#3}%
  \global\expandafter\def\csname #1Value\endcsname{\code{#4}}%
  \global\expandafter\def\csname #1Full\endcsname{#3 (waarde: \code{#4})}%
  \thedatasnippets. & #2 & \code{#4} & #3 \\
    \addlinespace
}
\newenvironment{datasnippets}
 {
    \immediate\openout\tempfile=scenarios.properties
    \immediate\write\tempfile{\althashchar This is a generated file, *DO NOT EDIT* directly.}
    \immediate\write\tempfile{\althashchar Instead, update the data snippets inside the data.tex file of the scenarios documentation and regenerate.}

    \par
        \small
        \begin{longtable}{
            p{0.4cm}
            p{4cm}
            p{3cm}
            >{\raggedright\arraybackslash}p{\dimexpr\textwidth-8\tabcolsep-0.4cm-4cm-3cm\relax}
        }
        \toprule
        & \textbf{Name} & \textbf{Value} & \textbf{Description} \\
        \midrule
        \endhead
 }
 {%
    \bottomrule
  \end{longtable}
    \immediate\closeout\tempfile
 }


\begin{document}

\section{Data Overview}
\begin{datasnippets}
% Formaat: naam (dit wordt in het document gebruikt om het commando te gebruiken), korte beschrijving (KORT!), lange beschrijving (duidelijk!), waarde (enkel de waarde, liefst in \code{} wrap)
\datasnippet{someVariable}{Variable}{Just an example}{ThisWorks}
\datasnippet{aProblem}{Problem Variable}{An illustration of a value that layouts fine, but is exported incorrectly.}{A\_B01}
\end{datasnippets}

\section{Data Usage}

As you can see, I can now simply refer to \someVariableValue\ and its full description: \someVariableFull . A side effect is that upon compiling, a properties file is generated which can be used during testing.

\end{document}

Any suggestions? Thanks!

  • You could use the \texttt{\detokenize{...}} in your TeX file. Or you might use \url{} provided by hyperref. – Skillmon May 30 '17 at 8:41
  • It wasn't clear from my original question, but it's not just about URLs, but any other escapable sequence of characters. Maybe the detokenize works, but I do not really see where I should add it then? – Yves V. May 30 '17 at 8:57
  • Could you please provide a complete compilable example (beginning at \documentclass and ending at \end{document}) – Skillmon May 30 '17 at 8:59
  • I have added a full compilable example. Thanks for your time. The essence is that I can simply use the defined commands in my document, and that they are exported correctly in the output file. I prefer a more complex definition of my environment over a more complex escaping/usage as non-latex people will be defining test scenarios and datasnippets as well. – Yves V. May 30 '17 at 9:10
1

The following does work for the examples you provided so far:

\documentclass[]{article}

\def\myurl{http://www.my_coolstore.com/}% no escaped underscores
\newwrite\tempfile
\immediate\openout\tempfile=scenarios.properties

\begin{document}
\texttt{\expandafter\detokenize\expandafter{\myurl}}% this prints the url in the pdf
\immediate\write\tempfile{\myurl}% this puts the url in your file
\immediate\closeout\tempfile
\end{document}

EDIT: Working example of your MWE with adaptions to your \code. You mustn't escape the underscores (no \_) with the new \code. Then it works fine for me.

\documentclass[11pt, a4paper]{article}
\usepackage{booktabs}
\usepackage{framed}
\usepackage{longtable}
\usepackage{hyperref}
\usepackage{array}
\usepackage{fancyhdr}
\date{}
\pagestyle{fancy}
\newcommand{\code}[1]{\texttt{\expandafter\detokenize\expandafter{#1}}}
\newwrite\tempfile


\edef\althashchar{\string#\space}%
\newcounter{datasnippets}
\newcommand{\datasnippet}[4]{%
    \immediate\write\tempfile{\unexpanded{#1=#4}}
  \refstepcounter{datasnippets}\label{data:#1}%
  \global\expandafter\def\csname #1\endcsname{#2}%
  \global\expandafter\def\csname #1lc\endcsname{\MakeLowercase{#2}}%    
  \global\expandafter\def\csname #1Description\endcsname{#3}%
  \global\expandafter\def\csname #1Value\endcsname{\code{#4}}%
  \global\expandafter\def\csname #1Full\endcsname{#3 (waarde: \code{#4})}%
  \thedatasnippets. & #2 & \code{#4} & #3 \\
    \addlinespace
}
\newenvironment{datasnippets}
 {
    \immediate\openout\tempfile=scenarios.properties
    \immediate\write\tempfile{\althashchar This is a generated file, *DO NOT EDIT* directly.}
    \immediate\write\tempfile{\althashchar Instead, update the data snippets inside the data.tex file of the scenarios documentation and regenerate.}

    \par
        \small
        \begin{longtable}{
            p{0.4cm}
            p{4cm}
            p{3cm}
            >{\raggedright\arraybackslash}p{\dimexpr\textwidth-8\tabcolsep-0.4cm-4cm-3cm\relax}
        }
        \toprule
        & \textbf{Name} & \textbf{Value} & \textbf{Description} \\
        \midrule
        \endhead
 }
 {%
    \bottomrule
  \end{longtable}
    \immediate\closeout\tempfile
 }


\begin{document}

\section{Data Overview}
\begin{datasnippets}
% Formaat: naam (dit wordt in het document gebruikt om het commando te gebruiken), korte beschrijving (KORT!), lange beschrijving (duidelijk!), waarde (enkel de waarde, liefst in \code{} wrap)
\datasnippet{someVariable}{Variable}{Just an example}{ThisWorks}
\datasnippet{aProblem}{Problem Variable}{An illustration of a value that layouts fine, but is exported incorrectly.}{A_B01}
\end{datasnippets}

\section{Data Usage}

As you can see, I can now simply refer to \someVariableValue\ and its full description: \someVariableFull . A side effect is that upon compiling, a properties file is generated which can be used during testing.

\end{document}

EDIT2: To allow % in the arguments of \datasnippet we can change the catcode of % in the environment datasnippets. This way % is treated as a normal character, this way, comments are not supported inside of the environment. The only thing, which doesn't work this way, is to have a \ as the last character in the arguments of \datasnippet.

\documentclass[11pt, a4paper]{article}
\usepackage{booktabs}
\usepackage{framed}
\usepackage{longtable}
\usepackage{hyperref}
\usepackage{array}
\usepackage{fancyhdr}
\date{}
\pagestyle{fancy}
\newcommand{\code}[1]{\texttt{\expandafter\detokenize\expandafter{#1}}}
\newwrite\tempfile


\edef\althashchar{\string#\space}%
\newcounter{datasnippets}
\newcommand{\datasnippet}[4]{%
    \immediate\write\tempfile{\unexpanded{#1=#4}}
  \refstepcounter{datasnippets}\label{data:#1}%
  \global\expandafter\def\csname #1\endcsname{#2}%
  \global\expandafter\def\csname #1lc\endcsname{\MakeLowercase{#2}}%    
  \global\expandafter\def\csname #1Description\endcsname{#3}%
  \global\expandafter\def\csname #1Value\endcsname{\code{#4}}%
  \global\expandafter\def\csname #1Full\endcsname{#3 (waarde: \code{#4})}%
  \thedatasnippets. & #2 & \code{#4} & #3 \\
    \addlinespace
}
\newenvironment{datasnippets}
 {
     \catcode`\%=11
    \immediate\openout\tempfile=scenarios.properties
    \immediate\write\tempfile{\althashchar This is a generated file, *DO NOT EDIT* directly.}
    \immediate\write\tempfile{\althashchar Instead, update the data snippets inside the data.tex file of the scenarios documentation and regenerate.}

    \par
        \small
        \begin{longtable}{
            p{0.4cm}
            p{4cm}
            p{3cm}
            >{\raggedright\arraybackslash}p{\dimexpr\textwidth-8\tabcolsep-0.4cm-4cm-3cm\relax}
        }
        \toprule
        & \textbf{Name} & \textbf{Value} & \textbf{Description} \\
        \midrule
        \endhead
 }
 {%
    \bottomrule
  \end{longtable}
    \immediate\closeout\tempfile
 }


\begin{document}

\section{Data Overview}
% Formaat: naam (dit wordt in het document gebruikt om het commando te gebruiken), korte beschrijving (KORT!), lange beschrijving (duidelijk!), waarde (enkel de waarde, liefst in \code{} wrap)
\begin{datasnippets}
\datasnippet{someVariable}{Variable}{Just an example}{ThisWorks}
\datasnippet{aProblem}{Problem Variable}{An illustration of a value that layouts
fine, but is exported incorrectly.}{A_B01%\ }
\end{datasnippets}
% comment

\section{Data Usage}

As you can see, I can now simply refer to \someVariableValue\ and its full description: \someVariableFull . A side effect is that upon compiling, a properties file is generated which can be used during testing.

\end{document}
  • @YvesV. note that this way % is impossible to enter into your last field. – Skillmon May 30 '17 at 9:22
  • I do not have such a variable right now, but I am interested to see how the approach could be adapted to allow any kind of character. – Yves V. May 30 '17 at 9:25
  • @YvesV. you could (temporarily) change the catcode of % to allow it. – Skillmon May 30 '17 at 11:16

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.