diff --git a/README.md b/README.md index 092a55a..e6b658e 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,6 @@ # Form edit -Paredit in Fennel for Clojure +Paredit in Fennel for Clojure using Treesitter ## Features @@ -8,7 +8,7 @@ Paredit in Fennel for Clojure - Lists (s-exp, quoted list), vector, set are all under one text object - so instead of `di(` `di[` `di{` just `dif` (or any other text object command) - `f` for current form. `F` for root form -- Slurp +- Slurp (Forward + Backwards) - Bring in element/form into your form - Raise - Remove parent form and replace with current form diff --git a/fnl/formedit/barf.fnl b/fnl/formedit/barf.fnl new file mode 100644 index 0000000..ee4c821 --- /dev/null +++ b/fnl/formedit/barf.fnl @@ -0,0 +1,27 @@ +(local find (require :formedit.find)) +(local ts (require :vim.treesitter)) + +(fn forward [] + (let [form (find.form) + last (find.last form) + [row col] [(form:end_)] + [last-row-start last-col-start last-row-end last-col-end] [(last:range)] + text (ts.get_node_text last 0) + text (.. " " text)] + (vim.api.nvim_buf_set_text 0 row col row col [text]) + (vim.api.nvim_buf_set_text 0 last-row-start (- last-col-start 1) + last-row-end last-col-end [""]))) + +(fn backward [] + (let [form (find.form) + first (find.first form) + text (ts.get_node_text first 0) + text (.. text " ") + [row-start col-start row-end col-end] [(first:range)] + _ (vim.api.nvim_buf_set_text 0 row-start col-start row-end + (+ col-end 1) [""]) + nform (find.form) + [nrow-start ncol-start] [(nform:start)]] + (vim.api.nvim_buf_set_text 0 nrow-start ncol-start nrow-start ncol-start [text]))) + +{: forward : backward} diff --git a/fnl/formedit/find.fnl b/fnl/formedit/find.fnl index a279a87..d727c08 100644 --- a/fnl/formedit/find.fnl +++ b/fnl/formedit/find.fnl @@ -33,6 +33,13 @@ (when (node:parent) (find-root-form (node:parent)))))) +(fn first [form] + (form:named_child 0)) + +(fn last [form] + (let [count (form:named_child_count)] + (form:child count))) + ;; Find node (fn form [] (let [node (ts.get_node_at_cursor)] @@ -42,4 +49,4 @@ (let [node (ts.get_node_at_cursor)] (find-root-form node))) -{: form : root : insert-offset : start-offset} +{: form : root : insert-offset : start-offset : first : last} diff --git a/fnl/spec/barf_spec.fnl b/fnl/spec/barf_spec.fnl new file mode 100644 index 0000000..7a0c3fb --- /dev/null +++ b/fnl/spec/barf_spec.fnl @@ -0,0 +1,36 @@ +(local {: describe : it : before_each} (require :plenary.busted)) +(local h (require :spec.helper)) +(local barf (require :formedit.barf)) + +(local forward-keymap "<)") +(local backward-keymap ">(") + +(describe "barf forward" + (fn [] + (before_each (fn [] + (vim.keymap.set :n forward-keymap barf.forward))) + (it :element + (fn [] + (h.setup {:content "((1 2))" :cursor [1 1]}) + (h.feedkeys forward-keymap) + (h.expect {:content "((1) 2)" :cursor [1 1]}))) + (it :form + (fn [] + (h.setup {:content "(((1) (2)))" :cursor [1 1]}) + (h.feedkeys forward-keymap) + (h.expect {:content "(((1)) (2))" :cursor [1 1]}))))) + +(describe "barf backwards" + (fn [] + (before_each (fn [] + (vim.keymap.set :n backward-keymap barf.backward))) + (it :element + (fn [] + (h.setup {:content "((1 2))" :cursor [1 1]}) + (h.feedkeys backward-keymap) + (h.expect {:content "(1 (2))" :cursor [1 1]}))) + (it :form + (fn [] + (h.setup {:content "(((1) 2))" :cursor [1 1]}) + (h.feedkeys backward-keymap) + (h.expect {:content "((1) (2))" :cursor [1 1]}))))) diff --git a/lua/formedit/barf.lua b/lua/formedit/barf.lua new file mode 100644 index 0000000..a755cbd --- /dev/null +++ b/lua/formedit/barf.lua @@ -0,0 +1,37 @@ +-- [nfnl] Compiled from fnl/formedit/barf.fnl by https://github.com/Olical/nfnl, do not edit. +local find = require("formedit.find") +local ts = require("vim.treesitter") +local function forward() + local form = find.form() + local last = find.last(form) + local _let_1_ = {form:end_()} + local row = _let_1_[1] + local col = _let_1_[2] + local _let_2_ = {last:range()} + local last_row_start = _let_2_[1] + local last_col_start = _let_2_[2] + local last_row_end = _let_2_[3] + local last_col_end = _let_2_[4] + local text = ts.get_node_text(last, 0) + local text0 = (" " .. text) + vim.api.nvim_buf_set_text(0, row, col, row, col, {text0}) + return vim.api.nvim_buf_set_text(0, last_row_start, (last_col_start - 1), last_row_end, last_col_end, {""}) +end +local function backward() + local form = find.form() + local first = find.first(form) + local text = ts.get_node_text(first, 0) + local text0 = (text .. " ") + local _let_3_ = {first:range()} + local row_start = _let_3_[1] + local col_start = _let_3_[2] + local row_end = _let_3_[3] + local col_end = _let_3_[4] + local _ = vim.api.nvim_buf_set_text(0, row_start, col_start, row_end, (col_end + 1), {""}) + local nform = find.form() + local _let_4_ = {nform:start()} + local nrow_start = _let_4_[1] + local ncol_start = _let_4_[2] + return vim.api.nvim_buf_set_text(0, nrow_start, ncol_start, nrow_start, ncol_start, {text0}) +end +return {forward = forward, backward = backward} diff --git a/lua/formedit/find.lua b/lua/formedit/find.lua index 4b3abf9..369aee0 100644 --- a/lua/formedit/find.lua +++ b/lua/formedit/find.lua @@ -30,6 +30,13 @@ local function find_root_form(node) end end end +local function first(form) + return form:named_child(0) +end +local function last(form) + local count = form:named_child_count() + return form:child(count) +end local function form() local node = ts.get_node_at_cursor() return find_current_form(node) @@ -38,4 +45,4 @@ local function root() local node = ts.get_node_at_cursor() return find_root_form(node) end -return {form = form, root = root, ["insert-offset"] = insert_offset, ["start-offset"] = start_offset} +return {form = form, root = root, ["insert-offset"] = insert_offset, ["start-offset"] = start_offset, first = first, last = last} diff --git a/lua/spec/barf_spec.lua b/lua/spec/barf_spec.lua new file mode 100644 index 0000000..cb30db2 --- /dev/null +++ b/lua/spec/barf_spec.lua @@ -0,0 +1,47 @@ +-- [nfnl] Compiled from fnl/spec/barf_spec.fnl by https://github.com/Olical/nfnl, do not edit. +local _local_1_ = require("plenary.busted") +local describe = _local_1_["describe"] +local it = _local_1_["it"] +local before_each = _local_1_["before_each"] +local h = require("spec.helper") +local barf = require("formedit.barf") +local forward_keymap = "<)" +local backward_keymap = ">(" +local function _2_() + local function _3_() + return vim.keymap.set("n", forward_keymap, barf.forward) + end + before_each(_3_) + local function _4_() + h.setup({content = "((1 2))", cursor = {1, 1}}) + h.feedkeys(forward_keymap) + return h.expect({content = "((1) 2)", cursor = {1, 1}}) + end + it("element", _4_) + local function _5_() + h.setup({content = "(((1) (2)))", cursor = {1, 1}}) + h.feedkeys(forward_keymap) + return h.expect({content = "(((1)) (2))", cursor = {1, 1}}) + end + return it("form", _5_) +end +describe("barf forward", _2_) +local function _6_() + local function _7_() + return vim.keymap.set("n", backward_keymap, barf.backward) + end + before_each(_7_) + local function _8_() + h.setup({content = "((1 2))", cursor = {1, 1}}) + h.feedkeys(backward_keymap) + return h.expect({content = "(1 (2))", cursor = {1, 1}}) + end + it("element", _8_) + local function _9_() + h.setup({content = "(((1) 2))", cursor = {1, 1}}) + h.feedkeys(backward_keymap) + return h.expect({content = "((1) (2))", cursor = {1, 1}}) + end + return it("form", _9_) +end +return describe("barf backwards", _6_)