1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
|
-- based on the ideas from:
-- https://github.com/RRethy/nvim-align
local M = {}
function M.align_lines(pat, line1, line2, preview_ns, preview_bufnr)
local re = vim.regex(pat)
local bufnr = vim.api.nvim_get_current_buf()
local lines = vim.api.nvim_buf_get_lines(bufnr, line1 - 1, line2, false)
local newlines = {}
local preview_buf_line = 0
-- find the longest match
local max = -1
for _, line in pairs(lines) do
local s = re:match_str(line)
if s and max < s then
max = s
end
end
-- exit if nothing was found
if max == -1 then
return error('nothing found')
end
for i, line in pairs(lines) do
local s = re:match_str(line)
if s then
local rep = max - s
local changeset = {
string.sub(line, 1, s),
string.rep(' ', rep),
string.sub(line, s + 1),
}
local newline = table.concat(changeset)
-- append to changse if not inside the preview callback
if not preview_ns then
newlines[#newlines + 1] = newline
end
if preview_ns ~= nil then
-- set extmarks inside the live buffer
vim.api.nvim_buf_set_extmark(bufnr, preview_ns, line1 + i - 2, 0, {
hl_mode = 'combine',
virt_text_pos = 'overlay',
virt_text = {
{ changeset[1] },
{ changeset[2], 'Substitute' },
{ changeset[3] },
},
})
-- modify preview buffer
if preview_bufnr ~= nil then
local prefix = string.format('|%d| ', line1 + i - 1)
vim.api.nvim_buf_set_lines(
preview_bufnr,
preview_buf_line,
preview_buf_line,
false,
{ prefix .. newline }
)
vim.api.nvim_buf_add_highlight(
preview_bufnr,
preview_ns,
'Substitute',
preview_buf_line,
#prefix + s,
#prefix + s + #changeset[2]
)
preview_buf_line = preview_buf_line + 1
end
end
end
end
-- only change buffer when not previewing
if not preview_ns then
-- exit if nothing was changed
if #newlines == 0 then
return error('nothing changed')
end
vim.api.nvim_buf_set_lines(bufnr, line1 - 1, line2, 0, newlines)
return 0
end
if preview_ns ~= nil then
-- open preview buffer only if there is more than a single line of change
return (#preview_buf_line > 1) and 2 or 1
end
end
function M.align(pat)
local top, bot = vim.fn.getpos("'<"), vim.fn.getpos("'>")
M.align_lines(pat, top[2] - 1, bot[2])
vim.fn.setpos("'<", top)
vim.fn.setpos("'>", bot)
end
local function aligncmd(opts, preview_ns, preview_bufnr)
return M.align_lines(opts.fargs[1], opts.line1, opts.line2, preview_ns, preview_bufnr)
end
local default_opts = {
bindings = true,
}
function M.setup(opts)
opts = vim.tbl_extend('keep', opts or {}, default_opts)
vim.api.nvim_create_user_command(
'SimpleAlign',
aligncmd,
{ nargs = 1, range = '%', preview = aligncmd }
)
-- if opts.bindings then
-- vim.keymap.set('v', '<enter>', ':SimpleAlign ')
-- end
end
return M
|