Skip to content

Commit 84492e8

Browse files
authored
fix: index_to_pos on Windows machines. (#401)
The APIs used in converting 1D and 2D indices are asymmetric in that one of them assumes EOL is 1 byte, and the other uses the EOL provided by the current buffer's `fileformat`.
1 parent ad60cea commit 84492e8

File tree

2 files changed

+42
-4
lines changed

2 files changed

+42
-4
lines changed

lua/nvim-surround/patterns.lua

Lines changed: 23 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,18 @@ local buffer = require("nvim-surround.buffer")
22

33
local M = {}
44

5+
-- Gets the EOL character for the current buffer, based on the file format.
6+
---@returns string @The EOL character for the buffer.
7+
---@nodiscard
8+
local end_of_line = function()
9+
if vim.bo.fileformat == "dos" then
10+
return "\r\n"
11+
elseif vim.bo.fileformat == "mac" then
12+
return "\r"
13+
end
14+
return "\n"
15+
end
16+
517
-- Converts a 1D index into the buffer to the corresponding 2D buffer position.
618
---@param index integer The index of the character in the buffer (viewed as a single `\n`-joined string).
719
---@return position @The position of the character in the buffer.
@@ -18,7 +30,14 @@ end
1830
---@return integer @The index of the character into the buffer.
1931
---@nodiscard
2032
M.pos_to_index = function(pos)
21-
return vim.api.nvim_buf_get_offset(0, pos[1] - 1) + pos[2]
33+
local index = vim.api.nvim_buf_get_offset(0, pos[1] - 1) + pos[2]
34+
-- The API call assumes that the EOL character is 1 byte, but on Windows machines CRLF is 2 bytes. Here we add back
35+
-- the expected number of `\r` bytes when computing the index.
36+
if vim.bo.fileformat == "dos" then
37+
index = index + pos[1] - 1
38+
end
39+
40+
return index
2241
end
2342

2443
-- Expands a selection to properly contain multi-byte characters.
@@ -38,7 +57,7 @@ end
3857
M.get_selection = function(find)
3958
-- Get the current cursor position, buffer contents
4059
local curpos = buffer.get_curpos()
41-
local buffer_text = table.concat(buffer.get_lines(1, -1), "\n")
60+
local buffer_text = table.concat(buffer.get_lines(1, -1), end_of_line())
4261
-- Find which character the cursor is in the file
4362
local cursor_index = M.pos_to_index(curpos)
4463
-- Find the character positions of the pattern in the file (after/on the cursor)
@@ -48,7 +67,7 @@ M.get_selection = function(find)
4867
-- Linewise search for the pattern before/on the cursor
4968
for lnum = curpos[1], 1, -1 do
5069
-- Get the file contents from the first line to current line
51-
local cur_text = table.concat(buffer.get_lines(1, lnum - 1), "\n")
70+
local cur_text = table.concat(buffer.get_lines(1, lnum - 1), end_of_line())
5271
-- Find the character positions of the pattern in the file (before the cursor)
5372
b_first, b_last = buffer_text:find(find, #cur_text + 1)
5473
if b_first and b_first <= cursor_index then
@@ -112,7 +131,7 @@ end
112131
---@nodiscard
113132
M.get_selections = function(selection, pattern)
114133
local offset = M.pos_to_index(selection.first_pos)
115-
local str = table.concat(buffer.get_text(selection), "\n")
134+
local str = table.concat(buffer.get_text(selection), end_of_line())
116135
-- Get the surrounding pair, and the start/end indices
117136
local ok, _, left_delimiter, first_index, right_delimiter, last_index = str:find(pattern)
118137
-- Validate that a match was found

tests/basics_spec.lua

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -904,4 +904,23 @@ describe("nvim-surround", function()
904904
vim.cmd("normal 3csbr")
905905
check_lines({ "some [[more placeholder]] text" })
906906
end)
907+
908+
it("can perform operations on Windows", function()
909+
vim.bo.fileformat = "dos"
910+
set_lines({
911+
"(removing these parenthesis works)",
912+
"{",
913+
"(removing these parenthesis creates behaves weirdly and changes characters)",
914+
"}",
915+
})
916+
set_curpos({ 1, 1 })
917+
vim.cmd("normal dsbjjds)")
918+
919+
check_lines({
920+
"removing these parenthesis works",
921+
"{",
922+
"removing these parenthesis creates behaves weirdly and changes characters",
923+
"}",
924+
})
925+
end)
907926
end)

0 commit comments

Comments
 (0)