URL with track changes and line breaking

soultrackchangesurls

I am trying to handle URLs such that I can:

  • split the URL in multiple lines if too long exceeding the page width
  • include a track change mode which means being able to:
    • strikethrough and underline the URL text, and
    • change color of the text

To do this, I started from the recursive macro \bignumber{123456....} proposed by Michael Ummels in Splitting very big numbers over several lines and re-worked it a bit to allow me to introduce, within the text of the URL, two macros: \added{} and \deleted{} which control the text formatting for the track changes mode. These macros in turn use the \bignumber macro (\bignumberAdded{} and \bignumberDeleted{}) to make sure that also the text provided in track change mode is split in multiple lines.

This is the code, including a series of examples to show what the code does.

\documentclass[a4paper,10pt]{article}

% ---------------------------------------------------------
% LOAD USER-SPECIFIC PACKAGES
% ---------------------------------------------------------
\RequirePackage[top=1in, bottom=1in, left=0.7in, right=0.7in]{geometry}
\RequirePackage[parfill]{parskip} % Non-zero paragraph
\RequirePackage{fontspec}         % Specify system fonts
\RequirePackage{xstring}        % Used for string manipulation, such as IfEqCase
\RequirePackage{soul}           % Used to underline and strike out
\RequirePackage{amsmath}        % Used to enable deleted and added inside math formulas
\RequirePackage{lipsum}

\RequirePackage[
    colorlinks=true,
    citecolor=esadeepspace,
    urlcolor=blue,
    linkcolor=black]{hyperref} 

% ------------------------------------------------------------------------------
% TRACK CHANGES TYPESETTING
% ------------------------------------------------------------------------------
%%% redlining of text
 
