chlorine-clover

About Chlorine for Atom and Clover for VS Code: https://atom.io/packages/chlorine and https://marketplace.visualstudio.com/items?itemName=mauricioszabo.clover
jaihindhreddy 2021-03-28T10:59:36.035400Z

Hello, Mauricio had talked about customising rendering on Chlorine via CLJS config. I was unable to find how to do this, from reading the docs on Atom's site, and the linked FAQ. Is this an upcoming thing, or are the details somewhere I haven't looked?

jaihindhreddy 2021-03-28T11:04:31.036400Z

Also, is there a way for me to write a modified version of evaluate-top-block that does one level down if the top block happens to be a comment form?

mauricio.szabo 2021-03-28T12:11:02.036500Z

Hi, yes, it is already on Chlorine and Clover, but it's not really that well documented.

👍 1
mauricio.szabo 2021-03-28T12:12:25.036600Z

For now, you need to write a custom eval command with the "interactive eval". It's on the path to becoming more easy and better to write :)

💯 1
mauricio.szabo 2021-03-28T12:14:52.036700Z

Also, yes, there's a way to write this modified command. It's not that easy to do what you want, because you'll be transforming strings, but you can replace the command with do, for example. Let me get into a computer and I'll open a thread with examples on how to handle both cases @jaihindhreddy

1
mauricio.szabo 2021-03-28T13:18:41.037100Z

Ok, so for this case of converting comment into do:

(defn top-block-ignoring-comment []
  (p/let [code (editor/get-top-block)
          code (update code :text #(str/replace-first % #"\(.*?comment" "(do "))]
    (editor/eval-and-render code)))

mauricio.szabo 2021-03-28T13:20:24.037300Z

As for the way to customize the rendering, there's some documentation here: https://github.com/mauricioszabo/atom-chlorine/blob/master/docs/extending.md#interactive-results and also here: https://github.com/mauricioszabo/atom-chlorine/blob/master/docs/custom-renderers.md

mauricio.szabo 2021-03-28T13:21:34.037700Z

But the idea, if you don't need to use external JS libraries (for example, if you don't want to plot, or use d3, etc) is to create a custom command that will evaluate something that returns a map with :html, :state, and :fns keys

mauricio.szabo 2021-03-28T13:25:43.037900Z

So, :html will be a hiccup representing the HTML that you want to render. It'll bind the variable ?state into the state.

mauricio.szabo 2021-03-28T13:34:17.038100Z

This is an example on how to evaluate a map and render as a table:

(defn map-as-table []
  (p/let [code (editor/get-top-block)
          text (pr-str '{:html '[:div.rows
                                 [:div.title "Result"]
                                 [:table {:border "2"}
                                  [:tbody
                                   (for [[k v] ?state]
                                     [:tr {:key k}
                                      [:td (pr-str k)]
                                      [:td (pr-str v)]])]]]
                         :state ?placeholder})
          code (update code :text #(str/replace-first text "?placeholder" %))]
    (editor/eval-interactive code)))

mauricio.szabo 2021-03-28T13:36:28.038300Z

Place notice the quoting for the map form (so it's easier to prepare the code that will be evaluated in the REPL so that it returns the map structure that I want) and the quoting just after :html (it will ask for clojure to ALSO quote that hiccup for, when you run into the REPL). If you don't add the quote after :html, the Clojure REPL will think that ?state is a variable, and try to evaluate it - and we don't really want this 😄

mauricio.szabo 2021-03-28T13:37:04.038500Z

If you want this code to work with other data structure too, you can add a guard/use :div/clj to render as the default way

mauricio.szabo 2021-03-28T13:38:16.038700Z

So, in this case, the code will be:

(defn map-as-table []
  (p/let [code (editor/get-top-block)
          text (pr-str '{:html '[:div.rows
                                 [:div.title "Result"]
                                 (if (map? ?state)
                                   [:table {:border "2"}
                                    [:tbody
                                     (for [[k v] ?state]
                                       [:tr {:key k}
                                        [:td (pr-str k)]
                                        [:td (pr-str v)]])]]
                                   [:div/clj ?state])]
                         :state ?placeholder})
          code (update code :text #(str/replace-first text "?placeholder" %))]
    (editor/eval-interactive code)))

mauricio.szabo 2021-03-28T13:38:24.038900Z

I really hope that helps, @jaihindhreddy 🙂

mauricio.szabo 2021-03-28T13:38:57.039100Z

In the future, the idea is that Chlorine should be able to add metadata to results, and these will be used to render the results. It'll become way easier 🙂

jaihindhreddy 2021-03-28T13:44:22.039300Z

Helps a lot! Thanks!

mauricio.szabo 2021-03-28T13:45:09.039500Z

Please, don't hesitate to ask for more info 🙂. I'm aware that this implementation is a little bit confusing too 😄