summaryrefslogtreecommitdiff
path: root/mut/neovim/pack/plugins/start/blink.cmp/lua/blink/cmp/sources/path/init.lua
blob: bb5f50880fa786a3a99c9df0b335236ec52dd133 (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
-- credit to https://github.com/hrsh7th/cmp-path for the original implementation
-- and https://codeberg.org/FelipeLema/cmp-async-path for the async implementation

--- @class blink.cmp.PathOpts
--- @field trailing_slash boolean
--- @field label_trailing_slash boolean
--- @field get_cwd fun(context: blink.cmp.Context): string
--- @field show_hidden_files_by_default boolean

--- @class blink.cmp.Source
--- @field opts blink.cmp.PathOpts
local path = {}

function path.new(opts)
  local self = setmetatable({}, { __index = path })

  --- @type blink.cmp.PathOpts
  opts = vim.tbl_deep_extend('keep', opts, {
    trailing_slash = true,
    label_trailing_slash = true,
    get_cwd = function(context) return vim.fn.expand(('#%d:p:h'):format(context.bufnr)) end,
    show_hidden_files_by_default = false,
  })
  require('blink.cmp.config.utils').validate('sources.providers.path', {
    trailing_slash = { opts.trailing_slash, 'boolean' },
    label_trailing_slash = { opts.label_trailing_slash, 'boolean' },
    get_cwd = { opts.get_cwd, 'function' },
    show_hidden_files_by_default = { opts.show_hidden_files_by_default, 'boolean' },
  }, opts)

  self.opts = opts
  return self
end

function path:get_trigger_characters() return { '/', '.' } end

function path:get_completions(context, callback)
  -- we use libuv, but the rest of the library expects to be synchronous
  callback = vim.schedule_wrap(callback)

  local lib = require('blink.cmp.sources.path.lib')

  local dirname = lib.dirname(self.opts.get_cwd, context)
  if not dirname then return callback({ is_incomplete_forward = false, is_incomplete_backward = false, items = {} }) end

  local include_hidden = self.opts.show_hidden_files_by_default
    or (string.sub(context.line, context.bounds.start_col, context.bounds.start_col) == '.' and context.bounds.length == 0)
    or (
      string.sub(context.line, context.bounds.start_col - 1, context.bounds.start_col - 1) == '.'
      and context.bounds.length > 0
    )
  lib
    .candidates(context, dirname, include_hidden, self.opts)
    :map(
      function(candidates)
        callback({ is_incomplete_forward = false, is_incomplete_backward = false, items = candidates })
      end
    )
    :catch(function() callback() end)
end

function path:resolve(item, callback)
  require('blink.cmp.sources.path.fs')
    .read_file(item.data.full_path, 1024)
    :map(function(content)
      local is_binary = content:find('\0')

      -- binary file
      if is_binary then
        item.documentation = {
          kind = 'plaintext',
          value = 'Binary file',
        }
      -- highlight with markdown
      else
        local ext = vim.fn.fnamemodify(item.data.path, ':e')
        item.documentation = {
          kind = 'markdown',
          value = '```' .. ext .. '\n' .. content .. '```',
        }
      end

      return item
    end)
    :map(function(resolved_item) callback(resolved_item) end)
    :catch(function() callback(item) end)
end

return path