Skip to content

Commit 6561b45

Browse files
authored
Merge pull request #4 from hat0uma/display_mode_border
feat(view): Added a `display_mode = "border"` option for table-like display
2 parents fe20c8f + c3302fc commit 6561b45

File tree

4 files changed

+135
-39
lines changed

4 files changed

+135
-39
lines changed

β€ŽREADME.md

Lines changed: 25 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,8 +10,23 @@ With this plugin, you can easily view and edit CSV files within Neovim.
1010
- Displays the CSV file in a tabular format using virtual text.
1111
- Dynamically updates the CSV view as you edit, ensuring a seamless editing experience.
1212
- Asynchronous parsing enables comfortable handling of large CSV files.
13-
14-
**Note:** The plugin is currently a work in progress (WIP) and only implements basic functionality.
13+
- Supports two display modes:
14+
- `highlight`: Highlights the delimiter.
15+
- `border`: Displays the delimiter with `β”‚`.
16+
17+
<table>
18+
<tr>
19+
<th>display_mode = "highlight"</th>
20+
<th>display_mode = "border"</th>
21+
</tr>
22+
<td>
23+
<img src="https://github.com/user-attachments/assets/cb26e430-c3cb-407f-bb80-42c11ba7fa19" />
24+
</td>
25+
<td>
26+
<img src="https://github.com/user-attachments/assets/17e5fc01-9a58-4801-b2a6-3d23ca48e26f" />
27+
</td>
28+
</tr>
29+
</table>
1530

1631
## Requirements
1732

