summary refs log tree commit diff
path: root/.vim/lua/job.lua
diff options
context:
space:
mode:
authorRobert Günzler <r@gnzler.io>2021-08-02 13:55:25 +0200
committerRobert Günzler <r@gnzler.io>2021-08-02 13:55:25 +0200
commitb22dc38564dcc8903f501ed92843aa9db9fd44a7 (patch)
tree60820b77a81a6c96ca7a86e82fa4727c30c5247f /.vim/lua/job.lua
parenta640482e61fa6afcbdb6e974ef9b0bb956a9649c (diff)
vim: use plenary for jobs
Diffstat (limited to '')
-rw-r--r--.vim/lua/job.lua129
1 files changed, 98 insertions, 31 deletions
diff --git a/.vim/lua/job.lua b/.vim/lua/job.lua
index a3591e5..7261d24 100644
--- a/.vim/lua/job.lua
+++ b/.vim/lua/job.lua
@@ -1,45 +1,112 @@
+local Job = require ('plenary.job')
+local List = require('plenary.collections.py_list')
+local spinner = require('spinner.core')
 
-local M = {}
+local M = {
+  current_jobs = {}
+}
 
-function M.jobstart(cmd)
-  local output = {}
+function M.jobstart(opts, _wrap_command_for_presentation)
+  local opts = opts or {}
 
-  local function on_event(job_id, data, event)
-    if event == 'stdout' or event == 'stderr' then
-      if data then
-        vim.list_extend(output, data)
-      end
+  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
-    if event == 'exit' then
-      vim.fn.setqflist({}, ' ', {
-        title = cmd,
-        lines = output,
-      })
+    vim.fn.setqflist({}, ' ', {
+      title = title,
+      lines = lines,
+    })
+    if #lines > 0 then
       vim.api.nvim_command('doautocmd QuickFixCmdPost')
     end
-  end
 
-  local job_id = require('spinner.job').jobstart(cmd, {
-    on_stdout = on_event,
-    on_stderr = on_event,
-    on_exit = on_event,
-    stdout_buffered = true,
-    stderr_buffered = true,
-  })
-  return job_id
+    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(args)
-  local args = args or {}
-  local makeprg = vim.opt.makeprg:get()
-  local cmd = vim.split(vim.fn.expandcmd(makeprg), ' ')
-  table.foreach(args, function(_, v) table.insert(cmd, v) end)
-  return M.jobstart(cmd)
+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.sh(cmd)
-  local cmd = {vim.env.SHELL, '-c', cmd}
-  return M.jobstart(cmd)
+
+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