Skip to main content
replaced http://tex.stackexchange.com/ with https://tex.stackexchange.com/
Source Link

This issue is driving me nuts. Ever since the friendly and knowledgeable people here on tex SE have guided me to doing multiple string replacements the proper wayguided me to doing multiple string replacements the proper way, I've been trying to incorporate that knowledge into my code — to no available so far. The difficulties are:

\documentclass[a4paper]{article} \usepackage{xstring} \usepackage[usenames,dvipsnames,svgnames,table]{xcolor} % ----------------------------------------------------------------- % URL escaping simplified; % as per httphttps://tex.stackexchange.com/questions/153215/how-to-do-multiple-string-replacements \newcommand{\urlescapestep}[2]{% \expandafter\StrSubstitute\expandafter{\x}{#1}{#2}[\x]% } \newcommand{\urlescape}[1]{{% \noexpandarg% \StrSubstitute{#1}{\%}{\%25}[\x]% \urlescapestep{/}{\%2F}% \urlescapestep{a}{A}% just for this test; imagine useful stuff here \x}} \newcommand{\escapeONE}[1]{*#1*} \newcommand{\escapeTWO}[1]{\StrSubstitute{#1}{a}{A}} % ----------------------------------------------------------------- % Execute a command with `\write18`: \newcommand{\CXtempoutroute}{/tmp/CXtempout.tex} \newcommand{\exec}[1]{% \immediate\write18{#1 > "\CXtempoutroute"}\input{\CXtempoutroute}} % ----------------------------------------------------------------- % `curl` commands using the string replacement commands: \newcommand{\curlPlain}[4]{% \exec{curl --silent --show-error #1 #2/#3#4}} \newcommand{\curlUrlescape}[4]{% \exec{curl --silent --show-error #1 #2/#3\urlescape{#4}}} \newcommand{\curlONE}[4]{% \exec{curl --silent --show-error #1 #2/#3\escapeONE{#4}}} \newcommand{\curlTWO}[4]{% \exec{curl --silent --show-error #1 #2/#3\escapeTWO{#4}}} % ----------------------------------------------------------------- \begin{document} First, let's show our three string escaping mechanisms all work under normal circumstances: \verb#\urlescape#: \urlescape{abc} \verb#\escapeONE#: \escapeONE{abc} \verb#\escapeTWO#: \escapeTWO{abc} These do work and turn \verb#abc# into \verb#Abc#, \verb#*abc*#, and \verb#Abc#, respectively. Now let's use the various \verb#curl*# methods: works: \verb#\curlPlain{}{127.0.0.1:8910}{foobar.tex/helo/}{abc}#: \curlPlain{}{127.0.0.1:8910}{foobar.tex/helo/}{abc} works: \verb#\curlONE{}{127.0.0.1:8910}{foobar.tex/helo/}{abc}#: \curlONE{}{127.0.0.1:8910}{foobar.tex/helo/}{abc} throws: \verb#\curlTWO{}{127.0.0.1:8910}{foobar.tex/helo/}{abc}#: \curlTWO{}{127.0.0.1:8910}{foobar.tex/helo/}{abc} \end{document} 

This issue is driving me nuts. Ever since the friendly and knowledgeable people here on tex SE have guided me to doing multiple string replacements the proper way, I've been trying to incorporate that knowledge into my code — to no available so far. The difficulties are:

