Skip to content
Rónán Carrigan edited this page Feb 20, 2022 · 20 revisions

Examples of use cases for nvim-notify

Output of Command

Uses libuv (vim.loop) to run asynchronously

local function notify_output(command)
  local stdin = vim.loop.new_pipe()
  local stdout = vim.loop.new_pipe()
  local stderr = vim.loop.new_pipe()
  local output = ""
  local error_output = ""
  local notify = function (msg, level)
    vim.notify(msg, level, { title = table.concat(command, " ") })
  end
  vim.loop.spawn(command[1], {
    stdio = { stdin, stdout, stderr },
    detached = true,
    args = #command > 1 and vim.list_slice(command, 2, #command) or nil,
  }, function(code, _)
    stdin:close()
    stdout:close()
    stderr:close()
    if #output > 0 then
      notify(output)
    end
    if #error_output > 0 then
      notify(error_output, "error")
    end
    if #output == 0 and #error_output == 0 then
      notify("No output of command, exit code: "..code, "warn")
    end
  end)
  stdout:read_start(function(err, data)
    if err then
      error_output = error_output .. (err or data)
      return
    end
    if data then
      output = output .. data
    end
  end)
  stderr:read_start(function(err, data)
    if err or data then
      error_output = error_output .. (err or data)
    end
  end)
end

notify_output({"echo", "hello world"})

LSP Status Updates

local client_notifs = {}

local spinner_frames = { "", "", "", "", "", "", "", "" }

local function update_spinner(client_id, token)
  local notif_data = client_notifs[client_id][token]

  if notif_data and notif_data.spinner then
    local new_spinner = (notif_data.spinner + 1) % #spinner_frames

    local new_notif = vim.notify(nil, nil, {
      hidden = true,
      icon = spinner_frames[new_spinner],
      replace = notif_data.notification,
    })

    client_notifs[client_id][token] = {

      notification = new_notif,

      spinner = new_spinner,
    }

    vim.defer_fn(function()
      update_spinner(client_id, token)
    end, 100)
  end
end

local function format_title(title, client)
  return client.name .. (#title > 0 and ": " .. title or "")
end

local function format_message(message, percentage)
  return (percentage and percentage .. "%\t" or "") .. (message or "")
end

vim.lsp.handlers["$/progress"] = function(_, result, ctx)
  local client_id = ctx.client_id

  local val = result.value

  if not val.kind then
    return
  end
  if not client_notifs[client_id] then
    client_notifs[client_id] = {}
  end

  local notif_data = client_notifs[client_id][result.token]

  if val.kind == "begin" then
    local message = format_message(val.message, val.percentage)

    local notification = vim.notify(message, "info", {

      title = format_title(val.title, vim.lsp.get_client_by_id(client_id)),

      icon = spinner_frames[1],

      timeout = false,

      hidden = false,
    })

    client_notifs[client_id][result.token] = {

      notification = notification,

      spinner = 1,
    }

    update_spinner(client_id, result.token)
  elseif val.kind == "report" and notif_data then
    local new_notif = vim.notify(format_message(val.message, val.percentage), "info", {
      replace = notif_data.notification,
      hidden = false,
    })

    client_notifs[client_id][result.token] = {

      notification = new_notif,

      spinner = notif_data.spinner,
    }
  elseif val.kind == "end" and notif_data then
    local new_notif =
      vim.notify(val.message and format_message(val.message) or "Complete", "info", {
        icon = "",
        replace = notif_data.notification,
        timeout = 3000,
      })

    client_notifs[client_id][result.token] = {

      notification = new_notif,
    }
  end
end
Clone this wiki locally