summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--lua/clever_f/text_topology.lua42
-rw-r--r--tests/run.lua26
2 files changed, 48 insertions, 20 deletions
diff --git a/lua/clever_f/text_topology.lua b/lua/clever_f/text_topology.lua
index 56f3b9c..37365a0 100644
--- a/lua/clever_f/text_topology.lua
+++ b/lua/clever_f/text_topology.lua
@@ -324,22 +324,14 @@ function TextView.new(text, effective_encoding, options)
)
local encoder = selected_function(options, "encoder", "encode", default_encode)
- local lines = {}
- for line_number = 1, snapshot.line_count do
- lines[line_number] = index_line(
- snapshot:line(line_number),
- encoding,
- splitter,
- encoder
- )
- end
-
local view = setmetatable({}, text_view_metatable)
view_records[view] = {
snapshot = snapshot,
requested_encoding = requested_encoding,
encoding = encoding,
- lines = lines,
+ splitter = splitter,
+ encoder = encoder,
+ lines = {},
}
return view
end
@@ -375,7 +367,17 @@ local function line_record(view, line_number)
then
fail("line_number must identify a line in the TextView", 3)
end
- return record.lines[line_number]
+ local line = record.lines[line_number]
+ if line == nil then
+ line = index_line(
+ record.snapshot:line(line_number),
+ record.encoding,
+ record.splitter,
+ record.encoder
+ )
+ record.lines[line_number] = line
+ end
+ return line
end
local function require_character_index(line, character_index)
@@ -433,7 +435,7 @@ function TextView:text_suffix(position)
end
for line_number = position.line + 1, record.snapshot.line_count do
parts[#parts + 1] = "\n"
- parts[#parts + 1] = record.lines[line_number].text
+ parts[#parts + 1] = record.snapshot:line(line_number)
end
return table.concat(parts)
end
@@ -540,7 +542,7 @@ function TextView:is_character_start(position_or_line, byte_column)
if line_number > record.snapshot.line_count then
return false
end
- return record.lines[line_number].by_start[column] ~= nil
+ return line_record(self, line_number).by_start[column] ~= nil
end
function TextView:is_valid_cursor_position(position_or_line, byte_column)
@@ -549,7 +551,7 @@ function TextView:is_valid_cursor_position(position_or_line, byte_column)
if line_number > record.snapshot.line_count then
return false
end
- local line = record.lines[line_number]
+ local line = line_record(self, line_number)
if line.character_count == 0 then
return column == 1
end
@@ -740,7 +742,7 @@ function TextView:buffer_match_start_bounds()
local last
for line_number = 1, record.snapshot.line_count do
- local line = record.lines[line_number]
+ local line = line_record(self, line_number)
if line.character_count > 0 then
first = self:position_for_character_index(line_number, 1)
break
@@ -748,7 +750,7 @@ function TextView:buffer_match_start_bounds()
end
for line_number = record.snapshot.line_count, 1, -1 do
- local line = record.lines[line_number]
+ local line = line_record(self, line_number)
if line.character_count > 0 then
last = self:position_for_character_index(line_number, line.character_count)
break
@@ -810,7 +812,7 @@ end
local function step_character(view, position, direction)
local record = view_record(view)
- local line = record.lines[position.line]
+ local line = line_record(view, position.line)
local character_index = line.by_start[position.byte_column]
if direction == domain.Direction.FORWARD then
@@ -818,7 +820,7 @@ local function step_character(view, position, direction)
return view:position_for_character_index(position.line, character_index + 1)
end
for line_number = position.line + 1, record.snapshot.line_count do
- if record.lines[line_number].character_count > 0 then
+ if line_record(view, line_number).character_count > 0 then
return view:position_for_character_index(line_number, 1)
end
end
@@ -829,7 +831,7 @@ local function step_character(view, position, direction)
return view:position_for_character_index(position.line, character_index - 1)
end
for line_number = position.line - 1, 1, -1 do
- local previous_line = record.lines[line_number]
+ local previous_line = line_record(view, line_number)
if previous_line.character_count > 0 then
return view:position_for_character_index(
line_number,
diff --git a/tests/run.lua b/tests/run.lua
index 8b29fd3..069cc60 100644
--- a/tests/run.lua
+++ b/tests/run.lua
@@ -1942,6 +1942,32 @@ test("TextView creation reads one operation-local snapshot", function()
end, "immutable")
end)
+test("TextView indexes only lines required by an operation", function()
+ local indexed = {}
+ local view = text_topology.new({ "aaa", "bbb", "ccc" }, "utf-8", {
+ splitter = function(text)
+ indexed[#indexed + 1] = text
+ return text_topology.split_editor_characters(text)
+ end,
+ encoder = function(character)
+ return character
+ end,
+ })
+
+ same(0, #indexed)
+ local positions = collect_iteration(view:iter_strict_forward(
+ domain.Position.new(2, 1),
+ domain.SearchScope.CURRENT_LINE
+ ))
+ list_same({ "(2,2)", "(2,3)" }, position_strings(positions))
+ list_same({ "bbb" }, indexed)
+ same("bb\nccc", view:text_suffix(domain.Position.new(2, 2)))
+ list_same({ "bbb" }, indexed)
+
+ same(3, view:line_character_count(1))
+ list_same({ "bbb", "aaa" }, indexed)
+end)
+
test("All-empty buffers expose empty full-buffer iteration", function()
local view = text_topology.new({ "", "", "" }, "utf-8")
local bounds = view:buffer_match_start_bounds()