urbit / shrub

An operating function (Prototype)
https://urbit.org
MIT License
29 stars 2 forks source link

blue prototype #94

Closed hanfel-dovned closed 1 month ago

hanfel-dovned commented 2 months ago

blue is an experimental alternative to hawk that solves the problem described in #91.

On your desktop, you can right-click a file and attempt to open it with any software on your computer. If the file matches the software's specification, this will succeed.

blue thinks of renderers in the same way. A renderer is a shrub with a deps arm that (typically) expects a very specific implementation. The form of our imp/diary is:

++  state
  [%pro %diary]
++  poke
  (sy %diary-diff ~)
++  kids
  %-  some
  :-  %y
  %-  ~(gas by *lads:neo)
  :~  :-  [[%.n %da] %.n]
      [[%only %txt] ~]

The deps arm of a diary renderer, then, will define:

++  deps
  %-  ~(gas by *band:neo)
  :~  :-  %src
      ^-  fief:neo
      :-  req=&
      ^-  quay:neo
      :-  [pro/%diary (sy %diary-diff ~)]
      ^-  (unit port:neo)
      :+  ~  %y
      %-  ~(gas by *lads:neo)
      :~  :-  [[%.n %da] %.n]
          `lash:neo`[[%only %txt] ~]
      ==
  ==

blue's state contains a map of pith to stud, with this stud representing a default renderer for the shrub at the pith. Upon receiving an HTTP request, blue will make the renderer, passing in the request as state and the pith as its dependency. The renderer then handles the request.

(How this map gets populated is an open question and will be somewhat dependent on software distribution, but the desired user experience is, again, similar to your desktop, where the user might have to manually choose a renderer once, and then that renderer will be used for all shrubs of that type. URL parameters could be used to manually specify a renderer: ?renderer=some-renderer)

For the devex of this to work, this means splitting out some parts of hawk-eyre-handler's code into a library and absorbing other parts into the higher level request handler. This should conceptually feel very nice and necessary anyway, and overlaps a lot with the required work for sandboxing UIs within iframes.

Once this system of treating renderers as shrubs is working, we get %make wizards for free. Specify a ?wizard=some-wizard-renderer URL parameter, and blue will create that rendering shrub (with no dependencies, since the shrub we're making doesn't exist yet). You could imagine a similar setup for embedding tree in Sky.

blue itself is an experiment and of course will have to merge with our other lines of work (request-response rewrite, iframes). This incomplete branch illustrates the concept.

To the extent that Sky has "apps," renderers are those apps.

(Bonus: a renderer could allow multiple types of dependencies.)

hanfel-dovned commented 1 month ago

This code still has a couple of issues; I'm still getting a bad-deal error when I run it, and there's a crucial XML library function that I still have yet to write. It compiles though, and conceptually, all the pieces are here for a shrub-based rendering framework that allows for recursion, abstracts away HTTP handling, and is future-proof against here.bowl being removed.

The basic flow is:

liam-fitzgerald commented 1 month ago

Now you're thinking with portals. In all honesty this displays an impressive command of the shrub gnosis, great work! Going to take a closer review tomorrow.

hanfel-dovned commented 1 month ago

To-Do

hanfel-dovned commented 1 month ago

I've spent the past couple days flip-flopping between two design directions. Here's the tension:

  1. It would be cool for recursive renderers to be able to operate on output from their children.
  2. It would be cool for individual elements on the page to auto-update when their corresponding state changes.

1 requires immediate parents to capture their children's UI state. 2 requires only the top-level request handler to capture all children's UI state (because if you instead roll these changes up through the ancestral tree, the final output will just be the entire webpage again, and auto-refreshing the entire page and wiping potentially important user context would be evil). I haven't come up with a way to do both of these at once without substantially complicating the devex of this model; it would look something like propagating effects up the call stack via gifts and asking devs to manually choose which ones to ignore.

For the time being, in the spirit of All Robot & Computers Must Shut The Hell Up, I advocate for 1 over 2. Adding styling to your children's nested ui seems to me like it's a prerequisite for any real-world recursive rendering. 1 also feels more shrubbish to me in its emphasis on immediate parent-child relationships, and by respecting the bemoaned gap between client and server that so much software tries and fails to make invisible, it allows each a webpage to be a timestamped view into the namespace that only advances to the next case when the user asks it to. This doesn't mean that auto-refreshing won't be useful for plenty of software written on Shrubbery, but the standard UI model that we teach developers would be much simpler to learn without adding a temporal dimension on top of recursion.

I'd like to discuss how what merging Blue's logic into Sky looks like, and then we can see what supporting multiple types of renderers looks like...

hanfel-dovned commented 1 month ago

How to have multiple rendering methodologies? Shrubbery fixes this: we move up a layer and make each methodology its own shrub. Send an HTTP request to /neo/prism along with a URL parameter for which renderer you want to handle the request. Prism simply forwards the request on and then washes its hands of it.

blue handles GET and POST requests like an HTTP server, with powerful request handling and recursion. You could imagine a mast-style green that's more inclined towards auto-refreshing and channels, a purple that serves %make wizards, or even an orange that uses con files (because screw it, why not?). We write the rendering frameworks we need with unique use cases cleanly separated into distinct pieces of software, a trillion rendering frameworks can bloom on top of that, and Sky can grab whichever one it needs for its purposes at any given moment.

hanfel-dovned commented 1 month ago

Supplanted by #113!