local Job = require ('plenary.job') local List = require('plenary.collections.py_list') local spinner = require('spinner.core') local M = { current_jobs = {} } --create a new job and register --@return ~/.local/share/nvim/site/pack/packer/start/plenary.nvim/lua/plenary/job.lua function M.jobstart(opts) opts = opts or {} -- required options vim.tbl_extend('force', opts, { enable_recording = true, -- enable job:result() }) -- default options opts.populate_quickfix = opts.populate_quickfix or true opts.enable_spinner = opts.enable_spinner or true local title if opts.format_title then title = opts.format_title(opts.command, opts.args) opts.format_title = nil else title = opts.command end opts.on_exit = vim.schedule_wrap(function(j, code) if opts.enable_spinner then spinner.on_progress('end', j.pid, j.pid) spinner.on_exit(nil, nil, j.pid) table.remove(M.current_jobs, j.pid) end local lines if code == 0 then lines = j:result() else lines = j:stderr_result() end -- strip ansi terminal color codes for i = 1, #lines do lines[i] = (lines[i]):gsub(string.char(27) .. '[[0-9;]*m', '') end -- only show quickfix if there is output if opts.populate_quickfix and #lines > 0 then vim.fn.setqflist({}, 'r', { title = title, lines = lines, efm = '%m', }) vim.cmd([[doautocmd QuickFixCmdPost]]) end end) local j = Job:new(opts) j:start() M.current_jobs[j.pid] = j if opts.enable_spinner then spinner.on_attach(j.pid, title, vim.fn.bufnr()) spinner.on_progress('begin', j.pid, j.pid) end return j end function M.make(extra_args) local makeprg = vim.fn.expandcmd(vim.opt.makeprg:get()) -- split makeprg into command + args local args = vim.split(makeprg, ' ') local command = args[1] table.remove(args, 1) local extra_args = extra_args or {} table.foreach(extra_args, function(_, v) table.insert(args, v) end) return M.jobstart { command = command, args = args, } end function M.sh(command_string) return M.jobstart { command = vim.env.SHELL, args = {'-c', command_string}, -- strip 'sh -c' from the title (used by progress reporting etc.) format_title = function(_, args) return List(args):slice(2,#args):join(' ') end } end function M.gen_entry_from_job() return function(entry) return { value = entry, ordinal = entry.pid, display = entry.command .. ' ' .. table.concat(entry.args, ' '), } end end function M.cancel_job() if #M.current_jobs < 1 then return end require('telescope.pickers').new({}, { prompt_title = 'Jobs', finder = require('telescope.finders').new_table { results = M.current_jobs, entry_maker = M.gen_entry_from_job(), }, sorter = require('telescope.sorters').fuzzy_with_index_bias(), attach_mappings = function(bufnr) require('telescope.actions.set').select:replace(function(bufnr, type) local entry = require('telescope.actions.state').get_selected_entry() require('telescope.actions').close(bufnr) entry.value:shutdown(1, 'SIGKILL') end) return true end }):find() end return M