4

I am trying to create an easier way to write math-formulas in tex for multiple assignments. At the current time, I am almost there. This example might not seem very intuitive, but I had to leave out a great deal to make it small enough.

What I am trying to accomplish in this example, is simply some string replacement. For every occurrence of string defined in \allvars, replace them with whatever \varprint{string for \allvars} outputs. However, I have messed up the expansion here, and have tried a few other ways, but I just don't quite understand really. The string-replacement works as expected, but I need StrSubstitute to rerun with its own output on the next index in allvars. Any help on this is greatly appreciated.

\documentclass[11pt]{article}
\usepackage{xinttools, xstring}
\newcommand{\allvars}{sideA,sideB,sideC}
\newcommand{\varPrint}[1]{%
great(#1)
} % just a command used in this example. in real document, a more advanced output is to be expected from this.
\newcommand{\matte}[1]{%
    \edef\mattetempB{#1}
        \xintFor ##1 in {\allvars}\do%
     {\def\mattetempB{%
        \StrSubstitute{\mattetempB}{##1}%
        {\varPrint{##1}}%
        }%
     }%
     \mattetemp
    }%


\begin{document}
\matte{sideA+sideB=sideC},\\

Would like to see something like the following:\\

great(sideA)+great(sideB)=great(sideC)\\

But only sees:\\

sideA+sideB=great(sideC) ,

\end{document}
Runar
  • 6,082
  • 2
    \StrSubstitute definitely doesn't work in \edef. – egreg Dec 18 '15 at 10:01
  • ok, thanks. I have just been trying different things on it. Do you know how to move forward? – Runar Dec 18 '15 at 10:10
  • 1
    To catch the output of \StrSubstitute, you'll need to use the optional output parameter; something like \StrSubstitute{}{}{}[\OutputMacro]. Then afterwards you can use \def\mattetemp{\OutputMacro}. – Tom Bombadil Dec 18 '15 at 10:13
  • So you sort of reinventing the wheel? The easiest way to write TeX formulas is to write them as regular TeX code. – georgmierau Dec 18 '15 at 10:14
  • I should probably explain this better. I have stored some variables which holds how a variable should be printed, what it's value is, what kind of unit it is, and any extra options passed to siunitx. So, instead of writing: a_{car}=\frac{v_car}{t_car}, a_{car}=\frac{\SI{20}{metre\per\second}}{\SI{20}{seconds}}, I would just write \matte{acar=\frac{vcar}{tcar}, and it would expand to what I first wrote here. – Runar Dec 18 '15 at 10:18
  • @TomBombadil, That solves my problem. If you add it as an answer I'll mark it. Thanks – Runar Dec 18 '15 at 10:31
  • 1
    You're welcome! As I was struggeling a lot with this myself a few years back I'm glad to be able to spare you the trouble. – Tom Bombadil Dec 18 '15 at 10:42
  • minor point, not addressing your problem: you have a spurious end of line space after \edef\mattetempB{#1}, should be \edef\mattetempB{#1}%. On the other hand the % after \do can be removed. Spaces after control words are removed by TeX. –  Dec 18 '15 at 11:51

2 Answers2

3

The macros in the xstring package output text directly, which can't be used to feed into other macros. To return text that can be used for further manipulation you can use the trailing optional parameter which will save the output in the macro specified there. So instead of something like

\newcommand{\MySubst}{\StrSubstitute{abracadabra}{a}{o}}

you'll first need to save the output and do your definition afterwards:

\StrSubstitute{abracadabra}{a}{o}[\MyOutput]
\newcommand{\MySubst}{\MyOutput}
Tom Bombadil
  • 40,123
  • Thanks, I really should have thought of that. I was looking at that very piece in the documentation for xstring, but I was too focused on expansion. – Runar Dec 18 '15 at 11:02
  • 1
    I know what you mean. When I was struggling with this I kept wondering why it wasn't working when it obviousely put out the expected text. Especially bad if you're used to just using a function to return the argument of another function as you would do in e.g. Python. – Tom Bombadil Dec 18 '15 at 11:26
  • perhaps using \edef{\MySubst}{\MyOutput} (or xdef for global scope) could be envisioned else any later use of \StrSubstitute will have to use something else than \MyOutput else will overwrite it, hence also \MySubst will change. –  Dec 18 '15 at 11:48
  • during testing you can use \typeout{\meaning\foo}, or even \ttfamily \meaning\foo to see what \foo really looks like (and not only its textual output). –  Dec 18 '15 at 11:54
2

Here's a more generic version, based on l3regex.

\documentclass{article}
\usepackage{xparse,l3regex,siunitx}

\ExplSyntaxOn

\prop_new:N \g_runart_variables_prop
\tl_new:N \l__runart_variables_matte_tl
\tl_new:N \l__runart_variables_item_tl

\NewDocumentCommand{\definevariable}{mm}
 { % #1 is the name, #2 is the formatting
  \prop_gput:Nnn \g_runart_variables_prop { #1 } { #2 }
 }

\NewDocumentCommand{\removevariable}{m}
 { % #1 is the name
  \prop_gremove:Nn \g_runart_variables_prop { #1 }
 }

\NewDocumentCommand{\matte}{m}
 { % #1 is the expression to output
  \tl_set:Nn \l__runart_variables_matte_tl { #1 }
  \prop_map_inline:Nn \g_runart_variables_prop
   {
    \tl_set:Nn \l__runart_variables_item_tl { ##2 }
    \regex_replace_all:nnN
     { ##1 }
     { \u{l__runart_variables_item_tl} }
     \l__runart_variables_matte_tl
   }
  \tl_use:N \l__runart_variables_matte_tl
 }

\cs_new_protected:Nn \runart_variable_use:n
 {
  \prop_item:Nn \g_runart_variables_prop { #1 }
 }
\ExplSyntaxOff

\definevariable{a_car}{\SI{20}{\metre\per\second}}
\definevariable{v_car}{\SI{40}{\metre}}
\definevariable{t_car}{\SI{2}{\second}}

\begin{document}

\[
\matte{
  a_car=\frac{v_car}{t_car}
}
\]

\end{document}

enter image description here

egreg
  • 1,121,712
  • This does almost all I am trying to do. I do have some problems using it in my script. Any hints for what to change? I currently define vars this way:

    \NewDocumentCommand{\varSet}{mmmmo} { \prop_gclear_new:c { g_giacomo_var_#1_prop } \prop_gput:cnx { g_giacomo_var_#1_prop } { value } { #2 } \prop_gput:cnn { g_giacomo_var_#1_prop } { unit } { #3 } \prop_gput:cnn { g_giacomo_var_#1_prop } { name } { #4 } }

    – Runar Dec 18 '15 at 12:08
  • 1
    @runartrollet Please, make a new question linking to this one. The setting is much more complicated than you showed here. – egreg Dec 18 '15 at 12:34
  • I agree. Here is the new question. http://tex.stackexchange.com/questions/283760/expandable-math – Runar Dec 18 '15 at 12:54