~technomancy/fennel

This thread contains a patchset. You're looking at the original emails, but you may wish to use the patch review UI. Review patch
2 2

[PATCH] add ,apropos and ,apropos-doc repl commands

Details
Message ID
<20210718120428.57511-1-andreyorst@gmail.com>
DKIM signature
pass
Download raw message
Patch: +77 -1
This patch adds two new commands: ,apropos and ,apropos-doc
Both commands accept a Lua pattern as an input.

,apropos table%. will print all function names matching this pattern,
e.g. all functions from the table module

,aprops-doc works similarly, but instead of printing all names, prints
all docs for functions that match the pattern.
---
 changelog.md        |  1 +
 src/fennel/repl.fnl | 56 +++++++++++++++++++++++++++++++++++++++++++++
 test/repl.fnl       | 21 ++++++++++++++++-
 3 files changed, 77 insertions(+), 1 deletion(-)

diff --git a/changelog.md b/changelog.md
index c1da599..4091d44 100644
--- a/changelog.md
+++ b/changelog.md
@@ -4,6 +4,7 @@ Changes are **marked in bold** which could result in backwards-incompatibility.

## 0.10.0 / ???

* Add `,apropos pattern` and `,apropos-doc pattern` repl commands
* Deprecate `pick-args` macro
* Support repl completion on methods inside tables
* Add separate `FENNEL_MACRO_PATH` environment variable for `fennel.macro-path`
diff --git a/src/fennel/repl.fnl b/src/fennel/repl.fnl
index 4dda65e..563a151 100644
--- a/src/fennel/repl.fnl
+++ b/src/fennel/repl.fnl
@@ -174,6 +174,62 @@ For more information about the language, see https://fennel-lang.org/reference")
(compiler.metadata:set commands.complete :fnl/docstring
                       "Print all possible completions for a given input.")

(fn apropos* [pattern module prefix seen names]
  ;; package.loaded can contain modules with dots in the names.  Such
  ;; names are renamed to contain / instead of a dot.
  (each [name module (pairs module)]
    (when (and (= :string (type name))
               (not= package module))
      (match (type module)
        :function (when (: (.. prefix name) :match pattern)
                    (table.insert names (.. prefix name)))
        :table (when (not (. seen module))
                 (apropos* pattern
                           module
                           (.. prefix
                               (if (= prefix "")
                                   (pick-values 1 (name:gsub "%." "/"))
                                   name)
                               ".")
                           (doto seen (tset module true))
                           names)))))
  names)

(fn apropos [pattern]
  ;; _G. part is stripped from patterns to provide more stable output.
  ;; The order we traverse package.loaded is arbitrary, so we may see
  ;; top level functions either as is or under the _G module.
  (let [names (apropos* pattern package.loaded "" {} [])]
    (icollect [_ name (ipairs names)]
      (name:gsub "^_G%." ""))))

(fn commands.apropos [env read on-values on-error scope]
  (match (pcall read)
    (true true input) (on-values (apropos (tostring input)))
    (_ _ ?msg) (on-error :Parse (or ?msg "Couldn't parse apropos input."))))

(compiler.metadata:set commands.apropos :fnl/docstring
                       "Print all functions matching a pattern in all loaded modules.")

(fn apropos-doc [pattern]
  "Search for function documentation for a given pattern."
  (each [_ path (ipairs (apropos pattern))]
    (let [paths (icollect [p (path:gmatch "[^%.]+")] p)]
      (var tgt package.loaded)
      (each [_ path (ipairs paths)]
        (set tgt (. tgt (pick-values 1 (path:gsub "%/" "."))))
        (if (= nil tgt) (lua :break)))
      (match (type tgt)
        :function (print (specials.doc tgt path) "\n")))))

(fn commands.apropos-doc [env read _ on-error scope]
  (match (pcall read)
    (true true input) (apropos-doc (tostring input))
    (_ _ ?msg) (on-error :Parse (or ?msg "Couldn't parse apropos-doc input."))))

(compiler.metadata:set commands.apropos-doc :fnl/docstring
                       "Print all functions documentations matching a pattern")

(fn load-plugin-commands []
  (when (and utils.root utils.root.options utils.root.options.plugins)
    (each [_ plugin (ipairs utils.root.options.plugins)]
diff --git a/test/repl.fnl b/test/repl.fnl
index 7194b5d..496b33f 100644
--- a/test/repl.fnl
+++ b/test/repl.fnl
@@ -125,6 +125,24 @@
      (l.assertEquals bxor-result [:0])
      (l.assertStrContains (. bxor-result 1) "error:.*attempt to index.*global 'bit'"
                           "--use-bit-lib should make bitops fail in non-luajit"))))

(fn test-apropos []
  (local (send) (wrap-repl))
  (let [res (. (send ",apropos table%.") 1)]
    (l.assertEquals
     (doto (icollect [item (res:gmatch "[^%s]+")] item)
       (table.sort))
     ["table.concat" "table.insert" "table.move"
      "table.pack" "table.remove" "table.sort"
      "table.unpack"]
     "apropos returns all matching patterns"))
  (let [res (. (send ",apropos not-found") 1)]
    (l.assertEquals
     (doto (icollect [item (res:gmatch "[^%s]+")] item)
       (table.sort))
     []
     "apropos returns no results for unknown pattern")))

;; Skip REPL tests in non-JIT Lua 5.1 only to avoid engine coroutine
;; limitation. Normally we want all tests to run on all versions, but in
;; this case the feature will work fine; we just can't use this method of
@@ -138,5 +156,6 @@
     : test-reload
     : test-reset
     : test-plugins
     : test-options}
     : test-options
     : test-apropos}
    {})
-- 
2.31.1
Details
Message ID
<87lf63ux92.fsf@whirlwind>
In-Reply-To
<20210718120428.57511-1-andreyorst@gmail.com> (view parent)
DKIM signature
permerror
Download raw message
Andrey Listopadov <andreyorst@gmail.com> writes:

> This patch adds two new commands: ,apropos and ,apropos-doc
> Both commands accept a Lua pattern as an input.
>
> ,apropos table%. will print all function names matching this pattern,
> e.g. all functions from the table module
>
> ,aprops-doc works similarly, but instead of printing all names, prints
> all docs for functions that match the pattern.

Oh, I think maybe I miscommunicated this--my intent was that apropos-doc
would search the docstrings and print the names of the matches, not that
it would run doc on the results from apropos. Sorry for the confusion
with that.

I think that what you've written is still useful but maybe we could find
a different name for it?

-Phil
Details
Message ID
<CAAKhXoZPx2xv4yiEJx8UT5gVmW7rrVdiFC4WfjAisv3GRBF+mA@mail.gmail.com>
In-Reply-To
<87lf63ux92.fsf@whirlwind> (view parent)
DKIM signature
pass
Download raw message
> Oh, I think maybe I miscommunicated this--my intent was that apropos-doc
> would search the docstrings and print the names of the matches, not that
> it would run doc on the results from apropos. Sorry for the confusion
> with that.

Ohh, haha

I've once asked on IRC something like "should it spit all docs that
mathc the pattern" and you was like "yeah", so I've assumed this is
what you want :D

Yeah, no problem I'll add docstring search - with the given foundation
it's not that hard to do, just might take some time

> I think that what you've written is still useful but maybe we could find
> a different name for it?

I'm open to variants. Apropos-all-docs or apropos-show-docs maybe?

Also, additional question, should this doc-printing apropos variant
print #<undocumented> items?


-- 
Andrey Listopadov
Reply to thread Export thread (mbox)