~technomancy/fennel#216: 
improve plugin loading options, allow lua plugins

Right now, loading plugins has a few barriers that make it difficult to easily integrate them into, say, the REPL without

For the CLI, it would be useful to accept lua plugins either with the --plugin option (by extension) or via an extra --lua-plugin option.

The main use-case here is to leverage AOT compilation either for plugins written in a different fennel version or, more likely, to precompile a plugin with --require-as-include to bundle in any library component it relies upon.

#Better plugin loading from API?

Additionally, loading plugins by way of the Fennel API (instead of CLI) currently requires manually reproducing the code in launcher.fnl, as in the usecase example below.

#Usecase example

I have a WIP pretty-macrodebug plugin to replace the old macro hack implementation in fnlfmt. It works, but depends on fnlfmt.fnl being somewhere on fennel.path. It would be a lot more useful in tooling plugins that incorporate a library to be able to simply drop a single file either into a project, or into e.g. ${XDG_CONFIG_HOME/fennel for easy use from fennelrc.

Currently, using the plugin requires a fair amount of boilerplate:

(local (*opts* {: view &as fennel}) ...)
(local {:format str/fmt :gmatch str/gmatch :gsub str/gsub :sub str/sub} string)
(local HOME (os.getenv :HOME))
(local dir-sep (str/sub package.config 1 1))

(λ warn [msg-str ...]
  (if (= 0 (select :# ...))
    (io.stderr:write (.. msg-str "\n"))
    (io.stderr:write (str/fmt (.. msg-str "\n") ...)))
  nil)
 
(fn pat/escape [str]
  (str/gsub str "([#$%^%%&*()%][-])" "%%%1") )

(fn tbl/copy [from to]
  (collect [k v (pairs (or from {})) &into (or to {})] k v))

(fn str/split [str sep]
  (icollect [part (str/gmatch str (.. "[^" (pat/escape sep) "]+"))]
    part))

(fn load-plugin [plugin-file ?opts ...]
  (let [opts (tbl/copy (or ?opts {})
                       {:env :_COMPILER :compiler-env _G :useMetadata true})
        (ok plugin) (pcall fnl.dofile plugin-file opts ...) ]
    (if ok
        (table.insert *opts*.plugins plugin)
        (warn (.. "Failed to load plugin '%s': %s" plugin-file
                  (or (and plugin (tostring plugin)) ""))))
    ok))

;; load REPL plugins
(let [fnlfmt-path (table.concat [HOME "dev" "fnl-libs" "fnlfmt"] dir-sep)]
  ;; pretty-macrodebug needs fnlfmt on package.path
  (set fnl.path (.. fnl.path ";" fnlfmt-path dir-sep "?.fnl"))
  (load-plugin (.. fnlfmt-path dir-sep "macrodebug-plugin.fnl") {} ...))
Status
RESOLVED IMPLEMENTED
Submitter
~jaawerth
Assigned to
No-one
Submitted
1 year, 4 days ago
Updated
10 months ago
Labels
enhancement next-release

~technomancy REPORTED IMPLEMENTED 10 months ago

Implemented in 4217c2f but not documented for now because I think we should probably treat it as experimental for a while.

Register here or Log in to comment, or comment via email.