Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Packed printing #52

Open
wants to merge 18 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -27,9 +27,9 @@
},
"dependencies": {
"historic-readline": "^1.0.8",
"lumo": "^0.20.6",
"lumo-cljs": "1.7.0",
"os-homedir": "^1.0.2",
"packed-printer": "^0.3.0",
"unzipper": "^0.8.11"
}
}
2 changes: 1 addition & 1 deletion resources/unrepl/blob.clj

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion scripts/run
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
#!/usr/bin/env bash

node_modules/.bin/lumo -c src -m unravel.core "$@"
node_modules/.bin/lumo -c src:node_modules/packed-printer/src/ -m unravel.core "$@"
33 changes: 21 additions & 12 deletions src/unravel/loop.cljs
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
(ns unravel.loop
(:require [clojure.string :as str]
[clojure.pprint :refer [pprint]]
[clojure.walk]
[lumo.core]
[lumo.io :refer [slurp]]
Expand All @@ -13,7 +12,9 @@
[unravel.log :as ud]
[unravel.util :as uu]
[unravel.lisp :as ul]
[unravel.exception :as ue]))
[unravel.exception :as ue]
[net.cgrand.packed-printer :as pp]
[unravel.pprint]))

(defn squawk [rl & xs]
(println)
Expand Down Expand Up @@ -54,10 +55,15 @@
(some-> ctx :aux-out .end)
(some-> ctx :loader-out .destroy)) ; plain .end hangs

