Ccmmutty logo
Commutty IT
4 min read

Neovim Autocmdを便利に書くFennelマクロ

https://cdn.magicode.io/media/notebox/9c99a306-8510-412e-8f05-bfa10b3d80d3.jpeg
autocommandを楽にかけるFennelマクロを紹介します.
たくさんautocommandを書く人におすすめです.

使用例

Quick fixを閉じる
(au! :grep-cmd :QuickFixCmdPost :cwindow {:pattern :*grep*})
カーソルの場所を覚えておく
;; remind cursor position
(au! :restore-position 
     :BufReadPost 
     (when (and (> (vim.fn.line "'\"") 1)
                (<= (vim.fn.line "'\"") (vim.fn.line "$")))
       (vim.cmd "normal! g'\"")))
非同期に実行する
(au! :reload-copilot
     :VimEnter
     (async-do! (vim.cmd "Copilot restart")))

マクロ

(local M {})

(fn _callback [group event body ?opt]
  `(let [opt# {:callback (λ [] ,body)
               :group (vim.api.nvim_create_augroup ,group {:clear true})}]
     (each [k# v# (pairs (or ,?opt {}))]
       (tset opt# k# v#))
     (vim.api.nvim_create_autocmd ,event opt#)))

(fn _command [group event command ?opt]
  `(let [opt# {:command ,command
               :group (vim.api.nvim_create_augroup ,group {:clear true})}]
     (each [k# v# (pairs (or ,?opt {}))]
       (tset opt# k# v#))
     (vim.api.nvim_create_autocmd ,event opt#)))

(fn M.au! [group event body ?opt]
  (if
    (= (type body) :table) (_callback group event body ?opt)
    (= (type body) :string) (_command group event body ?opt)
    (assert-compile false "au: body must be a sequence or string" body)))

(fn M.async-do! [body]
  `(do
     (var async# nil)
     (set async#
          (vim.loop.new_async
            (vim.schedule_wrap
                  (λ []
                    ,body
                    (async#:close)))))
     (async#:send)))

M

追記

グループを共有できるようにしてみました.
(fn _group_handler [group]
  `(if 
     (= (type ,group) :string)
     (vim.api.nvim_create_augroup ,group {:clear true})
     (= (type ,group) :number)
     ,group
     (print "au: group must be number or string" ,group)))

(fn _callback [group event body ?opt]
  `(let [opt# {:callback (λ [] ,body)
               :group ,(_group_handler group)}]
     (each [k# v# (pairs (or ,?opt {}))]
       (tset opt# k# v#))
     (vim.api.nvim_create_autocmd ,event opt#)))

(fn _command [group event command ?opt]
  `(let [opt# {:command ,command
               :group ,(_group_handler group)}]
     (each [k# v# (pairs (or ,?opt {}))]
       (tset opt# k# v#))
     (vim.api.nvim_create_autocmd ,event opt#)))

(fn M.au! [group event body ?opt]
  (if
    (= (type body) :table) (_callback group event body ?opt)
    (= (type body) :string) (_command group event body ?opt)
    (assert-compile false "au: body must be a sequence or string" body)))

使用例

cmp-skkeleton
(let [g (vim.api.nvim_create_augroup :init-skkeleton {:clear true})]
            (au! g :User
                 (vim.fn.skkeleton#config {})
                 {:pattern :skkeleton-initialize-pre})
            (au! g :User (let [cmp (require :cmp)]
                           (cmp.setup.buffer {:view {:entries :native}}))
                 {:pattern :skkeleton-enable-pre})
            (au! g :User (let [cmp (require :cmp)]
                           (cmp.setup.buffer {:view {:entries :custom}}))
                 {:pattern :skkeleton-disable-pre})
            (au! g :User :redrawstatus {:pattern :skkeleton-mode-changed}))

Discussion

コメントにはログインが必要です。