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$
  • $\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$ – Fred Kline May 4 '16 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 May 4 '16 at 18:21
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$
  • 1
    $\begingroup$ Sorry I couldn't give you +2. $\endgroup$ – Fred Kline May 4 '16 at 19:09
  • $\begingroup$ @FredKline lol -- thanks :-) $\endgroup$ – Mr.Wizard May 4 '16 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$

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$
  • $\begingroup$ Nice idea! +1 :-) $\endgroup$ – Mr.Wizard May 11 '16 at 20:45
2
$\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$

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.