\newcommand distorts \qrcode

To quote the qrcode documentation:

As with all verbatim modes, however, because TEX irrevocably sets catcodes when it first encounters characters, this will not work if the \qrcode macro is contained in another macro. If you call \qrcode inside an \fbox or a \marginpar, for example, and if your URL contains one of those special characters, you will either encounter error messages or (worse, because it is undetectable to the naked eye) have the wrong QR code typeset. In this scenario, you can still include any of the characters #$&^_~% \{} by escaping them with an extra backslash; so long as they eventually pass unexpanded to \qrcode, they will produce the correct QR code. A line break may be obtained with \?.

So it is caused by the line breaks and the spaces (the indention). You can fix it by replacing the line breaks with \?.

An example with identical barcodes:

\documentclass[border=1cm]{standalone}
\usepackage[]{qrcode}


\newcommand{\contact}{
     \qrcode[]{\?%
       BEGIN:VCARD\?%
        VERSION:4.0\?%
        EMAIL:[email protected]\?%
        FN:John Doe\?%
        N:Doe;John;;;\?%
        TEL;TYPE=home:123456789\?%
        UID:8cbddd73-d45d-45ad-a1e4-9587984e880d\?%
        URL:www.doe.net\?%
        END:VCARD\?%
     }
}


\begin{document}

     \qrcode[]{
BEGIN:VCARD
VERSION:4.0
EMAIL:[email protected]
FN:John Doe
N:Doe;John;;;
TEL;TYPE=home:123456789
UID:8cbddd73-d45d-45ad-a1e4-9587984e880d
URL:www.doe.net
END:VCARD
}


     \contact
\end{document}

enter image description here


The problem is:

\qrcode does first modify the catcode-régime and then call some internal macros.

The internal macros in turn shall cause LaTeX to read from the .tex-input-file and tokenize their arguments under the modified catcode-régime.

This reading and tokenizing arguments under the modified catcode-régime is outmaneuvered when tokenizing the entire call to \qrcode takes place under normal/non-modified catcode-régime at the time of defining the macro \contact.

Reading from the .tex-input-file and tokenizing things under different catcode-régimes yields different sets of tokens which in turn yield different qr-codes.

A workaround for defining the macro \contact can be reading and tokenizing the entire call to \qrcode under verbatim-catcode-régime and passing it to \scantokens which in turn pretends unexpanded-writing things to a text-file and reading that text-file. \scantokens'reading-part ensures that things get re-tokenized whereby the changes of the catcode-régime performed by \qrcode affect things.

My -eh- private toolkit for LaTeX-programming contains a macro \UDcollectverbarg which can be used for having things tokenized under verbatim-catcode-régime before passing them as arguments to other commands:

\documentclass[border=1cm]{standalone}

