reveal

Docs: https://vlaaad.github.io/reveal/ Source: https://github.com/vlaaad/reveal
wilkerlucio 2020-12-15T02:00:11.395600Z

does reveal makes use of datafy/nav protocols?

vlaaad 2020-12-15T08:05:14.412Z

Morning! (at least it’s morning here in Sweden)

vlaaad 2020-12-15T08:07:39.412200Z

A lot to unpack here, but I’m glad you resolved your issue @wilkerlucio!

vlaaad 2020-12-15T08:40:59.412400Z

I can describe how datafy/nav works in Reveal :) When maps are printed to Reveal, map keys are annotated with corresponding values, and values are annotated with corresponding keys, and both keys and values are annotated with collection they are in. That provides all necessary information for actions to do nav (coll, k, v) when some key OR value is selected: the counterpart will be there. The relevant code is here: https://github.com/vlaaad/reveal/blob/master/src/vlaaad/reveal/stream.clj#L202-L218 Reveal also performs datafy-then-nav when it suggests nav action, but there is a twist: datafied data structure might be substantially different from the original one. For example, entity map from datomic might have only preloaded keys in its default form, but perform a request to load all its keys when datafied, so we can then lookup related values from those keys:

;; original entity:

{:db/id 123}

;; datafied entity:

{:db/id 123
 :user/name "fred"
 :user/orders "not loaded, nav this key to load"}
Reveal prints original undatafied map, and with that map it’s impossible to nav to :user/orders key because it’s not in the map — it appears when datafication happens. That’s why Reveal’s nav action does not suggest itself if datafication is different: you are missing out on other keys. Instead, you should select the coll and execute datafy action to get those keys, and only then nav in the returned data structure. This is why Reveal suggests datafy action only when datafication is different, by the way — if it’s the same, you can just nav in the printed data structure.

👍 1
seancorfield 2020-12-15T18:36:10.416Z

Great explanation! Thanks, @vlaaad!

wilkerlucio 2020-12-15T02:08:52.395800Z

I see a nav option in the menu, but that doens't seem to be using the nav protocol

seancorfield 2020-12-15T02:21:54.396Z

Yes, it does. I use it quite a bit with next.jdbc results.

seancorfield 2020-12-15T02:22:30.396200Z

Unlike REBL, it doesn't datafy things automatically, but when you choose nav, it calls datafy and then nav.

seancorfield 2020-12-15T02:22:56.396400Z

