12
$\begingroup$

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]
$\endgroup$
9
  • $\begingroup$ NotebookRead@Cells[] and work with CellExpression is the final choice I like. $\endgroup$ Jun 14, 2013 at 9:20
  • $\begingroup$ I suppose it would be nice if we can use regexes in the find/replace box... $\endgroup$ Jun 14, 2013 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$ Jun 15, 2013 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, 2015 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$ Apr 22, 2015 at 18:15

2 Answers 2

6
$\begingroup$
  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 :> 
               (NotebookFind[SelectedNotebook[], 
                ToString[target, InputForm]]; 
                NotebookWrite[SelectedNotebook[], ToString[r, InputForm]]; 
              target-> r), Infinity] &) /@ 
         If[ListQ[content], content, {content}]] // Flatten
    

Examples:

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

results: Style["test string", Bold]

Also you can do:

Foo[1]
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 :)

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

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)[__])] :=
 Block[
  {pNb, str, searchStr},
  pNb = NotebookGet[nb];
  str = First[
    FrontEndExecute[FrontEnd`ExportPacket[pNb, "PlainText"]]];
  searchStr =
   First@StringCases[str, rule];
  NotebookFind[nb, searchStr];
  SetSelectedNotebook[nb]
  ]

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 \
notebook*)
{1, {1, 1, 1}, 1, 1};
SelectionMove[EvaluationCell[], Before, CellContents];
pattSearch[nb, 
 "\n" ~~ Shortest[___] ~~ 
   x : Longest["{1," ~~ Except["\n"] ... ~~ "}"] ~~ Shortest[___] ~~ 
   "\n" :> x]

Notes

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.

$\endgroup$
5
  • $\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$ Jul 22, 2013 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$ Jul 22, 2013 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, 2015 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$ Apr 17, 2015 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$ Apr 17, 2015 at 7:48

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

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