I have a list of elements in an outline, here is an example that is only 3 levels deep:
{
{{"1"},"Setup code"},
{{"1","1"},"Local variables"},
{{"1","2"},"Option variables"},
{{"1","3"},"Check for null Input"},
{{"2"},"Argument Logic"},
{{"2","1"},"X Spec"},
{{"2","2"},"One Dimensional Case"},
{{"2","2","1"},"Tick and Label Generation"},
{{"2","2","2"},"plot generation"},
{{"2","2","3"},"bin names generation"},
{{"2","2","4"},"bar chart generation"},
{{"2","3"},"Y Spec"}
}
And I'd like to transform it into a list of trees of the form {parentNode, {childNode1, childNode2, ...}}, and the nodes themselves are are like {{"1","2",...}, "label"}. For example, the above would become:
answer = {
{
{{"1"},"Setup code"},
{
{{"1","1"},"Local variables"},
{{"1","2"},"Option variables"},
{{"1","3"},"Check for null Input"}
}
},
{
{{"2"},"Argument Logic"},
{
{{"2","1"},"X Spec"},
{
{{"2","2"},"One Dimensional Case"},
{
{{"2","2","1"},"Tick and Label Generation"},
{{"2","2","2"},"plot generation"},
{{"2","2","3"},"bin names generation"},
{{"2","2","4"},"bar chart generation"}
}
},
{{"2","3"},"Y Spec"}
}
}
}
The reason being that once it is in this form, OpenerView[] could be used to make an interactive collapsable outline, for instance:
ToOutline[l_List] :=
Panel @ Grid[
Partition[
Panel /@ ToOutline1 /@ l //. {x_, list_List} :>
ToOutline1[{x, list}], 4, 4, 1, {}],
Alignment -> Top] /. {n : {__String}, s_String} :>
Row[{StringJoin @ Riffle[n, "."] , " ", s}];
ToOutline1[{x_, list_List}] :=
OpenerView[{x, Column[Panel /@ list]}, True]
ToOutline[answer]
generates
Motivation
This questions helps solve the problem of extracting comments from a file in Wolfram Workbench of the form (* tag:1:2:2:3... text... *)
. So for example if I had commented my function MyFun with a comment like (* MyFun:1:... text... *)
, I could extract them as follows:
CommentsToOutlineElements[filePath_, ID_] := Module[{allComments, commentsIDs, IDs, commentsStrings},
allComments = Cases[Import[filePath, "Comments"], _?(!StringFreeQ[#, ID]&)]
commentsIDs = StringSplit[#1, Whitespace][[1]]& /@ allComments;
commentsStrings = StringCases[#1, Shortest[s__]~~Whitespace~~Longest[c__] :> c][[1]]& /@ allComments;
IDs = Rest[StringSplit[#,":"]]& /@ commentsIDs;
Transpose @ {IDs, commentsStrings}
]
CommentsToOutlineElements["User/...", "MyFun"]
And then generate a nice outline of the function, as per this question.