From 49b0acc90ef2cdc6f1c076cd5b2b16f5140be699 Mon Sep 17 00:00:00 2001 From: Julien Vincent Date: Tue, 15 Oct 2024 18:42:30 +0100 Subject: [PATCH 1/2] Simplify utils for writing tests The current utils for writing buffer operation tests are quite wordy and not easy for a human to interpret at a glance. In an effort to make it easier to write detailed, language specific tests I have added a way to describe test prepare and check content as a string. This works by looking for `|` characters in test content and using this to infer the cursor position. --- tests/nvim-paredit/barf_spec.lua | 222 +++++++++++------------------ tests/nvim-paredit/cursor_spec.lua | 14 +- tests/nvim-paredit/utils.lua | 87 ++++++++--- 3 files changed, 155 insertions(+), 168 deletions(-) diff --git a/tests/nvim-paredit/barf_spec.lua b/tests/nvim-paredit/barf_spec.lua index cf624ca..63adba1 100644 --- a/tests/nvim-paredit/barf_spec.lua +++ b/tests/nvim-paredit/barf_spec.lua @@ -14,87 +14,73 @@ describe("barfing ::", function() expect_all(paredit.barf_forwards, { { "list", - before_content = "(a)", - before_cursor = { 1, 1 }, - after_content = "()a", - after_cursor = { 1, 1 }, + { "(|a)" }, + { "(|)a" }, }, { "vector", - before_content = "[a]", - before_cursor = { 1, 1 }, - after_content = "[]a", - after_cursor = { 1, 1 }, + { "[|a]" }, + { "[|]a" }, }, { "quoted list", - before_content = "`(a)", - before_cursor = { 1, 2 }, - after_content = "`()a", - after_cursor = { 1, 2 }, + "`(|a)", + { "`(|)a" }, }, { "quoted list", - before_content = "'(a)", - before_cursor = { 1, 2 }, - after_content = "'()a", - after_cursor = { 1, 2 }, + "'(|a)", + "'(|)a", }, { "anon fn", - before_content = "#(a)", - before_cursor = { 1, 2 }, - after_content = "#()a", - after_cursor = { 1, 2 }, + { "#(|a)" }, + { "#(|)a" }, }, { "set", - before_content = "#{a}", - before_cursor = { 1, 2 }, - after_content = "#{}a", - after_cursor = { 1, 2 }, + "#{|a}", + "#{|}a", }, { "reader conditional", - before_content = "#?(:cljs a :clj b)", - before_cursor = { 1, 3 }, - after_content = "#?(:cljs a :clj) b", - after_cursor = { 1, 3 }, + { "#?(|:cljs a :clj b)" }, + "#?(|:cljs a :clj) b", }, }) end) it("should skip comments", function() prepare_buffer({ - content = { "(", ";; comment", "a)" }, - cursor = { 1, 1 }, + "(|", + ";; comment", + "a)", }) paredit.barf_forwards() expect({ - content = { "()", ";; comment", "a" }, - cursor = { 1, 0 }, + "|()", + ";; comment", + "a", }) prepare_buffer({ - content = { "(a ;; comment", ")" }, - cursor = { 1, 1 }, + "(|a ;; comment", + ")", }) paredit.barf_forwards() expect({ - content = "()a ;; comment", - cursor = { 1, 1 }, + "(|)a ;; comment", + "", }) end) it("should do nothing in an empty form", function() prepare_buffer({ - content = "()", - cursor = { 1, 1 }, + "(|)", }) paredit.barf_forwards() expect({ - content = "()", - cursor = { 1, 1 }, + "(|)", }) end) @@ -102,17 +88,13 @@ describe("barfing ::", function() expect_all(paredit.barf_forwards, { { "from root", - before_content = { "(a)", "" }, - before_cursor = { 2, 0 }, - after_content = { "(a)", "" }, - after_cursor = { 2, 0 }, + { "(a)", "|" }, + { "(a)", "|" }, }, { "from another list", - before_content = { "(a)", "()" }, - before_cursor = { 2, 1 }, - after_content = { "(a)", "()" }, - after_cursor = { 2, 1 }, + { "(a)", "(|)" }, + { "(a)", "(|)" }, }, }) end) @@ -121,17 +103,13 @@ describe("barfing ::", function() expect_all(paredit.barf_forwards, { { "double nested list", - before_content = "(() a)", - before_cursor = { 1, 2 }, - after_content = "(()) a", - after_cursor = { 1, 2 }, + "((|) a)", + "((|)) a", }, { "list with quoted list", - before_content = "('())", - before_cursor = { 1, 3 }, - after_content = "()'()", - after_cursor = { 1, 1 }, + { "('(|))" }, + { "(|)'()" }, }, }) end) @@ -144,17 +122,13 @@ describe("barfing ::", function() expect_all(barf_with_behaviour, { { "single line", - before_content = "(aa bb)", - before_cursor = { 1, 5 }, - after_content = "(aa) bb", - after_cursor = { 1, 3 }, + { "(aa b|b)" }, + "(aa|) bb", }, { "multi line", - before_content = { "(aa", "bb)" }, - before_cursor = { 2, 1 }, - after_content = { "(aa)", "bb" }, - after_cursor = { 1, 3 }, + { "(aa", "b|b)" }, + { "(aa|)", "bb" }, }, }) end) @@ -167,17 +141,13 @@ describe("barfing ::", function() expect_all(barf_with_behaviour, { { "single line", - before_content = "(aa bb cc)", - before_cursor = { 1, 4 }, - after_content = "(aa bb) cc", - after_cursor = { 1, 6 }, + { "(aa |bb cc)" }, + "(aa bb|) cc", }, { "multi line", - before_content = { "(aa", "bb", "cc)" }, - before_cursor = { 1, 1 }, - after_content = { "(aa", "bb)", "cc" }, - after_cursor = { 2, 2 }, + { "(|aa", "bb", "cc)" }, + { "(aa", "bb|)", "cc" }, }, }) end) @@ -188,80 +158,68 @@ describe("barfing ::", function() expect_all(paredit.barf_backwards, { { "list", - before_content = "(a)", - before_cursor = { 1, 1 }, - after_content = "a()", - after_cursor = { 1, 2 }, + { "(|a)" }, + { "a(|)" }, }, { "vector", - before_content = "[a]", - before_cursor = { 1, 1 }, - after_content = "a[]", - after_cursor = { 1, 2 }, + { "[|a]" }, + { "a[|]" }, }, { "quoted list", - before_content = "`(a)", - before_cursor = { 1, 2 }, - after_content = "a`()", - after_cursor = { 1, 3 }, + { "`(|a)" }, + { "a`(|)" }, }, { "quoted list", - before_content = "'(a)", - before_cursor = { 1, 2 }, - after_content = "a'()", - after_cursor = { 1, 3 }, + { "'(|a)" }, + { "a'(|)" }, }, { "anon fn", - before_content = "#(a)", - before_cursor = { 1, 2 }, - after_content = "a#()", - after_cursor = { 1, 3 }, + { "#(|a)" }, + { "a#(|)" }, }, { "set", - before_content = "#{a}", - before_cursor = { 1, 2 }, - after_content = "a#{}", - after_cursor = { 1, 3 }, + { "#{|a}" }, + { "a#{|}" }, }, }) end) it("should skip comments", function() prepare_buffer({ - content = { "(", ";; comment", "a)" }, - cursor = { 1, 1 }, + "(|", + ";; comment", + "a)", }) paredit.barf_backwards() expect({ - content = { "", ";; comment", "a()" }, - cursor = { 3, 1 }, + "", + ";; comment", + "a|()", }) prepare_buffer({ - content = { "(a ;; comment", ")" }, - cursor = { 1, 1 }, + "(|a ;; comment", + ")", }) paredit.barf_backwards() expect({ - content = { "a ;; comment", "()" }, - cursor = { 2, 0 }, + "a ;; comment", + "|()", }) end) it("should do nothing in an empty form", function() prepare_buffer({ - content = "()", - cursor = { 1, 1 }, + "(|)", }) paredit.barf_backwards() expect({ - content = "()", - cursor = { 1, 1 }, + "(|)", }) end) @@ -269,17 +227,13 @@ describe("barfing ::", function() expect_all(paredit.barf_backwards, { { "from root", - before_content = { "(a)", "" }, - before_cursor = { 2, 0 }, - after_content = { "(a)", "" }, - after_cursor = { 2, 0 }, + { "(a)", "|" }, + { "(a)", "|" }, }, { "from another list", - before_content = { "(a)", "()" }, - before_cursor = { 2, 1 }, - after_content = { "(a)", "()" }, - after_cursor = { 2, 1 }, + { "(a)", "(|)" }, + { "(a)", "(|)" }, }, }) end) @@ -288,17 +242,13 @@ describe("barfing ::", function() expect_all(paredit.barf_backwards, { { "double nested list", - before_content = "(a ())", - before_cursor = { 1, 4 }, - after_content = "a (())", - after_cursor = { 1, 4 }, + { "(a (|))" }, + { "a ((|))" }, }, { "list with quoted list", - before_content = "('())", - before_cursor = { 1, 3 }, - after_content = "'()()", - after_cursor = { 1, 4 }, + { "('(|))" }, + "'()(|)", }, }) end) @@ -311,17 +261,13 @@ describe("barfing ::", function() expect_all(barf_with_behaviour, { { "single line", - before_content = "(aa bb)", - before_cursor = { 1, 1 }, - after_content = "aa (bb)", - after_cursor = { 1, 4 }, + { "(|aa bb)" }, + { "aa (|bb)" }, }, { "multi line", - before_content = { "(aa", "bb)" }, - before_cursor = { 1, 1 }, - after_content = { "aa", "(bb)" }, - after_cursor = { 2, 0 }, + { "(|aa", "bb)" }, + { "aa", "|(bb)" }, }, }) end) @@ -334,17 +280,13 @@ describe("barfing ::", function() expect_all(barf_with_behaviour, { { "single line", - before_content = "(aa bb cc)", - before_cursor = { 1, 1 }, - after_content = "aa (bb cc)", - after_cursor = { 1, 4 }, + { "(|aa bb cc)" }, + { "aa (|bb cc)" }, }, { "multi line", - before_content = { "(aa", "bb", "cc)" }, - before_cursor = { 1, 1 }, - after_content = { "aa", "(bb", "cc)" }, - after_cursor = { 2, 0 }, + { "(|aa", "bb", "cc)" }, + { "aa", "|(bb", "cc)" }, }, }) end) diff --git a/tests/nvim-paredit/cursor_spec.lua b/tests/nvim-paredit/cursor_spec.lua index b803f86..9363cd4 100644 --- a/tests/nvim-paredit/cursor_spec.lua +++ b/tests/nvim-paredit/cursor_spec.lua @@ -9,8 +9,7 @@ describe("cursor pos api tests", function() it("should place cursor inside form at the beginning", function() prepare_buffer({ - content = { "(a (b))" }, - cursor = { 1, 0 }, + "|(a (b))", }) local cursor_pos = paredit.cursor.get_cursor_pos({ 0, 0, 0, 6 }, { placement = "inner_start" }) @@ -25,8 +24,7 @@ describe("cursor pos api tests", function() it("should place cursor outside form at the beginning", function() prepare_buffer({ - content = { "(a (b))" }, - cursor = { 1, 0 }, + "|(a (b))", }) local cursor_pos = paredit.cursor.get_cursor_pos({ 0, 0, 0, 6 }, { placement = "left_edge" }) @@ -41,8 +39,8 @@ describe("cursor pos api tests", function() it("should place cursor inside form at the end", function() prepare_buffer({ - content = { "(a ", " (b))" }, - cursor = { 1, 0 }, + "|(a ", + " (b))", }) local cursor_pos = paredit.cursor.get_cursor_pos({ 0, 0, 1, 4 }, { placement = "inner_end" }) @@ -57,8 +55,8 @@ describe("cursor pos api tests", function() it("should place cursor outside form at the end", function() prepare_buffer({ - content = { "(a ", " (b))" }, - cursor = { 1, 0 }, + "|(a ", + " (b))", }) local cursor_pos = paredit.cursor.get_cursor_pos({ 0, 0, 1, 4 }, { placement = "right_edge" }) diff --git a/tests/nvim-paredit/utils.lua b/tests/nvim-paredit/utils.lua index af7883f..cb0e95a 100644 --- a/tests/nvim-paredit/utils.lua +++ b/tests/nvim-paredit/utils.lua @@ -8,48 +8,95 @@ function M.feedkeys(keys) vim.api.nvim_feedkeys(escape_keys(keys), "xmt", true) end +local function extract_cursor_from_content(content) + for i, line in ipairs(content) do + local cursor_index = line:find("|") + if cursor_index then + local modified_content = vim.deepcopy(content) + modified_content[i] = line:sub(1, cursor_index - 1) .. line:sub(cursor_index + 1) + local cursor = { i, cursor_index - 1 } + return cursor, modified_content + end + end + return nil, content +end + function M.prepare_buffer(params) - local content = params.content + local content = params.content or params if type(content) == "string" then - content = { content } + content = vim.split(content, "\n") end + local cursor + cursor, content = extract_cursor_from_content(content) + + cursor = params.cursor or cursor + vim.api.nvim_buf_set_lines(0, 0, -1, true, content) - vim.api.nvim_win_set_cursor(0, params.cursor) + if cursor then + vim.api.nvim_win_set_cursor(0, cursor) + end vim.treesitter.get_parser(0):parse() end -function M.expect(params) - if params.content then - if type(params.content) == "table" then - assert.are.same(params.content, vim.api.nvim_buf_get_lines(0, 0, -1, false)) - else - assert.are.same(params.content, vim.api.nvim_buf_get_lines(0, 0, -1, false)[1]) - end +function M.expect(before, action, after) + if not action and not after then + after = before + before = nil + end + + if before then + M.prepare_buffer(before) end - if params.cursor then - assert.are.same(params.cursor, vim.api.nvim_win_get_cursor(0)) + if action then + action() + end + + local content = after.content or after + if type(content) == "string" then + content = { content } + end + + local cursor + cursor, content = extract_cursor_from_content(content) + + cursor = after.cursor or cursor + + if #content > 0 then + assert.are.same(content, vim.api.nvim_buf_get_lines(0, 0, -1, false)) + end + + if cursor then + assert.are.same(cursor, vim.api.nvim_win_get_cursor(0)) end end function M.expect_all(action, expectations) for _, fixture in pairs(expectations) do it(fixture[1], function() - M.prepare_buffer({ - content = fixture.before_content, - cursor = fixture.before_cursor, - }) + if fixture[2] then + M.prepare_buffer(fixture[2]) + else + M.prepare_buffer({ + content = fixture.before_content, + cursor = fixture.before_cursor, + }) + end if fixture.action then fixture.action() else action() end - M.expect({ - content = fixture.after_content, - cursor = fixture.after_cursor, - }) + if fixture[3] then + M.expect(fixture[3]) + else + M.expect({ + content = fixture.after_content, + cursor = fixture.after_cursor, + }) + end vim.treesitter.get_parser(0):parse() end) From d412077fb60e369913bedb0e3be145f212587c9c Mon Sep 17 00:00:00 2001 From: Julien Vincent Date: Sun, 13 Oct 2024 21:11:57 +0100 Subject: [PATCH 2/2] Add treesitter queries and tests for commonlisp --- README.md | 11 ++- lua/nvim-paredit/defaults.lua | 2 +- lua/nvim-paredit/treesitter/forms.lua | 5 +- queries/commonlisp/paredit/forms.scm | 13 +++ tests/config.lua | 2 +- .../commonlisp/element_raise_spec.lua | 52 ++++++++++ .../commonlisp/form_raise_spec.lua | 50 ++++++++++ tests/nvim-paredit/commonlisp/motion_spec.lua | 47 +++++++++ tests/nvim-paredit/commonlisp/slurp_spec.lua | 96 +++++++++++++++++++ 9 files changed, 272 insertions(+), 6 deletions(-) create mode 100644 queries/commonlisp/paredit/forms.scm create mode 100644 tests/nvim-paredit/commonlisp/element_raise_spec.lua create mode 100644 tests/nvim-paredit/commonlisp/form_raise_spec.lua create mode 100644 tests/nvim-paredit/commonlisp/motion_spec.lua create mode 100644 tests/nvim-paredit/commonlisp/slurp_spec.lua diff --git a/README.md b/README.md index 424d38c..9df6b27 100644 --- a/README.md +++ b/README.md @@ -73,7 +73,7 @@ paredit.setup({ -- for new filetypes. -- -- Defaults to all supported filetypes. - filetypes = { "clojure", "fennel", "scheme" }, + filetypes = { "clojure", "fennel", "scheme", "lisp" }, -- This is some language specific configuration. Right now this is just used for -- setting character lists that are considered whitespace. @@ -288,8 +288,13 @@ understand the AST. Right now `nvim-paredit` has built-in support for: - `clojure` -- `fennel` -- `scheme` +- `fennel` * +- `scheme` * +- `commonlisp` * + +> [!NOTE] +> +> Items marked with `*` only have partial test coverage. Not all language syntax is guaranteed to work. Take a look at the [Language Queries Spec](./docs/language-queries.md) if you are wanting to add support for languages not built-in to nvim-paredit, or you want to develop on the existing queries. diff --git a/lua/nvim-paredit/defaults.lua b/lua/nvim-paredit/defaults.lua index b6c2380..be0ff0b 100644 --- a/lua/nvim-paredit/defaults.lua +++ b/lua/nvim-paredit/defaults.lua @@ -119,7 +119,7 @@ M.defaults = { enabled = false, indentor = require("nvim-paredit.indentation.native").indentor, }, - filetypes = { "clojure", "fennel", "scheme" }, + filetypes = { "clojure", "fennel", "scheme", "lisp" }, languages = { clojure = { whitespace_chars = { " ", "," }, diff --git a/lua/nvim-paredit/treesitter/forms.lua b/lua/nvim-paredit/treesitter/forms.lua index 712fc29..2337be6 100644 --- a/lua/nvim-paredit/treesitter/forms.lua +++ b/lua/nvim-paredit/treesitter/forms.lua @@ -94,7 +94,7 @@ end -- (list_lit -- (kw_lit)) @form.inner) @form.outer -- ``` --- +-- -- Given the above AST we would want to extract the `list_lit` annotated in -- this example with @form.inner. function M.get_form_inner(form_node, opts) @@ -140,6 +140,9 @@ local function get_last_anon_child_of_form_head(node) return current end local child = node:child(i) + if not child then + return + end if child:named() then return current end diff --git a/queries/commonlisp/paredit/forms.scm b/queries/commonlisp/paredit/forms.scm new file mode 100644 index 0000000..6471c82 --- /dev/null +++ b/queries/commonlisp/paredit/forms.scm @@ -0,0 +1,13 @@ +;; We only consider a list_lit a form if it starts with a "(" anonymous node. +;; Some constructs like `(defun)` or `(loop)` are constructed as: +;; +;; (list_lit +;; (defun ...)) +;; +;; And in these cases we want to consider the `(defun)` the form inner and +;; 'ignore' the `list_lit` node +(list_lit + open: "(") @form + +(loop_macro) @form +(defun) @form diff --git a/tests/config.lua b/tests/config.lua index 37c0dd1..5ad8a9a 100644 --- a/tests/config.lua +++ b/tests/config.lua @@ -11,6 +11,6 @@ vim.bo.swapfile = false require("nvim-treesitter.configs").setup({ parser_install_dir = vim.fn.getcwd() .. "/.build/parsers", - ensure_installed = { "clojure", "fennel", "scheme" }, + ensure_installed = { "clojure", "fennel", "scheme", "commonlisp" }, sync_install = true, }) diff --git a/tests/nvim-paredit/commonlisp/element_raise_spec.lua b/tests/nvim-paredit/commonlisp/element_raise_spec.lua new file mode 100644 index 0000000..7339752 --- /dev/null +++ b/tests/nvim-paredit/commonlisp/element_raise_spec.lua @@ -0,0 +1,52 @@ +local paredit = require("nvim-paredit.api") + +local prepare_buffer = require("tests.nvim-paredit.utils").prepare_buffer +local expect = require("tests.nvim-paredit.utils").expect + +describe("element raising", function() + vim.api.nvim_set_option_value("filetype", "lisp", { + buf = 0, + }) + + it("should raise the element", function() + prepare_buffer({ + "(a (|b))", + }) + paredit.raise_element() + expect({ + "(a |b)", + }) + end) + + it("should raise form elements when cursor is placed on edge", function() + prepare_buffer({ + "(a |(b))", + }) + + paredit.raise_element() + expect({ + "|(b)", + }) + + prepare_buffer({ + "(a |#(b))", + }) + + paredit.raise_element() + expect({ + "|#(b)", + }) + end) + + it("should do nothing if it is a direct child of the document root", function() + prepare_buffer({ + "|a", + "b", + }) + paredit.raise_form() + expect({ + "|a", + "b", + }) + end) +end) diff --git a/tests/nvim-paredit/commonlisp/form_raise_spec.lua b/tests/nvim-paredit/commonlisp/form_raise_spec.lua new file mode 100644 index 0000000..203039f --- /dev/null +++ b/tests/nvim-paredit/commonlisp/form_raise_spec.lua @@ -0,0 +1,50 @@ +local paredit = require("nvim-paredit.api") + +local prepare_buffer = require("tests.nvim-paredit.utils").prepare_buffer +local expect_all = require("tests.nvim-paredit.utils").expect_all +local expect = require("tests.nvim-paredit.utils").expect + +describe("form raising", function() + vim.api.nvim_set_option_value("filetype", "lisp", { + buf = 0, + }) + + it("should raise the form", function() + expect_all(paredit.raise_form, { + { + "list", + { "(a (b |c))" }, + { "|(b c)" }, + }, + { + "list with reader", + { "(a #(|b c))" }, + { "|#(b c)" }, + }, + }) + end) + + it("should do nothing if it is a direct child of the document root", function() + prepare_buffer({ + "(|a)", + "b", + }) + paredit.raise_form() + expect({ + "(|a)", + "b", + }) + end) + + it("should do nothing if it is outside of a form", function() + prepare_buffer({ + "|a", + "b", + }) + paredit.raise_form() + expect({ + "|a", + "b", + }) + end) +end) diff --git a/tests/nvim-paredit/commonlisp/motion_spec.lua b/tests/nvim-paredit/commonlisp/motion_spec.lua new file mode 100644 index 0000000..5693e70 --- /dev/null +++ b/tests/nvim-paredit/commonlisp/motion_spec.lua @@ -0,0 +1,47 @@ +local paredit = require("nvim-paredit.api") + +local prepare_buffer = require("tests.nvim-paredit.utils").prepare_buffer +local expect = require("tests.nvim-paredit.utils").expect + +describe("motions", function() + vim.api.nvim_set_option_value("filetype", "lisp", { + buf = 0, + }) + + it("should jump to next element in form (tail)", function() + prepare_buffer({ + "(a|a (bb) #(cc))", + }) + + paredit.move_to_next_element_tail() + expect({ + "(aa (bb|) #(cc))", + }) + + paredit.move_to_next_element_tail() + expect({ + "(aa (bb) #(cc|))", + }) + + paredit.move_to_next_element_tail() + expect({ + "(aa (bb) #(cc|))", + }) + end) + + it("should jump to next element in form (head)", function() + prepare_buffer({ + "(a|a (bb) #(cc))", + }) + + paredit.move_to_next_element_head() + expect({ + "(aa |(bb) #(cc))", + }) + + paredit.move_to_next_element_head() + expect({ + "(aa (bb) |#(cc))", + }) + end) +end) diff --git a/tests/nvim-paredit/commonlisp/slurp_spec.lua b/tests/nvim-paredit/commonlisp/slurp_spec.lua new file mode 100644 index 0000000..cb704b8 --- /dev/null +++ b/tests/nvim-paredit/commonlisp/slurp_spec.lua @@ -0,0 +1,96 @@ +local paredit = require("nvim-paredit.api") + +local expect_all = require("tests.nvim-paredit.utils").expect_all +local expect = require("tests.nvim-paredit.utils").expect + +describe("commonlisp slurping ::", function() + vim.api.nvim_set_option_value("filetype", "lisp", { + buf = 0, + }) + + describe("slurping backwards", function() + it("should slurp different form types", function() + expect_all(paredit.slurp_backwards, { + { + "list", + { "a (|)" }, + { "(a |)" }, + }, + { + "vector", + { "a |#()" }, + { "#(|a )" }, + }, + }) + end) + + it("should skip comments", function() + expect( + { + "a", + ";; comment", + "|()", + }, + paredit.slurp_backwards, + { + "(a", + ";; comment", + "|)", + } + ) + end) + end) + + describe("slurping forward", function() + it("should slurp forward different form types", function() + expect_all(paredit.slurp_forwards, { + { + "list", + { "(|) a" }, + { "(| a)" }, + }, + { + "vector", + { "#|() a" }, + { "#|( a)" }, + }, + { + "lambda", + { "(l|ambda (a b)) a" }, + { "(l|ambda (a b) a)" }, + }, + { + "lambda params inner", + { "(lambda (a b|) a)" }, + { "(lambda (a b| a))" }, + }, + { + "lambda params outer", + { "(lambda (a b|)) a" }, + { "(lambda (a b|) a)" }, + }, + { + "loop", + { "(loop for i from 1 to 10 do", " (print |i)) a" }, + { "(loop for i from 1 to 10 do", " (print |i) a)" }, + }, + }) + end) + + it("should skip comments", function() + expect( + { + "(|)", + ";; comment", + "a", + }, + paredit.slurp_forwards, + { + "|(", + ";; comment", + "a)", + } + ) + end) + end) +end)