Introduced the constraint that all cursors must be in order.
This commit is contained in:
parent
b065b52067
commit
6915d86d59
|
@ -110,7 +110,7 @@ local commands = {
|
||||||
end,
|
end,
|
||||||
|
|
||||||
["doc:newline"] = function()
|
["doc:newline"] = function()
|
||||||
for idx, line, col in doc():get_selections() do
|
for idx, line, col in doc():get_selections(false, true) do
|
||||||
local indent = doc().lines[line]:match("^[\t ]*")
|
local indent = doc().lines[line]:match("^[\t ]*")
|
||||||
if col <= #indent then
|
if col <= #indent then
|
||||||
indent = indent:sub(#indent + 2 - col)
|
indent = indent:sub(#indent + 2 - col)
|
||||||
|
@ -208,7 +208,6 @@ local commands = {
|
||||||
|
|
||||||
["doc:indent"] = function()
|
["doc:indent"] = function()
|
||||||
for idx, line1, col1, line2, col2 in doc_multiline_selections(true) do
|
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)
|
local l1, c1, l2, c2 = doc():indent_text(false, line1, col1, line2, col2)
|
||||||
if l1 then
|
if l1 then
|
||||||
doc():set_selections(idx, l1, c1, l2, c2)
|
doc():set_selections(idx, l1, c1, l2, c2)
|
||||||
|
|
|
@ -107,18 +107,56 @@ function Doc:get_change_id()
|
||||||
return self.undo_stack.idx
|
return self.undo_stack.idx
|
||||||
end
|
end
|
||||||
|
|
||||||
function Doc:set_selections(idx, line1, col1, line2, col2, swap)
|
-- Cursor section. Cursor indices are *only* valid during a get_selections() call.
|
||||||
|
-- Cursors will always be iterated in order from top to bottom. Through normal operation
|
||||||
|
-- curors can never swap positions; only merge or split, or change their position in cursor
|
||||||
|
-- order.
|
||||||
|
function Doc:get_selection(sort)
|
||||||
|
local idx, line1, col1, line2, col2 = self:get_selections(sort)({ self.selections, sort }, 0)
|
||||||
|
return line1, col1, line2, col2, sort
|
||||||
|
end
|
||||||
|
|
||||||
|
function Doc:has_selection()
|
||||||
|
local line1, col1, line2, col2 = self:get_selection(false)
|
||||||
|
return line1 ~= line2 or col1 ~= col2
|
||||||
|
end
|
||||||
|
|
||||||
|
function Doc:sanitize_selection()
|
||||||
|
for idx, line1, col1, line2, col2 in self:get_selections() do
|
||||||
|
self:set_selections(idx, line1, col1, line2, col2)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
local function sort_positions(line1, col1, line2, col2)
|
||||||
|
if line1 > line2 or line1 == line2 and col1 > col2 then
|
||||||
|
return line2, col2, line1, col1
|
||||||
|
end
|
||||||
|
return line1, col1, line2, col2
|
||||||
|
end
|
||||||
|
|
||||||
|
function Doc:set_selections(idx, line1, col1, line2, col2, swap, rm)
|
||||||
assert(not line2 == not col2, "expected 3 or 5 arguments")
|
assert(not line2 == not col2, "expected 3 or 5 arguments")
|
||||||
if swap then line1, col1, line2, col2 = line2, col2, line1, col1 end
|
if swap then line1, col1, line2, col2 = line2, col2, line1, col1 end
|
||||||
line1, col1 = self:sanitize_position(line1, col1)
|
line1, col1 = self:sanitize_position(line1, col1)
|
||||||
line2, col2 = self:sanitize_position(line2 or line1, col2 or col1)
|
line2, col2 = self:sanitize_position(line2 or line1, col2 or col1)
|
||||||
common.splice(self.selections, (idx - 1)*4 + 1, 4, { line1, col1, line2, col2 })
|
common.splice(self.selections, (idx - 1)*4 + 1, rm == nil and 4 or rm, { line1, col1, line2, col2 })
|
||||||
|
end
|
||||||
|
|
||||||
|
function Doc:add_selection(line1, col1, line2, col2, swap)
|
||||||
|
local l1, c1 = sort_positions(line1, col1, line2, col2)
|
||||||
|
local target = #self.selections / 4 + 1
|
||||||
|
for idx, tl1, tc1 in self:get_selections(true) do
|
||||||
|
if l1 < tl1 or l1 == tl1 and c1 < tc1 then
|
||||||
|
target = idx
|
||||||
|
break
|
||||||
|
end
|
||||||
|
end
|
||||||
|
self:set_selections(target, line1, col1, line2, col2, swap, 0)
|
||||||
end
|
end
|
||||||
|
|
||||||
function Doc:set_selection(line1, col1, line2, col2, swap)
|
function Doc:set_selection(line1, col1, line2, col2, swap)
|
||||||
self.selections = {}
|
self.selections, self.cursor_clipboard = {}, {}
|
||||||
self:set_selections(1, line1, col1, line2, col2, swap)
|
self:set_selections(1, line1, col1, line2, col2, swap)
|
||||||
self.cursor_clipboard = {}
|
|
||||||
end
|
end
|
||||||
|
|
||||||
function Doc:merge_cursors(idx)
|
function Doc:merge_cursors(idx)
|
||||||
|
@ -133,43 +171,20 @@ function Doc:merge_cursors(idx)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
local function sort_positions(line1, col1, line2, col2)
|
local function selection_iterator(invariant, idx)
|
||||||
if line1 > line2 or line1 == line2 and col1 > col2 then
|
local target = invariant[3] and (#invariant[1] - 3 - idx * 4) or (idx*4 + 1)
|
||||||
return line2, col2, line1, col1
|
if idx * 4 >= #invariant[1] then return end
|
||||||
end
|
if invariant[2] then
|
||||||
return line1, col1, line2, col2
|
return idx+1, sort_positions(unpack(invariant[1], target, target+4))
|
||||||
end
|
else
|
||||||
|
return idx+1, unpack(invariant[1], target, target+4)
|
||||||
function Doc:get_selection(sort)
|
|
||||||
local idx, line1, col1, line2, col2 = self:get_selections(sort)(self.selections, 0)
|
|
||||||
return line1, col1, line2, col2, sort
|
|
||||||
end
|
|
||||||
|
|
||||||
function Doc:get_selections(sort)
|
|
||||||
return function(selections, idx)
|
|
||||||
local target = idx*4 + 1
|
|
||||||
if target >= #selections then return end
|
|
||||||
if sort then
|
|
||||||
return idx+1, sort_positions(unpack(selections, target, target+4))
|
|
||||||
else
|
|
||||||
return idx+1, unpack(selections, target, target+4)
|
|
||||||
end
|
|
||||||
end, self.selections, 0
|
|
||||||
end
|
|
||||||
|
|
||||||
|
|
||||||
function Doc:has_selection()
|
|
||||||
local line1, col1, line2, col2 = self:get_selection(false)
|
|
||||||
return line1 ~= line2 or col1 ~= col2
|
|
||||||
end
|
|
||||||
|
|
||||||
|
|
||||||
function Doc:sanitize_selection()
|
|
||||||
for idx, line1, col1, line2, col2 in self:get_selections() do
|
|
||||||
self:set_selections(idx, line1, col1, line2, col2)
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
function Doc:get_selections(sort_intra, reverse)
|
||||||
|
return selection_iterator, { self.selections, sort_intra, reverse }, 0
|
||||||
|
end
|
||||||
|
-- End of cursor seciton.
|
||||||
|
|
||||||
function Doc:sanitize_position(line, col)
|
function Doc:sanitize_position(line, col)
|
||||||
line = common.clamp(line, 1, #self.lines)
|
line = common.clamp(line, 1, #self.lines)
|
||||||
|
|
|
@ -278,6 +278,7 @@ function DocView:on_mouse_moved(x, y, ...)
|
||||||
local clicks = self.mouse_selecting.clicks
|
local clicks = self.mouse_selecting.clicks
|
||||||
if keymap.modkeys["ctrl"] then
|
if keymap.modkeys["ctrl"] then
|
||||||
if l1 > l2 then l1, l2 = l2, l1 end
|
if l1 > l2 then l1, l2 = l2, l1 end
|
||||||
|
self.doc.selections = { }
|
||||||
for i = l1, l2 do
|
for i = l1, l2 do
|
||||||
self.doc:set_selections(i - l1 + 1, i, math.min(c1, #self.doc.lines[i]), i, math.min(c2, #self.doc.lines[i]))
|
self.doc:set_selections(i - l1 + 1, i, math.min(c1, #self.doc.lines[i]), i, math.min(c2, #self.doc.lines[i]))
|
||||||
end
|
end
|
||||||
|
|
Loading…
Reference in New Issue