\documentclass[a4paper]{article} \usepackage{xstring} \usepackage[usenames,dvipsnames,svgnames,table]{xcolor} % ----------------------------------------------------------------- % URL escaping simplified; % as per http://tex.stackexchange.com/questions/153215/how-to-do-multiple-string-replacements \newcommand{\urlescapestep}[2]{% \expandafter\StrSubstitute\expandafter{\x}{#1}{#2}[\x]% } \newcommand{\urlescape}[1]{{% \noexpandarg% \StrSubstitute{#1}{\%}{\%25}[\x]% \urlescapestep{/}{\%2F}% \urlescapestep{a}{A}% just for this test; imagine useful stuff here \x}} \newcommand{\escapeONE}[1]{*#1*} \newcommand{\escapeTWO}[1]{\StrSubstitute{#1}{a}{A}} % ----------------------------------------------------------------- % Execute a command with `\write18`: \newcommand{\CXtempoutroute}{/tmp/CXtempout.tex} \newcommand{\exec}[1]{% \immediate\write18{#1 > "\CXtempoutroute"}\input{\CXtempoutroute}} % ----------------------------------------------------------------- % `curl` commands using the string replacement commands: \newcommand{\curlPlain}[4]{% \exec{curl --silent --show-error #1 #2/#3#4}} \newcommand{\curlUrlescape}[4]{% \exec{curl --silent --show-error #1 #2/#3\urlescape{#4}}} \newcommand{\curlONE}[4]{% \exec{curl --silent --show-error #1 #2/#3\escapeONE{#4}}} \newcommand{\curlTWO}[4]{% \exec{curl --silent --show-error #1 #2/#3\escapeTWO{#4}}} % ----------------------------------------------------------------- \begin{document} First, let's show our three string escaping mechanisms all work under normal circumstances: \verb#\urlescape#: \urlescape{abc} \verb#\escapeONE#: \escapeONE{abc} \verb#\escapeTWO#: \escapeTWO{abc} These do work and turn \verb#abc# into \verb#Abc#, \verb#*abc*#, and \verb#Abc#, respectively. Now let's use the various \verb#curl*# methods: works: \verb#\curlPlain{}{127.0.0.1:8910}{foobar.tex/helo/}{abc}#: \curlPlain{}{127.0.0.1:8910}{foobar.tex/helo/}{abc} works: \verb#\curlONE{}{127.0.0.1:8910}{foobar.tex/helo/}{abc}#: \curlONE{}{127.0.0.1:8910}{foobar.tex/helo/}{abc} throws: \verb#\curlTWO{}{127.0.0.1:8910}{foobar.tex/helo/}{abc}#: \curlTWO{}{127.0.0.1:8910}{foobar.tex/helo/}{abc} \end{document} 

This issue is driving me nuts. Ever since the friendly and knowledgeable people here on tex SE have guided me to doing multiple string replacements the proper way, I've been trying to incorporate that knowledge into my code — to no available so far. The difficulties are:

\documentclass[a4paper]{article} \usepackage{xstring} \usepackage[usenames,dvipsnames,svgnames,table]{xcolor} % ----------------------------------------------------------------- % URL escaping simplified; % as per https://tex.stackexchange.com/questions/153215/how-to-do-multiple-string-replacements \newcommand{\urlescapestep}[2]{% \expandafter\StrSubstitute\expandafter{\x}{#1}{#2}[\x]% } \newcommand{\urlescape}[1]{{% \noexpandarg% \StrSubstitute{#1}{\%}{\%25}[\x]% \urlescapestep{/}{\%2F}% \urlescapestep{a}{A}% just for this test; imagine useful stuff here \x}} \newcommand{\escapeONE}[1]{*#1*} \newcommand{\escapeTWO}[1]{\StrSubstitute{#1}{a}{A}} % ----------------------------------------------------------------- % Execute a command with `\write18`: \newcommand{\CXtempoutroute}{/tmp/CXtempout.tex} \newcommand{\exec}[1]{% \immediate\write18{#1 > "\CXtempoutroute"}\input{\CXtempoutroute}} % ----------------------------------------------------------------- % `curl` commands using the string replacement commands: \newcommand{\curlPlain}[4]{% \exec{curl --silent --show-error #1 #2/#3#4}} \newcommand{\curlUrlescape}[4]{% \exec{curl --silent --show-error #1 #2/#3\urlescape{#4}}} \newcommand{\curlONE}[4]{% \exec{curl --silent --show-error #1 #2/#3\escapeONE{#4}}} \newcommand{\curlTWO}[4]{% \exec{curl --silent --show-error #1 #2/#3\escapeTWO{#4}}} % ----------------------------------------------------------------- \begin{document} First, let's show our three string escaping mechanisms all work under normal circumstances: \verb#\urlescape#: \urlescape{abc} \verb#\escapeONE#: \escapeONE{abc} \verb#\escapeTWO#: \escapeTWO{abc} These do work and turn \verb#abc# into \verb#Abc#, \verb#*abc*#, and \verb#Abc#, respectively. Now let's use the various \verb#curl*# methods: works: \verb#\curlPlain{}{127.0.0.1:8910}{foobar.tex/helo/}{abc}#: \curlPlain{}{127.0.0.1:8910}{foobar.tex/helo/}{abc} works: \verb#\curlONE{}{127.0.0.1:8910}{foobar.tex/helo/}{abc}#: \curlONE{}{127.0.0.1:8910}{foobar.tex/helo/}{abc} throws: \verb#\curlTWO{}{127.0.0.1:8910}{foobar.tex/helo/}{abc}#: \curlTWO{}{127.0.0.1:8910}{foobar.tex/helo/}{abc} \end{document} 

