From b42708fe56f8749e46fddf5ea089cbeef51ab6ed Mon Sep 17 00:00:00 2001 From: Adam Harrison Date: Sun, 6 Jun 2021 20:30:09 -0400 Subject: [PATCH] Cleaned up functions. --- data/core/commands/doc.lua | 51 +++++++--------- data/core/common.lua | 20 +++++++ data/core/doc/init.lua | 120 +++++++++---------------------------- data/core/docview.lua | 2 +- 4 files changed, 70 insertions(+), 123 deletions(-) diff --git a/data/core/commands/doc.lua b/data/core/commands/doc.lua index 1331901b..27da949a 100644 --- a/data/core/commands/doc.lua +++ b/data/core/commands/doc.lua @@ -25,14 +25,10 @@ end local function doc_multiline_selections(sort) - local iter, state, idx = doc():get_selections(sort) + local iter, state, idx, line1, col1, line2, col2 = doc():get_selections(sort) return function() - local line1, col1, line2, col2 idx, line1, col1, line2, col2 = iter(state, idx) - if not idx then - return - end - if line2 > line1 and col2 == 1 then + if idx and line2 > line1 and col2 == 1 then line2 = line2 - 1 col2 = #doc().lines[line2] end @@ -62,9 +58,9 @@ local function cut_or_copy(delete) doc():delete_to(idx, 0) end full_text = full_text == "" and text or (full_text .. "\n" .. text) - doc():set_cursor_clipboard(idx, text) + doc().cursor_clipboard[idx] = text else - doc():set_cursor_clipboard(idx, "") + doc().cursor_clipboard[idx] = "" end end system.set_clipboard(full_text) @@ -89,7 +85,7 @@ local commands = { ["doc:paste"] = function() for idx, line1, col1, line2, col2 in doc():get_selections() do - local value = doc():get_cursor_clipboard(idx) or system.get_clipboard() + local value = doc().cursor_clipboard[idx] or system.get_clipboard() doc():text_input(value:gsub("\r", ""), idx) end end, @@ -121,18 +117,18 @@ local commands = { end, ["doc:delete"] = function() - for idx, line, col in doc():get_selections() do - if not doc():has_selection(idx) and doc().lines[line]:find("^%s*$", col) then - doc():remove(line, col, line, math.huge) + for idx, line1, col1, line2, col2 in doc():get_selections() do + if line1 == line2 and col1 == col2 and doc().lines[line1]:find("^%s*$", col1) then + doc():remove(line1, col1, line1, math.huge) end doc():delete_to(idx, translate.next_char) end end, ["doc:backspace"] = function() - for idx, line, col in doc():get_selections() do - if not doc():has_selection(idx) then - local text = doc():get_text(line, 1, line, col) + for idx, line1, col1, line2, col2 in doc():get_selections() do + if line1 == line2 and col1 == col2 then + local text = doc():get_text(line1, 1, line1, col1) if #text >= config.indent_size and text:find("^ *$") then doc():delete_to(idx, 0, -config.indent_size) return @@ -167,7 +163,7 @@ local commands = { end, ["doc:join-lines"] = function() - for idx, line1, _, line2 in doc():get_selections(true) do + for idx, line1, col1, line2, col2 in doc():get_selections(true) do if line1 == line2 then line2 = line2 + 1 end local text = doc():get_text(line1, 1, line2, math.huge) text = text:gsub("(.-)\n[\t ]*", function(x) @@ -175,7 +171,7 @@ local commands = { end) doc():insert(line1, 1, text) doc():remove(line1, #text + 1, line2, math.huge) - if doc():has_selection(idx) then + if line1 ~= line2 or col1 ~= col2 then doc():set_selections(idx, line1, math.huge) end end @@ -183,6 +179,7 @@ local commands = { ["doc:indent"] = function() for idx, line1, col1, line2, col2 in doc_multiline_selections(true) do + print("LINE", line1, col1, line2, col2) local l1, c1, l2, c2 = doc():indent_text(false, line1, col1, line2, col2) if l1 then doc():set_selections(idx, l1, c1, l2, c2) @@ -398,25 +395,21 @@ for name, fn in pairs(translations) do end commands["doc:move-to-previous-char"] = function() - for idx, line, col in doc():get_selections(true) do - if doc():has_selection(idx) then - doc():set_selections(idx, line, col) + for idx, line1, col1, line2, col2 in doc():get_selections(true) do + if line1 ~= line2 or col1 ~= col2 then + doc():set_selections(idx, line1, col1) end end - if not doc():has_selection() then - doc():move_to(nil, translate.previous_char) - end + doc():move_to(nil, translate.previous_char) end commands["doc:move-to-next-char"] = function() - for idx, _, _, line, col in doc():get_selections(true) do - if doc():has_selection(idx) then - doc():set_selections(idx, line, col) + for idx, line1, col1, line2, col2 in doc():get_selections(true) do + if line1 ~= line2 or col1 ~= col2 then + doc():set_selections(idx, line2, col2) end end - if not doc():has_selection() then - doc():move_to(nil, translate.next_char) - end + doc():move_to(nil, translate.next_char) end command.add("core.docview", commands) diff --git a/data/core/common.lua b/data/core/common.lua index b7dd61db..548b5faa 100644 --- a/data/core/common.lua +++ b/data/core/common.lua @@ -61,6 +61,26 @@ function common.color(str) end +function common.splice(t, at, remove, insert) + insert = insert or {} + local offset = #insert - remove + local old_len = #t + if offset < 0 then + for i = at - offset, old_len - offset do + t[i + offset] = t[i] + end + elseif offset > 0 then + for i = old_len, at, -1 do + t[i + offset] = t[i] + end + end + for i, item in ipairs(insert) do + t[at + i - 1] = item + end +end + + + local function compare_score(a, b) return a.score > b.score end diff --git a/data/core/doc/init.lua b/data/core/doc/init.lua index f5bfbe57..80c8e5de 100644 --- a/data/core/doc/init.lua +++ b/data/core/doc/init.lua @@ -16,26 +16,6 @@ local function split_lines(text) return res end - -local function splice(t, at, remove, insert) - insert = insert or {} - local offset = #insert - remove - local old_len = #t - if offset < 0 then - for i = at - offset, old_len - offset do - t[i + offset] = t[i] - end - elseif offset > 0 then - for i = old_len, at, -1 do - t[i + offset] = t[i] - end - end - for i, item in ipairs(insert) do - t[at + i - 1] = item - end -end - - function Doc:new(filename) self:reset() if filename then @@ -127,91 +107,48 @@ function Doc:get_change_id() return self.undo_stack.idx end -function Doc:get_cursor_clipboard(idx) - return self.cursor_clipboard[idx] -end -function Doc:set_cursor_clipboard(idx, value) - self.cursor_clipboard[idx] = value -end - -function Doc:set_selection(line1, col1, line2, col2, swap) - assert(not line2 == not col2, "expected 2 or 4 arguments") - if swap then line1, col1, line2, col2 = line2, col2, line1, col1 end - line1, col1 = self:sanitize_position(line1, col1) - line2, col2 = self:sanitize_position(line2 or line1, col2 or col1) - self.selections = { line1, col1, line2, col2 } - self.cursor_clipboard = {} -end - function Doc:set_selections(idx, line1, col1, line2, col2, swap) assert(not line2 == not col2, "expected 3 or 5 arguments") if swap then line1, col1, line2, col2 = line2, col2, line1, col1 end line1, col1 = self:sanitize_position(line1, col1) line2, col2 = self:sanitize_position(line2 or line1, col2 or col1) - local target = (idx - 1)*4 + 1 - self.selections[target] = line1 - self.selections[target+1] = col1 - self.selections[target+2] = line2 - self.selections[target+3] = col2 + common.splice(self.selections, (idx - 1)*4 + 1, 4, { line1, col1, line2, col2 }) end +function Doc:set_selection(line1, col1, line2, col2, swap) + self.selections = {} + self:set_selections(1, line1, col1, line2, col2, swap) + self.cursor_clipboard = {} +end local function sort_positions(line1, col1, line2, col2) - if line1 > line2 - or line1 == line2 and col1 > col2 then - return line2, col2, line1, col1, true + if line1 > line2 or line1 == line2 and col1 > col2 then + return line2, col2, line1, col1 end - return line1, col1, line2, col2, false + return line1, col1, line2, col2 end - function Doc:get_selection(sort) - if sort then - local result = {} - for sidx, line1, col1, line2, col2 in self:get_selections(true) do - table.insert(result, line1) - table.insert(result, col1) - table.insert(result, line2) - table.insert(result, col2) - end - return result - end - return unpack(self.selections) -end - -function Doc:get_cursor_count() - return #self.selections / 4 + local idx, line1, col1, line2, col2 = self:get_selections(sort)(self.selections, 0) + return line1, col1, line2, col2 end function Doc:get_selections(sort) return function(selections, idx) local target = idx*4 + 1 - if target >= #selections then - return - end + if target >= #selections then return end if sort then - return idx+1, sort_positions(selections[target], selections[target+1], selections[target+2], selections[target+3]) + return idx+1, sort_positions(unpack(selections, target, target+4)) else - return idx+1, selections[target], selections[target+1], selections[target+2], selections[target+3] + return idx+1, unpack(selections, target, target+4) end end, self.selections, 0 end -function Doc:has_selection(idx) - if idx then - local target = (idx-1)*4+1 - return - self.selections[target] ~= self.selections[target+2] or - self.selections[target+1] ~= self.selections[target+3] - end - for target = 1, #self.selections, 4 do - if self.selections[target] ~= self.selections[target+2] or - self.selections[target+1] ~= self.selections[target+3] then - return true - end - end - return false +function Doc:has_selection() + local line1, col1, line2, col2 = self:get_selection(false) + return line1 ~= line2 or col1 ~= col2 end @@ -341,7 +278,7 @@ function Doc:raw_insert(line, col, text, undo_stack, time) lines[#lines] = lines[#lines] .. after -- splice lines into line array - splice(self.lines, line, 1, lines) + common.splice(self.lines, line, 1, lines) -- push undo local line2, col2 = self:position_offset(line, col, #text) @@ -365,7 +302,7 @@ function Doc:raw_remove(line1, col1, line2, col2, undo_stack, time) local after = self.lines[line2]:sub(col2) -- splice line into line array - splice(self.lines, line1, line2 - line1 + 1, { before .. after }) + common.splice(self.lines, line1, line2 - line1 + 1, { before .. after }) -- update highlighter and assure selection is in bounds self.highlighter:invalidate(line1) @@ -402,12 +339,12 @@ end function Doc:text_input(text, idx) - for sidx, line, col in self:get_selections() do + for sidx, line1, col1, line2, col2 in self:get_selections() do if not idx or idx == sidx then - if self:has_selection(sidx) then + if line1 ~= line2 or col1 ~= col2 then self:delete_to(sidx) end - self:insert(line, col, text) + self:insert(line1, col1, text) self:move_to(sidx, #text) end end @@ -415,11 +352,8 @@ end function Doc:replace(fn) - local line1, col1, line2, col2, swap - local had_selection = self:has_selection() - if had_selection then - line1, col1, line2, col2, swap = self:get_selection(true) - else + local line1, col1, line2, col2 = self:get_selection(true) + if line1 == line2 and col1 == col2 then line1, col1, line2, col2 = 1, 1, #self.lines, #self.lines[#self.lines] end local old_text = self:get_text(line1, col1, line2, col2) @@ -429,7 +363,7 @@ function Doc:replace(fn) self:remove(line1, col1, line2, col2) if had_selection then line2, col2 = self:position_offset(line1, col1, #new_text) - self:set_selection(line1, col1, line2, col2, swap) + self:set_selection(line1, col1, line2, col2) end end return n @@ -439,10 +373,10 @@ end function Doc:delete_to(idx, ...) for sidx, line1, col1, line2, col2 in self:get_selections(true) do if not idx or sidx == idx then - if self:has_selection(sidx) then + if line1 ~= line2 or col1 ~= col2 then self:remove(line1, col1, line2, col2) else - local l2, c2 = self:position_offset(line, col, ...) + local l2, c2 = self:position_offset(line1, col1, ...) self:remove(line1, col1, l2, c2) line1, col1 = sort_positions(line1, col1, l2, c2) end diff --git a/data/core/docview.lua b/data/core/docview.lua index 081c7966..15ecb838 100644 --- a/data/core/docview.lua +++ b/data/core/docview.lua @@ -361,7 +361,7 @@ function DocView:draw_line_body(idx, x, y) end for lidx, line1, col1, line2, col2 in self.doc:get_selections(true) do -- draw line highlight if caret is on this line - if config.highlight_current_line and not self.doc:has_selection(lidx) + if config.highlight_current_line and (line1 == line2 and col1 == col2) and line1 == idx and core.active_view == self then self:draw_line_highlight(x + self.scroll.x, y) end