StringReplace adds "~~" to words with Tooltip
This is because the elements of wordsWithTooltips
aren't strings. If you convert to strings, there's no issue.
StringReplace[txt, #1 -> ToString[#2, TraditionalForm] & @@@ tls]
I prefer avoiding TraditionalForm
strings, e.g.,
ToString[Tooltip[x/y,stuff],TraditionalForm]//FullForm
(* "\!\(\*FormBox[TagBox[TooltipBox[FractionBox[\"x\", \"y\"], \"stuff\"],
Function[Annotation[Slot[1], stuff, \"Tooltip\"]]], TraditionalForm]\)" *)
Instead, I would use StringForm
. The simplest version would be:
indices = {"`1`", "`2`", "`3`"};
StringForm[
StringReplace[txt, Thread[Rule[words, indices]]],
Sequence @@ Thread[Tooltip[words, tooltips]]
]
(* StringForm["Good, `2`, `3`. Never let it rest. 'Til your `1` is `2` and your
`2` is `3`.", Tooltip["good", "good2"], Tooltip["better", "better2"],
Tooltip["best", "best2"]] *)
However, you wanted to use IgnoreCase
. The Tooltip
will have to be different for different cases, and a priori, you don't know how many versions with different cases there will be. So, the indices will have to be generated dynamically as the string is processed. To do this, I introduce a helper function:
toIndex[word_] := toIndex[word] = CompoundExpression[
Sow[ToLowerCase[word] /. Thread[Rule[words, tooltips]], word],
"`"<>ToString[i++]<>"`"
]
Then, I use this helper function to convert words into their indexed form:
Internal`InheritedBlock[{i=1, toIndex},
Apply[
StringForm[#1, Sequence@@#2]&,
Reap[
StringReplace[txt, x:Alternatives@@words :> toIndex[x], IgnoreCase->True],
_String,
Tooltip[#1, #2[[1]]]&
]
]
]
(* StringForm["`1`, `2`, `3`. Never let it rest. 'Til your `4` is `2` and your
`2` is `3`.", Tooltip["Good", "good2"], Tooltip["better", "better2"],
Tooltip["best", "best2"], Tooltip["good", "good2"]] *)
This question is closely related to:
- How to 'merge' a list like FromDigits, but with a mixture of numbers and symbols?
- Using subscript in a string
As Chip Hurst already explained your Tooltip
expressions need to be converted to strings if they are to be appended as strings. You could also display the expression as a Row
instead:
Row@*List @@ StringReplace[txt, Rule @@@ tls]
If that expression needs to be converted to a string it can be done en masse:
ToString[%, StandardForm];
% // Head
String