How to get a regex search-replace yield markup rather than plain text

This is probably simple, but I’m not getting it right.

What I want is for the following to yield

  • Water: H2O
  • Aspirin: C9H8O4
\define digits() \d+
\define replacement() <sub>$&</sub>

\define formula(form)
<$text text={{{ [<__form__>search-replace:g:regexp<digits>,<replacement>] }}} />
\end

* Water: <<formula "H2O">>
* Aspirin: <<formula "C9H8O4">>

But instead it yields

  • Water: H<sub>2</sub>O
  • Aspirin: C<sub>9</sub>H<sub>8</sub>O<sub>4</sub>

In other words, it doesn’t treat the output as HTML but as raw text for the output.

What am I doing wrong?

This would seem to be a case where $wikify is appropriate.

\define formula(form)
<$wikify name=out mode=inline output=html
   text={{{ [<__form__>search-replace:g:regexp<digits>,<replacement>] }}}>
<<out>>
\end

Note that the usual concern about $wikify is that it can have significant overhead.
However, in the above use-case, it isn’t being called multiple times within a $list widget loop, nor is it processing overly complex wikitext syntax, so the overhead is reasonably minimal.

-e

4 Likes
\define digits() \d+
\define replacement() <sub>$&</sub>

\define formula(form)
<$let result={{{ [[$form$]search-replace:g:regexp<digits>,<replacement>] }}}>
<<result>>
</$let>
\end

The TEXT widget is correctly outputting plain text, try the above revision instead.

4 Likes

Thank you both!

I really should have figured out either version. I think perhaps I should quit now and go to bed early.

Wow, wonderful!
Using the provided macros, I can have a small tool to display chemical formula very easy in TiddlyWiki!
I should steal this!

I am wondering how using this approch one can have

<<formula "2H2+O2 -> 2H2O">> to produce

2H2 + O2 → 2H2O

Of course. I’m greatly in your debt for all the wonderful tools you offer, as well as for all your help in this forum. If I can give a little back, I’m very happy!

Sure. It will just take a slightly more sophisticated regular expression, plus another search-replace for the arrow:

\define digits() ([A-Za-z])(\d+)
\define replacement() $1<sub>$2</sub>

\define formula(form)
\whitespace trim
<$let tv-wikilinks="no">
<$wikify name=out mode=inline output=html
   text={{{ [<__form__>search-replace:g:regexp<digits>,<replacement>search-replace:g:[->],[→]] }}}>
<<out>>
\end

With it:

* Water: <<formula "H2O">>
* Aspirin: <<formula "C9H8O4" >>
* Salt: <<formula "NaCl">>
* First Equation: <<formula "2H2+O2 -> 2H2O">>
* Second Equation: <<formula "SiCl4 + 4H2O → H4SiO4 + 4HCl" >>

yields:

  • Water: H2O
  • Aspirin: C9H8O4
  • Salt: NaCl
  • First Equation: 2H2+O2 → 2H2O
  • Second Equation: SiCl4 + 4H2O → H4SiO4 + 4HCl

macros_formula.json (493 Bytes)

1 Like

@Scott_Sauyet,

I notice in your latest response to @Mohammad, that you are using $wikify in your <<formula>> macro.

However, @Brian_Radspinner’s code (which you marked as “solution”) is more efficient, since it avoid using $wikify.

Combining his solution with the tweaks I suggested for handling whitespace and wikilinks, the best <<formula>> macro definition would be:

\define formula(form)
\define tv-wikilinks() no
\define digits() ([A-Za-z])(\d+)
\define replacement() $1<sub>$2</sub>
\whitespace trim
<$let out={{{ [<__form__>search-replace:g:regexp<digits>,<replacement>search-replace:g:[->],[→]] }}}>
<<out>>
\end

Note also how the formula(form) macro definition contains some single-line LOCAL “utility” macro definitions for tv-wikilinks(), digits(), and replacement(). This allows you to make the <<formula>> macro global (by tagging the tiddler with $:/tags/Macro, while still using those utility macros internally, without adding any clutter to the global macro namespace.

-e

1 Like

When I had the other problem (solved by <$macrocall>), I was struggling and playing with all sorts of things. When this was finally working, it was a <$wikify> version that was in place. I will switch this over and update my previous post with a more efficient version.

Thank you for taking the time to teach here!

– Scott

1 Like

One last tweak… instead of using “local defines”, the code could be somewhat more compact by using $let, like this;

\define formula(form)
\whitespace trim
<$let tv-wikilinks=no digits="([A-Za-z])(\d+)" replacement="$1<sub>$2</sub>"
   out={{{ [<__form__>search-replace:g:regexp<digits>,<replacement>search-replace:g:[->],[→]] }}}>
<<out>>
\end

You are most welcome!

Much appreciated! Thank you.

Wow, now with less than 0.5kB of code I have chemical formula and stoichiometry equations in my wiki!

Thank you Eric, yes this is small and efficient!

Ah, yes, of course. I should be doing that more everywhere. I’m always bemoaning the lack of true let bindings in JS; I really should be using them when they’re available!

This is now quite nice. Thank you very much for your help!

macros_formula.json (435 Bytes)

I’m curious whether something I’m often doing for macros is common and whether there are good reasons not to do it. My actual version of that macro tiddler looks something like this:

\define formula(form)
\whitespace trim
<$let tv-wikilinks=no digits="([A-Za-z])(\d+)" replacement="$1<sub>$2</sub>"
   out={{{ [<__form__>search-replace:g:regexp<digits>,<replacement>search-replace:g:[->],[→]] }}}>
<<out>>
</$let>
\end


* Water: <<formula "H2O">>
* Aspirin: <<formula "C9H8O4" >>
* Salt: <<formula "NaCl">>
* First Equation: <<formula "2H2+O2 -> 2H2O">>
* Second Equation: <<formula "SiCl4 + 4H2O → H4SiO4 + 4HCl" >>

That is, I keep test cases inside the same tiddler that holds my macro, and use it to check whether it’s still working on save. (I rarely use preview mode.) Is there any strong reason to avoid this, outside the obvious concern about clutter and wiki size?

So this is what I will probably keep around: macros_formula_with_demos.json (653 Bytes)

1 Like

I have heard in the past that if using global macros the content after the definitions is ignored. This can be tested with the getvariable operator (the content is gone) because macros are just variables. But if you stop to think the define{s} are setting a macro/variable, no other part of the tiddler could be involved, unless it were transcluded.

Also consider choosing between the following tags;

  • System Tag: $:/tags/Macro
  • System Tag: $:/tags/Macro/View
  • System Tag: $:/tags/Macro/View/Body

Interesting thread :nerd_face:

I’m pretty sure that’s the case. The main question was whether there was a good reason for tiddlers tagged $:/tags/Macro to contain only macro definitions. The answer seems to be that no, there is no reason for that.

I had not heard of the latter two until I recently saw you mention them in another thread. If I read their docs correctly, these are mainly meant to avoid cluttering up the global namespace with things that only need to be used in the view/view-body. Useful I guess, and perhaps they have some minor performance benefits, and as most of my work is done in there, I supposed I could choose that, but I wonder if it makes sense to use these for generic tools like the <<formula>> above, especially in a plugin.