@@ -62,8 +77,16 @@ The configuration options are as follows:
6277
view = {
6378
--- minimum width of a column
6479
min_column_width = 5,
80+
6581
--- spacing between columns
6682
spacing = 2,
83+
84+
--- The display method of the delimiter
85+
--- "highlight" highlights the delimiter
86+
--- "border" displays the delimiter with `β”‚`
87+
--- see `Features` section of the README.
88+
---@type "highlight" | "border"
89+
display_mode = "highlight",
6790
},
6891
}
6992
```

β€Žlua/csvview/config.lua

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,8 +11,15 @@ M.defaults = {
1111
view = {
1212
--- minimum width of a column
1313
min_column_width = 5,
14+
1415
--- spacing between columns
1516
spacing = 2,
17+
18+
--- The display method of the delimiter
19+
--- "highlight" highlights the delimiter
20+
--- "border" displays the delimiter with `β”‚`
21+
---@type "highlight" | "border"
22+
display_mode = "highlight",
1623
},
1724
}
1825

β€Žlua/csvview/view.lua

Lines changed: 18 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -43,8 +43,14 @@ function CsvView:_align_left(lnum, offset, padding, field, border)
4343
})
4444
end
4545

46-
if border then
47-
-- self:_render_border(lnum, offset + field.len, padding)
46+
if not border then
47+
return
48+
end
49+
50+
-- render border or highlight delimiter
51+
if self.opts.view.display_mode == "border" then
52+
self:_render_border(lnum, offset + field.len)
53+
else
4854
self:_highlight_delimiter(lnum, offset + field.len)
4955
end
5056
end
@@ -64,8 +70,14 @@ function CsvView:_align_right(lnum, offset, padding, field, border)
6470
})
6571
end
6672

67-
if border then
68-
-- self:_render_border(lnum, offset + field.len, 0)
73+
if not border then
74+
return
75+
end
76+
77+
-- render border or highlight delimiter
78+
if self.opts.view.display_mode == "border" then
79+
self:_render_border(lnum, offset + field.len)
80+
else
6981
self:_highlight_delimiter(lnum, offset + field.len)
7082
end
7183
end
@@ -101,10 +113,9 @@ end
101113
--- render table border
102114
---@param lnum integer 1-indexed lnum
103115
---@param offset integer 0-indexed byte offset
104-
---@param padding integer
105-
function CsvView:_render_border(lnum, offset, padding)
116+
function CsvView:_render_border(lnum, offset)
106117
self.extmarks[#self.extmarks + 1] = vim.api.nvim_buf_set_extmark(self.bufnr, EXTMARK_NS, lnum - 1, offset, {
107-
virt_text = { { string.rep(" ", padding) .. "β”‚", "CsvViewDelimiter" } },
118+
virt_text = { { "β”‚", "CsvViewDelimiter" } },
108119
virt_text_pos = "overlay",
109120
})
110121
end

β€Žtests/view_spec.lua

Lines changed: 85 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -24,50 +24,105 @@ local function get_lines_with_extmarks(bufnr, ns)
2424
lines[lnum] = prefix .. virt_text[1] .. suffix
2525
col_offset[lnum] = col_offset[lnum] + #virt_text[1]
2626
end
27+
elseif details.virt_text_pos == "overlay" then
28+
local virt_text = details.virt_text[1][1]
29+
col_offset[lnum] = col_offset[lnum] or 0
30+
local prefix = lines[lnum]:sub(1, col + col_offset[lnum])
31+
local suffix = lines[lnum]:sub(col + col_offset[lnum] + 1 + vim.fn.strdisplaywidth(virt_text))
32+
lines[lnum] = prefix .. virt_text .. suffix
33+
col_offset[lnum] = col_offset[lnum] + #virt_text - vim.fn.strdisplaywidth(virt_text)
2734
end
2835
end
36+
2937
return lines
3038
end
3139

3240
describe("view", function()
3341
csvview.setup()
3442
local ns = vim.api.nvim_get_namespaces()["csv_extmark"]
3543
describe("CsvView:render", function()
36-
it("should align correctly even if it contains multibyte characters", function()
37-
local bufnr = vim.api.nvim_create_buf(false, true)
38-
local opts = config.get({
39-
view = { min_column_width = 5, spacing = 1 },
40-
})
41-
local lines = {
42-
"column1(number),column2(emoji),column3(string)",
43-
"111,πŸ˜€,abcde",
44-
"222222222222,πŸ˜’πŸ˜’πŸ˜’πŸ˜’,fgh",
45-
"333333333333333333,😎b😎b😎b😎b😎b😎b,ijk",
46-
}
47-
local expected = {
48-
"column1(number) ,column2(emoji) ,column3(string) ",
49-
" 111,πŸ˜€ ,abcde ",
50-
" 222222222222,πŸ˜’πŸ˜’πŸ˜’πŸ˜’ ,fgh ",
51-
" 333333333333333333,😎b😎b😎b😎b😎b😎b ,ijk ",
52-
}
44+
describe("should align correctly even if it contains multibyte characters", function()
45+
it("display_mode = 'highlight'", function()
46+
local bufnr = vim.api.nvim_create_buf(false, true)
47+
local opts = config.get({
48+
view = {
49+
min_column_width = 5,
50+
spacing = 1,
51+
display_mode = "highlight",
52+
},
53+
})
54+
local lines = {
55+
"column1(number),column2(emoji),column3(string)",
56+
"111,πŸ˜€,abcde",
57+
"222222222222,πŸ˜’πŸ˜’πŸ˜’πŸ˜’,fgh",
58+
"333333333333333333,😎b😎b😎b😎b😎b😎b,ijk",
59+
}
60+
local expected = {
61+
"column1(number) ,column2(emoji) ,column3(string) ",
62+
" 111,πŸ˜€ ,abcde ",
63+
" 222222222222,πŸ˜’πŸ˜’πŸ˜’πŸ˜’ ,fgh ",
64+
" 333333333333333333,😎b😎b😎b😎b😎b😎b ,ijk ",
65+
}
5366

54-
vim.api.nvim_buf_set_lines(bufnr, 0, -1, false, lines)
55-
local co = coroutine.running()
56-
metrics.compute_csv_metrics(bufnr, opts, function(fields, column_max_widths)
57-
local v = view.CsvView:new(bufnr, fields, column_max_widths, opts)
67+
vim.api.nvim_buf_set_lines(bufnr, 0, -1, false, lines)
68+
local co = coroutine.running()
69+
metrics.compute_csv_metrics(bufnr, opts, function(fields, column_max_widths)
70+
local v = view.CsvView:new(bufnr, fields, column_max_widths, opts)
5871

59-
-- test
60-
v:render(1, vim.api.nvim_buf_line_count(bufnr))
61-
local actual = get_lines_with_extmarks(bufnr, ns)
62-
for i, line in ipairs(actual) do
63-
assert.are.same(expected[i], line)
64-
end
65-
vim.schedule(function()
66-
coroutine.resume(co)
72+
-- test
73+
v:render(1, vim.api.nvim_buf_line_count(bufnr))
74+
local actual = get_lines_with_extmarks(bufnr, ns)
75+
for i, line in ipairs(actual) do
76+
assert.are.same(expected[i], line)
77+
end
78+
vim.schedule(function()
79+
coroutine.resume(co)
80+
end)
6781
end)
82+
83+
coroutine.yield()
6884
end)
6985

70-
coroutine.yield()
86+
it("display_mode = 'border'", function()
87+
local bufnr = vim.api.nvim_create_buf(false, true)
88+
local opts = config.get({
89+
view = {
90+
min_column_width = 5,
91+
spacing = 1,
92+
display_mode = "border",
93+
},
94+
})
95+
local lines = {
96+
"column1(number),column2(emoji),column3(string)",
97+
"111,πŸ˜€,abcde",
98+
"222222222222,πŸ˜’πŸ˜’πŸ˜’πŸ˜’,fgh",
99+
"333333333333333333,😎b😎b😎b😎b😎b😎b,ijk",
100+
}
101+
local expected = {
102+
"column1(number) β”‚column2(emoji) β”‚column3(string) ",
103+
" 111β”‚πŸ˜€ β”‚abcde ",
104+
" 222222222222β”‚πŸ˜’πŸ˜’πŸ˜’πŸ˜’ β”‚fgh ",
105+
" 333333333333333333β”‚πŸ˜Žb😎b😎b😎b😎b😎b β”‚ijk ",
106+
}
107+
108+
vim.api.nvim_buf_set_lines(bufnr, 0, -1, false, lines)
109+
local co = coroutine.running()
110+
metrics.compute_csv_metrics(bufnr, opts, function(fields, column_max_widths)
111+
local v = view.CsvView:new(bufnr, fields, column_max_widths, opts)
112+
113+
-- test
114+
v:render(1, vim.api.nvim_buf_line_count(bufnr))
115+
local actual = get_lines_with_extmarks(bufnr, ns)
116+
for i, line in ipairs(actual) do
117+
assert.are.same(expected[i], line)
118+
end
119+
vim.schedule(function()
120+
coroutine.resume(co)
121+
end)
122+
end)
123+
124+
coroutine.yield()
125+
end)
71126
end)
72127
end)
73128
end)

0 commit comments

Comments
Β (0)