# Collapse a section of a huge function

Is there an elegant way of hiding/collapsing/folding only a portion of a function? If functions could span multiple cells, this would have been straight-forward!

-
One thing I like about Mathematica is that stuff that "doesn't exist" can often be made exist quite easily. I think this is doable and useful to have (+1). Some kind of shortcut that wraps the selected boxes with an InterpretationBox with a button "+" that restores the original boxes for example. If I have time I'll try it and post if it works. Let's hope someone does it first and better than I can –  Rojo Mar 14 '12 at 22:57

The Mathematica Front End does not have this feature. Wolfram Workbench does though.

However, it is possible to collapse cell groups in notebooks by double clicking their brackets. This is useful.

For navigating functions, the Ctrl+. key combination (extend selection) is extremely useful.

-
CTRL-. was a nice find! –  my account_ram Mar 14 '12 at 20:29
+1. One of the reasons that FE does not have this seems to be that it is centered around Mathematica expressions, not lines of code (unlike WB). There is a certain impedance mismatch between the two. I think, IDEs are more oriented towards statement-based rather than expression-based languages. –  Leonid Shifrin Mar 14 '12 at 21:04
@my account_ram for completeness: You can also double/triple/n-click anywhere in a cell and get the same effect as with Ctrl-., i.e. selection of successive expression levels. –  Yves Klett Mar 15 '12 at 10:03

Also, for ease of use when working with sections etc., activate the "Show open/close icon for cell groups" checkbox under Edit->Preferences. This adds a toggle chevron on the left side.

The frontend encourages/enforces you to break long code passages into smaller parts, which is not always a bad idea, especially for testing and debugging (although debugging in Mathematica is something of a sore point when you are used to other systems). Still, a solution for in-cell partitioning would be nice-to-have.

There is also some option to format sections so that a click on their content toggles open/close instead of just the tiny triangle, but I can´t remember at the moment how that worked. Perhaps someone will chip in here.

-
Just noticed for the first time that the "Language" option, while set to German by default here does change exactly nothing and leaves everything at English. I think the last german language pack was for version 5? –  Yves Klett Mar 15 '12 at 9:05
Mathematica 8 does not have a German language pack, so that drop down menu doesn't really do anything for German. –  Searke Mar 15 '12 at 13:15

### Preamble

I have been toying with this feature as a part of some set of tools I have been working on (the code formatter in particular). The recent question prompted me to post a small illustration here. This is more to show how things might work than a complete solution, though.

I prefer to work with the code formatter, but you don't have to, if you don't feel like it:

Import["https://raw.github.com/lshifr/CodeFormatter/master/CodeFormatter.m"]


### Code

Here are some functions we will need:

prn = CellPrint[Cell[BoxData[#1], "Input"]] &;

ClearAll[codeFoldSetDelayed];
codeFoldSetDelayed[boxes_] :=
boxes /. {
r : RowBox[{lhs_, ":=", rhs_}] :>
Module[{lhsVar, rhsVar},
With[{var1 = ToString[lhsVar], var2 = ToString[rhsVar]},
MakeBoxes[#] &@OpenerView[{lhsVar, rhsVar}] //. {var1 :> lhs,
var2 :> r}
]]
};

ClearAll[codeFolded, codeFoldedSimple];
SetAttributes[{codeFolded, codeFoldedSimple}, HoldAll];
codeFoldedSimple[code_] := prn @ codeFoldSetDelayed @ MakeBoxes@code;
codeFolded[code_] :=
prn @ codeFoldSetDelayed @
CodeFormatterFullCodeFormat @
CodeFormatterCodeFormatterMakeBoxes @ code


In what follows, I will use codeFolded, which will also format - but if you don't want to use the formatter, you can use codeFoldedSimple instead. Both functions implement, in a very crude and primitive way, code-folding based on the OpenerView.

### Example

So, now, I take some random piece of code from one of my recent posts:

codeFolded[
ff[a_, b_, n_] :=
With[{fibF =
Function[code,
Block[{fib}, fib[m_] := fib[m] = fib[m - 1] + fib[m - 2];
code], HoldAll]},
fibF[fib[1] = a; fib[2] = b; fib[n]] +
fibF[fib[1] = 2 a; fib[2] = 2 b; fib[n]]]
]


I deliberately did not format the function. Now, the result looks like

When you click on the opener, the result looks like

First, it should be clear that the resulting cell is not supposed to be evaluatable. One can probably make it evaluatable in at least two ways: either by using InterpretationBox, or by supplying some custom CellEvaluationFunction, which would assemble the original code correctly.

Next, the implementation above is just the proof of concept, nothing more. I am working on a more systematic and powerful version of this as a part of some larger set of tools on which I work (as a side project). So, hopefully, some time soon I will be able to say more.

One deeper reason why I connect this with the code formatter is that the pattern-matching based on boxes is fragile, so the proper way of doing this is via matching to the symbolic intermediate representation created by the formatter. Such functionality I call formatting annotations, and I do plan to include a general support for such annotations in the next versions of the formatter.

Finally, it may well be that this way of doing things is fundamentally flawed for reasons known to more knowledgable people than myself, since I am by far not an expert in FrontEnd.

-