observablehq / feedback

Customer submitted bugs and feature requests
42 stars 3 forks source link

Grab a notebook cell reference specified by a string #485

Open galopin opened 2 years ago

galopin commented 2 years ago

Is your feature request related to a problem? Please describe.

Observable is different: it functions like a spreadsheet, where cells (like formulas) run automatically whenever their referenced values change. Observable runs cells independently of their order in the notebook, giving you the flexibility to arrange your cells in whatever order you prefer for literate programming.

But it ain't a spreadsheet if you try to push the analogy further. In a spreadsheet, one can reference any cell whether it's explicitly named or not. Currently, Observable functions more or less the same as Airtable.

Sadly, there is currently no easy way to reference any notebook cell by string (or by using A1- & R1C1-style notation) as in Google Sheets or Excel… See Return a cell reference specified by a string and Return the reference specified by a text string.

PHP developers can also reference by string any available variable in global scope via $GLOBALS — whether it's good or bad practice is a matter of opinion…

It is currently undoable in Observable without resorting to hacks :-/

This is kind of strange considering there is this invaluable Minimap feature, which lists all the cells in a notebook and their dependencies. I understand you need to compartmentalize & secure things but I see no point in blocking a notebook from accessing its own cells programmatically ⁉️

Describe the solution you'd like

I'd like being able to reference a cell dynamically — whether it's explicitly named or not — within another notebook cell without having to modify this notebook cell snippet of code.

One could put the built-in JavaScript object Reflect to good use:

… where ʘ (or __O__, or another aptonymic variable) would be a notebook property referencing all notebook cells.

Describe alternatives you've considered

For example, I was able to bend Observable to my needs using the following snippet:

viewof format = Inputs.radio(
  ((data) =>
    d3.group(
      Object.entries(data).map(([k, v]) => ({
        handle:
          0 === k.indexOf("json")
            ? k.toUpperCase()
            : "text" === k
            ? "plain " + k
            : k,
        data: Reflect.get(data, k)
      })),
      (d) => d.handle
    ))({ CSV: d3.csvFormat(rules), json, jsonl, text }),
  {
    label: "Format",
    key: "plain text"
  }
)

… where rules, json, jsonl, and text are notebook cell references.

This snippet grabs the content of the selected cell because all the referenced notebook cells do have names. It took me a while to figure how to achieve this ;-)

Additional context

Interestingly, you may examine defined notebook cells through Web Inspector > Page Resources > Extra Scripts:

"use strict";(
function(/* ...arguments? */){ return( /* ...cell content */ ) }
)
//# sourceURL=observablehq-\d+

OR

"use strict";(
function(/* ...arguments? */){ /* ...cell statements */ }
)
//# sourceURL=observablehq-\d+
tomlarkworthy commented 2 years ago

yeah I would rephrase this as give us access to the underlying runtime through "inbuilt" variable , you can build some seriously cool stuff and gives us the tools to extend the platform. One of my better received show-and-tell tweets was about using Observable for "moldable development" https://mobile.twitter.com/tomlarkworthy/status/1543253986026954752 and required access to the runtime.