10

From within the Kernel, it is possible to access a Cell's options using CurrentValue. For instance, in a Cell tagged {"Bob", "Frank"}, executing this

CurrentValue[CellTags]
(* {"Bob", "Frank"} *)

But, how would one go about accessing the options of the parent cell in the hierarchy?

One difficulty is that the Cell knows nothing about the CellGroup it finds itself in, so attacking the problem from that direction seems difficult. However, the current executing Notebook can be accessed via EvaluationNotebook, so traversing the tree from that direction seems plausible, if not efficient.

rcollyer
  • 33,976
  • 7
  • 92
  • 191
  • Do cell groups have options? Or you meant an inline cell executing in place accesing the containing cell's options? – Rojo Jun 07 '12 at 18:31
  • 1
    @Rojo not as I understand it. Running NotebookGet[EvaluationNotebook[]] shows the structure Cell[CellGroupData[{Cell[...], Cell[CellGroupData[...]]..},Open]] where the first Cell is the parent, and the subsequent ones are the child groups. The cells containing CellGroupData do not appear to have any options set, they just provide structure and probably formatting. – rcollyer Jun 07 '12 at 18:42
  • but try to write somehow a cell group with options set. I haven't succeeded so far. The first cell in the cell group seems to get all the options. NotebookPut@ Notebook@List@Cell[CellGroupData[{Cell["a"], Cell["b"]}], FontWeight->"Bold"] – Rojo Jun 07 '12 at 18:45
  • @Rojo right, that's why it is the parent Cell, and why I think the Cell around CellGroupData is just there for structure. – rcollyer Jun 07 '12 at 18:50
  • I think so too. Ugly anyway. But, assuming that that is true, is there any question left? – Rojo Jun 07 '12 at 18:54
  • @Rojo yes, for a given Cell give me its parent. – rcollyer Jun 07 '12 at 18:56
  • @Rojo Do that, and I think we can answer Mr.Wizard's question on setting a Context at a specific level of the hierarchy. – rcollyer Jun 07 '12 at 19:00
  • I have the hunch it's not possible to set that option, just like any other, at the cell group level. But I just saw his question and I think I have an alternative. Check in a min – Rojo Jun 07 '12 at 19:11
  • @Rojo I don't intend to set it on the parent cell, but on the executing cell. If I can march up the hierarchy, accessing the parent's options as I go, I can use CellProlog or CellEvaluationFunction to mimic the effect of CellContext -> CellGrouping at higher levels in the hierarchy. – rcollyer Jun 07 '12 at 19:21
  • Oh, ok, so something like SelectionMove[nb, All, CellGroup]; NotebookRead[nb]; and then somehow editing all cells in each group? Yeah, seems ugly – Rojo Jun 07 '12 at 19:25
  • @Rojo no, something more like: CellProlog:> Begin[ParentCell[CellContext]]. – rcollyer Jun 07 '12 at 19:27
  • @Rojo I'd like this to be generic enough that I can specify the option I'm searching for. A good option would be Recursive -> True which can return all of the tree, or just the first not set, depending on what you want, likely another option. :) – rcollyer Jun 07 '12 at 19:36
  • The thing is that we fall back to the part where cell groups don't have options, right? – Rojo Jun 07 '12 at 19:39
  • 1
    Is what you want just a matter of having CellContext->CellGroup at a higher level of cell group? If so, then perhaps you might find it easier to change the CellGroupingRules on the relevant styles to confine the context the way you want. The CellGroup setting stops at cells with grouping higher than "InputGrouping". So, for example, I tried setting the Subsubsection style to CellGroupingRules->{-10, "InputGrouping"} in a private stylesheet, and $Context now spans Subsubsection cells in that notebook. – John Fultz Jun 10 '12 at 07:28
  • @JohnFultz, I'm not sure I understood, in my tests that's also changing the actual grouping of the subsection cells; I couldn't, with that "InputGrouping", to get a Subsubsection automatically grouping as it would with "SectionGrouping". By the way, you know if there is a way to get CurrentValue[{"CounterValue", "someCounter"}] to work? Or some way to programatically get the counter value at the point in the notebook where it's being evaluated? (sorry about mistyping your name, I do that a lot, nothing personal hehe ) – Rojo Jun 10 '12 at 17:40
  • @JohnFultz that destroys the grouping which is what I would like to preserve. Also, while my immediate purpose is solve Mr.Wizard's question, my question is more general than that. Having a cell able to tell where it lies in the hierarchy is potentially very powerful. – rcollyer Jun 11 '12 at 01:18

1 Answers1

4

Here's one way that seems to work.

parentcell[] := Module[{cellstyle, nb},
  nb = EvaluationNotebook[];
  SelectionMove[nb, All, EvaluationCell]; 
  firstcell[nb];       
  cellstyle = NotebookRead[nb][[2]];

  (* input cell may be grouped with output cell, ignore as parent *)
  If[cellstyle == "Input",
    SelectionMove[nb, All, CellGroup];
    firstcell[nb]
  ]
]

where firstcell goes to the first cell of the cellgroup

firstcell[nb_] := (SelectionMove[nb, All, CellGroup];
  SelectionMove[nb, Before, CellGroup];
  SelectionMove[nb, Next, Cell])

Since parentcell simply sets the notebook selection to the desired cell, one can access it's options using CurrentValue, e.g.:

parentcell[]; 
CurrentValue[NotebookSelection[EvaluationNotebook[]], CellTags]

This function can also be modified to go up until it hits a specified level in the cell grouping hierarchy (e.g., "Section"). This version currently does not terminate unless it finds a cell with the specified style.

parentcell[style_String] := Module[{nb},
  nb = EvaluationNotebook[];
  SelectionMove[nb, All, EvaluationCell]; 
  firstcell[nb];

  While[NotebookRead[nb][[2]] =!= style,
   SelectionMove[nb, All, CellGroup];
   firstcell[nb]
  ]
]

Finally, these functions have slightly strange behavior when used in cells with no hierarchy (except in/out grouping). The selection will end up either at the input cell or the first cell in the notebook.

dws
  • 801
  • 8
  • 9