I was thinking if there is something like Find and Replace (Crtl+F) functionality adapted to work with patterns.

Probably not, but it seems possible to create this with some effort and skills in low-level-notebook-programming.

My question is: if there is not such functionality bulid in, maybe someone have worked on this?

Example of what I'm thinking it should be able to do:

Text["test string"]

enter image description here

Style["test string", Bold]
  • $\begingroup$ NotebookRead@Cells[] and work with CellExpression is the final choice I like. $\endgroup$ – HyperGroups Jun 14 '13 at 9:20
  • $\begingroup$ I suppose it would be nice if we can use regexes in the find/replace box... $\endgroup$ – J. M.'s ennui Jun 14 '13 at 14:23
  • 1
    $\begingroup$ It doesn't exactly answer your question, but you probably should know that such functionality is available in the Wolfram Workbench, but restricted to the package files if I remember correctly. It will also search a whole directory, if you want. As that is basically a Mathematica plugin for eclipse, you'll also have access to a search with regexes. $\endgroup$ – Albert Retey Jun 15 '13 at 10:45
  • $\begingroup$ @Jacob I appreciate the attention you are bringing to this question. I have no answer however. Hopefully much like "multi undo" we will some day see this included in Mathematica itself. $\endgroup$ – Mr.Wizard Apr 22 '15 at 16:51
  • $\begingroup$ @Mr.Wizard that would be quite nice indeed. I remember I had a few ideas for improving my own function. One thing is that because we can only search on one line, we can always use a rule like this: "\n*"~~patt~~"*\n" :> patt. A user then always only has to specify a pattern and does not have to keep StringCases in mind when entering input. Anyway thank you for commenting, such a comment provides a lot of motivation for me :). $\endgroup$ – Jacob Akkerboom Apr 22 '15 at 18:15
  1. Parse cell objects to box data.
  2. Use MakeExpression[boxes] to convert boxes to Unevaluated standard form expressions.
  3. Find expressions that match the pattern p_.
  4. Use ToString[expr, InputForm]] to convert the target expressions to strings in InputForm.
  5. Find those strings in notebook and replace them to what you want (r_).

     NBReplace[p_, r_] := 
       Cases[NotebookRead /@ Cells[], Cell[BoxData[content_], "Input", ___] :> 
         (Cases[MakeExpression[#, StandardForm], 
            target: p :> 
                ToString[target, InputForm]]; 
                NotebookWrite[SelectedNotebook[], ToString[r, InputForm]]; 
              target-> r), Infinity] &) /@ 
         If[ListQ[content], content, {content}]] // Flatten


Style["test string", Bold]
NBReplace[Text[x_String], Style[x, Bold]]

results: Style["test string", Bold]

Also you can do:

NBReplace[Foo[x_Integer], Bar[x + 5]]

results: Bar[6]

If you want to bind to a custom shortcut, see this: https://stackoverflow.com/questions/4209405/customizing-mathematica-shortcuts
Hope it makes sense, cheers :)

  • $\begingroup$ Thank You for those remarks. This link is also correct anticipation of my needs. :) $\endgroup$ – Kuba Jun 14 '13 at 22:17

I figured out a way to "get the string". It turned out that information was available on this site. This now works

pattSearch[nb_, patt_] :=
 pattSearch[nb, x : patt :> x]
pattSearch[nb_, rule : ((Rule | RuleDelayed)[__])] :=
  {pNb, str, searchStr},
  pNb = NotebookGet[nb];
  str = First[
    FrontEndExecute[FrontEnd`ExportPacket[pNb, "PlainText"]]];
  searchStr =
   First@StringCases[str, rule];
  NotebookFind[nb, searchStr];

Example of use

{1, 1};
nb = EvaluationNotebook[];
SelectionMove[nb, Before, Notebook];
pattSearch[nb, Shortest["{1," ~~ ___ ~~ "}"]]

In the example the expression {1,1} is selected.

Another example, with rules

(*This comment makes sure the line below is not at the start of the \
{1, {1, 1, 1}, 1, 1};
SelectionMove[EvaluationCell[], Before, CellContents];
 "\n" ~~ Shortest[___] ~~ 
   x : Longest["{1," ~~ Except["\n"] ... ~~ "}"] ~~ Shortest[___] ~~ 
   "\n" :> x]


Remember to use Shortest, or to handle newlines yourself. We cannot search over multiple lines. I have set it up in terms of rules, so that you can manually search on a line, like in the second example. The second example is ugly in that the pattern does not account for the possibility that the expression is at the start of the notebook.

It would be really nice if we could cycle through the expressions found by StringCases. Also using First when we may find no pattern is not nice. Maybe I will try make this nicer.

  • $\begingroup$ @Kuba I was hoping my recent answer would help with this, but on closer look there is still a big gap to fill. Oh well :) $\endgroup$ – Jacob Akkerboom Jul 22 '13 at 9:02
  • $\begingroup$ @Kuba oh there is no new version :). Just this remark, I felt things were related. Hope to catch you later. $\endgroup$ – Jacob Akkerboom Jul 22 '13 at 9:06
  • $\begingroup$ And what now, you can't give this bounty yourself :) And I would like to add something to your answer rather than make new since I don't have time to polish this now. p.s. get you mail **** together Jacob! :) $\endgroup$ – Kuba Apr 17 '15 at 7:33
  • $\begingroup$ @Kuba ahhh, sorry about missing your mail Kuba. My gmail is a total mess right now, ever since I subscribed to some overly active github repository :P. (temporary message) $\endgroup$ – Jacob Akkerboom Apr 17 '15 at 7:48
  • $\begingroup$ Also I don't want the bounty myself, I want to get a rep of 6667 :). Feel free to edit my answer! It is fine if my rep vanishes. $\endgroup$ – Jacob Akkerboom Apr 17 '15 at 7:48

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.