vim

sheluchin 2023-06-29T11:26:32.314109Z

Using Conjure/Fennel, is there some simple way to create a mapping that would take the Clojure form under the cursor, wrap it in a time call (as a simple example), and execute it? I've started reading about plugin development with Fennel, but it'll take a little while before I'm familiar enough to do stuff like this. Just wondering if there's any "shortcut" in Conjure for doing things like this.

Phillip Mates 2023-06-29T11:57:20.904019Z

here is a related snippet that I use to send a form to the clojure REPL using the current filename, which is part of what you want:

(vim.keymap.set :n :<localleader>cs #(vim.cmd (.. "ConjureEval (nextjournal.clerk/show! \"" (vim.fn.expand "%:p") "\")")))

Phillip Mates 2023-06-29T12:02:07.363249Z

and https://github.com/Olical/conjure/blob/31a1626273e2bab479b6b8416a137f9edaba7daa/fnl/conjure/extract.fnl#L11-L17 in conjure is what gets the current form

Phillip Mates 2023-06-29T12:05:30.333419Z

so with those two together, what you're looking for should be

(set extract (require :conjure.extract))
(vim.keymap.set :n :<localleader>et #(vim.cmd (.. "ConjureEval (time " (. (extract.form {}) :content) ")")))

sheluchin 2023-06-29T12:15:17.753339Z

@phillipmates amazing, thanks very much! I think you meant (local extract ...) instead of set, but otherwise it works just as I wanted. This is a nice bit of ergonomics.

👍 1
sheluchin 2023-06-29T13:04:46.951189Z

Any idea how to make it work when the form contains linebreaks?

(vim.keymap.set :n :<leader>et #(vim.cmd (.. "ConjureEval (print " (. (extract.form {}) :content) ")")))
; eval (command): (print {:x "1" :y "2"})
; (out) {:x 1, :y 2}
nil
; --------------------------------------------------------------------------------
; eval (command): (print {:x "1"
; (err) Syntax error reading source at (REPL:1:1).
; (err) EOF while reading, starting at line 1

Phillip Mates 2023-06-29T13:06:15.009239Z

Not going through :ConjureEval but calling the conjure fnl function directly would probably do it

sheluchin 2023-06-29T14:01:53.800619Z

Sweet, that does it:

(defn time-form [extra-opts]
  (let [form (extract.form {})]
    (when form
      (let [{: content : range} form]
        (eval.eval-str
          (a.merge
            {:code (str.join ["(time " content ")"])
             :range range
             :origin :current-form}
            extra-opts))
        form))))

(vim.keymap.set :n :<leader>et #(time-form {}))
Thanks again, @phillipmates!

Phillip Mates 2023-06-29T14:03:02.410429Z

nice! it is a fun idea to be able to do custom wrappings like this

sheluchin 2023-06-29T14:19:31.290149Z

Yeah, there's potential to do some interesting things. You can tap> or time forms, render charts using Reveal/Portal/etc., execute your HoneySQL data structures as queries, and so on. One thing that would improve this is if it didn't work by gluing strings together, but it's good enough for me for now.