this thingThis issue is driving me nuts. everEver since the friendly and knowledgeable people here on tex SE have guided me to doing multiple string replacements the proper way, i'veI've been trying to incorporate that knowledge into my code—tocode — to no availavailable so far. the difficulty is (1) that the string replacement facility uses \noexpandarg / \expandafter, which does not cooperate with \write18 all too well, and (2) there is a nasty condition with \write18 and/or \input that causes (La)TeX to throw up a TeX capacity exceeded, sorry message. The difficulties are:

  1. The string replacement facility uses \noexpandarg / \expandafter, which does not cooperate with \write18 all too well, and
  2. There is a nasty condition with \write18 and/or \input that causes (La)TeX to throw up a TeX capacity exceeded, sorry message.

let'sLet's look at the M(W)E below—itbelow — it is not really working as it stands, because i'mI'm using curl to address a local server which is not featured here. forFor those who are interested: thisThis code is intended for CoffeeXeLaTeX, an attempt to make TeX scriptable with JavaScript (and, therefore, CoffeeScript). youYou cannot successfully run the code below unless you have a web server at the address specified; iI realize that this dependency is wholly fortuitous for the effects iI want to demonstrate, and i'mI'm willing to rewrite the example so we can take the brackets out of M(W)E. thatThat said, i'mI'm sure that many of you will just exclaim Aha"Aha! beginner'sBeginner's mistake!" when reading this code:

theThe code as it stands throws TeX capacity exceeded, sorry [text input levels=15], which would seem to indicate that TeX is recursively calling itself for too many times.

duringDuring the past endless hours, iI have also managed to get a TeX capacity exceeded, sorry [input stack size=5000], and, significantly, that dreaded use of StrSubstitute doesn't match its definition errors, depending on exactly where iI happened to put those magic \edef, \noexpand, \expandafter stuff.

iI fully admit that i've beenI was doing cargo cult programming, but then i'veI also takentook out my vintage 1990 Taiwan edition of The TeX Book, i've tried to. I read http://www.tug.org/TUGboat/Articles/tb09-1/tb20bechtolsheim.pdfBechtolsheim, i'veI searched the netinternet so often Google wants to send me a golden customer card now. i'veI erased the experimental code and started over so iI can post this question with some meaningful code; iI could probably try and reconstruct some of the intermittent attempts.

what i'veWhat I found out so far is that when TeX writes stuff to a file, it will postpone that writing because it assumes that "most of the time that is what you'll want" (not sure iI can agree with that; why not write \postpone\write18 if you really want to have it work that way?). youYou can make it act now with \immediate, but since there aint no bait with no hook in TeX, this does not exactly what you'd think it should, it only 'works similar in most cases'.

