From 65acb2f3cbdd7c337333522b114f10ce5ab445cf Mon Sep 17 00:00:00 2001 From: Scott Bauer Date: Tue, 13 Dec 2016 23:34:26 -0500 Subject: [PATCH] Add some docstrings to clojure.cljs and eval.clj namespaces (#93) Add docstrings to some functions and make use of the new :doc key. Various misc formatting doc changes too. --- .../src/lighttable/nrepl/eval.clj | 21 +++- src/lt/plugins/clojure.cljs | 100 ++++++++++++++---- 2 files changed, 98 insertions(+), 23 deletions(-) diff --git a/lein-light-nrepl/src/lighttable/nrepl/eval.clj b/lein-light-nrepl/src/lighttable/nrepl/eval.clj index d006f12..107ded3 100644 --- a/lein-light-nrepl/src/lighttable/nrepl/eval.clj +++ b/lein-light-nrepl/src/lighttable/nrepl/eval.clj @@ -53,7 +53,18 @@ (if (instance? clojure.lang.IObj thing) (meta thing))) -(defn clean-serialize [res & [opts]] +(defn clean-serialize + "Stringify the result `res` into a form appropiate to its type. Defaults to + using function `pr-str` for most types. + + Allowed options: + + - `:print-length` - Restricts length of stringified results to it. Defaults to 1000. + - `:allow-var?` - Whether to return a var itself or its stringified version. + Defaults to nil. + - `:result` - Whether to return an atom itself or its content. Defaults to nil. + - `:verbatim` - Whether to return an string itself or its 'pr-str' version." + [res & [opts]] (binding [*print-length* (or (:print-length opts) *print-length* 1000)] (cond (fn? res) 'fn @@ -70,7 +81,8 @@ (and (string? res) (:verbatim opts)) res :else (pr-str res)))) -(defn truncate [v] +(defn truncate + [v] v) (defn ->result [opts f] @@ -118,7 +130,10 @@ (str (reduce str "" (repeat (:start meta 0) "\n")) code))) -(defn watch [v meta] +(defn watch + "Stringify result-value `v` with pretty-print, send it back to Light Table, + and then return the value itself to continue the evaling call." + [v meta] (let [ppv (with-out-str (pprint v)) data {:meta meta :result (subs ppv 0 (dec (count ppv)))}] (core/safe-respond-to (:obj meta) :editor.eval.clj.watch data)) diff --git a/src/lt/plugins/clojure.cljs b/src/lt/plugins/clojure.cljs index aaee789..a9d7cdd 100644 --- a/src/lt/plugins/clojure.cljs +++ b/src/lt/plugins/clojure.cljs @@ -68,6 +68,7 @@ (run-local-server (clients/client! :nrepl.client)))))) (behavior ::on-eval.clj + :desc "Clojure: Eval editor content" :triggers #{:eval} :reaction (fn [editor] (object/raise clj-lang :eval! {:origin editor @@ -75,6 +76,7 @@ :print-length (object/raise-reduce editor :clojure.print-length+ nil) :code (watches/watched-range editor nil nil nil))}))) (behavior ::on-eval.cljs + :desc "Clojure: Eval editor content" :triggers #{:eval} :reaction (fn [editor] (object/raise clj-lang :eval! {:origin editor @@ -87,6 +89,7 @@ "(set! js/COMPILED js/COMPILED-temp)"))}))) (behavior ::on-eval.one + :desc "Clojure: Eval a single form in editor" :triggers #{:eval.one} :reaction (fn [editor] (let [code (watches/watched-range editor nil nil nil) @@ -103,12 +106,21 @@ :info info})))) -(defn fill-placeholders [editor exp] +(defn fill-placeholders + "Replace editor-selection-flags, that is `__SELECTION*__`, inside `exp` with the currently + selected code in `editor`." + [editor exp] (-> exp (string/replace "__SELECTION*__" (pr-str (ed/selection editor))) (string/replace "__SELECTION__" (ed/selection editor)))) (behavior ::on-eval.custom + :desc "Clojure: Eval a form that has been wrapped by custom code" + :doc "Example: + + ``` + (eval (time form)) ;; instead of (eval form) + ```" :triggers #{:eval.custom} :reaction (fn [editor exp opts] (let [code (fill-placeholders editor exp) @@ -168,7 +180,7 @@ (defn lighttable-ui-project? "Determine if path is part of a project that evals to LightTable's process - e.g. LightTable plugin or LightTable itself" + (i.e., LightTable plugin or LightTable itself)." [path] (or (files/walk-up-find path "plugin.edn") (files/walk-up-find path "plugin.json") @@ -176,6 +188,8 @@ (= 'lighttable (second (reader/read-string (:content (files/open-sync project-file)))))))) (behavior ::eval! + :desc "Clojure: Send event information for evaluation." + :doc "This event information goes to the appropriate nREPL or LightTable-UI client." :triggers #{:eval!} :reaction (fn [this event] (let [{:keys [info origin]} event @@ -263,6 +277,7 @@ (notifos/done-working))) (behavior ::cljs-result + :desc "Clojure: Receive a cljs result and dispatch it" :triggers #{:editor.eval.cljs.result} :reaction (fn [obj res] (notifos/done-working) @@ -271,6 +286,7 @@ (object/raise obj ev res)))) (behavior ::cljs-result.replace + :desc "Clojure: Replace current selection with the result of an evaluation" :triggers #{:editor.eval.cljs.result.replace} :reaction (fn [obj res] (if-let [err (or (:stack res) (:ex res))] @@ -278,6 +294,7 @@ (ed/replace-selection obj (unescape-unicode (or (:result res) "")))))) (behavior ::cljs-result.statusbar + :desc "Clojure: Show the result of an evaluation on the statusbar" :triggers #{:editor.eval.cljs.result.statusbar} :reaction (fn [obj res] (if-let [err (or (:stack res) (:ex res))] @@ -285,6 +302,8 @@ (notifos/set-msg! (unescape-unicode (or (:result res) "")) {:class "result"})))) (behavior ::cljs-result.inline + :desc "Clojure: Show the resulting evaluation on inline widget" + :doc "The resulting evaluation is dispatched either as an exception or an inline-result." :triggers #{:editor.eval.cljs.result.inline} :reaction (fn [obj res] (let [meta (:meta res) @@ -295,6 +314,8 @@ (object/raise obj :editor.result (unescape-unicode (or (:result res) "")) loc))))) (behavior ::cljs-result.inline-at-cursor + :desc "Clojure: Show the resulting evaluation inline at cursor location" + :doc "This is similar to `::cljs-result.inline`, but puts the result as the cursor location." :triggers #{:editor.eval.cljs.result.inline-at-cursor} :reaction (fn [obj res] (let [meta (:meta res) @@ -316,6 +337,8 @@ :meta meta}))))) (behavior ::clj-result + :desc "Clojure: Receive an eval! result and dispatch it" + :doc "The dispatch is according to the appropiate result type. Defaults to `:inline`." :triggers #{:editor.eval.clj.result} :reaction (fn [obj res] (notifos/done-working) @@ -324,6 +347,7 @@ (object/raise obj ev res)))) (behavior ::clj-result.replace + :desc "Clojure: Replace current selection with the result" :triggers #{:editor.eval.clj.result.replace} :reaction (fn [obj res] (doseq [result (-> res :results) @@ -335,6 +359,7 @@ (ed/replace-selection obj (:result result)))))) (behavior ::clj-result.statusbar + :desc "Clojure: Show evaluation result on the statusbar" :triggers #{:editor.eval.clj.result.statusbar} :reaction (fn [obj res] (doseq [result (-> res :results) @@ -346,6 +371,8 @@ (notifos/set-msg! (:result result) {:class "result"}))))) (behavior ::clj-result.inline + :desc "Clojure: Display eval result inline" + :doc "Dispatches as an exception or an inline-result." :triggers #{:editor.eval.clj.result.inline} :reaction (fn [obj res] (doseq [result (-> res :results) @@ -354,10 +381,11 @@ :start-line (dec (:line meta))}]] (if (:stack result) (object/raise obj :editor.eval.clj.exception result :passed) - (do - (object/raise obj :editor.result (:result result) loc)))))) + (object/raise obj :editor.result (:result result) loc))))) (behavior ::clj-result.inline-at-cursor + :desc "Clojure: Display the eval result inline at cursor location" + :doc "This is similar to `::clj-result.inline`, but puts the result at the cursor location." :triggers #{:editor.eval.clj.result.inline-at-cursor} :reaction (fn [obj res] (doseq [result (-> res :results) @@ -366,8 +394,7 @@ :start-line (-> res :meta :start)}]] (if (:stack result) (object/raise obj :editor.eval.clj.exception result :passed) - (do - (object/raise obj :editor.result (:result result) loc)))))) + (object/raise obj :editor.result (:result result) loc))))) (behavior ::clj-result.return :triggers #{:editor.eval.clj.result.return} @@ -382,6 +409,7 @@ :meta meta}))))) (behavior ::clj-exception + :desc "Clojure: Display stacktrace information and summary in statusbar" :triggers #{:editor.eval.clj.exception} :reaction (fn [obj res passed?] (when-not passed? @@ -390,10 +418,13 @@ loc {:line (dec (:end-line meta)) :ch (:end-column meta 0) :start-line (dec (:line meta 1))}] (notifos/set-msg! (:result res) {:class "error"}) - (object/raise obj :editor.exception (:stack res) loc)) - )) + (object/raise obj :editor.exception (:stack res) loc)))) (behavior ::cljs-exception + :desc "Clojure: Display stacktrace information and summary in statusbar" + ;; Line below is too long to include, but will be useful after https://github.com/LightTable/LightTable/issues/2197 + :doc "Take the result of evaling a cljs form, which resulted in an exception, + and displays a message in the status bar and an exception widget with the stacktrace." :triggers #{:editor.eval.cljs.exception} :reaction (fn [obj res passed?] (when-not passed? @@ -413,8 +444,7 @@ msg "Unknown error")] (notifos/set-msg! msg {:class "error"}) - (object/raise obj :editor.exception stack loc)) - )) + (object/raise obj :editor.exception stack loc)))) (behavior ::eval-print :triggers #{:editor.eval.clj.print} @@ -424,8 +454,7 @@ :line (when (object/has-tag? this :nrepl.client) "stdout") :id (:id str) - :content (:out str)} - )))) + :content (:out str)})))) (behavior ::eval-print-err :triggers #{:editor.eval.clj.print.err} @@ -517,18 +546,36 @@ ;; watches ;;**************************************************** +;; For more information on watches check +;; +;; Original anouncement: https://groups.google.com/forum/#!msg/light-table-discussion/lyFzPGI2XMs/ec8T1OUPvMsJ +;; +;; Blog posts: http://scattered-thoughts.net/blog/2014/01/27/were-not-even-trying/?utm_source=dlvr.it&utm_medium=twitter +;; https://medium.com/@zindlerb/guide-to-light-table-watches-fad560f698d3#.oqwq991sx +;; +;; Rolex watches plugin: https://groups.google.com/forum/#!topic/light-table-discussion/NQWGC0vVHMY + (behavior ::cljs-watch-src + :desc "Clojure: Wraps the watched source code" + :doc "Wraps watched code to catch its result and send it back to LightTable, + while continuing normal evaluation of an expression." :triggers #{:watch.src+} :reaction (fn [editor cur meta src] (let [meta (assoc meta :ev :editor.eval.cljs.watch)] (str "(js/lttools.watch " src " (clj->js " (pr-str meta) "))")))) (behavior ::clj-watch-src + :desc "Clojure: Wraps the watched source code" + :doc "Wraps watched code to catch its result and send it back to LightTable, + while continuing normal evaluation of an expression." :triggers #{:watch.src+} :reaction (fn [editor cur meta src] (str "(lighttable.nrepl.eval/watch " src " " (pr-str meta) ")"))) -(defn fill-watch-placeholders [exp src meta watch] +(defn fill-watch-placeholders + "Replace editor-selection-flags (placeholders) for custom watches inside `exp` + with the src-code to be watched." + [exp src meta watch] (-> exp (string/replace "\n" " ") (string/replace "__SELECTION*__" (pr-str src)) @@ -537,12 +584,20 @@ (string/replace #"__\|(.*)\|__" watch))) (behavior ::cljs-watch-custom-src + :desc "Clojure: Prepare expression for watching" + :doc "The expression is prepared by filling its placeholders and wrapping its watcher-code + with custom call to `:editor.eval.cljs.watch`." :triggers #{:watch.custom.src+} :reaction (fn [editor cur meta opts src] - (let [watch (str "(js/lttools.raise " (:obj meta) " :editor.eval.cljs.watch {:meta " (pr-str (merge (dissoc opts :exp) meta)) " :result $1})")] + (let [watch (str "(js/lttools.raise " (:obj meta) + " :editor.eval.cljs.watch {:meta " (pr-str (merge (dissoc opts :exp) meta)) + " :result $1})")] (fill-watch-placeholders (:exp opts) src meta watch)))) (behavior ::clj-watch-custom-src + :desc "Clojure: Prepare expression for watching" + :doc "The exp is prepared by filling its placeholders and wrapping its watcher-code + with custom call to `:editor.eval.clj.watch`" :triggers #{:watch.custom.src+} :reaction (fn [editor cur meta opts src] (let [wrapped (if (:verbatim opts) @@ -578,6 +633,7 @@ ;;**************************************************** (behavior ::clj-doc + :desc "Clojure: Request docstring for symbol at cursor from nREPL" :triggers #{:editor.doc} :reaction (fn [editor] (let [token (find-symbol-at-cursor editor) @@ -593,8 +649,7 @@ :info info :origin editor :create try-connect}) - command info :only editor))) - )) + command info :only editor))))) (behavior ::print-clj-doc :triggers #{:editor.clj.doc} @@ -617,6 +672,7 @@ (assoc token-left :loc loc))))) (behavior ::cljs-doc + :desc "Clojure: Request docstring for symbol at cursor from nREPL" :triggers #{:editor.doc} :reaction (fn [editor] (let [token (find-symbol-at-cursor editor) @@ -643,16 +699,20 @@ (object/raise editor :editor.doc.show! result))))) (behavior ::clj-doc-search + :desc "Clojure: Add trigger for Clojure in language documentation search" + :doc "Links the 'Search language docs' input-text on the sidebar with a trigger to + `:docs.clj.search` to retrieve all the documentation on a user-input." :triggers #{:types+} :reaction (fn [this cur] - (conj cur {:label "clj" :trigger :docs.clj.search :file-types #{"Clojure"}}) - )) + (conj cur {:label "clj" :trigger :docs.clj.search :file-types #{"Clojure"}}))) (behavior ::cljs-doc-search + :desc "Clojure: Add trigger for ClojureScript in language documentation search" + :doc "Links the 'Search language docs' input-text on the sidebar with a trigger to + `:docs.cljs.search` to retrieve all the documentation on a user-input." :triggers #{:types+} :reaction (fn [this cur] - (conj cur {:label "cljs" :trigger :docs.cljs.search :file-types #{"ClojureScript"}}) - )) + (conj cur {:label "cljs" :trigger :docs.cljs.search :file-types #{"ClojureScript"}}))) ;;**************************************************** ;; autocomplete