summary refs log tree commit diff
path: root/.vim/lua/job.lua
blob: 657a72d8d179435b8da62a174712550b638f4509 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
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