14
$\begingroup$

Frequently I'm working on a function that's at the top of my notebook in a "functions" section, but I'm looking at the output of it in a lower "body" section of the notebook. When I want to edit the function, I have to scroll all the way to the top, and locate it out of maybe 40 functions in that section.

It would be really handy if there was a way for Mathematica to automatically make it so if I'm in the "body" section, looking at the output of my function, if I do something like Ctrl + click the function's name, it brings me to where the function is.

Is there some way to do this easily? Thank you!

$\endgroup$
2
  • $\begingroup$ +1, good question. I would think that the rollover feature could be used to point to the function definition in the same notebook. Just as rolling over (say) Product gives you a chance to go to its definition, rolling over MyFunction could send you to its defining cell. $\endgroup$ Commented May 4, 2016 at 17:52
  • $\begingroup$ There is a menu which does this in .wl .m files. So you may consider writing definitions there. Otherwise you can go to the top and Ctrl+F $\endgroup$
    – Kuba
    Commented May 4, 2016 at 18:21

4 Answers 4

12
$\begingroup$

If the first appearance of the Symbol in the Notebook is the definition, or close enough to the definition to be convenient, you could use the following Palette button to find that first appearance for whatever token the cursor is within.

With[{nb := SelectedNotebook[]},
  DynamicModule[{token},
    Button["Find First",
      SelectionMove[nb, All, Word];
      token = NotebookRead @ nb;
      SelectionMove[nb, Before, Notebook];
      NotebookFind[nb, token]
    ]
  ] // CreatePalette
]

For more control you can add a Cell Tag that is identical to the function name to the cell that contains the definition, then use this Palette button to jump to that specific Cell:

With[{nb := SelectedNotebook[]},
  DynamicModule[{token},
    Button["Jump to Tag",
      SelectionMove[nb, All, Word];
      token = NotebookRead @ nb;
      SelectionMove[nb, Before, Notebook];
      NotebookFind[nb, token, Next, CellTags]
    ]
  ] // CreatePalette
]
$\endgroup$
2
  • 1
    $\begingroup$ Sorry I couldn't give you +2. $\endgroup$ Commented May 4, 2016 at 19:09
  • $\begingroup$ @FredKline lol -- thanks :-) $\endgroup$
    – Mr.Wizard
    Commented May 4, 2016 at 19:09
5
$\begingroup$

Similar approach to Mr.Wizard's but searching only code and input cells. Put that procedure inside joker.m file, as described in 72914 or as a procedure for Button in a Palette.

Module[{name, nb},
 nb = InputNotebook[];
 Label["readName"];
 name = NotebookRead[nb];
 If[name === {},
  FrontEndExecute@FrontEndToken[nb, "ExpandSelection"]; 
  Goto["readName"]
  ];
 (
    SelectionMove[#, Before, CellContents, AutoScroll -> False]; 
    If[NotebookFind[#, name, WordSearch -> True] =!= $Failed, Abort[]]
    ) & /@ Cells[nb, CellStyle -> {"Input", "Code"}]
 ]
$\endgroup$
3
$\begingroup$

Another way which makes a docked cell (much like a package notebook):

SetOptions[EvaluationNotebook[],DockedCells -> 
  Cell[
   BoxData@
   ToBoxes@
   DynamicModule[{cell$},
     Grid[{
      {Dynamic@ActionMenu["Functions",
        (#[[1]]:>(SelectionMove[EvaluationNotebook[],Before,Notebook,AutoScroll->False];
              SelectionMove[EvaluationNotebook[],Next,Cell,#[[2]],AutoScroll->True];
              FrontEndTokenExecute[FrontEndToken[EvaluationNotebook[],"OpenSelectionParents"]]))&/@
           Thread[
             {RawBoxes@*First@*First/@Extract[cell$,#],First/@#}&@
               Position[cell$,
                 RowBox[{Except[RowBox[{_,"[",RowBox[{"[",_,"]"}],"]"}],
                         RowBox[{_,"[","]"}]|RowBox[{_,"[",_,"]"}]|RowBox[{_,"[",s_String/;StringMatchQ[s,Whitespace],_,s_String/;StringMatchQ[s,Whitespace],"]"}]|RowBox[{RowBox[{_,"[",_,"]"}],"/;",___}]],
                         ___,"="|":="|"^:="|"^=",___}]|RowBox[{_,___,":="|"^:=",___}]|RowBox[{_,___,"="|":="|"^:="|"^=",RowBox[{"Function"|"Compile",___}]}]
                        ]
                 ],
              BaselinePosition->Center, MenuAppearance-> "Dropdown"],
          Button["Update",Dynamic[cell$ = NotebookRead[Cells[ButtonNotebook[]]]]]
        }}]],"SystemDockedCell"]]
$\endgroup$
3
$\begingroup$

I augmented Mr.Wizard's answer with a "Back" button:

With[{nb:=SelectedNotebook[]},
    DynamicModule[{token,backcell},
        Column[{
            Button["Find First",

            (* Expand selection to whole word *)
            SelectionMove[nb,All,Word];

            (* Create notebook sub-object based on current selection *)
            token=NotebookRead@nb;

            (* Expand selection to whole cell *)
            SelectionMove[nb,All,Cell];

            (* Remember where we came from *)
            backcell=NotebookRead@nb;

            (* Move cursor to top of file *)
            SelectionMove[nb,Before,Notebook];

            (* Move cursor to where sub-object 'token' appears *)
            NotebookFind[nb,token]],

            Button["Back",NotebookFind[nb,backcell]]
        }]]//CreatePalette]
$\endgroup$
1
  • $\begingroup$ Nice idea! +1 :-) $\endgroup$
    – Mr.Wizard
    Commented May 11, 2016 at 20:45

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.