|
@@ -0,0 +1,174 @@
|
|
|
|
+local Job = require('plenary.job')
|
|
|
|
+
|
|
|
|
+function make(opts)
|
|
|
|
+ local makeprg = vim.bo.makeprg
|
|
|
|
+ local errorformat = vim.bo.errorformat
|
|
|
|
+ if makeprg == '' then
|
|
|
|
+ return
|
|
|
|
+ end
|
|
|
|
+
|
|
|
|
+ -- escape special characters in args
|
|
|
|
+ args = string.gsub(opts.args or '', '%%', '%%%%')
|
|
|
|
+ -- substitute $*
|
|
|
|
+ makeprg, _ = string.gsub(makeprg, '%$%*', args);
|
|
|
|
+ -- expand
|
|
|
|
+ makeprg = vim.fn.expandcmd(makeprg)
|
|
|
|
+
|
|
|
|
+ local function on_exit(job, retval)
|
|
|
|
+ local result = {}
|
|
|
|
+ vim.list_extend(result, job:result())
|
|
|
|
+ vim.list_extend(result, job:stderr_result())
|
|
|
|
+ vim.notify(string.format(
|
|
|
|
+ ':!%s\n%s\n\nshell returned %d',
|
|
|
|
+ makeprg,
|
|
|
|
+ table.concat(result, '\n'),
|
|
|
|
+ retval
|
|
|
|
+ ))
|
|
|
|
+ vim.fn.setqflist({}, ' ', {
|
|
|
|
+ title = makeprg,
|
|
|
|
+ lines = result,
|
|
|
|
+ efm = errorformat,
|
|
|
|
+ })
|
|
|
|
+ vim.api.nvim_exec_autocmds('QuickFixCmdPost', {})
|
|
|
|
+
|
|
|
|
+ if #result > 0 then
|
|
|
|
+ vim.cmd('copen')
|
|
|
|
+ end
|
|
|
|
+ end
|
|
|
|
+
|
|
|
|
+ Job:new({
|
|
|
|
+ command = 'sh',
|
|
|
|
+ args = { '-c', makeprg },
|
|
|
|
+ on_exit = vim.schedule_wrap(on_exit),
|
|
|
|
+ }):start()
|
|
|
|
+end
|
|
|
|
+
|
|
|
|
+vim.api.nvim_create_user_command('Make', make, {
|
|
|
|
+ nargs = '*',
|
|
|
|
+ complete = 'file',
|
|
|
|
+})
|
|
|
|
+
|
|
|
|
+function ensure_log_buffer(bufname)
|
|
|
|
+ for _, buf in ipairs(vim.api.nvim_list_bufs()) do
|
|
|
|
+ if vim.api.nvim_buf_is_loaded(buf) and vim.api.nvim_buf_get_name(buf) == bufname then
|
|
|
|
+ vim.bo[buf].modifiable = true
|
|
|
|
+ vim.api.nvim_buf_set_lines(buf, 0, -1, true, {})
|
|
|
|
+ vim.bo[buf].modifiable = false
|
|
|
|
+ return buf
|
|
|
|
+ end
|
|
|
|
+ end
|
|
|
|
+
|
|
|
|
+ local bufnr = vim.api.nvim_create_buf(true, true)
|
|
|
|
+ vim.api.nvim_buf_set_name(bufnr, bufname)
|
|
|
|
+ vim.bo[bufnr].filetype = 'git'
|
|
|
|
+ vim.bo[bufnr].buftype = 'nofile'
|
|
|
|
+ vim.bo[bufnr].bufhidden = 'hide'
|
|
|
|
+ vim.bo[bufnr].swapfile = false
|
|
|
|
+ vim.bo[bufnr].modifiable = false
|
|
|
|
+ vim.api.nvim_win_set_buf(0, bufnr)
|
|
|
|
+
|
|
|
|
+ -- avoid ui thrashing
|
|
|
|
+ vim.opt_local.number = false
|
|
|
|
+ vim.opt_local.relativenumber = false
|
|
|
|
+
|
|
|
|
+ -- add fugitive mappings
|
|
|
|
+ vim.fn['fugitive#MapJumps']()
|
|
|
|
+
|
|
|
|
+ return bufnr
|
|
|
|
+end
|
|
|
|
+
|
|
|
|
+function git_lg(opts)
|
|
|
|
+ local argstr = ''
|
|
|
|
+ if #opts.args > 0 then
|
|
|
|
+ argstr = ' ' .. opts.args
|
|
|
|
+ end
|
|
|
|
+
|
|
|
|
+ -- we want a pseudo fqdn so that it's not considered relative to the current
|
|
|
|
+ -- directory
|
|
|
|
+ local bufname = 'cmd://git//lg' .. argstr
|
|
|
|
+ local bufnr = ensure_log_buffer(bufname)
|
|
|
|
+
|
|
|
|
+ local job
|
|
|
|
+ -- there are custom syntax highlights for --graph and --pretty
|
|
|
|
+ local args = {
|
|
|
|
+ 'log',
|
|
|
|
+ '--abbrev-commit',
|
|
|
|
+ '--graph',
|
|
|
|
+ '--pretty=%h %d %s (%cr) <%an>',
|
|
|
|
+ }
|
|
|
|
+ vim.list_extend(args, opts.fargs)
|
|
|
|
+
|
|
|
|
+ local stdout_lines = {}
|
|
|
|
+ local stderr_lines = {}
|
|
|
|
+ local first = true
|
|
|
|
+
|
|
|
|
+ local append_to_buf = vim.schedule_wrap(function(lines)
|
|
|
|
+ -- stop appending and terminate the job if the buffer is closed
|
|
|
|
+ if not vim.api.nvim_buf_is_loaded(bufnr) then
|
|
|
|
+ job:shutdown(0, 0)
|
|
|
|
+ return
|
|
|
|
+ end
|
|
|
|
+
|
|
|
|
+ -- the first append should replace the first line, succeeding appends
|
|
|
|
+ -- should append to the end
|
|
|
|
+ local start = -1
|
|
|
|
+ if first then
|
|
|
|
+ start = 0
|
|
|
|
+ first = false
|
|
|
|
+ end
|
|
|
|
+
|
|
|
|
+ vim.bo[bufnr].modifiable = true
|
|
|
|
+ vim.api.nvim_buf_set_lines(bufnr, start, -1, true, lines)
|
|
|
|
+ vim.bo[bufnr].modifiable = false
|
|
|
|
+ end)
|
|
|
|
+
|
|
|
|
+ local function on_stdout(error, data)
|
|
|
|
+ if data == nil then
|
|
|
|
+ return
|
|
|
|
+ end
|
|
|
|
+
|
|
|
|
+ -- we get called for every line of output so buffer the lines to avoid too
|
|
|
|
+ -- much overhead
|
|
|
|
+ table.insert(stdout_lines, data)
|
|
|
|
+ if #stdout_lines > 100 then
|
|
|
|
+ local done = stdout_lines
|
|
|
|
+ stdout_lines = {}
|
|
|
|
+ append_to_buf(done)
|
|
|
|
+ end
|
|
|
|
+ end
|
|
|
|
+
|
|
|
|
+ local function on_exit(job, retval)
|
|
|
|
+ append_to_buf(stdout_lines)
|
|
|
|
+ if retval ~= 0 then
|
|
|
|
+ vim.schedule(function()
|
|
|
|
+ vim.notify(string.format(
|
|
|
|
+ ':%s\n%s\n\nreturned %d',
|
|
|
|
+ 'GLg' .. argstr,
|
|
|
|
+ table.concat(stderr_lines, '\n'),
|
|
|
|
+ retval
|
|
|
|
+ ))
|
|
|
|
+ end)
|
|
|
|
+ end
|
|
|
|
+ end
|
|
|
|
+
|
|
|
|
+ job = Job:new({
|
|
|
|
+ command = 'git',
|
|
|
|
+ args = args,
|
|
|
|
+ enable_recording = false,
|
|
|
|
+ on_stdout = on_stdout,
|
|
|
|
+ on_stderr = function(error, data)
|
|
|
|
+ if data == nil then
|
|
|
|
+ return
|
|
|
|
+ end
|
|
|
|
+ table.insert(stderr_lines, data)
|
|
|
|
+ end,
|
|
|
|
+ on_exit = on_exit,
|
|
|
|
+ })
|
|
|
|
+
|
|
|
|
+ job:start()
|
|
|
|
+end
|
|
|
|
+
|
|
|
|
+vim.api.nvim_create_user_command('GLg', git_lg, {
|
|
|
|
+ nargs = '*',
|
|
|
|
+ complete = vim.fn['fugitive#LogComplete'],
|
|
|
|
+})
|