Skip to content

Commit

Permalink
Add treesitter queries and tests for commonlisp
Browse files Browse the repository at this point in the history
  • Loading branch information
julienvincent committed Oct 16, 2024
1 parent 49b0acc commit d412077
Show file tree
Hide file tree
Showing 9 changed files with 272 additions and 6 deletions.
11 changes: 8 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand Down Expand Up @@ -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.
Expand Down
2 changes: 1 addition & 1 deletion lua/nvim-paredit/defaults.lua
Original file line number Diff line number Diff line change
Expand Up @@ -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 = { " ", "," },
Expand Down
5 changes: 4 additions & 1 deletion lua/nvim-paredit/treesitter/forms.lua
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down Expand Up @@ -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
Expand Down
13 changes: 13 additions & 0 deletions queries/commonlisp/paredit/forms.scm
Original file line number Diff line number Diff line change
@@ -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
2 changes: 1 addition & 1 deletion tests/config.lua
Original file line number Diff line number Diff line change
Expand Up @@ -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,
})
52 changes: 52 additions & 0 deletions tests/nvim-paredit/commonlisp/element_raise_spec.lua
Original file line number Diff line number Diff line change
@@ -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)
50 changes: 50 additions & 0 deletions tests/nvim-paredit/commonlisp/form_raise_spec.lua
Original file line number Diff line number Diff line change
@@ -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)
47 changes: 47 additions & 0 deletions tests/nvim-paredit/commonlisp/motion_spec.lua
Original file line number Diff line number Diff line change
@@ -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)
96 changes: 96 additions & 0 deletions tests/nvim-paredit/commonlisp/slurp_spec.lua
Original file line number Diff line number Diff line change
@@ -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)

0 comments on commit d412077

Please sign in to comment.