3

I would like to define an environment which "parses" its content and changes it before displaying it.

An additional difficulty comes because I also need to replace whitespaces. The more flexibility in the replacement tools (regex would be ideal) the better.

I'm aware or xstring's StrSubstitute and this solution here: How to replace text. Yet they do not help so far.

Example:

\begin{changecontent}
some text 
 some text 
  some text 
\end{changecontent}

Simplified, what I would like to get from that is something like:

\command\\
~\command\\
~~\command\\

which then would compile into something where \command would be expanded to whatever it defined to before. This is an arbitrary example. It is not really crucial what this command is. It could be defined in the preamble, e.g. it could draw a tikz square or just expand to simple text.

The crucial steps are:

  1. keep spaces and newlines until the content is parsed, so that they can be used for the replacing part
  2. do replacements: in regex that would be in this example:

    • ^.* => \command\\
    • ^\s.* => ~\command\\
    • ^\s\s.* => ~~\command\\
  3. expand the result and output

There are no restrictions in terms of how this should be implemented.

Is this asking to much of *TeX?

sheß
  • 3,622
  • 3
    Can you add some more bits of explanation? How and where should \commandx and \commandy be defined? – egreg Sep 05 '15 at 10:29
  • Thank you for asking. I tried to clarify it a bit. Please let me know if crucial bits are still missing. – sheß Sep 05 '15 at 10:46
  • @anyone, feel free to edit my post if I'm using the wrong expressions for TeX (in particular "expansion" "interpret" etc) – sheß Sep 05 '15 at 10:53
  • What about cases of " some text" and " some text" (two and one leading spaces) that are not located at the start of a line? Should the spaces be preserved too? – Mico Sep 05 '15 at 11:13
  • The leading spaces should be somehow recognized. In the example above they're replace by "~". So yes, if that's what you mean by "preserved". – sheß Sep 05 '15 at 11:18

1 Answers1

2

Here's a LuaLaTeX-based solution. It defines an environment called changecontent. Within instances of this environment (and only within instances of this environment), all instances of the string "some text" are changed to \somecommand\par; and, all singleton or doubleton spaces that precede this string are converted to ~ (unbreakable spaces). If there are more than two spaces ahead of an instance of "some text", only the final two spaces are converted to ~. The Lua function that performs the substitutions is assigned to the process_input_buffer callback, which operates on the input stream at a very early stage, before the "eyes", "mouth", and "stomach" of TeX get to do anything.

For the code below, I've set up a dummy definition for \somecommand. You, should, of course, provide the real definition of \somecommand in the preamble of your document.

enter image description here

\documentclass{article}
\usepackage{luacode,luatexbase}

%% Lua-side code
\begin{luacode}
function sometexttocommand ( line )
    line = string.gsub ( line , "%s%ssome text", "~~\\somecommand\\par" )
    line = string.gsub ( line , "%ssome text",   "~\\somecommand\\par" )    
    line = string.gsub ( line , "some text",     "\\somecommand\\par" )
    return ( line )
end 
\end{luacode}

%% TeX-side code
\newenvironment{changecontext}{%
   \directlua{luatexbase.add_to_callback(
              "process_input_buffer",
              sometexttocommand, "sometexttocommand")}}{%
   \directlua{luatexbase.remove_from_callback(
              "process_input_buffer",
              "sometexttocommand")}}

% provide a dummy definition of "\somecommand"
\providecommand\somecommand{Hello World} 

\begin{document}
some text
 some text
  some text
   some text

\begin{changecontext}
some text
 some text
  some text
   some text
\end{changecontext}

some text
 some text
  some text
   some text

\end{document}
Mico
  • 506,678
  • Thanks for this! Somehow the environment delimiters (i.e. the "\end{changecontext}") are also passed to sometextcommand, which results in some undesired replacements happening there when the expressions match. Could this be avoided? – sheß Sep 05 '15 at 14:17
  • Not sure I fully understand your setup. (The problem you report encountering doesn't occur in my MWE, does it?) For sure, the name of the delimiting environment (e.g., changecontext) •must differ* from the search string used inside the environment. – Mico Sep 05 '15 at 14:52
  • No, you're right. Yout MWE does exactly what it's supposed to. It's more like a tiny follow up question regarding your implementation: Is there an easy/elegant way to have only the content of the environment parsed by sometextcommand – sheß Sep 05 '15 at 14:57
  • 1
    @sheß - Just noticed your new posting. The issue, then, was that the Lua function sometextcommand failed to cease running because LaTeX never terminated the changecontext environment. This problem arose because the backslash in \end{changecontext} was removed (inadvertently) by sometextcommand before LaTeX had a chance to process \end{changecontext}. One could "fix" this (indirectly!) by assigning sometextcommand to a callback that works at a later stage. However, by then LaTeX will have processed (i.e., deleted) the space characters at the start of the lines -- not acceptable. – Mico Sep 05 '15 at 20:30
  • Thanks for taking the time and writing such clear explanation. PS: I've been using your code here:http://tex.stackexchange.com/questions/249755/showing-nice-indentation-of-python-code – sheß Sep 05 '15 at 20:37