%the bignumber function is an iterative function to enable the split long numbers or long strings in multiple lines at any point of their body.
%this is however a re-work of original bignumber implementation to enable to put inside \deleted{} or \added{} strings
\newcounter{AddedDeletedLength}\setcounter{AddedDeletedLength}{0}
\newcounter{FLAGbignumber}\setcounter{FLAGbignumber}{0}
\makeatletter
\def\@bignumber#1#2{%
    %searching if there is any \added{} string wihin the href text
    \ifx#1\added{}%
    %print the found \added{}
    \added{#2}%\let\next\@bignumber%%%
    \setcounter{FLAGbignumber}{1}%
    \fi%
    %searching if there is any \deleted{} string wihin the href text
    \ifx#1\deleted{}%
    %print the found \deleted{}
    \deleted{#2}%\let\next\@bignumber%%%
    \setcounter{FLAGbignumber}{1}%
    \fi%
    %if any \added{} or \deleted{} is found, the length of their string is computed and set in counter
    \ifnum\value{FLAGbignumber}=1%
        \def\AddedDeletedString{#2}%
        \StrLen{\AddedDeletedString}[\tempstring]%
        \setcounter{AddedDeletedLength}{\tempstring}%%
    \fi%
    %enter here only when #1 is not \added or \deleted
    \ifnum\value{FLAGbignumber}=0%
            %enter here if #2 is an end line to split the bignumber in multiple lines
            \ifx#2\end%
                    %print #1 if only it is not part of \added{} or \deleted{}
                    \ifnum\value{AddedDeletedLength}<0%
                    #1%
                    \fi%
                    \ifnum\value{AddedDeletedLength}=0%
                    #1%
                    \fi%
            %enter here if #2 is NOT an end line, and add some glue to let the split in multiple lines
            \else%
                    %print #1 if only it is not part of \added{} or \deleted{}
                    \ifnum\value{AddedDeletedLength}<0%
                    #1\hspace{0pt plus 1pt}%
                    \fi%
                    \ifnum\value{AddedDeletedLength}=0%
                    #1\hspace{0pt plus 1pt}%
                    \fi%
            \fi%
    \fi%
            \ifx#2\end%
                \let\next\@gobble%
            %enter here if #2 is NOT an end line, and add some glue to let the split in multiple lines
            \else%
                \let\next\@bignumber%
            \fi%
    \ifnum\value{FLAGbignumber}=0%
        %Updating the length of AddedDeletedLength so to compute when #1 is no more part of \added{} or \deleted{}
        \def\AddedDeletedStringNEW{#1}%
        \StrLen{\AddedDeletedStringNEW}[\tempstring]%
        \setcounter{AddedDeletedLength}{\numexpr\value{AddedDeletedLength}-\tempstring\relax}%
    \fi%
    %FLAGbignumber is activated only once, at the beginning when \added{} or \deleted{} is encounter, in order to compute its length
    %othewise it is always zero
    \setcounter{FLAGbignumber}{0}%
    \next#2}%
\newcommand{\bignumber}[1]{\setcounter{AddedDeletedLength}{0}%
\def\temp{#1}\ifx\temp\empty\else\@bignumber#1\end\fi}
\makeatother



%This is a rework of the orginal bignumber function to make the string to appear with the \added{} font
\makeatletter
\def\@bignumberDeleted#1#2{%
  \ifx#2\end%
    \textcolor{red}{\st{#1}}\let\next\@gobble%
  \else%
    \textcolor{red}{\st{#1}}\hspace{0pt plus 1pt}\let\next\@bignumberDeleted%
  \fi%
  \next#2}
\newcommand{\bignumberDeleted}[1]{\def\temp{#1}\ifx\temp\empty\else\@bignumberDeleted#1\end\fi}
\makeatother

%This is a rework of the orginal bignumber function to make the string to appear with the \deleted{} font
\makeatletter
\def\@bignumberAdded#1#2{%
  \ifx#2\end%
    \textcolor{green}{\ul{#1}}\let\next\@gobble%
  \else%
    \textcolor{green}{\ul{#1}}\hspace{0pt plus 1pt}\let\next\@bignumberAdded%
  \fi%
  \next#2}
\newcommand{\bignumberAdded}[1]{\def\temp{#1}\ifx\temp\empty\else\@bignumberAdded#1\end\fi}
\makeatother

 
%%This is the newly created \href macro to handle my problem
\newcounter{hrefFLAG}\setcounter{hrefFLAG}{0}
\newcommand{\hrefMy}[2]{\setcounter{hrefFLAG}{1}\href{#1}{\bignumber{#2}}\setcounter{hrefFLAG}{0}}

%%This is a re-work of the original \deleted implementation to be able to handle also url using the \hrefMy function
\setstcolor{red}
\DeclareRobustCommand{\deleted}[1]{%
  \ifmmode\text{{\textcolor{red}{\texorpdfstring{\st{$#1$}}{}}}}\else{%
  \ifnum \value{hrefFLAG}>0%
    \bignumberDeleted{#1}%
  \else%
  \textcolor{red}{\texorpdfstring{\st{#1}}{}}%
  \fi}\fi} 


%This is a re-work of the original \added implementation to be able to handle also url using the \hrefMy function
\setulcolor{green}
\DeclareRobustCommand{\added}[1]{%
  \ifmmode\text{{\textcolor{green}{\texorpdfstring{\ul{$#1$}}{}}}}\else{%
  \ifnum \value{hrefFLAG}>0%
    \bignumberAdded{#1}%
  \else%
  \textcolor{green}{\texorpdfstring{\ul{#1}}{}}%
  \fi}\fi}



%=========================================================
\begin{document}

  
\textbf{Example of added plein text:}

\added{Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Ut purus elit, vestibulum ut, placerat ac, adipiscing vitae,
felis. Curabitur dictum gravida mauris. Nam arcu libero, nonummy eget, consectetuer id, vulputate a, magna.
Donec vehicula augue eu neque. Pellentesque habitant morbi tristique senectus et netus et malesuada fames ac
turpis egestas. Mauris ut leo. Cras viverra metus rhoncus sem. Nulla et lectus vestibulum urna fringilla ultrices.}

\textbf{Example of deleted plein text:}

\deleted{Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Ut purus elit, vestibulum ut, placerat ac, adipiscing vitae,
felis. Curabitur dictum gravida mauris. Nam arcu libero, nonummy eget, consectetuer id, vulputate a, magna.
Donec vehicula augue eu neque. Pellentesque habitant morbi tristique senectus et netus et malesuada fames ac
turpis egestas. Mauris ut leo. Cras viverra metus rhoncus sem. Nulla et lectus vestibulum urna fringilla ultrices.}


\textbf{Example of using the hrefMy\{\} macro with track changes by adding and deleting a very long URL:}

\hrefMy{https://www.google.com/}{very-long-url-very-long-url-very-long-url-very-long-url-very-long-url-very-long-url-very-long-url-very-long-url-very-long-url-very-long-url-very-long-url-very-long-url-very-long-url-very-long-url-very-long-url\added{very-long-url-very-long-url-very-long-url-very-long-url-very-long-url-very-long-url-very-long-url-very-long-url-very-long-url-very-long-url-very-long-url-very-long-url-very-long-url-very-long-url-very-long-url}\deleted{very-long-url-very-long-url-very-long-url-very-long-url-very-long-url-very-long-url-very-long-url-very-long-url-very-long-url-very-long-url-very-long-url-very-long-url-very-long-url-very-long-url-very-long-url}}

\textbf{Another example of using the hrefMy\{\} macro with track changes:}

\hrefMy{https://www.google.com/}{very-long-url-\deleted{veeery-long-url-}\added{very-long-url-}very-long-url-very-long-url-very-long-url-very-long-url-very-long-url-very-long-url-very-long-url-very-long-url-very-long-url-very-long-url-very-long-url-very-long-url}


\end{document}

enter image description here

Ok so far so good, it seems to work fine.
Now the problem is that it gives me a very weird error when I initiate the added or deleted url text by the same letter which is pretty strange.
In other words, using a very simple example, this works:

%=========================================================
\begin{document}

\hrefMy{https://www.google.com/}{abcdef}

\hrefMy{https://www.google.com/}{\added{abcdef}}

\hrefMy{https://www.google.com/}{\deleted{abcdef}}

\end{document}

This works as well (note that the string now starts with two consecutive "a"):

%=========================================================
\begin{document}

\hrefMy{https://www.google.com/}{aabcdef}

\end{document}

BUT this does NOT work:

%=========================================================
\begin{document}

\hrefMy{https://www.google.com/}{\added{aabcdef}}

\hrefMy{https://www.google.com/}{\deleted{aabcdef}}

\end{document}

due to the start of the text with "aa", i.e. two consecutive identical characters. Latex gives me the following error:

! Missing \endcsname inserted.
<to be read again>
\let
l.203 ...https://www.google.com/}{\added{aabcdef}}
The control sequence marked <to be read again> should
not appear between \csname and \endcsname.

Any help? How is it possible that the code is not able to handle strings that have two consecutive letters that are the same?

Thanks!

P.S. I cannot use other macros as sloppypar, seqsplit or even the common \url{} function because they are not compatible with the soul package that I use to strikethrough (\st{}) and underline (\ul{}).

Best Answer

Thanks to the tip from Ulrike, I found a solution to my own problem. I post here below the updated code in case it could be of any use to somebody else. If you test it and find other bugs, please write them down!

\documentclass[a4paper,10pt]{article}

% ---------------------------------------------------------
% LOAD USER-SPECIFIC PACKAGES
% ---------------------------------------------------------
\RequirePackage[top=1in, bottom=1in, left=0.7in, right=0.7in]{geometry}
\RequirePackage[parfill]{parskip} % Non-zero paragraph
\RequirePackage{fontspec}         % Specify system fonts
\RequirePackage{xstring}        % Used for string manipulation, such as IfEqCase
\RequirePackage{soul}           % Used to underline and strike out
\RequirePackage{amsmath}        % Used to enable deleted and added inside math formulas


\RequirePackage[
    colorlinks=true,
    citecolor=esadeepspace,
    urlcolor=blue,
    linkcolor=black]{hyperref} 


% ------------------------------------------------------------------------------
% TRACK CHANGES TYPESETTING
% ------------------------------------------------------------------------------
%%% redlining of text
 
%the bignumber function is an iterative function to enable the split long numbers or long strings in multiple lines at any point of their body.
%this is however a re-work of original bignumber implementation to enable to put inside \deleted{} or \added{} strings
\newcounter{AddedDeletedLength}\setcounter{AddedDeletedLength}{0}
\newcounter{FLAGbignumber}\setcounter{FLAGbignumber}{0}
\makeatletter
\def\@bignumber#1#2{%
    %searching if there is any \added{} string wihin the href text
    \ifx#1\added{}%
    %print the found \added{}
    \bignumberAdded{#2}%%
    \setcounter{FLAGbignumber}{1}%
    \fi%
    %searching if there is any \deleted{} string wihin the href text
    \ifx#1\deleted{}%
    %print the found \deleted{}
    \bignumberDeleted{#2}%%
    \setcounter{FLAGbignumber}{1}%
    \fi%
    %if any \added{} or \deleted{} is found, the length of their string is computed and set in counter
    \ifnum\value{FLAGbignumber}=1%
        \def\AddedDeletedString{#2}%
        \StrLen{\AddedDeletedString}[\tempstring]%
        \setcounter{AddedDeletedLength}{\tempstring}%%
    \fi%
    %enter here only when #1 is not \added or \deleted
    \ifnum\value{FLAGbignumber}=0%
            \relax%
            %enter here if #2 is an end line to split the bignumber in multiple lines
            \ifx#2\end%
                    %print #1 if only it is not part of \added{} or \deleted{}
                    \ifnum\value{AddedDeletedLength}<0%
                    {#1}%
                    \fi%
                    \ifnum\value{AddedDeletedLength}=0%
                    {#1}%
                    \fi%
            %enter here if #2 is NOT an end line, and add some glue to let the split in multiple lines
            \else%
                    %print #1 if only it is not part of \added{} or \deleted{}
                    \ifnum\value{AddedDeletedLength}<0%
                    {#1}\hspace{0pt plus 1pt}%
                    \fi%
                    \ifnum\value{AddedDeletedLength}=0%
                    {#1}\hspace{0pt plus 1pt}%
                    \fi%
            \fi%
    \fi%
    \ifnum\value{FLAGbignumber}=1%
                \let\next\@bignumber%
    \else%
            \ifx#2\end%
                \let\next\@gobble%
            %enter here if #2 is NOT an end line, and add some glue to let the split in multiple lines
            \else%
                \let\next\@bignumber%
            \fi%
    \fi%
    \ifnum\value{FLAGbignumber}=0%
        %Updating the length of AddedDeletedLength so to compute when #1 is no more part of \added{} or \deleted{}
        \def\AddedDeletedStringNEW{#1}%
        \StrLen{\AddedDeletedStringNEW}[\tempstring]%
        \setcounter{AddedDeletedLength}{\numexpr\value{AddedDeletedLength}-\tempstring\relax}%
    \fi%
    %FLAGbignumber is activated only once, at the beginning when \added{} or \deleted{} is encounter, in order to compute its length
    %othewise it is always zero
    \setcounter{FLAGbignumber}{0}%
    \next#2}%
\newcommand{\bignumber}[1]{\setcounter{AddedDeletedLength}{0}%
\def\temp{#1}\ifx\temp\empty\else\@bignumber#1\end\fi}
\makeatother

%This is a rework of the orginal bignumber function to make the string to appear with the \added{} font
\makeatletter
\def\@bignumberDeleted#1#2{%
  \ifx#2\end%
    \textcolor{red}{\st{#1}}\let\next\@gobble%
  \else%
    \textcolor{red}{\st{#1}}\hspace{0pt plus 1pt}\let\next\@bignumberDeleted%
  \fi%
  \next#2}
\newcommand{\bignumberDeleted}[1]{\def\temp{#1}\ifx\temp\empty\else\@bignumberDeleted#1\end\fi}
\makeatother

%This is a rework of the orginal bignumber function to make the string to appear with the \deleted{} font
\makeatletter
\def\@bignumberAdded#1#2{%
  \ifx#2\end%
    \textcolor{green}{\ul{#1}}\let\next\@gobble%
  \else%
    \textcolor{green}{\ul{#1}}\hspace{0pt plus 1pt}\let\next\@bignumberAdded%
  \fi%
  \next#2}
\newcommand{\bignumberAdded}[1]{\def\temp{#1}\ifx\temp\empty\else\@bignumberAdded#1\end\fi}
\makeatother


 
%%re-definition of href
\newcommand{\hrefMy}[2]{\href{#1}{\bignumber{#2}}}
  
%=========================================================
\begin{document}

  
\textbf{Example of using the hrefMy\{\} macro without any track change but with a very long URL spanning multiple lines:}

\hrefMy{https://www.google.com/}{very-long-url-very-long-url-very-long-url-very-long-url-very-long-url-very-long-url-very-long-url-very-long-url-very-long-url-very-long-url-very-long-url-very-long-url-very-long-url-very-long-url-very-long-url}

\textbf{Example of using the hrefMy\{\} macro with track changes by adding a very long URL:}

\hrefMy{https://www.google.com/}{\added{very-long-url-very-long-url-very-long-url-very-long-url-very-long-url-very-long-url-very-long-url-very-long-url-very-long-url-very-long-url-very-long-url-very-long-url-very-long-url-very-long-url-very-long-url}}

\textbf{Example of using the hrefMy\{\} macro with track changes by deleting a very long URL:}

\hrefMy{https://www.google.com/}{\deleted{very-long-url-very-long-url-very-long-url-very-long-url-very-long-url-very-long-url-very-long-url-very-long-url-very-long-url-very-long-url-very-long-url-very-long-url-very-long-url-very-long-url-very-long-url}}

\textbf{Example of using the hrefMy\{\} macro with track changes by adding and deleting a very long URL:}

\hrefMy{https://www.google.com/}{very-long-url-very-long-url-very-long-url-very-long-url-very-long-url-very-long-url-very-long-url-very-long-url-very-long-url-very-long-url-very-long-url-very-long-url-very-long-url-very-long-url-very-long-url\added{very-long-url-very-long-url-very-long-url-very-long-url-very-long-url-very-long-url-very-long-url-very-long-url-very-long-url-very-long-url-very-long-url-very-long-url-very-long-url-very-long-url-very-long-url}\deleted{very-long-url-very-long-url-very-long-url-very-long-url-very-long-url-very-long-url-very-long-url-very-long-url-very-long-url-very-long-url-very-long-url-very-long-url-very-long-url-very-long-url-very-long-url}}

\textbf{Another example of using the hrefMy\{\} macro with track changes:}

\hrefMy{https://www.google.com/}{very-long-url-\deleted{vveeery-long-url-}\added{vvery-long-url-}very-long-url-very-long-url-very-long-url-very-long-url-very-long-url-very-long-url-very-long-url-very-long-url-very-long-url-very-long-url-very-long-url-very-long-url}

\textbf{Another examples to test the use of consecutive characters:}

\hrefMy{https://www.google.com/}{abcdef}

\hrefMy{https://www.google.com/}{\added{abcdef}}

\hrefMy{https://www.google.com/}{\deleted{abcdef}}

\hrefMy{https://www.google.com/}{aabcdef}

\hrefMy{https://www.google.com/}{\added{aabcdef}}

\hrefMy{https://www.google.com/}{\deleted{aabcdef}}


\end{document}
Related Question