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

doc functions #144

Open
wants to merge 2 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.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
73 changes: 11 additions & 62 deletions resources/public/clojure-dbg.html
Original file line number Diff line number Diff line change
Expand Up @@ -31,38 +31,21 @@
(my.m/m 1)
</div>
<br/>
<div class="clojure">
`(let [x# 1] x#)
<div class="klojure">
(require '[klipse.lang.clojure.env :as e])
(e/doc* 'map)
</div>
<br/>

<div class="klojure">
(require-macros '[klipse.lang.clojure.env :refer [doc]])
(doc map)
</div>
<br/>
<div class="clojure">
(ns my.ns
(:require [clojure.set :as ss]))
=======
<head lang="en">
<meta charset="UTF-8">
<title>KLIPSE: a simple and elegant online cljs compiler and evaluator</title>
<link rel='shortcut icon' type='image/x-icon' href='img/klipse.png' />
<link rel="stylesheet" type="text/css" href="css/codemirror.css">
</head>
<body>
<div class="clojure">
</div>
<div class="clojure">
(ns my.ns
(:refer-clojure :exclude [distinct group-by update])
(:require clojure.string
[sqlingvo.core :as sql :refer [sql db select from]]))


(def my-db (db :postgresql))

(sql (select my-db [:first-name]
(from :people)))
</div>
<br/>



<div class="clojure">
(require-macros '[gadjett.core :refer [dbg]])
Expand All @@ -81,51 +64,17 @@
`(1 2 ~(map inc [1 2 3]))
</div>
<br/>
<div class="clojure">
(ns my.m$macros)
(defmacro m [x] x)
(my.m/m 1)
</div>
<br/>
<div class="clojure">
`(let [x# 1] x#)
</div>
<br/>
<div class="clojure">
(ns my.ns
(:require [clojure.set :as ss]))

(str ::ss/xx)
</div>
<br/>
<div class="clojure">
(ns my.moo$macros)
(defmacro dbg[x]
`(let [x# ~x]
(println (str '~x ": " x#))
x#))
(with-out-str
(my.moo/dbg (map inc [1 2 3])))
</div>
<br/>
<div class="clojure">
(ns my.test
(:require
[cljs.pprint :as pp :refer [pprint]]))
(with-out-str (pprint (for [x (range 10)] (range x))))
</div>
<br/>
<div class="clojure">
`(1 2 ~(map inc [1 2 3]))
</div>
<br/>
<script>
window.klipse_settings = {

};
if(window.location.search.match(/transpile=1/)) {
window.klipse_settings.selector_js = '.clojure';
} else {
window.klipse_settings.selector = '.clojure';
window.klipse_settings.selector = '.klojure';
}

</script>
Expand Down
43 changes: 23 additions & 20 deletions src/klipse/lang/clojure.cljs
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,10 @@
(:require-macros
[gadjett.core :as gadjett :refer [dbg]]
[purnam.core :refer [!]]
[klipse.lang.clojure.env :refer [doc]]
[cljs.core.async.macros :refer [go go-loop]])
(:require
[klipse.lang.clojure.env :refer [current-ns st]]
klipse.lang.clojure.bundled-namespaces
gadjett.core-fn
[goog.dom :as gdom]
Expand All @@ -29,9 +31,8 @@
(js* "window.cljs.user = {}")


(defonce ^:private current-ns (atom 'cljs.user))

(defonce create-state-eval (memoize cljs/empty-state))
(def create-state-compile (memoize cljs/empty-state))

(defn display [value {:keys [print-length beautify-strings]}]
(with-redefs [*print-length* print-length]
Expand Down Expand Up @@ -91,13 +92,13 @@
max-eval-duration (max max-eval-duration min-max-eval-duration)
the-emits (if compile-display-guard (partial my-emits max-eval-duration) original-emits)]
(with-redefs [compiler/emits the-emits]
(cljs/eval-str (create-state-eval) s
(cljs/eval-str (st) s
"cljs-in"
{
:eval eval-for-compilation
:ns @current-ns
:static-fns static-fns
:*compiler* (set! env/*compiler* (create-state-eval))
:*compiler* (set! env/*compiler* (st))
:verbose (verbose?)
:load (partial io/load-ns external-libs)
}
Expand All @@ -109,22 +110,24 @@
(defn core-eval-an-exp [s {:keys [static-fns external-libs max-eval-duration] :or {static-fns false external-libs nil max-eval-duration min-max-eval-duration}}]
(let [c (chan)
max-eval-duration (max max-eval-duration min-max-eval-duration)]
(with-redefs [compiler/emits (partial my-emits max-eval-duration)]
; we have to set `env/*compiler*` because `binding` and core.async don't play well together (https://www.reddit.com/r/Clojure/comments/4wrjw5/withredefs_doesnt_play_well_with_coreasync/) and the code of `eval-str` uses `binding` of `env/*compiler*`.
(cljs/eval-str (create-state-eval)
s
"my.klipse"
{:eval my-eval
:ns @current-ns
:def-emits-var true
:verbose (verbose?)
:*compiler* (set! env/*compiler* (create-state-eval))
:context :expr
:static-fns static-fns
:load (partial io/load-ns external-libs)}
(fn [res]
(update-current-ns res)
(put! c res))))
(with-redefs [cljs.analyzer/*cljs-ns* @current-ns
*ns* (create-ns @current-ns)
compiler/emits (partial my-emits max-eval-duration)]
; we have to set `env/*compiler*` because `binding` and core.async don't play well together (https://www.reddit.com/r/Clojure/comments/4wrjw5/withredefs_doesnt_play_well_with_coreasync/) and the code of `eval-str` uses `binding` of `env/*compiler*`.
(cljs/eval-str (st)
s
"my.klipse"
{:eval my-eval
:ns @current-ns
:def-emits-var true
:verbose (verbose?)
:*compiler* (set! env/*compiler* (st))
:context :expr
:static-fns static-fns
:load (partial io/load-ns external-libs)}
(fn [res]
(update-current-ns res)
(put! c res))))
c))

(defn split-expressions [s]
Expand Down
6 changes: 6 additions & 0 deletions src/klipse/lang/clojure/env.clj
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
(ns klipse.lang.clojure.env)

(defmacro doc
"Prints documentation for a var or special form given its name"
[name]
`(klipse.lang.clojure.env/doc* '~name))
120 changes: 120 additions & 0 deletions src/klipse/lang/clojure/env.cljs
Original file line number Diff line number Diff line change
@@ -0,0 +1,120 @@
(ns klipse.lang.clojure.env
(:require-macros
[cljs.env.macros :as env])
(:require [cljs.analyzer :as ana]
[cljs.repl :refer [print-doc]]
[clojure.string :as string]
[cljs.js :as cljs]))

(def st (memoize cljs/empty-state))
(defonce ^:private current-ns (atom 'cljs.user))

(defn- drop-macros-suffix
[ns-name]
(if (string/ends-with? ns-name "$macros")
(apply str (drop-last 7 ns-name))
ns-name))

(defn- add-macros-suffix
[sym]
(symbol (str (name sym) "$macros")))

(defn- all-ns
"Returns a sequence of all namespaces."
[]
(keys (::ana/namespaces @(st))))

(defn- all-macros-ns []
(->> (all-ns)
(filter #(string/ends-with? (str %) "$macros"))))

(defn- get-namespace
"Gets the AST for a given namespace."
[ns]
{:pre [(symbol? ns)]}
(get-in @(st) [::ana/namespaces ns]))

(defn- resolve-var
"Given an analysis environment resolve a var. Analogous to
clojure.core/resolve"
[env sym]
{:pre [(map? env) (symbol? sym)]}
(try
(ana/resolve-var env sym
(ana/confirm-var-exists-throw))
(catch :default _
(ana/resolve-macro-var env sym))))

(defn- get-macro-var
[env sym macros-ns]
{:pre [(symbol? macros-ns)]}
(when-let [macro-var (env/with-compiler-env (st)
(resolve-var env (symbol macros-ns (name sym))))]
(assoc macro-var :ns macros-ns)))

(defn- get-var
[env sym]
(binding [ana/*cljs-warning-handlers* nil]
(let [var (or (env/with-compiler-env (st) (resolve-var env sym))
(some #(get-macro-var env sym %) (all-macros-ns)))]
(when var
(-> (cond-> var
(not (:ns var))
(assoc :ns (symbol (namespace (:name var))))
(= (namespace (:name var)) (str (:ns var)))
(update :name #(symbol (name %))))
(update :ns (comp symbol drop-macros-suffix str)))))))

(defn- get-aenv []
(assoc (ana/empty-env)
:ns (get-namespace @current-ns)
:context :expr))

(defn- undo-reader-conditional-spacing
"Undoes the effect that wrapping a reader conditional around
a defn has on a docstring."
[s]
;; We look for five spaces (or six, in case that the docstring
;; is not aligned under the first quote) after the first newline
;; (or two, in case the doctring has an unpadded blank line
;; after the first), and then replace all five (or six) spaces
;; after newlines with two.
(when-not (nil? s)
(if (re-find #"[^\n]*\n\n?\s{5,6}\S.*" s)
(string/replace-all s #"\n ?" "\n ")
s)))

(defn- doc* [name]
(if-let [special-name ('{& fn catch try finally try} name)]
(doc* special-name)
(cond
;(special-doc-map name)
;(cljs.repl/print-doc (special-doc-map name))

;(repl-special-doc-map name)
;(cljs.repl/print-doc (repl-special-doc name))

;(get-namespace name)
;(cljs.repl/print-doc (select-keys (get-namespace name) [:name :doc]))

(get-var (get-aenv) name)
(symbol (with-out-str (print-doc (let [aenv (get-aenv)
var (get-var aenv name)
m (-> (select-keys var
[:ns :name :doc :forms :arglists :macro :url])
(update-in [:doc] undo-reader-conditional-spacing)
(merge
{:forms (-> var :meta :forms second)
:arglists (-> var :meta :arglists second)}))]
(cond-> (update-in m [:name] clojure.core/name)
(:protocol-symbol var)
(assoc :protocol true
:methods
(->> (get-in var [:protocol-info :methods])
(map (fn [[fname sigs]]
[fname {:doc (:doc
(get-var aenv
(symbol (str (:ns var)) (str fname))))
:arglists (seq sigs)}]))
(into {})))))))))))

3 changes: 2 additions & 1 deletion src/klipse/lang/clojure/io.cljs
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,7 @@

(def skip-ns-macros #{'cljs.core
'cljs.pprint
'cljs.repl
'cljs.env.macros
'cljs.analyzer.macros
'cljs.js
Expand Down Expand Up @@ -138,7 +139,7 @@
(src-cb nil)))))

(defn cached-macro-ns-regexp []
(:clojure_cached_macro_ns_regexp (klipse-settings) #"cljs\.core\.[async|match].*|clojure\.math\.macros|gadjett\.core|cljs\.test|clojure.test.check.*|reagent\..*|om\..*|cljs\.spec.*"))
(:clojure_cached_macro_ns_regexp (klipse-settings) #"klipse\..*|cljs\.core\.[async|match].*|clojure\.math\.macros|gadjett\.core|cljs\.test|clojure.test.check.*|reagent\..*|om\..*|cljs\.spec.*"))

(defn cached-macro-ns? [name]
(re-matches (cached-macro-ns-regexp) (str name)))
Expand Down