2025-08-13 10:34:32 -09:00

100 lines
3.7 KiB
Fennel

(module conjure-expand.main)
(local a (require "aniseed.core"))
(local nvim (require "aniseed.nvim"))
(local str (require "aniseed.string"))
(local bridge (require "conjure.bridge"))
(local client (require "conjure.client"))
(local eval (require "conjure.eval"))
(local extract (require "conjure.extract"))
(local log (require "conjure.log"))
(local mapping (require "conjure.mapping"))
(local buffer (require "conjure.buffer"))
(local editor (require "conjure.editor"))
;; Adapted from conjure.eval/current-form
(fn current-form []
(let [form (extract.form {})]
(when form
(let [{: content} form]
content))))
(fn clj-client [f args]
(client.with-filetype "clojure" f args))
(fn output-expanded [orig]
(fn [r]
(log.append (a.concat [(.. "; " orig)] (str.split r "\n")) {:break? true})))
(fn clj-macroexpand [expand-cmd]
(let [form (current-form)
me-form (.. "(" (or expand-cmd "clojure.walk/macroexpand-all") " '" form ")")]
(clj-client eval.eval-str
{:origin :conjure-macroexpand
:code me-form
:passive? true
:on-result (output-expanded me-form)})))
(fn dir-word []
(let [{: content : range : node} (extract.word)]
(when (not (a.empty? content))
(let [dir-code (.. "(clojure.repl/dir " content ")")]
(clj-client eval.eval-str
{:code dir-code
:range range
:node node
:origin :word})))))
(fn replace-with-expanded-form []
(let [form (extract.form {})]
(when form
(let [{: content : range} form
buf (vim.api.nvim_win_get_buf 0)
win (vim.api.nvim_tabpage_get_win 0)
me-form (.. "(clojure.walk/macroexpand-all '" content ")")]
(clj-client eval.eval-str
{:origin :conjure-macroreplace
:code me-form
:passive? true
:on-result
(fn [result]
(buffer.replace-range
buf
range result)
(editor.go-to
win
(a.get-in range [:start 1])
(a.inc (a.get-in range [:start 2]))))})))))
(fn tap-root []
(let [{: content : range : node} (extract.form {"root?" true})]
(when (not (a.empty? content))
(let [tap-code (.. "(tap> " content ")")]
(clj-client eval.eval-str
{:code tap-code
:range range
:node node
:origin :tap})))))
(fn add-buf-mappings []
(mapping.buf :CljMacroexpand "cm" #(clj-macroexpand)
{:desc "Call macroexpand-all on the symbol under the cursor"})
(mapping.buf :CljMacroexpand0 "c0" #(clj-macroexpand "clojure.core/macroexpand")
{:desc "Call macroexpand on the symbol under the cursor"})
(mapping.buf :CljMacroexpand1 "c1" #(clj-macroexpand "clojure.core/macroexpand-1")
{:desc "Call macroexpand-1 on the symbol under the cursor"})
(mapping.buf :CljMacroexpandReplace "mr" #(replace-with-expanded-form)
{:desc "Call macroexpand-1 on the symbol under the cursor then replace that src with the expansion"})
(mapping.buf :CljDirWord "dw" #(dir-word)
{:desc "Calls (clojure.repl/dir ,,,) for the namespace under the cursor"})
(mapping.buf :CljEvalTap "et" #(tap-root)
{:desc "Calls (tap> ,,,) for the root form under the cursor"}))
(fn init []
(when (or (not nvim.g.conjure_macroexpand_disable_mappings)
(= 0 nvim.g.conjure_macroexpand_disable_mappings))
(nvim.ex.autocmd
:FileType "clojure"
(bridge.viml->lua :conjure-expand.main :add-buf-mappings))))