2  Kindly

Kindly is a standard for requesting data visualizations in Clojure.

It specifies in what kinds of way Clojure forms and values should be displayed.

(ns kindly
  (:require [scicloj.kindly.v4.api :as kindly]
            [scicloj.kindly.v4.kind :as kind]
            [tablecloth.api :as tc]))

Kindly logo

2.1 Why

Different tools have had different ways of writing notes. For example:

2.2 Goal

  • Have a standard way to request data visualizations
  • for blog posts, books, slideshows, reports, dashboards, and interactive analyses,
  • that just will work across different tools,
  • without even mentioning those tools in the code.
  • We aim for copy/paste compatibility of visualisation code accross different tools:
    • as it is a given for normal Clojure code producing textual output in a text oriented repl,
    • visualisation code working in one tool should produce the same or very similar result in all compatible tools.

2.3 Status

  • supported by Clay
  • implemented a partially working adapter for Portal (kind-portal)
  • implemented a partially working adapter for Clerk (kind-clerk)
  • actively working to support other tools such as Cursive, Calva, and Clojupyter

2.4 Existing book/notebook projects using Kindly

2.5 Example

Here is how one may request something of kind/md, which means Markdown:

(kind/md
 "hello *hello* **hello**")

hello hello hello

2.6 The set of kinds

(sort kindly/known-kinds)
(:kind/code
 :kind/cytoscape
 :kind/dataset
 :kind/echarts
 :kind/edn
 :kind/emmy-viewers
 :kind/fn
 :kind/fragment
 :kind/hiccup
 :kind/hidden
 :kind/highcharts
 :kind/html
 :kind/htmlwidgets-ggplotly
 :kind/htmlwidgets-plotly
 :kind/image
 :kind/map
 :kind/md
 :kind/mermaid
 :kind/observable
 :kind/plotly
 :kind/portal
 :kind/pprint
 :kind/println
 :kind/reagent
 :kind/scittle
 :kind/seq
 :kind/set
 :kind/smile-model
 :kind/table
 :kind/test
 :kind/test-last
 :kind/tex
 :kind/var
 :kind/vector
 :kind/vega
 :kind/vega-lite
 :kind/video)

You can find more (details and examples of using these kinds)[/kindly-noted/kinds.html] in the Kindly book.

2.7 How to use Kinds?

2.7.1 Attaching metadata to forms

^:kind/md
["hello *hello* **hello**"]

hello hello hello

^kind/md
["hello *hello* **hello**"]

hello hello hello

2.7.2 Attaching metadata to values

(-> ["hello *hello* **hello**"]
    kind/md)

hello hello hello

(-> ["hello *hello* **hello**"]
    kind/md
    meta
    :kindly/kind)
:kind/md

2.7.3 Attaching metadata to values - cont.

(-> "hello *hello* **hello**"
    kind/md
    meta
    :kindly/kind)
:kind/md

Values that cannot have metadata are wrapped in a vector before attaching metadata.

(-> "hello *hello* **hello**"
    kind/md
    kind/pprint)
["hello *hello* **hello**"]
(-> "hello *hello* **hello**"
    kind/md
    meta)
#:kindly{:kind :kind/md, :options {:wrapped-value true}}

2.7.4 Using values annotated by libraries

(defn my-library-function-for-big-big-text [text]
  (kind/hiccup
   [:big {:style {:background "#ccddcc"}}
    [:big text]]))
(-> "hello"
    my-library-function-for-big-big-text)
hello
(-> "hello"
    my-library-function-for-big-big-text
    (assoc-in [1 :style]
              {:background "#ddccdd"}))
hello

2.7.5 Automatically-inferred kinds

In certain situations, kinds are inferred without annotation. The kindly-advice library provides the default inference behaviour and an option to extend it.

For example, images:

(def clj-image
  (->  "https://upload.wikimedia.org/wikipedia/commons/e/eb/Ash_Tree_-_geograph.org.uk_-_590710.jpg"
       (java.net.URL.)
       (javax.imageio.ImageIO/read)))
Syntax error macroexpanding at (dev.clj:137:8).

Can’t get input stream from URL! Server returned HTTP response code: 403 for URL: https://upload.wikimedia.org/wikipedia/commons/e/eb/Ash_Tree_-geograph.org.uk-_590710.jpg

                                               clojure.core/eval                         core.clj: 3215
                                                             ...                                      
          jdk.internal.reflect.DirectMethodHandleAccessor.invoke  DirectMethodHandleAccessor.java:  103
                                      javax.imageio.ImageIO.read                     ImageIO.java: 1405
                                         java.net.URL.openStream                         URL.java: 1325
sun.net.www.protocol.https.HttpsURLConnectionImpl.getInputStream      HttpsURLConnectionImpl.java:  223
      sun.net.www.protocol.http.HttpURLConnection.getInputStream           HttpURLConnection.java: 1615
     sun.net.www.protocol.http.HttpURLConnection.getInputStream0           HttpURLConnection.java: 2014
                    java.io.IOException: Server returned HTTP response code: 403 for URL: https://upload.wikimedia.org/wikipedia/commons/e/eb/Ash_Tree_-_geograph.org.uk_-_590710.jpg
             javax.imageio.IIOException: Can't get input stream from URL!
clojure.lang.Compiler$CompilerException: Syntax error macroexpanding at (dev.clj:137:8).
    data: #:clojure.error{:phase :execution,
                      :line 137,
                      :column 8,
                      :source "dev.clj"}

source: notebooks/kindly.clj