asAs a programmer, i'mI'm used to dealing with recursive function calling and delayed, asynchronous code execution in the event loop. curiouslyCuriously, this knowledge is of little help to me when TeX complains:

  • whereWhere do the recursive calls take place in the above code? iI cannot spot them.

  • whyWhy do i sometimes get those stack size exceeded errors for innocuous input files when using \input(i believe)?

  • whyWhy does the presence of \noexpand / \expandafter break \write18?

  • whatWhat am iI supposed to do against these symptoms (short of reading the implementation code down to the last expansion of every command inside the argument to `write18write18)?

  • isIs all this in some way related to the issue of robust / fragile commands and 'moveable arguments'?

iI feel justified to ask this convoluted, huge question because my feeling after fiddling for some months with TeX (and managing to produce output, so it's worth the try) iI feel that these are the convoluted, shady quarters of TeX where visitors don't like to go, where no easy transport is available, and where only the toughest can make it work at all. whichWhich about sums up my motivation for coming up with CoffeeXeLaTeX.

this thing is driving me nuts. ever since the friendly and knowledgeable people here on tex SE have guided me to doing multiple string replacements the proper way, i've been trying to incorporate that knowledge into my code—to no avail so far. the difficulty is (1) that the string replacement facility uses \noexpandarg / \expandafter, which does not cooperate with \write18 all too well, and (2) there is a nasty condition with \write18 and/or \input that causes (La)TeX to throw up a TeX capacity exceeded, sorry message.

let's look at the M(W)E below—it is not really working as it stands, because i'm using curl to address a local server which is not featured here. for those interested: this code is intended for CoffeeXeLaTeX, an attempt to make TeX scriptable with JavaScript (and, therefore, CoffeeScript). you cannot successfully run the code below unless you have a web server at the address specified; i realize that this dependency is wholly fortuitous for the effects i want to demonstrate, and i'm willing to rewrite the example so we can take the brackets out of M(W)E. that said, i'm sure that many of you will just exclaim Aha! beginner's mistake! when reading this code:

the code as it stands throws TeX capacity exceeded, sorry [text input levels=15], which would seem to indicate that TeX is recursively calling itself for too many times.

during the past endless hours, i have also managed to get a TeX capacity exceeded, sorry [input stack size=5000], and, significantly, that dreaded use of StrSubstitute doesn't match its definition errors, depending on exactly where i happened to put those magic \edef, \noexpand, \expandafter stuff.

i fully admit that i've been doing cargo cult programming, but then i've also taken out my vintage 1990 Taiwan edition of The TeX Book, i've tried to read http://www.tug.org/TUGboat/Articles/tb09-1/tb20bechtolsheim.pdf, i've searched the net so often Google wants to send me a golden customer card now. i've erased the experimental code and started over so i can post this question with some meaningful code; i could probably try and reconstruct some of the intermittent attempts.

what i've found out so far is that when TeX writes stuff to a file, it will postpone that writing because it assumes that "most of the time that is what you'll want" (not sure i can agree with that; why not write \postpone\write18 if you really want to have it work that way?). you can make it act now with \immediate, but since there aint no bait with no hook in TeX, this does not exactly what you'd think it should, it only 'works similar in most cases'.

as a programmer, i'm used to dealing with recursive function calling and delayed, asynchronous code execution in the event loop. curiously, this knowledge is of little help to me when TeX complains:

  • where do the recursive calls take place in the above code? i cannot spot them.

  • why do i sometimes get those stack size exceeded errors for innocuous input files when using \input(i believe)?

  • why does the presence of \noexpand / \expandafter break \write18?

  • what am i supposed to do against these symptoms (short of reading the implementation code down to the last expansion of every command inside the argument to `write18)?

  • is all this in some way related to the issue of robust / fragile commands and 'moveable arguments'?

