Skip to content

Commit 44ee797

Browse files
committed
perf: add ml_get_buf, ml_get_buf_len and skipwhite
1 parent f4e8e1a commit 44ee797

File tree

5 files changed

+79
-27
lines changed

5 files changed

+79
-27
lines changed

lua/hlchunk/mods/chunk/init.lua

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -201,7 +201,6 @@ function ChunkMod:createAutocmd()
201201
end
202202
debounce_render_cb(event)
203203
end
204-
205204
api.nvim_create_autocmd({ "CursorMovedI", "CursorMoved" }, {
206205
group = self.meta.augroup_name,
207206
callback = debounce_render_cb_with_pre_hook,

lua/hlchunk/mods/indent/init.lua

Lines changed: 0 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -51,15 +51,6 @@ function IndentMod:renderLine(bufnr, lnum, blankLen)
5151
local style = self.meta.hl_name_list[(i - 1 + shadow_char_num) % #self.meta.hl_name_list + 1]
5252
row_opts.virt_text = { { char, style } }
5353
row_opts.virt_text_win_col = offset + (i - 1) * self.meta.shiftwidth
54-
55-
-- when use treesitter, without this judge, when paste code will over render
56-
-- if row_opts.virt_text_win_col < 0 or row_opts.virt_text_win_col >= fn.indent(index) then
57-
-- vim.notify(tostring(index))
58-
-- -- if the len of the line is 0, and have leftcol, we should draw it indent by context
59-
-- if api.nvim_buf_get_lines(bufnr, index - 1, index, false)[1] ~= "" then
60-
-- return
61-
-- end
62-
-- end
6354
api.nvim_buf_set_extmark(bufnr, self.meta.ns_id, lnum, 0, row_opts)
6455
end
6556
end

lua/hlchunk/utils/cFunc.lua

Lines changed: 44 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -2,31 +2,69 @@ local ffi = require("ffi")
22

33
ffi.cdef([[
44
typedef struct {} Error;
5+
typedef int colnr_T;
56
typedef struct file_buffer buf_T;
67
typedef int32_t linenr_T;
78
buf_T *find_buffer_by_handle(int buffer, Error *err);
8-
int get_indent_buf(buf_T *buf, linenr_T lnum);
9-
int get_sw_value(buf_T *buf);
9+
int get_indent_buf(buf_T *buf, linenr_T lnum); // fn.indent
10+
int get_sw_value(buf_T *buf); // fn.shiftwidth
11+
char *ml_get_buf(buf_T *buf, linenr_T lnum); // fn.getbufline
12+
colnr_T ml_get_buf_len(buf_T *buf, linenr_T lnum); // #fn.getbufline
13+
14+
// string utils
15+
char *skipwhite(const char *p);
1016
]])
1117
local C = ffi.C
1218

1319
local M = {}
1420

1521
---@param bufnr number
16-
---@param row number 0-index
22+
---@param lnum number 0-index
1723
---@return number
18-
function M.get_indent(bufnr, row)
24+
function M.get_indent(bufnr, lnum)
1925
local line_cnt = vim.api.nvim_buf_line_count(bufnr)
20-
if row >= line_cnt then
26+
if lnum >= line_cnt then
2127
return -1
2228
end
2329
local handler = C.find_buffer_by_handle(bufnr, ffi.new("Error"))
24-
return C.get_indent_buf(handler, row + 1)
30+
return C.get_indent_buf(handler, lnum + 1)
2531
end
2632

2733
function M.get_sw(bufnr)
2834
local handler = C.find_buffer_by_handle(bufnr, ffi.new("Error"))
2935
return C.get_sw_value(handler)
3036
end
3137

38+
---@param bufnr number
39+
---@param lnum number 0-index
40+
---@return string
41+
function M.get_line(bufnr, lnum)
42+
local line_cnt = vim.api.nvim_buf_line_count(bufnr)
43+
if lnum >= line_cnt then
44+
return ""
45+
end
46+
local handler = C.find_buffer_by_handle(bufnr, ffi.new("Error"))
47+
return C.ml_get_buf(handler, lnum + 1)
48+
end
49+
50+
---@param bufnr number
51+
---@param lnum number 0-index
52+
---@return number
53+
function M.get_line_len(bufnr, lnum)
54+
local line_cnt = vim.api.nvim_buf_line_count(bufnr)
55+
if lnum >= line_cnt then
56+
return 0
57+
end
58+
local handler = C.find_buffer_by_handle(bufnr, ffi.new("Error"))
59+
return C.ml_get_buf_len(handler, lnum + 1)
60+
end
61+
62+
---return the first non-white character in the string, or '' if the string is empty or contains only white characters
63+
---@param s string
64+
---@return string
65+
function M.skipwhite(s)
66+
local c = ffi.string(C.skipwhite(s), 1)
67+
return c == "\0" and "" or c
68+
end
69+
3270
return M

lua/hlchunk/utils/indentHelper.lua

Lines changed: 18 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -3,12 +3,17 @@ local cFunc = require("hlchunk.utils.cFunc")
33

44
-- get the virtual indent of the given line
55
---@param bufnr number
6-
---@param line number
6+
---@param lnum number 0-indexed
77
---@return number
8-
local function get_virt_indent(bufnr, line)
9-
return vim.api.nvim_buf_call(bufnr, function()
10-
return cFunc.get_indent(bufnr, fn.nextnonblank(line + 1) - 1)
11-
end)
8+
local function get_virt_indent(bufnr, lnum)
9+
local line_cnt = vim.api.nvim_buf_line_count(bufnr)
10+
for i = lnum + 1, line_cnt do
11+
local line = cFunc.get_line(bufnr, i)
12+
if cFunc.skipwhite(line) ~= "" then
13+
return cFunc.get_indent(bufnr, i)
14+
end
15+
end
16+
return -1
1217
end
1318

1419
local indentHelper = {}
@@ -40,11 +45,12 @@ indentHelper.ROWS_INDENT_RETCODE = {
4045
---@return table<number, number>
4146
local function get_rows_indent_by_context(range)
4247
local rows_indent = {}
48+
local bufnr = range.bufnr
4349

4450
for i = range.finish, range.start, -1 do
45-
rows_indent[i] = cFunc.get_indent(range.bufnr, i)
46-
if rows_indent[i] == 0 and #fn.getline(i + 1) == 0 then
47-
rows_indent[i] = get_virt_indent(range.bufnr, i)
51+
rows_indent[i] = cFunc.get_indent(bufnr, i)
52+
if rows_indent[i] == 0 and cFunc.get_line_len(bufnr, i) == 0 then
53+
rows_indent[i] = get_virt_indent(bufnr, i)
4854
end
4955
end
5056

@@ -61,13 +67,14 @@ local function get_rows_indent_by_treesitter(range)
6167
return indentHelper.ROWS_INDENT_RETCODE.NO_TS, {}
6268
end
6369

70+
local bufnr = range.bufnr
6471
for i = range.start, range.finish, -1 do
65-
rows_indent[i] = vim.api.nvim_buf_call(range.bufnr, function()
72+
rows_indent[i] = vim.api.nvim_buf_call(bufnr, function()
6673
local indent = ts_indent.get_indent(i + 1)
6774
if indent == -1 then
6875
indent = fn.indent(i + 1)
69-
if indent == 0 and #fn.getline(i + 1) == 0 then
70-
indent = get_virt_indent(range.bufnr, i)
76+
if indent == 0 and cFunc.get_line_len(bufnr, i) == 0 then
77+
indent = get_virt_indent(bufnr, i)
7178
end
7279
end
7380
---@diagnostic disable-next-line: redundant-return-value

test/features/cFunc_spec.lua

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
local assert = require("luassert")
2+
local cFunc = require("hlchunk.utils.cFunc")
3+
4+
describe("cFunc", function()
5+
it("skipwhite", function()
6+
local str
7+
8+
str = " abc"
9+
assert.equals(cFunc.skipwhite(str), "a")
10+
str = " "
11+
assert.equals(cFunc.skipwhite(str), "")
12+
str = ""
13+
assert.equals(cFunc.skipwhite(str), "")
14+
str = "abc"
15+
assert.equals(cFunc.skipwhite(str), "a")
16+
end)
17+
end)

0 commit comments

Comments
 (0)