diff --git a/lua/argonaut/cursor.lua b/lua/argonaut/cursor.lua index 954c5db..43c7dc3 100644 --- a/lua/argonaut/cursor.lua +++ b/lua/argonaut/cursor.lua @@ -2,57 +2,81 @@ local Cursor = {} Cursor.__index = Cursor function Cursor.new(row, col) - local cursor = { - row = row, - col = col, - } - + local cursor = {row = row, col = col} return setmetatable(cursor, Cursor) end +function Cursor.get_first() + local row = 1 + local line = vim.fn.getline(row) + return Cursor.new(row, #line) +end + +function Cursor.get_last() + local row = vim.fn.line('$') + local line = vim.fn.getline(row) + return Cursor.new(row, #line) +end + function Cursor.get_current() local _, row, col, _ = unpack(vim.fn.getpos('.')) return Cursor.new(row, col) end function Cursor:set_current() - assert(self:is_valid()) - vim.fn.setcursorcharpos({self.row, self.col}) end function Cursor:get_value() - assert(self:is_valid()) - local line = vim.fn.getline(self.row) return line:sub(self.col, self.col) end +function Cursor:get_syntax_name() + local syn_id = vim.fn.synID(self.row, self.col, false) + return vim.fn.synIDattr(syn_id, 'name') +end + function Cursor:is_valid() return self.row > 0 and self.col > 0 end -function Cursor:is_literal() - assert(self:is_valid()) - - 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$') ~= nil or syn_attr:find('Comment$') ~= nil +function Cursor:is_comment() + local name = self:get_syntax_name() + return name:find('Comment$') ~= nil end -function Cursor:next() - assert(self:is_valid()) +function Cursor:is_string() + local name = self:get_syntax_name() + return name:find('String$') ~= nil +end - local current_line = vim.fn.getline(self.row) - local next_col = self.col + 1 - local next_row = self.row +function Cursor:get_previous() + if self > Cursor.get_first() then + local previous_cursor = Cursor.new(self.row, self.col - 1) - if next_col > #current_line then - next_row = next_row + 1 - next_col = 1 + if previous_cursor.col < 1 then + previous_cursor.row = previous_cursor.row - 1 + local line = vim.fn.getline(previous_cursor.row ) + previous_cursor.col = #line + end + + return previous_cursor end +end - return Cursor.new(next_row, next_col) +function Cursor:get_next() + if self < Cursor.get_last() then + local line = vim.fn.getline(self.row) + local next_cursor = Cursor.new(self.row, self.col + 1) + + if next_cursor.col > #line then + next_cursor.row = next_cursor.row + 1 + next_cursor.col = 1 + end + + return next_cursor + end end function Cursor.__lt(cursor_1, cursor_2) diff --git a/lua/argonaut/options.lua b/lua/argonaut/options.lua index e7a9d0e..a261c5f 100644 --- a/lua/argonaut/options.lua +++ b/lua/argonaut/options.lua @@ -30,8 +30,6 @@ local function setup(opt) end local function query(param_name, pairing) - assert(pairing) - local default_param_value = options_current.default[param_name] local param_value = default_param_value diff --git a/lua/argonaut/pairing.lua b/lua/argonaut/pairing.lua index e2e0e32..71e760d 100644 --- a/lua/argonaut/pairing.lua +++ b/lua/argonaut/pairing.lua @@ -51,7 +51,7 @@ function Pairing:find_closest(forward) local ignore_func = function() local cursor = Cursor.get_current() - return cursor:is_literal() + return cursor:is_comment() or cursor:is_string() end local escaped_pair = self:get_escaped() diff --git a/lua/argonaut/param.lua b/lua/argonaut/param.lua index 8aea334..64abf16 100644 --- a/lua/argonaut/param.lua +++ b/lua/argonaut/param.lua @@ -1,43 +1,87 @@ +local ParamCursorCell = {} +ParamCursorCell.__index = ParamCursorCell + +function ParamCursorCell.new(cursor) + local param_cell_cursor = {cursor = cursor} + return setmetatable(param_cell_cursor, ParamCursorCell) +end + +function ParamCursorCell:write(builder) + builder:write(self.cursor:get_value()) +end + +function ParamCursorCell:hit_test(cursor) + if self.cursor == cursor then + return {} + end +end + +function ParamCursorCell:hit_search() + return self.cursor +end + +function ParamCursorCell:get_start_row() + return self.cursor.row +end + +function ParamCursorCell:get_stop_row() + return self.cursor.row +end + +function ParamCursorCell:is_empty() + return not self.cursor:get_value():match('%S') +end + +local ParamRangeCell = {} +ParamRangeCell.__index = ParamRangeCell + +function ParamRangeCell.new(range) + local param_cell_range = {range = range} + return setmetatable(param_cell_range, ParamRangeCell) +end + +function ParamRangeCell:write(builder, wrapped) + self.range:write(builder, wrapped) +end + +function ParamRangeCell:hit_test(cursor) + return self.range:hit_test(cursor) +end + +function ParamRangeCell:hit_search(trace, depth) + return self.range:hit_search(trace, depth + 1) +end + +function ParamRangeCell:get_start_row() + return self.range.start_cursor.row +end + +function ParamRangeCell:get_stop_row() + return self.range.stop_cursor.row +end + +function ParamRangeCell:is_empty() + return false +end + local Param = {} Param.__index = Param -local function is_empty_cell(cell) - return cell.type == 'cursor' and not cell.value:get_value():match('%S') -end - -local function get_param_start_row(param) - local cell = param.cells[1] - if cell.type == 'range' then - return cell.value.start_cursor.row - elseif cell.type == 'cursor' then - return cell.value.row - end -end - -local function get_param_stop_row(param) - local cell = param.cells[#param.cells] - if cell.type == 'range' then - return cell.value.stop_cursor.row - elseif cell.type == 'cursor' then - return cell.value.row - end -end - function Param.new(range, index, cells) - local param = { - range = range, - index = index, - cells = cells or {}, - } - + local param = {range = range, index = index, cells = cells or {}} return setmetatable(param, Param) end -function Param:append(value, type) - table.insert(self.cells, { - value = value, - type = type, - }) +function Param.new_cursor_cell(cursor) + return ParamCursorCell.new(cursor) +end + +function Param.new_range_cell(range) + return ParamRangeCell.new(range) +end + +function Param:append(cell) + table.insert(self.cells, cell) end function Param:stripped() @@ -45,25 +89,15 @@ function Param:stripped() for i = self:find_index_begin(), self:find_index_end() do table.insert(cells, self.cells[i]) end + return Param.new(self.range, self.index, cells) end function Param:hit_test(cursor) for i, cell in ipairs(self.cells) do - local trace = nil - if cell.type == 'range' then - local trace_param = cell.value:hit_test(cursor) - if trace_param then - trace = {i} - for _, trace_param_frame in ipairs(trace_param) do - table.insert(trace, trace_param_frame) - end - end - elseif cell.type == 'cursor' and cell.value == cursor then - trace = {i} - end - + local trace = cell:hit_test(cursor) if trace then + table.insert(trace, 1, i) return trace end end @@ -71,43 +105,42 @@ end function Param:hit_search(trace, depth) local index = trace[depth] - local cell = self.cells[index] - if cell.type == 'range' then - return cell.value:hit_search(trace, depth + 1) - elseif cell.type == 'cursor' then - return cell.value - end + return self.cells[index]:hit_search(depth) end function Param:write(builder, wrapped) for i = self:find_index_begin(), self:find_index_end() do - local cell = self.cells[i] - if cell.type == 'range' then - cell.value:write(builder, wrapped) - elseif cell.type == 'cursor' then - builder:write(cell.value:get_value()) - end - end -end - -function Param:is_wrapped() - local previous_param = self:get_previous() - if previous_param then - return get_param_stop_row(previous_param) ~= get_param_start_row(self) - else - return self.range.start_cursor.row ~= get_param_start_row(self) + self.cells[i]:write(builder, wrapped) end end function Param:get_previous() if self.index > 1 then - return self.range.params[self.index-1] + return self.range.params[self.index - 1] + end +end + +function Param:get_next() + if self.index < #self.range.params then + return self.range.params[self.index + 1] + end +end + +function Param:get_start_row() + if #self.cells > 0 then + return self.cells[1]:get_start_row() + end +end + +function Param:get_stop_row() + if #self.cells > 0 then + return self.cells[#self.cells]:get_stop_row() end end function Param:find_index_begin() for i = 1, #self.cells do - if not is_empty_cell(self.cells[i]) then + if not self.cells[i]:is_empty() then return i end end @@ -115,12 +148,21 @@ end function Param:find_index_end() for i = #self.cells, 1, -1 do - if not is_empty_cell(self.cells[i]) then + if not self.cells[i]:is_empty() then return i end end end +function Param:is_wrapped() + local previous_param = self:get_previous() + if previous_param then + return previous_param:get_stop_row() ~= self:get_start_row() + else + return self.range.start_cursor.row ~= self:get_start_row() + end +end + function Param:is_empty() return self:find_index_begin() == nil end diff --git a/lua/argonaut/range.lua b/lua/argonaut/range.lua index f5302ab..2e6924b 100644 --- a/lua/argonaut/range.lua +++ b/lua/argonaut/range.lua @@ -64,12 +64,12 @@ function Range:parse() local param = nil local param_index = 1 - local append_param_value = function(value, type) + local append_param_value = function(cell) if not param then param = Param.new(self, param_index) param_index = param_index + 1 end - param:append(value, type) + param:append(cell) end local append_param = function() @@ -79,25 +79,25 @@ function Range:parse() param = nil end - local cursor = self.start_cursor:next() + local cursor = self.start_cursor:get_next() while cursor ~= self.stop_cursor do local value = cursor:get_value() - if cursor:is_literal() then - append_param_value(cursor, 'cursor') + if cursor:is_string() or cursor:is_comment() then + append_param_value(Param.new_cursor_cell(cursor)) else local range = find_at_cursor(cursor) if range then - append_param_value(range, 'range') + append_param_value(Param.new_range_cell(range)) cursor = range.stop_cursor elseif value == ',' then append_param() else - append_param_value(cursor, 'cursor') + append_param_value(Param.new_cursor_cell(cursor)) end end - cursor = cursor:next() + cursor = cursor:get_next() end append_param()