From 3e5838290dd57116457e4b11eb6ba21e83b260a4 Mon Sep 17 00:00:00 2001 From: Ekaitz Zarraga Date: Sat, 27 Jan 2024 22:32:16 +0100 Subject: Initial commit --- lua/nvim-paredit-scheme/extension.lua | 175 ++++++++++++++++++++++++++++++++++ lua/nvim-paredit-scheme/init.lua | 27 ++++++ 2 files changed, 202 insertions(+) create mode 100644 lua/nvim-paredit-scheme/extension.lua create mode 100644 lua/nvim-paredit-scheme/init.lua (limited to 'lua') diff --git a/lua/nvim-paredit-scheme/extension.lua b/lua/nvim-paredit-scheme/extension.lua new file mode 100644 index 0000000..2eb6f91 --- /dev/null +++ b/lua/nvim-paredit-scheme/extension.lua @@ -0,0 +1,175 @@ +-- nvim-paredit extension for scheme +-- Copyright (C) 2023 Ekaitz Zarraga +-- +-- This program is free software: you can redistribute it and/or modify +-- it under the terms of the GNU General Public License as published by +-- the Free Software Foundation, either version 3 of the License, or +-- (at your option) any later version. +-- +-- This program is distributed in the hope that it will be useful, +-- but WITHOUT ANY WARRANTY; without even the implied warranty of +-- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +-- GNU General Public License for more details. +-- +-- You should have received a copy of the GNU General Public License +-- along with this program. If not, see . + + +local traversal = require("nvim-paredit.utils.traversal") + +-- THIS IS A REFERENCE, UNUSED +local nodes = { + "comment", + "block_comment", -- for example, #| something |# + "directive", -- for example, #!r6rs + "boolean", + "character", + "string", + "escape_sequence", -- escape sequence in string, for example, \n in "abc\n" + "number", + "symbol", -- identifier + "keyword", -- #:identifier + "list", -- things surrounded by () or [] or {} + "quote", -- ' + "quasiquote", -- ` + "syntax", -- #' + "quasisyntax", --` + "unquote", -- , + "unquote_splicing", -- ,@ + "unsyntax", -- #, + "unsyntax_splicing", -- #,@ + "vector", + "byte_vector", +} + +local forms = { + comment = {2, 0}, -- for srfi 62, #; + block_comment = {2, 2}, -- for example, #| something |# + string = {1, 1}, + list = {1, 1}, -- things surrounded by () or [] or {} + vector = {2, 1}, -- #(...) + byte_vector = {5, 1}, -- #vu8(...) + vector = {2, 1}, +} + + +local function find_next_parent_form(current_node) + if forms[current_node:type()] then + return current_node + end + + local parent = current_node:parent() + if parent then + return find_next_parent_form(parent) + end + + return current_node +end + +local function find_parent_comment(node) + if node:type() == "comment" then + return node + end + local parent = node:parent() + + if parent then + return find_parent_comment(parent) + else + return nil + end +end + +local M = {} + +-- Should return the 'root' of the given Treesitter node. For example: +-- The node at cursor in the below example is `()` or 'list_lit': +-- '(|) +-- But the node root is `'()` or 'quoting_lit' +M.get_node_root = function(node) + local search_point = node + if M.node_is_form(node) then + search_point = node:parent() + end + + local root = find_next_parent_form(search_point) + return traversal.find_root_element_relative_to(root, node) +end +-- This is the inverse of `get_node_root` for forms and should find the inner +-- node for which the forms elements are direct children. +-- +-- For example given the node `'()` or 'quoting_lit', this function should +-- return `()` or 'list_lit'. +M.unwrap_form = function(node) + if forms[node:type()] then + return node + end + local child = node:named_child(0) + if child then + return M.unwrap_form(child) + end +end +-- Accepts a Treesitter node and should return true or false depending on +-- whether the given node can be considered a 'form' +M.node_is_form = function(node) + if M.unwrap_form(node) then + return true + else + return false + end +end +-- Accepts a Treesitter node and should return true or false depending on +-- whether the given node can be considered a 'comment' +M.node_is_comment = function(node) + return (find_parent_comment(node) + or node:type() == "comment" + or node:type() == "block_comment") +end +-- Accepts a Treesitter node representing a form and should return the +-- 'edges' of the node. This includes the node text and the range covered by +-- the node +M.get_form_edges = function(node) + local node_range = { node:range() } + + local form = M.unwrap_form(node) + local form_range = { form:range() } + + -- Get the size of the form boundaries + local size = forms[node:type()] + if not size then + -- default to {1, 1} + size = {1, 1} + end + -- If it's an inline comment don't do anything + if node:type() == "comment" + and vim.api.nvim_buf_get_text(0, form_range[1], form_range[2], + form_range[3], form_range[4], {})[1]:sub(1,1) == ";" + then + return {} + end + + local left_range = { node_range[1], node_range[2] } + left_range[3] = form_range[1] + left_range[4] = form_range[2] + size[1] + + local right_range = { form:range() } + right_range[1] = right_range[3] + right_range[2] = right_range[4] - size[2] + + local left_text = vim.api.nvim_buf_get_text(0, left_range[1], left_range[2], + left_range[3], left_range[4], {}) + local right_text = vim.api.nvim_buf_get_text(0, right_range[1], + right_range[2], right_range[3], right_range[4], {}) + + return { + left = { + text = left_text[1], + range = left_range, + }, + right = { + text = right_text[1], + range = right_range, + }, + } +end + +return M diff --git a/lua/nvim-paredit-scheme/init.lua b/lua/nvim-paredit-scheme/init.lua new file mode 100644 index 0000000..ac19807 --- /dev/null +++ b/lua/nvim-paredit-scheme/init.lua @@ -0,0 +1,27 @@ +-- nvim-paredit extension for scheme +-- Copyright (C) 2023 Ekaitz Zarraga +-- +-- This program is free software: you can redistribute it and/or modify +-- it under the terms of the GNU General Public License as published by +-- the Free Software Foundation, either version 3 of the License, or +-- (at your option) any later version. +-- +-- This program is distributed in the hope that it will be useful, +-- but WITHOUT ANY WARRANTY; without even the implied warranty of +-- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +-- GNU General Public License for more details. +-- +-- You should have received a copy of the GNU General Public License +-- along with this program. If not, see . + +local extension = require("nvim-paredit-scheme.extension") + +local M = { + extension = extension +} + +function M.setup(paredit) + paredit.extension.add_language_extension("scheme", extension) +end + +return M -- cgit v1.2.3