(because you can only nav things that have been datafy'd)

seancorfield 2020-12-15T02:24:23.396600Z

@wilkerlucio Does that help?

wilkerlucio 2020-12-15T02:25:01.396800Z

kind of, but I think I'm finding a bug in reveal

wilkerlucio 2020-12-15T02:25:08.397Z

I'm looking at the nav action definition

wilkerlucio 2020-12-15T02:25:16.397200Z

(defaction ::nav [x {:vlaaad.reveal.nav/keys [coll key val]
                     :or {key ::not-found
                          val ::not-found}}]
  (let [datafied-coll (d/datafy coll)]
    (when (= datafied-coll coll)
      (cond
        (not= key ::not-found) #(d/nav datafied-coll key x)
        (not= val ::not-found) #(d/nav datafied-coll x val)))))

wilkerlucio 2020-12-15T02:25:47.397400Z

and after some debug, I notice the :vlaaad.reveal.nav/key comes with numbers for vector items, but comes blank for map entries

wilkerlucio 2020-12-15T02:25:55.397600Z

trying to understand, maybe its because Im using a custom map type

wilkerlucio 2020-12-15T02:26:06.398Z

still digging on it

seancorfield 2020-12-15T02:26:22.398200Z

That does look a bit weird... why would the datafied coll be equal to the original coll?

wilkerlucio 2020-12-15T02:26:34.398400Z

I guess to make sure its datafied

wilkerlucio 2020-12-15T02:26:48.398600Z

that check is to define if the action itself must be presented or absent

seancorfield 2020-12-15T02:27:00.398800Z

That makes no sense. datafy can produce something completely different from the underlying data.

wilkerlucio 2020-12-15T02:27:14.399Z

but the datafy of datafy should always be the same value, right?

seancorfield 2020-12-15T02:27:46.399300Z

Er, no. Are you saying it's calling datafy twice?

wilkerlucio 2020-12-15T02:29:32.399500Z

I believe the intention of this check is to only offer "nav" when Reveal thinks the data is datafied, and one way to check that is calling datafy on it again, I guess the property is true: (defn datafied? [x] (= x (datafy x)))

wilkerlucio 2020-12-15T02:30:12.399700Z

but I start doubting my logic now

wilkerlucio 2020-12-15T02:31:03.399900Z

yeah, maybe the check should be about the parent implementing Datafiable

seancorfield 2020-12-15T02:31:25.400100Z

Lots of things can implement Datafiable

seancorfield 2020-12-15T02:31:58.400300Z

It looks like @vlaaad has changed this at some point and now datafy is offered as a separate action, at least sometimes.

seancorfield 2020-12-15T02:32:19.400500Z

(find-ns 'user) produces a value that can be datafy'd for example

wilkerlucio 2020-12-15T02:32:19.400700Z

I'm trying to create my own custom action

wilkerlucio 2020-12-15T02:32:35.400900Z

but I'm getting confused with the meta-data provided by Reveal, it seems incomplete for properly call nav

seancorfield 2020-12-15T02:35:09.401500Z

Yeah, try this:

(with-meta {} {`p/datafy (fn [x] (with-meta {:a 1 :b 2} {`p/nav (fn [coll k v] (if (= :b k) (* 2 v) v))}))})

seancorfield 2020-12-15T02:35:52.401700Z

Then right-click > datafy it. Then go to :a in the result and right-click > nav -- you'll get 1, then go to :b in the result and right-click > nav and you'll get 4.

seancorfield 2020-12-15T02:36:26.401900Z

So it works, but the code in the nav action is pretty counter-intuitive.

wilkerlucio 2020-12-15T02:42:39.402100Z

I just got it working

wilkerlucio 2020-12-15T02:42:49.402300Z

the problem is related to lazy navigation

wilkerlucio 2020-12-15T02:43:07.402500Z

with the current nav impl it doesn't properly use the nav protocol to find lazy data, as far as I understood

wilkerlucio 2020-12-15T02:43:12.402700Z

I got it to work with this action:

wilkerlucio 2020-12-15T02:43:18.402900Z

(rx/defaction ::my-nav
  [x {:vlaaad.reveal.nav/keys [coll key val]
      :as m
      :or                     {key ::not-found
                               val ::not-found}}]
  (when (satisfies? clojure.core.protocols/Navigable coll)
    (let [source (-> coll meta :clojure.datafy/obj)]
     (cond
       (not= ::not-found val)
       #(d/nav source x val)

       (not= ::not-found key)
       #(d/nav source key (get coll key))))))

wilkerlucio 2020-12-15T02:44:04.403200Z

its similar, but note in my version I use the nav in the source object (which comes as part of the datafied data meta)

seancorfield 2020-12-15T02:44:13.403400Z

That's not right.

wilkerlucio 2020-12-15T02:44:22.403600Z

this way, the nav can return data that is different from what datafy returned

wilkerlucio 2020-12-15T02:44:29.403800Z

allowing for lazy navigation

seancorfield 2020-12-15T02:44:32.404Z

You're trying to nav on the original object which is wrong.

seancorfield 2020-12-15T02:44:42.404200Z

You should nav on the result of datafy.

wilkerlucio 2020-12-15T02:45:10.404400Z

let me try to bring my situation, maybe it will make more sense

seancorfield 2020-12-15T02:45:16.404600Z

In a lot of real world cases, datafy is what adds the nav protocol implementation.

seancorfield 2020-12-15T02:45:32.404800Z

You can datafy some arbitrary thing and the result will be nav'able.

wilkerlucio 2020-12-15T02:45:37.405Z

the problem is that, how do I datafy without doign recursive explosion?

wilkerlucio 2020-12-15T02:45:54.405200Z

in my case, I have a DS that's a map like, but it has some cached data, and some unrealized data

wilkerlucio 2020-12-15T02:46:17.405400Z

if I realize everything on datafy, it causes stack overflow before it goes infinite recursion

seancorfield 2020-12-15T02:46:17.405600Z

datafy is a no-op on most things but you must call datafy first before nav

wilkerlucio 2020-12-15T02:46:43.405800Z

so, I need to return something to say that those keys exist, but I can't evaluate then ahead of time

wilkerlucio 2020-12-15T02:47:04.406Z

maybe I'm using it wrong, but this is the only way I found to be able to know the navigatable keys, but only realize on nav

seancorfield 2020-12-15T02:47:17.406200Z

You are doing it wrong 🙂

wilkerlucio 2020-12-15T02:47:29.406400Z

is there a way to solve my problem "doing it right"?

seancorfield 2020-12-15T02:47:46.406600Z

Explain your problem again...

wilkerlucio 2020-12-15T02:48:06.406800Z

I have this data structure that contains cached data, and some keys that are "possibly available"

wilkerlucio 2020-12-15T02:48:54.407Z

like a datomic entity, where a read may or may not cause an index download, but in my case I have an arbritary number of keys, that may return other complex data in it

seancorfield 2020-12-15T02:49:29.407200Z

So datafy should produce a pure data representation that has those keys but doesn't have to realize them... so they're placeholders that can be displayed as pure data.

wilkerlucio 2020-12-15T02:49:40.407400Z

my goal is to make a navigatable environment on this special map, so during datafy I need to expose all possible keys, but can't evaluate all of them (only the cached, that I know its a limited space, the "possible" is bound to infinity)

wilkerlucio 2020-12-15T02:49:52.407600Z

yeah, that's what I'm doing

wilkerlucio 2020-12-15T02:49:58.407800Z

I return a special keyword on those cases

wilkerlucio 2020-12-15T02:50:44.408Z

ah, I think I may realized the solution, use metadata on the values instead of the protocol on the parent type

seancorfield 2020-12-15T02:50:58.408200Z

Have a look at how next.jdbc does it

seancorfield 2020-12-15T02:51:13.408400Z

It does lazy navigation through a database based on assumed foreign keys.

seancorfield 2020-12-15T02:52:08.408600Z

datafy adds the nav protocol implementation that does the DB fetch when invoked.

seancorfield 2020-12-15T02:55:40.408800Z

If you're in doubt, fire up REBL and try it in that: it definitely does datafy/nav "the right way" so if your impl doesn't work in REBL, it's not right.

seancorfield 2020-12-15T02:55:49.409Z

Reveal is... a bit odd in that respect...

wilkerlucio 2020-12-15T02:58:56.409200Z

for some reason REBL is crashing my process when I try to get it up here

wilkerlucio 2020-12-15T03:03:06.409500Z

ok, I got the nav to work as expected now, thanks for pointing the direction @seancorfield 🙏

seancorfield 2020-12-15T03:05:35.409700Z

Excellent!

wilkerlucio 2020-12-15T05:48:44.410700Z

is there a way to make the maps print in reveal with the keys sorted?

vlaaad 2020-12-15T08:45:50.413Z

I was considering doing that, but was worried it might give users an incorrect view of their program: they might get an impression all maps are always sorted. I usually use eval-on-selection and write sort when I want something sorted

wilkerlucio 2020-12-15T13:41:53.413400Z

I think would be nice to have the option, because for example if I try to to do this with a Nav object, then I can't navigated on the sorted list, and I quite like the view of regular map on sorted. by personal experience with Fulcro Inspect I know that I'm mostly happier having then sorted, would you consider having this as a configurable thing?

vlaaad 2020-12-15T14:45:16.413700Z

you can have custom :vlaaad.reveal.stream/type meta key for your data structure and make that sort the keys at the point of printing

wilkerlucio 2020-12-15T15:34:40.413900Z

I think it would be better to have it for everything, I guess its a preference on the user side, in my case I normally deal with quite large maps, unsorted keys is really painful with those

wilkerlucio 2020-12-15T15:34:56.414100Z

could be a pref like the Theme on Reveal, but I would like to apply to every map by default

vlaaad 2020-12-16T08:04:47.433800Z

Putting it into pref is a good idea, thanks! I’ll give it a thought

seancorfield 2020-12-15T06:06:10.411200Z

No, but you can right-click > table view and then sort keys or values

vlaaad 2020-12-15T08:46:44.413200Z

or Space, type sort, Enter

seancorfield 2020-12-15T06:06:40.411900Z

(my :dev alias in my dot-clojure repo has an auto-table-display function built-in)

wilkerlucio 2020-12-15T17:42:41.414400Z

another thing on maps, had you consider the option to collapse map values (and sequences)?

vlaaad 2020-12-16T08:07:25.434Z

@wilkerlucio I released 1.1.178 that bumped text max length in tables a little. Ideally that could be done as a preference, but it’s a bigger task

🙏 1
vlaaad 2020-12-16T08:11:01.434200Z

@genekim My pleasure 😊 Unfortunately, not truncating the keys is not possible today, since keys can be so long (e.g. (range 1000000)) that trying to show them as JavaFX text nodes will kill UI performance. Maybe one day I’ll be able to implement some sort of intelligent text nodes that render themselves on-demand, but it’s a big task-small payoff, so maybe later ¯\(ツ)

vlaaad 2020-12-15T17:48:59.414600Z

I thought about that. There is no decision yet, but table view is semantically pretty close to collapsing values to get overview of keys/items, and structural navigation allows fast jumping between values in the output panel, so that's pretty low priority for me, but I keep it in mind/todo list

wilkerlucio 2020-12-15T18:00:32.414800Z

one bug I see on the table view is that the keys column content doesn't resize when you resize the column

wilkerlucio 2020-12-15T18:00:45.415Z

and since I use quite large keys that's also a problem

vlaaad 2020-12-15T18:01:28.415200Z

Hmm, can you show how it looks?

wilkerlucio 2020-12-15T18:04:57.415400Z

not right now, but I can send later

wilkerlucio 2020-12-15T18:05:10.415600Z

in summary, it keeps "..." at the end of the keys

wilkerlucio 2020-12-15T18:05:17.415800Z

and when I expand the column size, they remain as "..."

vlaaad 2020-12-15T18:57:26.416200Z

Ah, now I understand! I probably should bump the max length of printed object

👍 1
vlaaad 2020-12-15T22:26:42.421800Z

Hey there! I just released 1.1.177 that is almost ready to be 1.2.* release with the UI improvements in the area of result navigation: • now you can have multiple result panels by pressing Ctrl+Enter in the action popup — this will make comparisons between different results/views easier; • switching between tabs is more discoverable (there are buttons with tooltips); • in every result panel you can see a result tree that shows all items in this panel hierarchically (available with Ctrl+Up); I'll fix some minor issues and then will announce it as 1.2.*

🎉 5
seancorfield 2020-12-15T22:37:51.422800Z

Very nice! Just in time for my presentation tonight, where I'll be showing off my workflow which includes Reveal!