Skip to content

Commit

Permalink
nvim(completion): Add new sources for gitcommit
Browse files Browse the repository at this point in the history
This includes handle completion (requires `sort`, `git` and `jq`) and
keyword completion.
  • Loading branch information
Nelyah committed Jul 30, 2022
1 parent 574df66 commit f4cdb6a
Show file tree
Hide file tree
Showing 3 changed files with 256 additions and 55 deletions.
76 changes: 76 additions & 0 deletions .config/nvim/lua/completion-sources/gitcommit-keywords.lua
Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@
local M = {}

local registered = false

M.setup = function(handle_file)
if registered then
return
end
registered = true

local has_cmp, cmp = pcall(require, 'cmp')
if not has_cmp then
return
end

local source = {}

source.new = function()
return setmetatable({}, {__index = source})
end

source.get_keyword_pattern = function()
-- Add dot to existing keyword characters (\k).
return [[\%(\k\|\.\)\+]]
end

source.complete = function(_, request, callback)
local input = string.sub(request.context.cursor_before_line, request.offset - 1)
-- local prefix = string.sub(request.context.cursor_before_line, 1, request.offset - 1)

local gitcommit_keywords = {
'Addresses:',
'Co-Authored-By:',
'Resolves:',
'Approved-by:',
'Reviewed-by:',
'Signed-off-by:',
}

if request.context.cursor.col <= 2 then
local items = {}
for _, keyword in ipairs(gitcommit_keywords) do
table.insert(items, {
filterText = keyword,
label = keyword,
textEdit = {
newText = keyword,
range = {
start = {
line = request.context.cursor.row - 1,
character = request.context.cursor.col - 1 - #input,
},
['end'] = {
line = request.context.cursor.row - 1,
character = request.context.cursor.col - 1,
},
},
},
}
)
end
callback {
items = items,
isIncomplete = true,
}
else
callback({isIncomplete = true})
end
end

cmp.register_source('gitcommit_keywords', source.new())

end

return M

116 changes: 116 additions & 0 deletions .config/nvim/lua/completion-sources/handles.lua
Original file line number Diff line number Diff line change
@@ -0,0 +1,116 @@
local handles = {}

local Job = require('plenary.job')

local registered = false

local register_source = function(json_string)
if registered then
return
end
registered = true

local has_cmp, cmp = pcall(require, 'cmp')
if not has_cmp then
return
end
local success, handles_with_names_and_emails = pcall(function()
return vim.fn.json_decode(json_string)
end)

if not success then
return
end

local source = {}

source.new = function()
return setmetatable({}, {__index = source})
end

source.get_trigger_characters = function()
return { '@' }
end

source.get_keyword_pattern = function()
-- Add dot to existing keyword characters (\k).
return [[\%(\k\|\.\)\+]]
end

source.complete = function(_, request, callback)
local input = string.sub(request.context.cursor_before_line, request.offset - 1)
local prefix = string.sub(request.context.cursor_before_line, 1, request.offset - 1)

if vim.startswith(input, '@') and (prefix == '@' or vim.endswith(prefix, ' @')) then
local items = {}
for handle, name_and_email in pairs(handles_with_names_and_emails) do
table.insert(items, {
filterText = handle .. ' ' .. name_and_email,
label = name_and_email,
textEdit = {
newText = name_and_email,
range = {
start = {
line = request.context.cursor.row - 1,
character = request.context.cursor.col - 1 - #input,
},
['end'] = {
line = request.context.cursor.row - 1,
character = request.context.cursor.col - 1,
},
},
},
}
)
end
callback {
items = items,
isIncomplete = true,
}
else
callback({isIncomplete = true})
end
end

cmp.register_source('handles', source.new())
end

handles.setup = function()
local json_lines = {}

Job:new({
command = 'jq',
args = {'-s', '--compact-output', [[
map (select(keys[] != "jenkins" and keys[] != "terrier-lottery-results-domain"))
| reduce .[] as $item ({}; . + $item)
]]},
writer = Job:new({
command = 'sed',
args = {'-r', '-e', '/<>/d',
'-e', 's/"//g',
'-e', 's/^(.*<([^@]+)@.*)$/{"\\2": "\\1"}/'},
writer = Job:new({
command = 'sort',
args = {'-u'},
writer = Job:new({
command = 'git',
args = { 'log', '--oneline', '--format=format:%aN <%ae>'},
}),
}),
}),
on_stdout = function(_, line)
table.insert(json_lines, line)
end,
on_exit = function(_, _)
local timer = vim.loop.new_timer()
timer:start(0, 0, vim.schedule_wrap(function()
register_source(json_lines)
end))
end
}):start()

end


return handles

119 changes: 64 additions & 55 deletions .config/nvim/lua/plugins/nvim-cmp.lua
Original file line number Diff line number Diff line change
@@ -1,67 +1,76 @@
local M = {}

function M.setup ()
-- vim.g.cpp_simple_highlight = 1
local setup_cmp = function()
local cmp = require('cmp')

