summary refs log tree commit diff
path: root/.vim/lua/internal/sortline.lua
blob: 69f7f64da1e562619de9a291988107ca8f90ba5b (plain) (blame)
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
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