local M = {} local function get_visual_selection(intact) intact = intact or false local top = vim.fn.getpos("'<") top = { ln = top[2], col = top[3] } local bot = vim.fn.getpos("'>") bot = { ln = bot[2], col = bot[3] } local lines = vim.api.nvim_buf_get_lines(0, (top.ln - 1), bot.ln, false) if not intact then if vim.opt.selection:get() == 'inclusive' then lines[#lines] = lines[#lines]:sub(1, bot.col) else lines[#lines] = lines[#lines]:sub(1, (bot.col - 1)) end lines[1] = lines[1]:sub(top.col) end return top, bot, lines end local function sortline(line, a, o, separator) separator = separator or ' ' local result, _ = string.gsub(line, string.sub(line, a, o), table.concat(vim.fn.sort(vim.fn.split(string.sub(line, a, o), separator)), separator), 1) return result end function M.sort_lines(_, preview_ns, preview_bufnr) local bufnr = vim.api.nvim_get_current_buf() local top, bot, lines = get_visual_selection(true) vim.pretty_print(top, bot, lines) for i = 1, #lines do local a = 0; if i == 1 then a = top.col end local o = -1; if i == #lines then o = bot.col end lines[i] = sortline(lines[i], a, o, ' ') end if not preview_ns then vim.api.nvim_buf_set_lines(bufnr, top.ln - 1, bot.ln, false, lines) return 0 end -- inccommand preview if preview_ns ~= nil then for i, line in ipairs(lines) do vim.api.nvim_buf_set_extmark(bufnr, preview_ns, top.ln + i - 2, 0, { hl_mode = 'combine', virt_text_pos = 'overlay', virt_text = { { line, 'Substitute' } }, }) if preview_bufnr ~= nil then local prefix = string.format('|%d| ', top.ln + i - 1) vim.api.nvim_buf_set_lines(preview_bufnr, i - 1, -1, false, { prefix .. line }) vim.api.nvim_buf_add_highlight( preview_bufnr, preview_ns, 'Substitute', i, #prefix, #prefix + #line ) end end return (#lines > 1 and 2 or 1) end end function M.setup(opts) vim.api.nvim_create_user_command( 'SortLine', M.sort_lines, { desc = 'sort line', range = '%', preview = M.sort_lines } ) end return M