summaryrefslogtreecommitdiff
path: root/script/text-merger.lua
diff options
context:
space:
mode:
Diffstat (limited to 'script/text-merger.lua')
-rw-r--r--script/text-merger.lua99
1 files changed, 99 insertions, 0 deletions
diff --git a/script/text-merger.lua b/script/text-merger.lua
new file mode 100644
index 00000000..9e01ba1c
--- /dev/null
+++ b/script/text-merger.lua
@@ -0,0 +1,99 @@
+local files = require 'files'
+local util = require 'utility'
+
+local function splitRows(text)
+ local rows = {}
+ for line in util.eachLine(text, true) do
+ rows[#rows+1] = line
+ end
+ return rows
+end
+
+local function getLeft(text, char)
+ local left
+ local length = util.utf8Len(text)
+
+ if char == 0 then
+ left = ''
+ elseif char >= length then
+ left = text
+ else
+ left = text:sub(1, utf8.offset(text, char + 1) - 1)
+ end
+
+ return left
+end
+
+local function getRight(text, char)
+ local right
+ local length = util.utf8Len(text)
+
+ if char == 0 then
+ right = text
+ elseif char >= length then
+ right = ''
+ else
+ right = text:sub(utf8.offset(text, char + 1))
+ end
+
+ return right
+end
+
+local function mergeRows(rows, change)
+ local startLine = change.range['start'].line + 1
+ local startChar = change.range['start'].character
+ local endLine = change.range['end'].line + 1
+ local endChar = change.range['end'].character
+
+ local insertRows = splitRows(change.text)
+ -- 先把双方的行数调整成一致
+ local delta = #insertRows - (endLine - startLine + 1)
+ if delta ~= 0 then
+ table.move(rows, endLine, #rows, endLine + delta)
+ -- 如果行数变少了,要清除多余的行
+ if delta < 0 then
+ for i = #rows, #rows + delta + 1, -1 do
+ rows[i] = nil
+ end
+ end
+ end
+ -- 先处理第一行和最后一行
+ local newEndLine = startLine + #insertRows - 1
+ local left = getLeft(rows[startLine], startChar)
+ local right = getRight(rows[newEndLine], endChar)
+ if startLine == newEndLine then
+ rows[startLine] = left .. insertRows[1] .. right
+ else
+ rows[startLine] = left .. insertRows[1]
+ rows[newEndLine] = insertRows[#insertRows] .. right
+ end
+ -- 修改中间的每一行
+ for i = 2, #insertRows - 1 do
+ local currentLine = startLine + i - 1
+ local insertText = insertRows[i]
+ rows[currentLine] = insertText
+ end
+end
+
+return function (uri, changes)
+ local text
+ for _, change in ipairs(changes) do
+ if change.range then
+ local rows = files.getCachedRows(uri)
+ if not rows then
+ text = text or files.getOriginText(uri)
+ rows = splitRows(text)
+ end
+ mergeRows(rows, change)
+ files.setCachedRows(uri, rows)
+ else
+ files.setCachedRows(uri, nil)
+ text = change.text
+ end
+ end
+ local rows = files.getCachedRows(uri)
+ if rows then
+ text = table.concat(rows)
+ end
+ return text
+end