diff --git a/lua/argonaut/types.lua b/lua/argonaut/types.lua index 8200ac7..457096d 100644 --- a/lua/argonaut/types.lua +++ b/lua/argonaut/types.lua @@ -1,22 +1,50 @@ +-- +-- Cursor +-- + Cursor = {} -function Cursor.new(x, y) - local cursor = { - x = x, - y = y, - } - +function Cursor.new(row, col) + local cursor = {row = row, col = col} return setmetatable(cursor, {__index = Cursor}) end -function Cursor:print() - print('x: ' .. self.x .. ' y: ' .. self.y) +function Cursor.current() + local _, row, col, _ = unpack(vim.fn.getpos('.')) + return Cursor.new(row, col) end +function Cursor:is_string_literal() + local syn_id = vim.fn.synID(self.row, self.col, false) + local syn_attr = vim.fn.synIDattr(syn_id, 'name') + return syn_attr:find('String$') +end + +function Cursor:is_valid() + return self.row > 0 and self.col > 0 +end + +-- +-- BracePair +-- + BracePair = {} -function BracePair.new(brace) - local escape = function(brace_raw) +function BracePair.new(brace_open, brace_close) + local brace_pair = {open = brace_open, close = brace_close} + return setmetatable(brace_pair, {__index = BracePair}) +end + +function BracePair.from_brace(brace) + for _, brace_set in ipairs({{'(', ')'}, {'[', ']'}, {'{', '}'}, {'<', '>'}}) do + if brace_set[1] == brace or brace_set[2] == brace then + return BracePair.new(brace_set[1], brace_set[2]) + end + end +end + +function BracePair:escaped() + local escape_brace = function(brace_raw) if brace_raw == '[' or brace_raw == ']' then return '\\' .. brace_raw else @@ -24,22 +52,38 @@ function BracePair.new(brace) end end - for _, brace_set in ipairs({{'(', ')'}, {'[', ']'}, {'{', '}'}, {'<', '>'}}) do - if brace_set[1] == brace or brace_set[2] == brace then - local brace_pair = { - open = brace_set[1], - close = brace_set[2], - escaped = { - open = escape(brace_set[1]), - closed = escape(brace_set[2]), - } - } + return BracePair.new(escape_brace(self.open), escape_brace(self.close)) +end - return setmetatable(brace_pair, {__index = BracePair}) +function BracePair:find(backward) + -- See flags: https://neovim.io/doc/user/builtin.html#search() + local flags = 'Wcn' + if backward then + flags = 'Wbn' + end + + local escaped_pair = self:escaped() + local position = vim.fn.searchpairpos( + escaped_pair.open, + '', + escaped_pair.close, + flags, + function() + local cursor = Cursor:current() + return cursor:is_string_literal() end + ) + + local cursor = Cursor.new(unpack(position)) + if cursor:is_valid() then + return cursor end end +-- +-- BraceRange +-- + BraceRange = {} function BraceRange.new(start_cursor, stop_cursor, brace_pair, brace_params) @@ -47,8 +91,18 @@ function BraceRange.new(start_cursor, stop_cursor, brace_pair, brace_params) start_cursor = start_cursor, stop_cursor = stop_cursor, brace_pair = brace_pair, - brace_params = brace_params or {}, + brace_params = brace_params, } return setmetatable(brace_range, {__index = BraceRange}) end + +function BraceRange.find(brace_pair) + local start_cursor = brace_pair:find(false) + if start_cursor then + local stop_cursor = brace_pair:find(true) + if stop_cursor then + return BraceRange.new(start_cursor, stop_cursor, brace_pair, {}) + end + end +end