local Job = require ('plenary.job') local List = require('plenary.collections.py_list') local spinner = require('spinner.core') local M = { current_jobs = {} } function M.jobstart(opts, _wrap_command_for_presentation) local opts = opts or {} if opts.format_title then title = opts.format_title(opts.command, opts.args) opts.format_title = nil else title = opts.command end opts.enable_recording = true -- enable job:result() opts.on_exit = vim.schedule_wrap(function(j, retval) spinner.on_progress('end', j.pid, j.pid) spinner.on_exit(nil, nil, j.pid) local lines = j:result() if not lines or #lines < 1 then 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 vim.fn.setqflist({}, ' ', { title = title, lines = lines, }) if #lines > 0 then vim.api.nvim_command('doautocmd QuickFixCmdPost') end for k, v in ipairs(M.current_jobs) do if v.pid == j.pid then table.remove(M.current_jobs, k) break end end end) local j = Job:new(opts) j:start() table.insert(M.current_jobs, j) spinner.on_attach(j.pid, title, vim.fn.bufnr()) spinner.on_progress('begin', j.pid, j.pid) return j end function M.make(extra_args) local makeprg = vim.fn.expandcmd(vim.opt.makeprg:get()) 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}, 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