diff --git a/README.md b/README.md index 6902b01..217d5fc 100644 --- a/README.md +++ b/README.md @@ -75,6 +75,7 @@ paredit.setup({ -- list of default keybindings keys = { + ["@"] = { paredit.unwrap.unwrap_form_under_cursor, "Splice sexp" }, [">)"] = { paredit.api.slurp_forwards, "Slurp forwards" }, [">("] = { paredit.api.barf_backwards, "Barf backwards" }, @@ -327,7 +328,7 @@ Cursor api `paredit.cursor` - `placement` - enumeration `left_edge`,`inner_start`,`inner_end`,`right_edge` - `mode` - currently only `insert` is supported, defaults to `normal` -## API usage recipes +## Additional API usage recipes ### `vim-sexp` wrap form (head/tail) replication diff --git a/lua/nvim-paredit/api/unwrap.lua b/lua/nvim-paredit/api/unwrap.lua new file mode 100644 index 0000000..ab7dbc5 --- /dev/null +++ b/lua/nvim-paredit/api/unwrap.lua @@ -0,0 +1,47 @@ +local traversal = require("nvim-paredit.utils.traversal") +local langs = require("nvim-paredit.lang") +local ts = require("nvim-treesitter.ts_utils") + +local M = {} + +function M.unwrap_form(buf, form) + local lang = langs.get_language_api() + local edges = lang.get_form_edges(form) + local left = edges.left + local right = edges.right + vim.api.nvim_buf_set_text( + buf, + right.range[1], + right.range[2], + right.range[3], + right.range[4], + { "" } + ) + vim.api.nvim_buf_set_text( + buf, + left.range[1], + left.range[2], + left.range[3], + left.range[4], + { "" } + ) +end + +function M.unwrap_form_under_cursor() + local buf = vim.api.nvim_get_current_buf() + local lang = langs.get_language_api() + local node = ts.get_node_at_cursor() + local current_element = lang.get_node_root(node) + local form = traversal.find_nearest_form( + current_element, + { lang = lang, use_source = false } + ) + if not form then + return false + end + + M.unwrap_form(buf, form) + return true +end + +return M diff --git a/lua/nvim-paredit/defaults.lua b/lua/nvim-paredit/defaults.lua index 972bb7c..03eb727 100644 --- a/lua/nvim-paredit/defaults.lua +++ b/lua/nvim-paredit/defaults.lua @@ -1,8 +1,11 @@ local api = require("nvim-paredit.api") +local unwrap = require("nvim-paredit.api.unwrap") local M = {} M.default_keys = { + ["@"] = { unwrap.unwrap_form_under_cursor, "Splice sexp", }, + [">)"] = { api.slurp_forwards, "Slurp forwards" }, [">("] = { api.barf_backwards, "Barf backwards" }, diff --git a/lua/nvim-paredit/init.lua b/lua/nvim-paredit/init.lua index 64b0895..66437b6 100644 --- a/lua/nvim-paredit/init.lua +++ b/lua/nvim-paredit/init.lua @@ -33,6 +33,7 @@ end local M = { api = require("nvim-paredit.api"), wrap = require("nvim-paredit.api.wrap"), + unwrap = require("nvim-paredit.api.unwrap"), cursor = require("nvim-paredit.api.cursor"), extension = { add_language_extension = add_language_extension, diff --git a/tests/nvim-paredit/form_unwrap_spec.lua b/tests/nvim-paredit/form_unwrap_spec.lua new file mode 100644 index 0000000..768c745 --- /dev/null +++ b/tests/nvim-paredit/form_unwrap_spec.lua @@ -0,0 +1,56 @@ +local paredit = require("nvim-paredit") +local prepare_buffer = require("tests.nvim-paredit.utils").prepare_buffer +local expect = require("tests.nvim-paredit.utils").expect + +describe("form uwrap (e.g. splice)", function() + vim.api.nvim_buf_set_option(0, "filetype", "clojure") + local unwrap = paredit.unwrap + + it("should uwrap list under cursor", function() + prepare_buffer({ + content = { "(+ 2 :foo/bar)" }, + cursor = { 1, 0 }, + }) + + unwrap.unwrap_form_under_cursor() + expect({ + content = { "+ 2 :foo/bar" }, + }) + end) + + it("should uwrap list under cursor", function() + prepare_buffer({ + content = { "(+ 2 :foo/bar)" }, + cursor = { 1, 13 }, + }) + + unwrap.unwrap_form_under_cursor() + expect({ + content = { "+ 2 :foo/bar" }, + }) + end) + + it("should uwrap set under cursor", function() + prepare_buffer({ + content = { "#{1 2 3}" }, + cursor = { 1, 4 }, + }) + + unwrap.unwrap_form_under_cursor() + expect({ + content = { "1 2 3" }, + }) + end) + + it("should uwrap fn under cursor", function() + prepare_buffer({ + content = { "#(+ % 2 3)" }, + cursor = { 1, 4 }, + }) + + unwrap.unwrap_form_under_cursor() + expect({ + content = { "+ % 2 3" }, + }) + end) +end)