\makeatletter
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% Implement stuff for reading arguments "verbatim":
%
% Usually \endlinechar has the value `\^^M which implies that
% LaTeX usually does insert character 13 (return) at each line-ending.
% There are situations where this needs to be replaced by the
% newline-character (usually ^^J). (E.g., with \scantokens' 
% unexpanded-writing-to-file-part...)
%
% Maybe the routine for \UDcollectverbarg could be shorter but I wanted
% both syntax |verbatim-arg| and syntax {verbatim-arg} to be possible.
%
% Syntax of \UDcollectverbarg:
%
%   \UDcollectverbarg{<^^M-replacement>}{<Mandatory 1>}{<Mandatory 2>}<verbatim-Arg>
%
% yields:
%
%   <Mandatory 1>{<Mandatory2>{<verbatim-Arg>}}
%
% Syntax of \UDconcatverbarg:
%
%   \UDconcatverbarg{<^^M-replacement>}{<Mandatory 1>}{<Mandatory 2>}<verbatim-Arg>
%
% yields:
%
%   <Mandatory 1>{<Mandatory2><verbatim-Arg>}
%
% with each character ^^M (usually=\endline-char) replaced by
%   token-sequence <^^M-replacement>
%
% The Mandatory-Arguments are mandatory. If they consist of several
% tokens, they must be nested into catcode-1/2-character-pair / braces.
% If reading is necessary, they will be read under normal catcode-
% conditions.
% The verbatim-Arg is also mandatory. It will be read under
% verbatim-catcode-conditions. If its first character is a brace,
% it will be "assumed" that the argument is nested into braces.
% Otherwise it will be assumed, that the argument is delimited
% by the first character - like the argument of \verb.
%
% Empty-lines will not be ignored.
%
% By nesting calls to \UDcollectverbarg within \UDcollectverbarg's first
% argument, you can collect "verbatim-arguments" within its second
% argument.
%
% E.g.,
%
%   \UDcollectverbarg{<^^M-replacement>}{\UDcollectverbarg{<^^M-replacement>}{\UDcollectverbarg{<^^M-replacement>}{<actionA>}}}% <- Mandatory 1
%                {<actionB>}%                     <- Mandatory
%                <verbatim-Arg1><verbatim-Arg2><verbatim-Arg3>
%
% yields:
%
%  \UDcollectverbarg{<^^M-replacement>}{\UDcollectverbarg{<^^M-replacement>}{<actionA>}}% <- Mandatory 1
%               {<actionB><verbatim-Arg1>}%        <- Mandatory 2
%               <verbatim-Arg2><verbatim-Arg3>
%
% yields:
%
%  \UDcollectverbarg{<^^M-replacement>}{<actionA>}% <- Mandatory 1
%               {<actionB>{<verbatim-Arg1>}{<verbatim-Arg2>}}% <- Mandatory 2
%               <verbatim-Arg3>
%
% yields:
%
%  <actionA>{<actionB>{<verbatim-Arg1>}{<verbatim-Arg2>}{<verbatim-Arg3>}}
%
% Assume <actionA> = \@firstofone -> equals:
%
%     \@firstofone{<actionB>{<verbatim-Arg1>}{<verbatim-Arg2>}{<verbatim-Arg3>}}
%
%    yields:
%
%     <actionB>{<verbatim-Arg1>}{<verbatim-Arg2>}{<verbatim-Arg3>}
\newcommand\@CheckWhetherNull[1]{%
  \romannumeral0\expandafter\@secondoftwo\string{\expandafter
  \@secondoftwo\expandafter{\expandafter{\string#1}\expandafter
  \@secondoftwo\string}\expandafter\@firstoftwo\expandafter{\expandafter
  \@secondoftwo\string}\expandafter\expandafter\@firstoftwo{ }{}%
  \@secondoftwo}{\expandafter\expandafter\@firstoftwo{ }{}\@firstoftwo}%
}%
\begingroup
\catcode`\^^M=12 %
\@firstoftwo{%
  \endgroup%%%%
  \newcommand\UDEndlreplace[2]{\romannumeral0\@UDEndlreplace{#2}#1^^M\relax{}}%
  \newcommand*\@UDEndlreplace{}%
  \long\def\@UDEndlreplace#1#2^^M#3\relax#4#5{%
    \@CheckWhetherNull{#3}%
    { #5{#4#2}}{\@UDEndlreplace{#1}#3\relax{#4#2#1}{#5}}%
  }%
}{}%
\newcommand\UDcollectverbarg{\@UDverbarg{\@UDcollectverbarg}}%
\newcommand\@UDverbarg[4]{%
  \@bsphack
  \begingroup
  \let\do\@makeother\dospecials
  \catcode`\{=1 %
  \catcode`\ =10 %
  \@ifnextchar\bgroup
  {\catcode`\}=2 \@@UDverbarg{#1}{#2}{#3}{#4}{}}%
  {\do\{\@@UDverbarg{#1}{#2}{#3}{#4}}%
}%
\newcommand\@@UDverbarg[5]{%
  \do\ %
  \catcode`\^^M=12 %
  \long\def\@tempb##1#5{%
    \edef\@tempb{##1}%
    \@onelevel@sanitize\@tempb
    \expandafter\UDEndlreplace\expandafter{\@tempb}{#2}{\def\@tempb}%
    \expandafter#1\expandafter{\@tempb}{#3}{#4}%
  }%
  \@tempb
}%
\newcommand\@UDcollectverbarg[3]{%
  \endgroup
  \@esphack
  #2{#3{#1}}%
}%
\makeatother
% Implementing stuff for reading arguments "verbatim" done.
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

\usepackage[]{qrcode}

\begingroup
\newlinechar=`\^^J %
\catcode`\^^J=12 %
\UDcollectverbarg{^^J}{\endgroup\newcommand{\contact}}{\scantokens}|%
     \qrcode[]{
BEGIN:VCARD
VERSION:4.0
EMAIL:[email protected]
FN:John Doe
N:Doe;John;;;
TEL;TYPE=home:123456789
UID:8cbddd73-d45d-45ad-a1e4-9587984e880d
URL:www.doe.net
END:VCARD
}%
|%


\begin{document}

     \qrcode[]{
BEGIN:VCARD
VERSION:4.0
EMAIL:[email protected]
FN:John Doe
N:Doe;John;;;
TEL;TYPE=home:123456789
UID:8cbddd73-d45d-45ad-a1e4-9587984e880d
URL:www.doe.net
END:VCARD
}

\contact

\end{document}

enter image description here

Tags:

Macros

Qrcode