aboutsummaryrefslogtreecommitdiff
path: root/lua/tasks/utils.lua
blob: fab3be7a1f884b138318c023321e4070b4a4cbbd (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
local scandir = require('plenary.scandir')
local Path = require('plenary.path')
local utils = {}

local args_regex = vim.regex([[\s\%(\%([^'"]*\(['"]\)[^'"]*\1\)*[^'"]*$\)\@=]])

--- A small wrapper around `vim.notify` that adds plugin title.
---@param msg string
---@param log_level number
function utils.notify(msg, log_level) vim.notify(msg, log_level, { title = 'Tasks' }) end

--- Splits command line arguments respecting quotes.
---@param args string?
---@return table
function utils.split_args(args)
  if not args then
    return {}
  end

  -- Split on spaces unless in quotes.
  args = vim.trim(args)
  local splitted_args = {}
  local match_beg
  while true do
    match_beg = args_regex:match_str(args)
    if match_beg then
      table.insert(splitted_args, args:sub(1, match_beg))
      args = args:sub(match_beg + 2)
    else
      -- Insert last arg left.
      table.insert(splitted_args, args)
      break
    end
  end

  -- Remove quotes
  for i, arg in ipairs(splitted_args) do
    splitted_args[i] = arg:gsub('"', ''):gsub("'", '')
  end
  return splitted_args
end

--- Joins command line arguments respecting spaces by putting double quotes around them.
---@param args table?
---@return string
function utils.join_args(args)
  if not args then
    return ''
  end

  -- Add quotes if argument contain spaces
  for index, arg in ipairs(args) do
    if arg:find(' ') then
      args[index] = '"' .. arg .. '"'
    end
  end

  return table.concat(args, ' ')
end

---@return table
function utils.get_module_names()
  local module_dir = Path:new(debug.getinfo(1).source:sub(2)):parent() / 'module'

  local modules = {}
  for _, entry in ipairs(scandir.scan_dir(module_dir.filename, { depth = 1 })) do
    -- Strip full path and extension
    local extension_len = 4
    local parent_offset = 2
    table.insert(modules, entry:sub(#Path:new(entry):parent().filename + parent_offset, #entry - extension_len))
  end

  return modules
end

--- Find a module by name
---@param module_type string name of a module or `auto` string to pick a first module that match a condition.
---@return table?, string?: module and its name.
function utils.get_module(module_type)
  if module_type == 'auto' then
    for _, name in ipairs(utils.get_module_names()) do
      local module = require('tasks.module.' .. name)
      if module.condition() then
        return module, name
      end
    end

    utils.notify('Unable to autodetect module for this working directory', vim.log.levels.ERROR)
    return nil, nil
  end

  local module = require('tasks.module.' .. module_type)
  if not module then
    utils.notify('Unable to find a module named ' .. module_type, vim.log.levels.ERROR)
    return nil, nil
  end

  return module, module_type
end

return utils