mirror of
https://github.com/janet-lang/janet
synced 2024-11-28 19:19:53 +00:00
Merge pull request #602 from pyrmont/feature.module-docstrings
Display module-level docstrings with (doc)
This commit is contained in:
commit
0acf167e84
@ -1745,346 +1745,6 @@
|
|||||||
|
|
||||||
~(do ,;(reverse stack)))
|
~(do ,;(reverse stack)))
|
||||||
|
|
||||||
###
|
|
||||||
###
|
|
||||||
### Documentation
|
|
||||||
###
|
|
||||||
###
|
|
||||||
|
|
||||||
(defn- env-walk
|
|
||||||
[pred &opt env local]
|
|
||||||
(default env (fiber/getenv (fiber/current)))
|
|
||||||
(def envs @[])
|
|
||||||
(do (var e env) (while e (array/push envs e) (set e (table/getproto e)) (if local (break))))
|
|
||||||
(def ret-set @{})
|
|
||||||
(loop [envi :in envs
|
|
||||||
k :keys envi
|
|
||||||
:when (pred k)]
|
|
||||||
(put ret-set k true))
|
|
||||||
(sort (keys ret-set)))
|
|
||||||
|
|
||||||
(defn all-bindings
|
|
||||||
`Get all symbols available in an environment. Defaults to the current
|
|
||||||
fiber's environment. If local is truthy, will not show inherited bindings
|
|
||||||
(from prototype tables).`
|
|
||||||
[&opt env local]
|
|
||||||
(env-walk symbol? env local))
|
|
||||||
|
|
||||||
(defn all-dynamics
|
|
||||||
`Get all dynamic bindings in an environment. Defaults to the current
|
|
||||||
fiber's environment. If local is truthy, will not show inherited bindings
|
|
||||||
(from prototype tables).`
|
|
||||||
[&opt env local]
|
|
||||||
(env-walk keyword? env local))
|
|
||||||
|
|
||||||
(defn doc-format
|
|
||||||
`Reformat a docstring to wrap a certain width. Docstrings can either be plaintext
|
|
||||||
or a subset of markdown. This allows a long single line of prose or formatted text to be
|
|
||||||
a well-formed docstring. Returns a buffer containing the formatted text.`
|
|
||||||
[str &opt width indent]
|
|
||||||
(default indent 4)
|
|
||||||
(def max-width (- (or width (dyn :doc-width 80)) 8))
|
|
||||||
(def len (length str))
|
|
||||||
(def res @"")
|
|
||||||
(var pos 0)
|
|
||||||
(def line @"")
|
|
||||||
(var line-width 0)
|
|
||||||
(def levels @[0])
|
|
||||||
(var leading 0)
|
|
||||||
(var c nil)
|
|
||||||
|
|
||||||
(set pos 0)
|
|
||||||
|
|
||||||
(defn skip-line-indent []
|
|
||||||
(var pos* pos)
|
|
||||||
(set c (get str pos*))
|
|
||||||
(while (and c
|
|
||||||
(not= 10 c)
|
|
||||||
(= 32 c))
|
|
||||||
(set c (get str (++ pos*))))
|
|
||||||
(set leading (- pos* pos))
|
|
||||||
(set pos pos*))
|
|
||||||
|
|
||||||
(defn update-levels []
|
|
||||||
(while (< leading (array/peek levels))
|
|
||||||
(array/pop levels)
|
|
||||||
(if (empty? levels) (break))))
|
|
||||||
|
|
||||||
(defn start-nl? []
|
|
||||||
(= 10 (get str pos)))
|
|
||||||
|
|
||||||
(defn start-fcb? []
|
|
||||||
(and (= 96 (get str (+ pos)))
|
|
||||||
(= 96 (get str (+ pos 1)))
|
|
||||||
(= 96 (get str (+ pos 2)))))
|
|
||||||
|
|
||||||
(defn end-fcb? []
|
|
||||||
(and (= 96 (get str (+ pos)))
|
|
||||||
(= 96 (get str (+ pos 1)))
|
|
||||||
(= 96 (get str (+ pos 2)))
|
|
||||||
(= 10 (get str (+ pos 3)))))
|
|
||||||
|
|
||||||
(defn start-icb? []
|
|
||||||
(and (not= leading (array/peek levels))
|
|
||||||
(or (= 4 leading)
|
|
||||||
(= 4 (- leading (array/peek levels))))))
|
|
||||||
|
|
||||||
(defn start-ul? []
|
|
||||||
(var pos* pos)
|
|
||||||
(var c* (get str pos*))
|
|
||||||
(while (and c* (= 32 c*))
|
|
||||||
(set c* (get str (++ pos*))))
|
|
||||||
(and (or (= 42 c*)
|
|
||||||
(= 43 c*)
|
|
||||||
(= 45 c*))
|
|
||||||
(= 32 (get str (+ pos* 1)))))
|
|
||||||
|
|
||||||
(defn start-ol? []
|
|
||||||
(var pos* pos)
|
|
||||||
(var c* (get str pos*))
|
|
||||||
(while (and c* (= 32 c*))
|
|
||||||
(set c* (get str (++ pos*))))
|
|
||||||
(while (and c*
|
|
||||||
(<= 48 c*)
|
|
||||||
(>= 57 c*))
|
|
||||||
(set c* (get str (++ pos*))))
|
|
||||||
(set c* (get str (-- pos*)))
|
|
||||||
(and (<= 48 c*)
|
|
||||||
(>= 57 c*)
|
|
||||||
(= 46 (get str (+ pos* 1)))
|
|
||||||
(= 32 (get str (+ pos* 2)))))
|
|
||||||
|
|
||||||
(defn push-line []
|
|
||||||
(buffer/push-string res (buffer/new-filled indent 32))
|
|
||||||
(set c (get str pos))
|
|
||||||
(while (and c (not= 10 c))
|
|
||||||
(buffer/push-byte res c)
|
|
||||||
(set c (get str (++ pos))))
|
|
||||||
(buffer/push-byte res 10)
|
|
||||||
(++ pos))
|
|
||||||
|
|
||||||
(defn push-bullet []
|
|
||||||
(var pos* pos)
|
|
||||||
(buffer/push-string line (buffer/new-filled leading 32))
|
|
||||||
(set c (get str pos*))
|
|
||||||
# Add bullet
|
|
||||||
(while (and c (not= 32 c))
|
|
||||||
(buffer/push-byte line c)
|
|
||||||
(set c (get str (++ pos*))))
|
|
||||||
# Add item indentation
|
|
||||||
(while (= 32 c)
|
|
||||||
(buffer/push-byte line c)
|
|
||||||
(set c (get str (++ pos*))))
|
|
||||||
# Record indentation if necessary
|
|
||||||
(def item-indent (+ leading (- pos* pos)))
|
|
||||||
(when (not= item-indent (array/peek levels))
|
|
||||||
(array/push levels item-indent))
|
|
||||||
# Update line width
|
|
||||||
(+= line-width item-indent)
|
|
||||||
# Update position
|
|
||||||
(set pos pos*))
|
|
||||||
|
|
||||||
(defn push-word [hang-indent]
|
|
||||||
(def word @"")
|
|
||||||
(var word-len 0)
|
|
||||||
# Build a word
|
|
||||||
(while (and c
|
|
||||||
(not= 10 c)
|
|
||||||
(not= 32 c))
|
|
||||||
(buffer/push-byte word c)
|
|
||||||
(++ word-len)
|
|
||||||
(set c (get str (++ pos))))
|
|
||||||
# Start new line if necessary
|
|
||||||
(when (> (+ line-width word-len) max-width)
|
|
||||||
# Push existing line
|
|
||||||
(buffer/push-byte line 10)
|
|
||||||
(buffer/push-string res line)
|
|
||||||
(buffer/clear line)
|
|
||||||
# Indent new line
|
|
||||||
(buffer/push-string line (buffer/new-filled hang-indent 32))
|
|
||||||
(set line-width hang-indent))
|
|
||||||
# Add single space if not beginning of line
|
|
||||||
(when (not= line-width hang-indent)
|
|
||||||
(buffer/push-byte line 32)
|
|
||||||
(++ line-width))
|
|
||||||
# Push word onto line
|
|
||||||
(buffer/push-string line word)
|
|
||||||
(set line-width (+ line-width word-len)))
|
|
||||||
|
|
||||||
(defn push-nl []
|
|
||||||
(when (< pos len)
|
|
||||||
(buffer/push-byte res 10)
|
|
||||||
(++ pos)))
|
|
||||||
|
|
||||||
(defn push-list []
|
|
||||||
(update-levels)
|
|
||||||
# Indent first line
|
|
||||||
(buffer/push-string line (buffer/new-filled indent 32))
|
|
||||||
(set line-width indent)
|
|
||||||
# Add bullet
|
|
||||||
(push-bullet)
|
|
||||||
# Add words
|
|
||||||
(set c (get str pos))
|
|
||||||
(while (and c
|
|
||||||
(not= 10 c))
|
|
||||||
# Skip spaces
|
|
||||||
(while (= 32 c)
|
|
||||||
(set c (get str (++ pos))))
|
|
||||||
# Add word
|
|
||||||
(push-word (+ indent (array/peek levels)))
|
|
||||||
(def old-c c)
|
|
||||||
(set c (get str (++ pos)))
|
|
||||||
# Check if next line is a new item
|
|
||||||
(when (and (= 10 old-c)
|
|
||||||
(or (start-ul?)
|
|
||||||
(start-ol?)))
|
|
||||||
(set c (get str (-- pos)))))
|
|
||||||
# Add final line
|
|
||||||
(buffer/push-string res line)
|
|
||||||
(buffer/clear line)
|
|
||||||
# Move position back for newline
|
|
||||||
(-- pos)
|
|
||||||
(push-nl))
|
|
||||||
|
|
||||||
(defn push-fcb []
|
|
||||||
(update-levels)
|
|
||||||
(push-line)
|
|
||||||
(while (and (< pos len) (not (end-fcb?)))
|
|
||||||
(push-line))
|
|
||||||
(push-line))
|
|
||||||
|
|
||||||
(defn push-icb []
|
|
||||||
(buffer/push-string res (buffer/new-filled leading 32))
|
|
||||||
(push-line)
|
|
||||||
(while (and (< pos len) (not (start-nl?)))
|
|
||||||
(push-line))
|
|
||||||
(push-nl))
|
|
||||||
|
|
||||||
(defn push-p []
|
|
||||||
(update-levels)
|
|
||||||
# Set up the indentation
|
|
||||||
(def para-indent (+ indent (array/peek levels)))
|
|
||||||
# Indent first line
|
|
||||||
(buffer/push-string line (buffer/new-filled para-indent 32))
|
|
||||||
(set line-width para-indent)
|
|
||||||
# Add words
|
|
||||||
(set c (get str pos))
|
|
||||||
(while (and c (not= 10 c))
|
|
||||||
# Skip spaces
|
|
||||||
(while (= 32 c)
|
|
||||||
(set c (get str (++ pos))))
|
|
||||||
# Add word
|
|
||||||
(push-word para-indent)
|
|
||||||
(set c (get str (++ pos))))
|
|
||||||
# Add final line
|
|
||||||
(buffer/push-string res line)
|
|
||||||
(buffer/clear line)
|
|
||||||
# Move position back for newline
|
|
||||||
(-- pos)
|
|
||||||
(push-nl)
|
|
||||||
(push-nl))
|
|
||||||
|
|
||||||
(while (< pos len)
|
|
||||||
(skip-line-indent)
|
|
||||||
(cond
|
|
||||||
(start-nl?)
|
|
||||||
(push-nl)
|
|
||||||
|
|
||||||
(start-ul?)
|
|
||||||
(push-list)
|
|
||||||
|
|
||||||
(start-ol?)
|
|
||||||
(push-list)
|
|
||||||
|
|
||||||
(start-fcb?)
|
|
||||||
(push-fcb)
|
|
||||||
|
|
||||||
(start-icb?)
|
|
||||||
(push-icb)
|
|
||||||
|
|
||||||
(push-p)))
|
|
||||||
res)
|
|
||||||
|
|
||||||
(defn- print-index
|
|
||||||
"Print bindings in the current environment given a filter function"
|
|
||||||
[fltr]
|
|
||||||
(def bindings (filter fltr (all-bindings)))
|
|
||||||
(def dynamics (map describe (filter fltr (all-dynamics))))
|
|
||||||
(print)
|
|
||||||
(print (doc-format (string "Bindings:\n\n" (string/join bindings " "))))
|
|
||||||
(print)
|
|
||||||
(print (doc-format (string "Dynamics:\n\n" (string/join dynamics " "))))
|
|
||||||
(print "\n Use (doc sym) for more information on a binding.\n"))
|
|
||||||
|
|
||||||
(defn- print-module-entry
|
|
||||||
[x]
|
|
||||||
(def bind-type
|
|
||||||
(string " "
|
|
||||||
(cond
|
|
||||||
(x :ref) (string :var " (" (type (in (x :ref) 0)) ")")
|
|
||||||
(x :macro) :macro
|
|
||||||
(type (x :value)))
|
|
||||||
"\n"))
|
|
||||||
(def sm (x :source-map))
|
|
||||||
(def d (x :doc))
|
|
||||||
(print "\n\n"
|
|
||||||
(if d bind-type "")
|
|
||||||
(if-let [[path line col] sm]
|
|
||||||
(string " " path " on line " line ", column " col "\n") "")
|
|
||||||
(if (or d sm) "\n" "")
|
|
||||||
(if d (doc-format d) " no documentation found.")
|
|
||||||
"\n\n"))
|
|
||||||
|
|
||||||
(def module/cache
|
|
||||||
"Table mapping loaded module identifiers to their environments."
|
|
||||||
@{})
|
|
||||||
|
|
||||||
(defn doc*
|
|
||||||
"Get the documentation for a symbol in a given environment. Function form of doc."
|
|
||||||
[&opt sym]
|
|
||||||
|
|
||||||
(cond
|
|
||||||
(string? sym)
|
|
||||||
(print-index (fn [x] (string/find sym x)))
|
|
||||||
|
|
||||||
sym
|
|
||||||
(do
|
|
||||||
(def x (dyn sym))
|
|
||||||
(if (not x)
|
|
||||||
(print "symbol " sym " not found.")
|
|
||||||
(print-module-entry x)))
|
|
||||||
|
|
||||||
# else
|
|
||||||
(print-index identity)))
|
|
||||||
|
|
||||||
(defmacro doc
|
|
||||||
`Shows documentation for the given symbol, or can show a list of available bindings.
|
|
||||||
If sym is a symbol, will look for documentation for that symbol. If sym is a string
|
|
||||||
or is not provided, will show all lexical and dynamic bindings in the current environment with
|
|
||||||
that prefix (all bindings will be shown if no prefix is given).`
|
|
||||||
[&opt sym]
|
|
||||||
~(,doc* ',sym))
|
|
||||||
|
|
||||||
(defn doc-of
|
|
||||||
`Searches all loaded modules in module/cache for a given binding and prints out its documentation.
|
|
||||||
This does a search by value instead of by name. Returns nil.`
|
|
||||||
[x]
|
|
||||||
(var found false)
|
|
||||||
(loop [module-set :in [[root-env] module/cache]
|
|
||||||
module :in module-set
|
|
||||||
value :in module]
|
|
||||||
(let [check (or (get value :ref) (get value :value))]
|
|
||||||
(when (= check x)
|
|
||||||
(print-module-entry value)
|
|
||||||
(set found true)
|
|
||||||
(break))))
|
|
||||||
(if-not found
|
|
||||||
(print "documentation for value " x " not found.")))
|
|
||||||
|
|
||||||
(undef env-walk)
|
|
||||||
(undef print-index)
|
|
||||||
(undef print-module-entry)
|
|
||||||
|
|
||||||
###
|
###
|
||||||
###
|
###
|
||||||
### Macro Expansion
|
### Macro Expansion
|
||||||
@ -2648,6 +2308,10 @@
|
|||||||
(defn- check-is-dep [x] (unless (or (string/has-prefix? "/" x) (string/has-prefix? "." x)) x))
|
(defn- check-is-dep [x] (unless (or (string/has-prefix? "/" x) (string/has-prefix? "." x)) x))
|
||||||
(defn- check-project-relative [x] (if (string/has-prefix? "/" x) x))
|
(defn- check-project-relative [x] (if (string/has-prefix? "/" x) x))
|
||||||
|
|
||||||
|
(def module/cache
|
||||||
|
"Table mapping loaded module identifiers to their environments."
|
||||||
|
@{})
|
||||||
|
|
||||||
(def module/paths
|
(def module/paths
|
||||||
```
|
```
|
||||||
The list of paths to look for modules, templated for module/expand-path.
|
The list of paths to look for modules, templated for module/expand-path.
|
||||||
@ -2906,6 +2570,350 @@
|
|||||||
[& modules]
|
[& modules]
|
||||||
~(do ,;(map |~(,import* ,(string $) :prefix "") modules)))
|
~(do ,;(map |~(,import* ,(string $) :prefix "") modules)))
|
||||||
|
|
||||||
|
###
|
||||||
|
###
|
||||||
|
### Documentation
|
||||||
|
###
|
||||||
|
###
|
||||||
|
|
||||||
|
(defn- env-walk
|
||||||
|
[pred &opt env local]
|
||||||
|
(default env (fiber/getenv (fiber/current)))
|
||||||
|
(def envs @[])
|
||||||
|
(do (var e env) (while e (array/push envs e) (set e (table/getproto e)) (if local (break))))
|
||||||
|
(def ret-set @{})
|
||||||
|
(loop [envi :in envs
|
||||||
|
k :keys envi
|
||||||
|
:when (pred k)]
|
||||||
|
(put ret-set k true))
|
||||||
|
(sort (keys ret-set)))
|
||||||
|
|
||||||
|
(defn all-bindings
|
||||||
|
`Get all symbols available in an environment. Defaults to the current
|
||||||
|
fiber's environment. If local is truthy, will not show inherited bindings
|
||||||
|
(from prototype tables).`
|
||||||
|
[&opt env local]
|
||||||
|
(env-walk symbol? env local))
|
||||||
|
|
||||||
|
(defn all-dynamics
|
||||||
|
`Get all dynamic bindings in an environment. Defaults to the current
|
||||||
|
fiber's environment. If local is truthy, will not show inherited bindings
|
||||||
|
(from prototype tables).`
|
||||||
|
[&opt env local]
|
||||||
|
(env-walk keyword? env local))
|
||||||
|
|
||||||
|
(defn doc-format
|
||||||
|
`Reformat a docstring to wrap a certain width. Docstrings can either be plaintext
|
||||||
|
or a subset of markdown. This allows a long single line of prose or formatted text to be
|
||||||
|
a well-formed docstring. Returns a buffer containing the formatted text.`
|
||||||
|
[str &opt width indent]
|
||||||
|
(default indent 4)
|
||||||
|
(def max-width (- (or width (dyn :doc-width 80)) 8))
|
||||||
|
(def len (length str))
|
||||||
|
(def res @"")
|
||||||
|
(var pos 0)
|
||||||
|
(def line @"")
|
||||||
|
(var line-width 0)
|
||||||
|
(def levels @[0])
|
||||||
|
(var leading 0)
|
||||||
|
(var c nil)
|
||||||
|
|
||||||
|
(set pos 0)
|
||||||
|
|
||||||
|
(defn skip-line-indent []
|
||||||
|
(var pos* pos)
|
||||||
|
(set c (get str pos*))
|
||||||
|
(while (and c
|
||||||
|
(not= 10 c)
|
||||||
|
(= 32 c))
|
||||||
|
(set c (get str (++ pos*))))
|
||||||
|
(set leading (- pos* pos))
|
||||||
|
(set pos pos*))
|
||||||
|
|
||||||
|
(defn update-levels []
|
||||||
|
(while (< leading (array/peek levels))
|
||||||
|
(array/pop levels)
|
||||||
|
(if (empty? levels) (break))))
|
||||||
|
|
||||||
|
(defn start-nl? []
|
||||||
|
(= 10 (get str pos)))
|
||||||
|
|
||||||
|
(defn start-fcb? []
|
||||||
|
(and (= 96 (get str (+ pos)))
|
||||||
|
(= 96 (get str (+ pos 1)))
|
||||||
|
(= 96 (get str (+ pos 2)))))
|
||||||
|
|
||||||
|
(defn end-fcb? []
|
||||||
|
(and (= 96 (get str (+ pos)))
|
||||||
|
(= 96 (get str (+ pos 1)))
|
||||||
|
(= 96 (get str (+ pos 2)))
|
||||||
|
(= 10 (get str (+ pos 3)))))
|
||||||
|
|
||||||
|
(defn start-icb? []
|
||||||
|
(and (not= leading (array/peek levels))
|
||||||
|
(or (= 4 leading)
|
||||||
|
(= 4 (- leading (array/peek levels))))))
|
||||||
|
|
||||||
|
(defn start-ul? []
|
||||||
|
(var pos* pos)
|
||||||
|
(var c* (get str pos*))
|
||||||
|
(while (and c* (= 32 c*))
|
||||||
|
(set c* (get str (++ pos*))))
|
||||||
|
(and (or (= 42 c*)
|
||||||
|
(= 43 c*)
|
||||||
|
(= 45 c*))
|
||||||
|
(= 32 (get str (+ pos* 1)))))
|
||||||
|
|
||||||
|
(defn start-ol? []
|
||||||
|
(var pos* pos)
|
||||||
|
(var c* (get str pos*))
|
||||||
|
(while (and c* (= 32 c*))
|
||||||
|
(set c* (get str (++ pos*))))
|
||||||
|
(while (and c*
|
||||||
|
(<= 48 c*)
|
||||||
|
(>= 57 c*))
|
||||||
|
(set c* (get str (++ pos*))))
|
||||||
|
(set c* (get str (-- pos*)))
|
||||||
|
(and (<= 48 c*)
|
||||||
|
(>= 57 c*)
|
||||||
|
(= 46 (get str (+ pos* 1)))
|
||||||
|
(= 32 (get str (+ pos* 2)))))
|
||||||
|
|
||||||
|
(defn push-line []
|
||||||
|
(buffer/push-string res (buffer/new-filled indent 32))
|
||||||
|
(set c (get str pos))
|
||||||
|
(while (and c (not= 10 c))
|
||||||
|
(buffer/push-byte res c)
|
||||||
|
(set c (get str (++ pos))))
|
||||||
|
(buffer/push-byte res 10)
|
||||||
|
(++ pos))
|
||||||
|
|
||||||
|
(defn push-bullet []
|
||||||
|
(var pos* pos)
|
||||||
|
(buffer/push-string line (buffer/new-filled leading 32))
|
||||||
|
(set c (get str pos*))
|
||||||
|
# Add bullet
|
||||||
|
(while (and c (not= 32 c))
|
||||||
|
(buffer/push-byte line c)
|
||||||
|
(set c (get str (++ pos*))))
|
||||||
|
# Add item indentation
|
||||||
|
(while (= 32 c)
|
||||||
|
(buffer/push-byte line c)
|
||||||
|
(set c (get str (++ pos*))))
|
||||||
|
# Record indentation if necessary
|
||||||
|
(def item-indent (+ leading (- pos* pos)))
|
||||||
|
(when (not= item-indent (array/peek levels))
|
||||||
|
(array/push levels item-indent))
|
||||||
|
# Update line width
|
||||||
|
(+= line-width item-indent)
|
||||||
|
# Update position
|
||||||
|
(set pos pos*))
|
||||||
|
|
||||||
|
(defn push-word [hang-indent]
|
||||||
|
(def word @"")
|
||||||
|
(var word-len 0)
|
||||||
|
# Build a word
|
||||||
|
(while (and c
|
||||||
|
(not= 10 c)
|
||||||
|
(not= 32 c))
|
||||||
|
(buffer/push-byte word c)
|
||||||
|
(++ word-len)
|
||||||
|
(set c (get str (++ pos))))
|
||||||
|
# Start new line if necessary
|
||||||
|
(when (> (+ line-width word-len) max-width)
|
||||||
|
# Push existing line
|
||||||
|
(buffer/push-byte line 10)
|
||||||
|
(buffer/push-string res line)
|
||||||
|
(buffer/clear line)
|
||||||
|
# Indent new line
|
||||||
|
(buffer/push-string line (buffer/new-filled hang-indent 32))
|
||||||
|
(set line-width hang-indent))
|
||||||
|
# Add single space if not beginning of line
|
||||||
|
(when (not= line-width hang-indent)
|
||||||
|
(buffer/push-byte line 32)
|
||||||
|
(++ line-width))
|
||||||
|
# Push word onto line
|
||||||
|
(buffer/push-string line word)
|
||||||
|
(set line-width (+ line-width word-len)))
|
||||||
|
|
||||||
|
(defn push-nl []
|
||||||
|
(when (< pos len)
|
||||||
|
(buffer/push-byte res 10)
|
||||||
|
(++ pos)))
|
||||||
|
|
||||||
|
(defn push-list []
|
||||||
|
(update-levels)
|
||||||
|
# Indent first line
|
||||||
|
(buffer/push-string line (buffer/new-filled indent 32))
|
||||||
|
(set line-width indent)
|
||||||
|
# Add bullet
|
||||||
|
(push-bullet)
|
||||||
|
# Add words
|
||||||
|
(set c (get str pos))
|
||||||
|
(while (and c
|
||||||
|
(not= 10 c))
|
||||||
|
# Skip spaces
|
||||||
|
(while (= 32 c)
|
||||||
|
(set c (get str (++ pos))))
|
||||||
|
# Add word
|
||||||
|
(push-word (+ indent (array/peek levels)))
|
||||||
|
(def old-c c)
|
||||||
|
(set c (get str (++ pos)))
|
||||||
|
# Check if next line is a new item
|
||||||
|
(when (and (= 10 old-c)
|
||||||
|
(or (start-ul?)
|
||||||
|
(start-ol?)))
|
||||||
|
(set c (get str (-- pos)))))
|
||||||
|
# Add final line
|
||||||
|
(buffer/push-string res line)
|
||||||
|
(buffer/clear line)
|
||||||
|
# Move position back for newline
|
||||||
|
(-- pos)
|
||||||
|
(push-nl))
|
||||||
|
|
||||||
|
(defn push-fcb []
|
||||||
|
(update-levels)
|
||||||
|
(push-line)
|
||||||
|
(while (and (< pos len) (not (end-fcb?)))
|
||||||
|
(push-line))
|
||||||
|
(push-line))
|
||||||
|
|
||||||
|
(defn push-icb []
|
||||||
|
(buffer/push-string res (buffer/new-filled leading 32))
|
||||||
|
(push-line)
|
||||||
|
(while (and (< pos len) (not (start-nl?)))
|
||||||
|
(push-line))
|
||||||
|
(push-nl))
|
||||||
|
|
||||||
|
(defn push-p []
|
||||||
|
(update-levels)
|
||||||
|
# Set up the indentation
|
||||||
|
(def para-indent (+ indent (array/peek levels)))
|
||||||
|
# Indent first line
|
||||||
|
(buffer/push-string line (buffer/new-filled para-indent 32))
|
||||||
|
(set line-width para-indent)
|
||||||
|
# Add words
|
||||||
|
(set c (get str pos))
|
||||||
|
(while (and c (not= 10 c))
|
||||||
|
# Skip spaces
|
||||||
|
(while (= 32 c)
|
||||||
|
(set c (get str (++ pos))))
|
||||||
|
# Add word
|
||||||
|
(push-word para-indent)
|
||||||
|
(set c (get str (++ pos))))
|
||||||
|
# Add final line
|
||||||
|
(buffer/push-string res line)
|
||||||
|
(buffer/clear line)
|
||||||
|
# Move position back for newline
|
||||||
|
(-- pos)
|
||||||
|
(push-nl)
|
||||||
|
(push-nl))
|
||||||
|
|
||||||
|
(while (< pos len)
|
||||||
|
(skip-line-indent)
|
||||||
|
(cond
|
||||||
|
(start-nl?)
|
||||||
|
(push-nl)
|
||||||
|
|
||||||
|
(start-ul?)
|
||||||
|
(push-list)
|
||||||
|
|
||||||
|
(start-ol?)
|
||||||
|
(push-list)
|
||||||
|
|
||||||
|
(start-fcb?)
|
||||||
|
(push-fcb)
|
||||||
|
|
||||||
|
(start-icb?)
|
||||||
|
(push-icb)
|
||||||
|
|
||||||
|
(push-p)))
|
||||||
|
res)
|
||||||
|
|
||||||
|
(defn- print-index
|
||||||
|
"Print bindings in the current environment given a filter function"
|
||||||
|
[fltr]
|
||||||
|
(def bindings (filter fltr (all-bindings)))
|
||||||
|
(def dynamics (map describe (filter fltr (all-dynamics))))
|
||||||
|
(print)
|
||||||
|
(print (doc-format (string "Bindings:\n\n" (string/join bindings " "))))
|
||||||
|
(print)
|
||||||
|
(print (doc-format (string "Dynamics:\n\n" (string/join dynamics " "))))
|
||||||
|
(print "\n Use (doc sym) for more information on a binding.\n"))
|
||||||
|
|
||||||
|
(defn- print-module-entry
|
||||||
|
[x]
|
||||||
|
(def bind-type
|
||||||
|
(string " "
|
||||||
|
(cond
|
||||||
|
(x :ref) (string :var " (" (type (in (x :ref) 0)) ")")
|
||||||
|
(x :macro) :macro
|
||||||
|
(x :module) (string :module " (" (x :kind) ")")
|
||||||
|
(type (x :value)))
|
||||||
|
"\n"))
|
||||||
|
(def sm (x :source-map))
|
||||||
|
(def d (x :doc))
|
||||||
|
(print "\n\n"
|
||||||
|
(when d bind-type)
|
||||||
|
(when-let [[path line col] sm]
|
||||||
|
(string " " path (when (and line col) (string " on line " line ", column " col)) "\n"))
|
||||||
|
(when (or d sm) "\n")
|
||||||
|
(if d (doc-format d) " no documentation found.")
|
||||||
|
"\n\n"))
|
||||||
|
|
||||||
|
(defn doc*
|
||||||
|
"Get the documentation for a symbol in a given environment. Function form of doc."
|
||||||
|
[&opt sym]
|
||||||
|
|
||||||
|
(cond
|
||||||
|
(string? sym)
|
||||||
|
(print-index (fn [x] (string/find sym x)))
|
||||||
|
|
||||||
|
sym
|
||||||
|
(do
|
||||||
|
(def x (dyn sym))
|
||||||
|
(if (not x)
|
||||||
|
(do
|
||||||
|
(def [fullpath mod-kind] (module/find (string sym)))
|
||||||
|
(if-let [mod-env (in module/cache fullpath)]
|
||||||
|
(print-module-entry {:module true
|
||||||
|
:kind mod-kind
|
||||||
|
:source-map [fullpath nil nil]
|
||||||
|
:doc (in mod-env :doc)})
|
||||||
|
(print "symbol " sym " not found.")))
|
||||||
|
(print-module-entry x)))
|
||||||
|
|
||||||
|
# else
|
||||||
|
(print-index identity)))
|
||||||
|
|
||||||
|
(defmacro doc
|
||||||
|
`Shows documentation for the given symbol, or can show a list of available bindings.
|
||||||
|
If sym is a symbol, will look for documentation for that symbol. If sym is a string
|
||||||
|
or is not provided, will show all lexical and dynamic bindings in the current environment with
|
||||||
|
that prefix (all bindings will be shown if no prefix is given).`
|
||||||
|
[&opt sym]
|
||||||
|
~(,doc* ',sym))
|
||||||
|
|
||||||
|
(defn doc-of
|
||||||
|
`Searches all loaded modules in module/cache for a given binding and prints out its documentation.
|
||||||
|
This does a search by value instead of by name. Returns nil.`
|
||||||
|
[x]
|
||||||
|
(var found false)
|
||||||
|
(loop [module-set :in [[root-env] module/cache]
|
||||||
|
module :in module-set
|
||||||
|
value :in module]
|
||||||
|
(let [check (or (get value :ref) (get value :value))]
|
||||||
|
(when (= check x)
|
||||||
|
(print-module-entry value)
|
||||||
|
(set found true)
|
||||||
|
(break))))
|
||||||
|
(if-not found
|
||||||
|
(print "documentation for value " x " not found.")))
|
||||||
|
|
||||||
|
(undef env-walk)
|
||||||
|
(undef print-index)
|
||||||
|
(undef print-module-entry)
|
||||||
|
|
||||||
###
|
###
|
||||||
###
|
###
|
||||||
### Debugger
|
### Debugger
|
||||||
|
Loading…
Reference in New Issue
Block a user