vim.cmd[[hi default LspCxxHlGroupNamespace ctermfg=Yellow guifg=#E5C07B cterm=none gui=none]]
vim.cmd[[hi default LspCxxHlGroupMemberVariable ctermfg=White guifg=#F16E77]]
cmp.setup({
snippet = {
expand = function(args)
-- vim.fn["vsnip#anonymous"](args.body) -- For `vsnip` users.
require('luasnip').lsp_expand(args.body) -- For `luasnip` users.
-- vim.fn["UltiSnips#Anon"](args.body) -- For `ultisnips` users.
-- require'snippy'.expand_snippet(args.body) -- For `snippy` users.
end,
},
mapping = {
['<c-n>'] = cmp.mapping.select_next_item({ behavior = cmp.SelectBehavior.Insert }),
['<c-p>'] = cmp.mapping.select_prev_item({ behavior = cmp.SelectBehavior.Insert }),
['<Tab>'] = cmp.mapping.select_next_item({ behavior = cmp.SelectBehavior.Insert }),
['<S-Tab>'] = cmp.mapping.select_prev_item({ behavior = cmp.SelectBehavior.Insert }),
['<C-d>'] = cmp.mapping(cmp.mapping.scroll_docs(-4), { 'i', 'c' }),
['<C-f>'] = cmp.mapping(cmp.mapping.scroll_docs(4), { 'i', 'c' }),
['<C-Space>'] = cmp.mapping(cmp.mapping.complete(), { 'i', 'c' }),
['<C-y>'] = cmp.config.disable, -- If you want to remove the default `<C-y>` mapping, You can specify `cmp.config.disable` value.
['<C-e>'] = cmp.mapping({
i = cmp.mapping.abort(),
c = cmp.mapping.close(),
}),
['<CR>'] = nil,
['<C-c>'] = cmp.mapping.confirm({ select = true }),
},
sources = cmp.config.sources({
{ name = 'neorg' },
{ name = 'nvim_lsp' },
-- { name = 'vsnip' }, -- For vsnip users.
-- { name = 'ultisnips' }, -- For ultisnips users.
-- { name = 'snippy' }, -- For snippy users.
{ name = 'path' },
{ name = 'buffer' },
})
})

local cmp = require'cmp'
-- Use buffer source for `/`.
cmp.setup.cmdline('/', {
sources = {
{ name = 'buffer' },
}
})

cmp.setup({
snippet = {
expand = function(args)
-- vim.fn["vsnip#anonymous"](args.body) -- For `vsnip` users.
require('luasnip').lsp_expand(args.body) -- For `luasnip` users.
-- vim.fn["UltiSnips#Anon"](args.body) -- For `ultisnips` users.
-- require'snippy'.expand_snippet(args.body) -- For `snippy` users.
end,
},
mapping = {
['<c-n>'] = cmp.mapping.select_next_item({ behavior = cmp.SelectBehavior.Insert }),
['<c-p>'] = cmp.mapping.select_prev_item({ behavior = cmp.SelectBehavior.Insert }),
['<Tab>'] = cmp.mapping.select_next_item({ behavior = cmp.SelectBehavior.Insert }),
['<S-Tab>'] = cmp.mapping.select_prev_item({ behavior = cmp.SelectBehavior.Insert }),
['<C-d>'] = cmp.mapping(cmp.mapping.scroll_docs(-4), { 'i', 'c' }),
['<C-f>'] = cmp.mapping(cmp.mapping.scroll_docs(4), { 'i', 'c' }),
['<C-Space>'] = cmp.mapping(cmp.mapping.complete(), { 'i', 'c' }),
['<C-y>'] = cmp.config.disable, -- If you want to remove the default `<C-y>` mapping, You can specify `cmp.config.disable` value.
['<C-e>'] = cmp.mapping({
i = cmp.mapping.abort(),
c = cmp.mapping.close(),
}),
['<CR>'] = nil,
['<C-c>'] = cmp.mapping.confirm({ select = true }),
},
sources = cmp.config.sources({
{ name = 'neorg' },
{ name = 'nvim_lsp' },
-- { name = 'vsnip' }, -- For vsnip users.
{ name = 'luasnip' }, -- For luasnip users.
-- { name = 'ultisnips' }, -- For ultisnips users.
-- { name = 'snippy' }, -- For snippy users.
{ name = 'path' },
}, {
{ name = 'buffer' },
})
})
-- Use cmdline & path source for ':'.
cmp.setup.cmdline(':', {
sources = cmp.config.sources({
{ name = 'path' },
{ name = 'cmdline' },
})
})

-- Use buffer source for `/`.
cmp.setup.cmdline('/', {
sources = {
{ name = 'buffer' },
}
})
cmp.setup.filetype('gitcommit', {
sources = cmp.config.sources({
{ name = 'handles' },
{ name = 'gitcommit_keywords' },
}),
})
end

-- Use cmdline & path source for ':'.
cmp.setup.cmdline(':', {
sources = cmp.config.sources({
{ name = 'path' }
}, {
{ name = 'cmdline' }
})
})
require('completion-sources.handles').setup()
require('completion-sources.gitcommit-keywords').setup()
setup_cmp()

end

vim.cmd[[hi default LspCxxHlGroupNamespace ctermfg=Yellow guifg=#E5C07B cterm=none gui=none]]
vim.cmd[[hi default LspCxxHlGroupMemberVariable ctermfg=White guifg=#F16E77]]


return M

0 comments on commit f4cdb6a

Please sign in to comment.