summaryrefslogtreecommitdiffstats
path: root/lua/core/misc.lua
blob: 5200c8b10790031f32647bb83fb93ac804d4dcc1 (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
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
local M = {}

--- vim.notify title
M.appid = "Nvim Config"

--- safe version of require
---@param fn string name of file to include
---@return any
function M.include(fn)
  local ok, r = pcall(require, fn)
  if not ok then
    vim.notify('Could not find "'..fn..'": '..r, vim.log.levels.WARN, { title = M.appid })
    return ok
  end
  return r
end

--- loop through files in directory
---@param path string absolute path of directory to be looped through
---@param body function function to use on every recursion of the loop
---@param ext string? desired file extension of files to be returned from directory
function M.loopf(path, body, ext)
  ext = ext and [[v:val =~ '\.]]..ext..[[$']] or nil
  for _, file in ipairs(vim.fn.readdir(path, ext)) do
    body(file)
  end
end

--- set colorscheme
---@param name string name of colorscheme
function M.colorscheme(name)
  vim.cmd.colorscheme(name)
  for _, v in pairs(vim.fn.getcompletion('', 'color')) do
    if v == name..'.ext' then
      vim.cmd.colorscheme(name..'.ext')
    end
  end
end

--- extend vim.kemap.set
---@param mode string|table mode for the keymap
---@param bind string|table keymap
---@param cmd function|string command to run
---@param opts table? keymap options
function M.map(mode, bind, cmd, opts)
  opts = opts or {}
  opts['noremap'] = true
  opts['silent'] = true

  if type(bind) == 'table' then
    for i in pairs(bind) do
      vim.keymap.set(mode, bind[i], cmd, opts)
    end
  elseif type(bind) == 'string' then
    vim.keymap.set(mode, bind, cmd, opts)
  end
end

--- a small map wrapper to easily create local buffer mappings
---@param mode string|table mode for the keymap
---@param bind string|table keymap
---@param cmd function|string command to run
---@param opts table? keymap options
function M.map_local(mode, bind, cmd, opts)
  opts = opts or {}
  opts["buffer"] = 0
  M.map(mode, bind, cmd, opts)
end

--- extend vim.api.nvim_create_autocmd
---@param event string|table event or events
---@param opts table options
function M.auto(event, opts)
  vim.api.nvim_create_autocmd(event, opts)
end

--- extend auto group
---@param name string name of the autogroup
---@param opts table? table of options
function M.augroup(name, opts)
  opts = opts or {}
  vim.api.nvim_create_augroup(name, opts)
end

--- extend vim.api.nvim_set_hl
---@param group string|table highlight group
---@param opts table highlight options
---@param namespace? number highlight space
function M.highlight(group, opts, namespace)
  namespace = namespace or 0

  if type(group) == 'table' then
    for i in pairs(group) do
      vim.api.nvim_set_hl(namespace, group[i], opts)
    end
  elseif type(group) == 'string' then
    vim.api.nvim_set_hl(namespace, group, opts)
  end
end

--- copy highlight group
---@param hlgroup string highlight group to copy
---@param namespace? number highlight space
---@return table
function M.cpyhl(hlgroup, namespace)
  namespace = namespace or 0

  local ok, hl = pcall(vim.api.nvim_get_hl, namespace, {
    name = hlgroup,
    create = false
  })
  if not ok then
    return {}
  end

  for _, key in pairs({"foreground", "background", "special"}) do
    if hl[key] then
      hl[key] = string.format("#%06x", hl[key])
    end
  end
  return hl
end

--- highlight something with some highlight group for a certain amount of time
---@param opts table? options
--- example:
--- ```lua
--- {
---   -- highlight group to use
---   hl = "IncSearch",
---
---   -- # of ms to stay highlighted for
---   timeout = 250,
---
---   -- line to highlight
---   line = vim.api.nvim_win_get_cursor(0)[1],
---
---   -- range to highlight if this is used line will be ignored
---   range = {
---     { 0, 0 },
---     { 0, 0 }
---   }
--- }
--- ```
--- opts is optional and if empty will simply highlight the current line for
--- 250ms using IncSearch as the highlight group
function M.timeout_highlight(opts)
  opts = opts or {}
  opts.hl = opts.hl or "IncSearch"
  opts.timeout = opts.timeout or 250
  if type(opts.range) ~= "table" or type(opts.range[1]) ~= "table" or
    type(opts.range[2]) ~= "table" then
    local curline = opts.line or vim.api.nvim_win_get_cursor(0)[1]
    opts.range = {
      { curline - 1, 0 },
      { curline, 0 }
    }
  end

  local namespaceid = vim.api.nvim_create_namespace("timeout_highlight")

  -- timer code was happily stolen from neovim/runtime/lua/vim/highlight.lua :)
  local timer, timer_cancel

  if timer then
    timer:close()
    assert(timer_cancel)
    timer_cancel()
  end

  -- set the highlight
  vim.highlight.range(0, namespaceid, opts.hl, opts.range[1], opts.range[2], {})

  timer_cancel = function()
    timer = nil
    timer_cancel = nil
    pcall(vim.api.nvim_buf_clear_namespace, 0, namespaceid, 0, -1)
    pcall(vim.api.nvim_win_remove_ns, 0, namespaceid)
  end

  timer = vim.defer_fn(timer_cancel, opts.timeout)
end

return M