summaryrefslogtreecommitdiff
path: root/mut/neovim/pack/plugins/start/quicker.nvim/lua/quicker/init.lua
blob: 42ae32b67fee51f9508011d16e772b9d249b613a (plain)
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
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
local M = {}

---@param opts? quicker.SetupOptions
local function setup(opts)
  local config = require("quicker.config")
  config.setup(opts)

  local aug = vim.api.nvim_create_augroup("quicker", { clear = true })
  vim.api.nvim_create_autocmd("FileType", {
    pattern = "qf",
    group = aug,
    desc = "quicker.nvim set up quickfix mappings",
    callback = function(args)
      require("quicker.highlight").set_highlight_groups()
      require("quicker.opts").set_opts(args.buf)
      require("quicker.keys").set_keymaps(args.buf)
      vim.api.nvim_buf_create_user_command(args.buf, "Refresh", function()
        require("quicker.context").refresh()
      end, {
        desc = "Update the quickfix list with the current buffer text for each item",
      })

      if config.constrain_cursor then
        require("quicker.cursor").constrain_cursor(args.buf)
      end

      config.on_qf(args.buf)
    end,
  })
  vim.api.nvim_create_autocmd("ColorScheme", {
    pattern = "*",
    group = aug,
    desc = "quicker.nvim set up quickfix highlight groups",
    callback = function()
      require("quicker.highlight").set_highlight_groups()
    end,
  })
  if config.edit.enabled then
    vim.api.nvim_create_autocmd("BufReadPost", {
      pattern = "quickfix",
      group = aug,
      desc = "quicker.nvim set up quickfix editing",
      callback = function(args)
        require("quicker.editor").setup_editor(args.buf)
      end,
    })
  end
  if config.follow.enabled then
    vim.api.nvim_create_autocmd({ "CursorMoved", "BufEnter" }, {
      desc = "quicker.nvim scroll to nearest location in quickfix",
      pattern = "*",
      group = aug,
      callback = function()
        require("quicker.follow").seek_to_position()
      end,
    })
  end

  vim.o.quickfixtextfunc = "v:lua.require'quicker.display'.quickfixtextfunc"

  -- If the quickfix/loclist is already open, refresh it so the quickfixtextfunc will take effect.
  -- This is required for lazy-loading to work properly.
  local list = vim.fn.getqflist({ all = 0 })
  if not vim.tbl_isempty(list.items) then
    vim.fn.setqflist({}, "r", list)
  end
  for _, winid in ipairs(vim.api.nvim_list_wins()) do
    if vim.api.nvim_win_is_valid(winid) then
      local llist = vim.fn.getloclist(winid, { all = 0 })
      if not vim.tbl_isempty(list.items) then
        vim.fn.setloclist(winid, {}, "r", llist)
      end
    end
  end
end

M.setup = setup

---Expand the context around the quickfix results.
---@param opts? quicker.ExpandOpts
---@note
--- If there are multiple quickfix items for the same line of a file, only the first
--- one will remain after calling expand().
M.expand = function(opts)
  return require("quicker.context").expand(opts)
end

---Collapse the context around quickfix results, leaving only the `valid` items.
M.collapse = function()
  return require("quicker.context").collapse()
end

---Toggle the expanded context around the quickfix results.
---@param opts? quicker.ExpandOpts
M.toggle_expand = function(opts)
  return require("quicker.context").toggle(opts)
end

---Update the quickfix list with the current buffer text for each item.
---@param loclist_win? integer
---@param opts? quicker.RefreshOpts
M.refresh = function(loclist_win, opts)
  return require("quicker.context").refresh(loclist_win, opts)
end

---@param loclist_win? integer Check if loclist is open for the given window. If nil, check quickfix.
M.is_open = function(loclist_win)
  return require("quicker.util").is_open(loclist_win)
end

---@class quicker.OpenCmdMods: vim.api.keyset.parse_cmd.mods

---@class (exact) quicker.OpenOpts
---@field loclist? boolean Toggle the loclist instead of the quickfix list
---@field focus? boolean Focus the quickfix window after toggling (default false)
---@field height? integer Height of the quickfix window when opened. Defaults to number of items in the list.
---@field min_height? integer Minimum height of the quickfix window. Default 4.
---@field max_height? integer Maximum height of the quickfix window. Default 10.
---@field open_cmd_mods? quicker.OpenCmdMods A table of modifiers for the quickfix or loclist open commands.

---Toggle the quickfix or loclist window.
---@param opts? quicker.OpenOpts
M.toggle = function(opts)
  ---@type {loclist: boolean, focus: boolean, height?: integer, min_height: integer, max_height: integer, open_cmd_mods?: quicker.OpenCmdMods}
  opts = vim.tbl_deep_extend("keep", opts or {}, {
    loclist = false,
    focus = false,
    min_height = 4,
    max_height = 10,
    open_cmd_mods = {},
  })
  local loclist_win = opts.loclist and 0 or nil
  if M.is_open(loclist_win) then
    M.close({ loclist = opts.loclist })
  else
    M.open(opts)
  end
end

---Open the quickfix or loclist window.
---@param opts? quicker.OpenOpts
M.open = function(opts)
  local util = require("quicker.util")
  ---@type {loclist: boolean, focus: boolean, height?: integer, min_height: integer, max_height: integer, open_cmd_mods?: quicker.OpenCmdMods}
  opts = vim.tbl_deep_extend("keep", opts or {}, {
    loclist = false,
    focus = false,
    min_height = 4,
    max_height = 10,
    open_cmd_mods = {},
  })
  local height
  if opts.loclist then
    local ok, err = pcall(vim.cmd.lopen, { mods = opts.open_cmd_mods })
    if not ok then
      vim.notify(err, vim.log.levels.ERROR)
      return
    end
    height = #vim.fn.getloclist(0)
  else
    vim.cmd.copen({ mods = opts.open_cmd_mods })
    height = #vim.fn.getqflist()
  end

  -- only set the height if the quickfix is not a full-height vsplit
  if not util.is_full_height_vsplit(0) then
    height = math.min(opts.max_height, math.max(opts.min_height, height))
    vim.api.nvim_win_set_height(0, height)
  end

  if not opts.focus then
    vim.cmd.wincmd({ args = { "p" } })
  end
end

---@class (exact) quicker.CloseOpts
---@field loclist? boolean Close the loclist instead of the quickfix list

---Close the quickfix or loclist window.
---@param opts? quicker.CloseOpts
M.close = function(opts)
  if opts and opts.loclist then
    vim.cmd.lclose()
  else
    vim.cmd.cclose()
  end
end

return M