(defn- print-result [ctx result]
(if (some-> ctx :options :flags :packed)
(pp/pprint result :as :unrepl/edn :strict 20 :width (quot (.-columns js/process.stdout) 1.11))
(ut/cyan #(prn result))))

(defmethod process [:conn :eval] [[_ result counter] _ ctx]
(if (and (some? (:trigger ctx)) (= (:trigger ctx) result))
(terminate! ctx)
(ut/cyan #(prn result)))
(print-result ctx result))
(assoc ctx :pending-eval nil))

(defmethod process [:conn :started-eval] [[_ {:keys [actions]}] _ ctx]
Expand Down Expand Up @@ -126,18 +132,18 @@
(println (str "Unravel " uv/version " connected to " host ":" port "\n"))
(println "Type ^O for full docs of symbol under cursor, ^D to quit,")
(println "^up and ^down to navigate history, ^C to interrupt current evaluation.")
(println "Enter #__help for help")
(println "Enter /help for help")
(println))

(defn help []
(println)
(println "Type ^O for full docs of symbol under cursor, ^D to quit.")
(println "Lines starting with `#__` are treated as special commands and
(println "Lines starting with `/` are treated as special commands and
interpreted by the REPL client. The following specials are available:

- `#__help` shows a help screen
- `#__1`, `#__2`, `#__3` ...: expand the numberd lazy seq ellipsis
- `#__`: expand the most recent lazy seq ellipsis ")
- `/help` shows a help screen
- `/1`, `/2`, `/3` ...: expand the numbered ellipsis
- `//`: expand the most recent lazy seq ellipsis ")
(println))

(defn read-payload []
Expand All @@ -150,9 +156,11 @@ interpreted by the REPL client. The following specials are available:
(help)
(.prompt rl))

(or (nil? cmd) (re-matches #"^\d*$" cmd))
(if-let [cmd (get @ug/ellipsis-store (or (some-> cmd js/parseInt) @ug/ellipsis-counter))]
(send-command ctx (str cmd))
(re-matches #"\d+|/" cmd)
(if-some [{:keys [unravel/source] :as m} (get @ug/ellipsis-store (if (= cmd "/") @ug/ellipsis-counter (js/parseInt cmd)))]
(case source
:unrepl (send-command ctx (pr-str (:get m)))
:unravel (print-result ctx (:value m)))
(.prompt rl))))

(defn socket-connector
Expand Down Expand Up @@ -459,7 +467,7 @@ interpreted by the REPL client. The following specials are available:
[[_ line] _ ctx]
(when (ut/rich?)
(doto (:ostream ctx) .clearLine .clearScreenDown))
(if-let [[_ cmd] (re-matches #"^\s*#__([a-zA-Z0-9]*)?\s*$" line)]
(if-let [[_ cmd] (re-matches #"^\s*/([/a-zA-Z0-9]+)\s*$" line)]
(special ctx cmd)
(send-command ctx line))
ctx)
Expand Down Expand Up @@ -522,4 +530,5 @@ interpreted by the REPL client. The following specials are available:
(fn [ctx origin msg]
(ud/dbug :receive {:origin origin} msg)
(process msg origin ctx)))]
#_(.on js/process.stdout "resize" #(sm :term-resize [(.-columns js/process.stdout) (.-rows js/process.stdout)]))
(.on conn-in "data" #(sm :conn %))))
116 changes: 116 additions & 0 deletions src/unravel/pprint.cljs
Original file line number Diff line number Diff line change
@@ -0,0 +1,116 @@
(ns unravel.pprint
(:require [net.cgrand.packed-printer.core :as core]
[net.cgrand.packed-printer.text.edn :as te]
[unravel.tags :as tags]))

(defn ansi [text ansi-text]
{:length (count text)
:text ansi-text
:start-length (count text)
:start-text ansi-text
:br-after? true})

(defn nobr [text]
{:length (count text)
:text text
:start-length (count text)
:start-text text})

(defn opening [s i]
{:start-length (count s)
:start-text (str "\33[2m" s "\33[22m")
:length (count s)
:text (str "\33[2m" s "\33[22m")
:indent i})

(defn closing [s]
{:length (count s)
:text (str "\33[2m" s "\33[22m")
:br-after? true
:indent -1})

(def delims
(-> {}
(into (map (fn [s] [s (opening s (count s))])) ["(" "[" "{" "#{"])
(into (map (fn [s] [s (closing s)])) [")" "]" "}"])))

(def comma {:length 1
:text "\33[2m,\33[22m"
:br-after? true})

(defn spans
"Turns x into a collection of spans for layout. Options supported are:
* kv-indent the amount of spaces by which to indent a value when it appears
at the start of a line (default 2),
* coll-indents a map of collection start delimiters (as strings) to the amount
by which to indent (default: length of the delimiter)."
[x {:keys [kv-indent coll-indents] :or {kv-indent 2 coll-indents {}}}]
(let [delims (into delims (map (fn [[s i]] [s (opening s i)])) coll-indents)
kv-open
{:length 0
:text ""
:start-length 0
:start-text ""
:indent kv-indent}
meta-open {:length 1
:text "\33[2m^\33[22m"
:start-length 1
:start-text "\33[2m^\33[22m"
:indent kv-indent}]
(letfn [(coll-spans
([x] (coll-spans x [te/space] spans))
([x sp spans]
(sequence (comp (map spans) (interpose sp) cat) x)))
(kv-spans [[k v]]
(if (instance? unravel.tags/Ellipsis k)
(spans v)
(-> [kv-open] (into (spans k)) (conj te/space) (into (spans v)) (conj te/kv-close))))
(spans [x]
(cond
(keyword? x) (let [s (str x)] [(ansi s (str "\33[36m" s "\33[m"))]) ; cyan
(tagged-literal? x)
(case (:tag x)
unrepl/meta (let [[m v] (:form x)]
(concat (cons meta-open (spans m)) (cons te/space (spans v)) [te/kv-close]))
unrepl.java/class [(ansi (str (:form x)) (str "\33[33m" (:form x) "\33[m"))] ; to distinguish from symbols
unrepl/string (let [[s e] (:form x)
s (pr-str s)] (cons (nobr s) (spans e)))
unrepl/ratio (let [[n d] (:form x)]
[(str n "/" d)])

unrepl/pattern (let [[n d] (:form x)]
[(pr-str (re-pattern (:form x)))])
unrepl/lazy-error
(concat [kv-open (ansi (str "/lazy-error")
(str "\33[31m/lazy-error\33[m"))
te/space]
(spans (-> x :form :form :cause))
[te/space
(let [cmd (str "/" (tags/elide (:form x)))]
(ansi cmd (str "\33[31m\33[4m" cmd "\33[m")))
te/kv-close])
error (concat
[kv-open (ansi (str "#" (pr-str (:tag x)))
(str "\33[31m#" (pr-str (:tag x)) "\33[m"))
te/space]
(spans (:form x)) [te/kv-close])
(concat [kv-open (str "#" (pr-str (:tag x))) te/space] (spans (:form x)) [te/kv-close]))
(vector? x) (concat [(delims "[")] (coll-spans x) [(delims "]")])
(set? x) (concat [(delims "#{")]
(coll-spans (if-some [e (some #(when (instance? unravel.tags/Ellipsis %) %) x)]
(concat (disj x e) [e])
x))
[(delims "}")])
(seq? x) (concat [(delims "(")] (coll-spans x) [(delims ")")])
(instance? unravel.tags.Ellipsis x) [(let [s (if-some [id (:id x)] (str "/" id) "/\u29B0")]
(ansi s (str "\33[4m" s "\33[24m")))]
(instance? unravel.tags.ClojureVar x) [(str "#'" (:name x))]
(map? x) (if-some [kv (find x tags/unreachable)]
(concat [(delims "{")] (coll-spans (concat (dissoc x tags/unreachable) [kv]) [comma te/space] kv-spans) [(delims "}")])
(concat [(delims "{")] (coll-spans x [comma te/space] kv-spans) [(delims "}")]))
:else [(pr-str x)]))]
(spans x))))

(defmethod core/spans [:text :unrepl/edn] [x to-as opts]
(spans x opts))

28 changes: 21 additions & 7 deletions src/unravel/tags.cljs
Original file line number Diff line number Diff line change
Expand Up @@ -5,26 +5,40 @@

(defonce ellipsis-store (atom {}))

(defrecord Ellipsis [get])
(defrecord Ellipsis [get id])

(def unreachable (Ellipsis. nil nil))

(defn ellipsis [m]
(if (:get m)
(let [counter (swap! ellipsis-counter inc)]
(swap! ellipsis-store assoc counter (assoc m :unravel/source :unrepl))
(Ellipsis. (:get m) counter))
unreachable))

(defn elide [value]
(let [counter (swap! ellipsis-counter inc)]
(swap! ellipsis-store assoc counter {:unravel/source :unravel :value value})
counter))

(defrecord ClojureVar [name])

(extend-protocol IPrintWithWriter
Ellipsis
(-pr-writer [v writer _]
(let [counter (swap! ellipsis-counter inc)]
(swap! ellipsis-store assoc counter (:get v))
(write-all writer "#__" counter)))
(if-some [id (:id v)]
(write-all writer "/" id)
(write-all writer "/\u29B0" (:id v))))

ClojureVar
(-pr-writer [v writer _]
(write-all writer "#'" (:name v))))

(def tag-map
{'unrepl/... map->Ellipsis
{'unrepl/... ellipsis
'clojure/var ->ClojureVar})

(defn register-tag-parsers []
(cljs.reader/register-default-tag-parser! tagged-literal)
(cljs.reader/register-tag-parser! 'unrepl/... map->Ellipsis)
(cljs.reader/register-tag-parser! 'clojure/var ->ClojureVar))
(doseq [[tag parser] tag-map]
(cljs.reader/register-tag-parser! tag parser)))
30 changes: 4 additions & 26 deletions yarn.lock
Original file line number Diff line number Diff line change
Expand Up @@ -133,10 +133,6 @@ duplexer2@~0.1.4:
dependencies:
readable-stream "^2.0.2"

earcut@2.1.2:
version "2.1.2"
resolved "https://registry.yarnpkg.com/earcut/-/earcut-2.1.2.tgz#542add0ca3a7b713452720e1d053937d3daf3784"

ecc-jsbn@~0.1.1:
version "0.1.1"
resolved "https://registry.yarnpkg.com/ecc-jsbn/-/ecc-jsbn-0.1.1.tgz#0fc73a9ed5f0d53c38193398523ef7e543777505"
Expand Down Expand Up @@ -320,10 +316,6 @@ listenercount@~1.0.1:
version "1.0.1"
resolved "https://registry.yarnpkg.com/listenercount/-/listenercount-1.0.1.tgz#84c8a72ab59c4725321480c975e6508342e70937"

lodash@4.17.4:
version "4.17.4"
resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.4.tgz#78203a4d1c328ae1d86dca6460e369b57f4055ae"

lumo-cljs@1.7.0:
version "1.7.0"
resolved "https://registry.yarnpkg.com/lumo-cljs/-/lumo-cljs-1.7.0.tgz#d9d70185b22683b4aa5e53c4189e26c22d51b609"
Expand All @@ -332,14 +324,6 @@ lumo-cljs@1.7.0:
progress "^2.0.0"
request "2.81.0"

lumo@^0.20.6:
version "0.20.7"
resolved "https://registry.yarnpkg.com/lumo/-/lumo-0.20.7.tgz#a1cf61be6fa1bb235d05493ea849529c7c48289a"
dependencies:
earcut "2.1.2"
lodash "4.17.4"
rbush "2.0.1"

mime-db@~1.27.0:
version "1.27.0"
resolved "https://registry.yarnpkg.com/mime-db/-/mime-db-1.27.0.tgz#820f572296bbd20ec25ed55e5b5de869e5436eb1"
Expand Down Expand Up @@ -380,6 +364,10 @@ os-homedir@^1.0.2:
version "1.0.2"
resolved "https://registry.yarnpkg.com/os-homedir/-/os-homedir-1.0.2.tgz#ffbc4988336e0e833de0c168c7ef152121aa7fb3"

packed-printer@^0.3.0:
version "0.3.0"
resolved "https://registry.yarnpkg.com/packed-printer/-/packed-printer-0.3.0.tgz#7176be03879ba4f248f8f302e5489f234694cdb2"

pako@~1.0.2:
version "1.0.5"
resolved "https://registry.yarnpkg.com/pako/-/pako-1.0.5.tgz#d2205dfe5b9da8af797e7c163db4d1f84e4600bc"
Expand Down Expand Up @@ -408,16 +396,6 @@ qs@~6.4.0:
version "6.4.0"
resolved "https://registry.yarnpkg.com/qs/-/qs-6.4.0.tgz#13e26d28ad6b0ffaa91312cd3bf708ed351e7233"

quickselect@^1.0.0:
version "1.0.0"
resolved "https://registry.yarnpkg.com/quickselect/-/quickselect-1.0.0.tgz#02630818f9aae4ecab26f0103f98d061c17c58f3"

rbush@2.0.1:
version "2.0.1"
resolved "https://registry.yarnpkg.com/rbush/-/rbush-2.0.1.tgz#4cfaca28c3064bc0ee75431a1b79990e875eefa9"
dependencies:
quickselect "^1.0.0"

readable-stream@^2.0.2:
version "2.3.3"
resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-2.3.3.tgz#368f2512d79f9d46fdfc71349ae7878bbc1eb95c"
Expand Down