i feel justified to ask this convoluted, huge question because my feeling after fiddling for some months with TeX (and managing to produce output, so it's worth the try) i feel that these are the convoluted, shady quarters of TeX where visitors don't like to go, where no easy transport is available, and where only the toughest can make it work at all. which about sums up my motivation for coming up with CoffeeXeLaTeX.

This issue is driving me nuts. Ever since the friendly and knowledgeable people here on tex SE have guided me to doing multiple string replacements the proper way, I've been trying to incorporate that knowledge into my code — to no available so far. The difficulties are:

  1. The string replacement facility uses \noexpandarg / \expandafter, which does not cooperate with \write18 all too well, and
  2. There is a nasty condition with \write18 and/or \input that causes (La)TeX to throw up a TeX capacity exceeded, sorry message.

Let's look at the M(W)E below — it is not really working as it stands, because I'm using curl to address a local server which is not featured here. For those who are interested: This code is intended for CoffeeXeLaTeX, an attempt to make TeX scriptable with JavaScript (and, therefore, CoffeeScript). You cannot successfully run the code below unless you have a web server at the address specified; I realize that this dependency is wholly fortuitous for the effects I want to demonstrate, and I'm willing to rewrite the example so we can take the brackets out of M(W)E. That said, I'm sure that many of you will just exclaim "Aha! Beginner's mistake!" when reading this code:

The code as it stands throws TeX capacity exceeded, sorry [text input levels=15], which would seem to indicate that TeX is recursively calling itself for too many times.

During the past endless hours, I have also managed to get a TeX capacity exceeded, sorry [input stack size=5000], and, significantly, that dreaded use of StrSubstitute doesn't match its definition errors, depending on exactly where I happened to put those magic \edef, \noexpand, \expandafter stuff.

I fully admit that I was doing cargo cult programming, but then I also took out my vintage 1990 Taiwan edition of The TeX Book. I read Bechtolsheim, I searched the internet so often Google wants to send me a golden customer card now. I erased the experimental code and started over so I can post this question with some meaningful code; I could probably try and reconstruct some of the intermittent attempts.

What I found out so far is that when TeX writes stuff to a file, it will postpone that writing because it assumes that "most of the time that is what you'll want" (not sure I can agree with that; why not write \postpone\write18 if you really want to have it work that way?). You can make it act now with \immediate, but since there aint no bait with no hook in TeX, this does not exactly what you'd think it should, it only 'works similar in most cases'.

As a programmer, I'm used to dealing with recursive function calling and delayed, asynchronous code execution in the event loop. Curiously, this knowledge is of little help to me when TeX complains:

  • Where do the recursive calls take place in the above code? I cannot spot them.

  • Why do i sometimes get those stack size exceeded errors for innocuous input files when using \input(i believe)?

  • Why does the presence of \noexpand / \expandafter break \write18?

  • What am I supposed to do against these symptoms (short of reading the implementation code down to the last expansion of every command inside the argument to write18)?

  • Is all this in some way related to the issue of robust / fragile commands and 'moveable arguments'?

I feel justified to ask this convoluted, huge question because my feeling after fiddling for some months with TeX (and managing to produce output, so it's worth the try) I feel that these are the convoluted, shady quarters of TeX where visitors don't like to go, where no easy transport is available, and where only the toughest can make it work at all. Which about sums up my motivation for coming up with CoffeeXeLaTeX.

Source Link
flow
  • 1.8k
  • 12
  • 26

How to deal with macro expansion and 'TeX capacity exceeded' when using write18?

this thing is driving me nuts. ever since the friendly and knowledgeable people here on tex SE have guided me to doing multiple string replacements the proper way, i've been trying to incorporate that knowledge into my code—to no avail so far. the difficulty is (1) that the string replacement facility uses \noexpandarg / \expandafter, which does not cooperate with \write18 all too well, and (2) there is a nasty condition with \write18 and/or \input that causes (La)TeX to throw up a TeX capacity exceeded, sorry message.

let's look at the M(W)E below—it is not really working as it stands, because i'm using curl to address a local server which is not featured here. for those interested: this code is intended for CoffeeXeLaTeX, an attempt to make TeX scriptable with JavaScript (and, therefore, CoffeeScript). you cannot successfully run the code below unless you have a web server at the address specified; i realize that this dependency is wholly fortuitous for the effects i want to demonstrate, and i'm willing to rewrite the example so we can take the brackets out of M(W)E. that said, i'm sure that many of you will just exclaim Aha! beginner's mistake! when reading this code:

\documentclass[a4paper]{article} \usepackage{xstring} \usepackage[usenames,dvipsnames,svgnames,table]{xcolor} % ----------------------------------------------------------------- % URL escaping simplified; % as per http://tex.stackexchange.com/questions/153215/how-to-do-multiple-string-replacements \newcommand{\urlescapestep}[2]{% \expandafter\StrSubstitute\expandafter{\x}{#1}{#2}[\x]% } \newcommand{\urlescape}[1]{{% \noexpandarg% \StrSubstitute{#1}{\%}{\%25}[\x]% \urlescapestep{/}{\%2F}% \urlescapestep{a}{A}% just for this test; imagine useful stuff here \x}} \newcommand{\escapeONE}[1]{*#1*} \newcommand{\escapeTWO}[1]{\StrSubstitute{#1}{a}{A}} % ----------------------------------------------------------------- % Execute a command with `\write18`: \newcommand{\CXtempoutroute}{/tmp/CXtempout.tex} \newcommand{\exec}[1]{% \immediate\write18{#1 > "\CXtempoutroute"}\input{\CXtempoutroute}} % ----------------------------------------------------------------- % `curl` commands using the string replacement commands: \newcommand{\curlPlain}[4]{% \exec{curl --silent --show-error #1 #2/#3#4}} \newcommand{\curlUrlescape}[4]{% \exec{curl --silent --show-error #1 #2/#3\urlescape{#4}}} \newcommand{\curlONE}[4]{% \exec{curl --silent --show-error #1 #2/#3\escapeONE{#4}}} \newcommand{\curlTWO}[4]{% \exec{curl --silent --show-error #1 #2/#3\escapeTWO{#4}}} % ----------------------------------------------------------------- \begin{document} First, let's show our three string escaping mechanisms all work under normal circumstances: \verb#\urlescape#: \urlescape{abc} \verb#\escapeONE#: \escapeONE{abc} \verb#\escapeTWO#: \escapeTWO{abc} These do work and turn \verb#abc# into \verb#Abc#, \verb#*abc*#, and \verb#Abc#, respectively. Now let's use the various \verb#curl*# methods: works: \verb#\curlPlain{}{127.0.0.1:8910}{foobar.tex/helo/}{abc}#: \curlPlain{}{127.0.0.1:8910}{foobar.tex/helo/}{abc} works: \verb#\curlONE{}{127.0.0.1:8910}{foobar.tex/helo/}{abc}#: \curlONE{}{127.0.0.1:8910}{foobar.tex/helo/}{abc} throws: \verb#\curlTWO{}{127.0.0.1:8910}{foobar.tex/helo/}{abc}#: \curlTWO{}{127.0.0.1:8910}{foobar.tex/helo/}{abc} \end{document} 

the code as it stands throws TeX capacity exceeded, sorry [text input levels=15], which would seem to indicate that TeX is recursively calling itself for too many times.

during the past endless hours, i have also managed to get a TeX capacity exceeded, sorry [input stack size=5000], and, significantly, that dreaded use of StrSubstitute doesn't match its definition errors, depending on exactly where i happened to put those magic \edef, \noexpand, \expandafter stuff.

i fully admit that i've been doing cargo cult programming, but then i've also taken out my vintage 1990 Taiwan edition of The TeX Book, i've tried to read http://www.tug.org/TUGboat/Articles/tb09-1/tb20bechtolsheim.pdf, i've searched the net so often Google wants to send me a golden customer card now. i've erased the experimental code and started over so i can post this question with some meaningful code; i could probably try and reconstruct some of the intermittent attempts.

what i've found out so far is that when TeX writes stuff to a file, it will postpone that writing because it assumes that "most of the time that is what you'll want" (not sure i can agree with that; why not write \postpone\write18 if you really want to have it work that way?). you can make it act now with \immediate, but since there aint no bait with no hook in TeX, this does not exactly what you'd think it should, it only 'works similar in most cases'.

as a programmer, i'm used to dealing with recursive function calling and delayed, asynchronous code execution in the event loop. curiously, this knowledge is of little help to me when TeX complains:

  • where do the recursive calls take place in the above code? i cannot spot them.

  • why do i sometimes get those stack size exceeded errors for innocuous input files when using \input(i believe)?

  • why does the presence of \noexpand / \expandafter break \write18?

  • what am i supposed to do against these symptoms (short of reading the implementation code down to the last expansion of every command inside the argument to `write18)?

  • is all this in some way related to the issue of robust / fragile commands and 'moveable arguments'?

i feel justified to ask this convoluted, huge question because my feeling after fiddling for some months with TeX (and managing to produce output, so it's worth the try) i feel that these are the convoluted, shady quarters of TeX where visitors don't like to go, where no easy transport is available, and where only the toughest can make it work at all. which about sums up my motivation for coming up with CoffeeXeLaTeX.