summaryrefslogtreecommitdiff
path: root/lua/99/ops/request_status.lua
blob: e084db9a318336776157daf95efec00dd1993f6e (plain)
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
local braille_chars =
  { "⠋", "⠙", "⠹", "⠸", "⠼", "⠴", "⠦", "⠧", "⠇", "⠏" }

--- @class _99.StatusLine
--- @field index number
--- @field title_line string
local StatusLine = {}
StatusLine.__index = StatusLine

--- @param title_line string
--- @return _99.StatusLine
function StatusLine.new(title_line)
  local self = setmetatable({}, StatusLine)
  self.index = 1
  self.title_line = title_line
  return self
end

function StatusLine:update()
  self.index = self.index + 1
end

--- @return string
function StatusLine:to_string()
  return braille_chars[self.index % #braille_chars + 1]
    .. " "
    .. self.title_line
end

--- @class _99.RequestStatus
--- @field update_time number the milliseconds per update to the virtual text
--- @field status_line _99.StatusLine
--- @field lines string[]
--- @field max_lines number
--- @field running boolean
--- @field mark? _99.Mark
--- @field callback? fun(status: string[]): nil
local RequestStatus = {}
RequestStatus.__index = RequestStatus

--- @param update_time number
--- @param max_lines number
--- @param title_line string
--- @param mark_or_fn _99.Mark | fun(status: string[]): nil
--- @return _99.RequestStatus
function RequestStatus.new(update_time, max_lines, title_line, mark_or_fn)
  local self = setmetatable({}, RequestStatus)
  self.update_time = update_time
  self.max_lines = max_lines
  self.status_line = StatusLine.new(title_line)
  self.lines = {}
  self.running = false
  if type(mark_or_fn) == "function" then
    self.callback = mark_or_fn
  else
    self.mark = mark_or_fn
  end
  return self
end

--- @return string[]
function RequestStatus:get()
  local result = { self.status_line:to_string() }
  for _, line in ipairs(self.lines) do
    table.insert(result, line)
  end
  return result
end

--- @param line string
function RequestStatus:push(line)
  table.insert(self.lines, line)
  if #self.lines > self.max_lines - 1 then
    table.remove(self.lines, 1)
  end
end

function RequestStatus:start()
  local function update_spinner()
    if not self.running then
      return
    end

    self.status_line:update()
    if self.mark then
      self.mark:set_virtual_text(self:get())
    end
    if self.callback then
      self.callback(self:get())
    end
    vim.defer_fn(update_spinner, self.update_time)
  end

  self.running = true
  vim.defer_fn(update_spinner, self.update_time)
end

function RequestStatus:stop()
  self.running = false
end

return RequestStatus