tjdevries / express_line.nvim

WIP: Statusline written in pure lua. Supports co-routines, functions and jobs.

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Multiple subscriptions get created

opened this issue · comments

Hi @tjdevries, I have noticed that config such as (simplified):

local _coc_diag = function(_, buf, severity)
  local ok, res = pcall(a.nvim_buf_get_var, buf.bufnr, 'coc_diagnostic_info' )

  if ok then
    local count = res[severity]
    return count > 0 and string.format(' %s%s ', severity:sub(1, 1), count) or ''
  end
end

local coc_information = sub.user_autocmd(
  'el_coc_diagnostic_changes_i',
  'CocDiagnosticChange',
  function(win, buf)
    return _coc_diag(win, buf, 'information')
  end
)
local git_branch = sub.buf_autocmd('el_git_branch', 'BufRead,CursorHold,CursorHoldI,FocusGained,WinEnter,TabEnter', function()
  local ok, branch = pcall(vim.fn.FugitiveHead)

  if ok then
    return branch .. ' '
  end
end)
local git_chunks = sub.user_autocmd('el_git_hunks', 'GitGutter', function(_, buf)
  local ok, res = pcall(a.nvim_buf_get_var, buf.bufnr, 'gitgutter')
  if not ok then return end

  local signs = {'+', '~', '-'}
  local input = res.summary
  local output = {}

  for k, v in pairs(input) do
    if v > 0 then
      table.insert(output, signs[k] .. tostring(v))
    end
  end

  if #output > 0 then
    return '(' .. table.concat(output, ' ') .. ') '
  end
end)

local statusline = function(window, buffer)
  return {
    hi({active = 'CocListBlackGreen',  inactive = ei}, coc_information),
    hi({active = 'Question',           inactive = nt}, git_chunks),
    hi({active = 'Normal',             inactive = nt}, git_branch),
  }
end

require('el').setup({generator = statusline})

will create multiple subscriptions, as per :autocmd User

ElUserSubscriptions  User
    CocDiagnosticChange
              :lua require("el.subscribe")._process_user_callback("CocDiagnosticChange")
              :lua require("el.subscribe")._process_user_callback("CocDiagnosticChange")
              :lua require("el.subscribe")._process_user_callback("CocDiagnosticChange")
              :lua require("el.subscribe")._process_user_callback("CocDiagnosticChange")
    GitGutter :lua require("el.subscribe")._process_user_callback("GitGutter")
    CocDiagnosticChange
              :lua require("el.subscribe")._process_user_callback("CocDiagnosticChange")
              :lua require("el.subscribe")._process_user_callback("CocDiagnosticChange")
              :lua require("el.subscribe")._process_user_callback("CocDiagnosticChange")
              :lua require("el.subscribe")._process_user_callback("CocDiagnosticChange")
    GitGutter :lua require("el.subscribe")._process_user_callback("GitGutter")
    CocDiagnosticChange
              :lua require("el.subscribe")._process_user_callback("CocDiagnosticChange")
              :lua require("el.subscribe")._process_user_callback("CocDiagnosticChange")
              :lua require("el.subscribe")._process_user_callback("CocDiagnosticChange")
              :lua require("el.subscribe")._process_user_callback("CocDiagnosticChange")
    GitGutter :lua require("el.subscribe")._process_user_callback("GitGutter")
    CocDiagnosticChange
              :lua require("el.subscribe")._process_user_callback("CocDiagnosticChange")
              :lua require("el.subscribe")._process_user_callback("CocDiagnosticChange")
              :lua require("el.subscribe")._process_user_callback("CocDiagnosticChange")

and it continues into hundreds, most likely increasing with time.

Buffer subscription behave better, creating only single callback per event per buffer.

I think user autocmds are broken then 😆 I will see if I can fix it sometime soonish. Thanks for reporting and detailed info!

@Katsika would you mind sharing you config with how to do this correctly? I am trying to integrate coc as well, and I have seen #34 (comment) but I am confused as to where exactly to put stuff in the generator.

My current config is pretty much default, but when I tried to put those functions in the generator, I got errors about incorrect data types:

local builtin = require('el.builtin')
local extensions = require('el.extensions')
local sections = require('el.sections')
local subscribe = require('el.subscribe')
local lsp_statusline = require('el.plugins.lsp_status')

local git_icon = subscribe.buf_autocmd("el_file_icon", "BufRead", function(_, bufnr)
  local icon = extensions.file_icon(_, bufnr)
  if icon then
    return icon .. ' '
  end

  return ''
end)

local git_branch = subscribe.buf_autocmd(
  "el_git_branch",
  "BufEnter",
  function(window, buffer)
    local branch = extensions.git_branch(window, buffer)
    if branch then
      return ' ' .. extensions.git_icon() .. ' ' .. branch
    end
  end
)

local git_changes = subscribe.buf_autocmd(
  "el_git_changes",
  "BufWritePost",
  function(window, buffer)
    return extensions.git_changes(window, buffer)
  end
)

local _coc_diag = function(_, buf, severity)
  local ok, res = pcall(vim.api.nvim_buf_get_var, buf.bufnr, 'coc_diagnostic_info' ) -- {'information': 0, 'hint': 0, 'lnums': [29, 13, 0, 0], 'warning': 15, 'error': 2}if ok then
    return res[severity]
  end
endlocal statusline = function(window, buffer)
  return {
    function(window, buffer)
      return _coc_diag(window, buffer, 'error')
    end,
  }
end

require('el').setup {
  generator = function(_, _)
    return {
      extensions.gen_mode {
        format_string = ' %s '
      },
      git_branch,
      ' ',
      sections.split,

      git_icon,
      sections.maximum_width(
        builtin.responsive_file(140, 90),
        0.30
      ),
      sections.collapse_builtin {
        ' ',
        builtin.modified_flag
      },
      sections.split,
      statusline,
      -- lsp_statusline.segment,
      -- lsp_statusline.current_function,
      -- lsp_statusline.server_progress,
      git_changes,
      '[', builtin.line_with_width(3), ':',  builtin.column_with_width(2), ']',
      sections.collapse_builtin {
        '[',
        builtin.help_list,
        builtin.readonly_list,
        ']',
      },
      builtin.filetype,
    }
  end
}

@ludwj61 Excerpt, hope it helps:

local a = vim.api
local hi = sections.highlight

local segment = {
  coc_diag = function(_, buf, severity)
    -- severity can be: error, warning, hint, information
    local ok, res = pcall(a.nvim_buf_get_var, buf.bufnr, "coc_diagnostic_info")

    if ok then
      local count = res[severity]

      if count > 0 then
        return count > 0 and string.format(" %s%s ", severity:sub(1, 1), count) or ""
      end
    end
  end
}

local statusline = function(win, buf)
  local ei = "ElMiddleInactive"

  return {
    hi(
      {active = "CocListBlackGreen", inactive = ei},
      function(win, buf)
        return segment.coc_diag(win, buf, "information")
      end
    ),
    hi(
      {active = "CocListBlackWhite", inactive = ei},
      function(win, buf)
        return segment.coc_diag(win, buf, "hint")
      end
    ),
    hi(
      {active = "CocListBlackYellow", inactive = ei},
      function(win, buf)
        return segment.coc_diag(win, buf, "warning")
      end
    ),
    hi(
      {active = "CocListBlackRed", inactive = ei},
      function(win, buf)
        return segment.coc_diag(win, buf, "error")
      end
    )
  }
end

require("el").setup({generator = statusline})

@Katsika thanks, it did.

commented

@Katsika could you check if the latest update in user auto command fixes this issue?

And this is an interesting one now. You can see in my configuration's excerpt I have one user and one buffer auto commands.

There are no duplication if I remove coc_information function, but as soon as it's added back in it causes GitGutterUser auto command to multiple.

:autocmd User GitGutter
--- Autocommands ---
ElUserSubscriptions  User
    GitGutter :lua require("el.subscribe")._process_user_callback(3, "el_gitgutter_summary")
              :lua require("el.subscribe")._process_user_callback(5, "el_gitgutter_summary")
              :lua require("el.subscribe")._process_user_callback(3, "el_gitgutter_summary")
    GitGutter :lua require("el.subscribe")._process_user_callback(3, "el_gitgutter_summary")
    GitGutter :lua require("el.subscribe")._process_user_callback(9, "el_gitgutter_summary")
    GitGutter :lua require("el.subscribe")._process_user_callback(3, "el_gitgutter_summary")
    GitGutter :lua require("el.subscribe")._process_user_callback(9, "el_gitgutter_summary")
    GitGutter :lua require("el.subscribe")._process_user_callback(3, "el_gitgutter_summary")
    GitGutter :lua require("el.subscribe")._process_user_callback(9, "el_gitgutter_summary")
    GitGutter :lua require("el.subscribe")._process_user_callback(3, "el_gitgutter_summary")
    GitGutter :lua require("el.subscribe")._process_user_callback(3, "el_gitgutter_summary")
    GitGutter :lua require("el.subscribe")._process_user_callback(9, "el_gitgutter_summary")
Press ENTER or type command to continue
commented

And this is an interesting one now. You can see in my configuration's excerpt I have one user and one buffer auto commands.

There are no duplication if I remove coc_information function, but as soon as it's added back in it causes GitGutterUser auto command to multiple.

:autocmd User GitGutter
--- Autocommands ---
ElUserSubscriptions  User
    GitGutter :lua require("el.subscribe")._process_user_callback(3, "el_gitgutter_summary")
              :lua require("el.subscribe")._process_user_callback(5, "el_gitgutter_summary")
              :lua require("el.subscribe")._process_user_callback(3, "el_gitgutter_summary")
    GitGutter :lua require("el.subscribe")._process_user_callback(3, "el_gitgutter_summary")
    GitGutter :lua require("el.subscribe")._process_user_callback(9, "el_gitgutter_summary")
    GitGutter :lua require("el.subscribe")._process_user_callback(3, "el_gitgutter_summary")
    GitGutter :lua require("el.subscribe")._process_user_callback(9, "el_gitgutter_summary")
    GitGutter :lua require("el.subscribe")._process_user_callback(3, "el_gitgutter_summary")
    GitGutter :lua require("el.subscribe")._process_user_callback(9, "el_gitgutter_summary")
    GitGutter :lua require("el.subscribe")._process_user_callback(3, "el_gitgutter_summary")
    GitGutter :lua require("el.subscribe")._process_user_callback(3, "el_gitgutter_summary")
    GitGutter :lua require("el.subscribe")._process_user_callback(9, "el_gitgutter_summary")
Press ENTER or type command to continue

interesting...
I don't use coc, but I have 2 buffer auto command subscriptions and 1 user auto command subscription.
I open 3 files, no duplicated user auto commands.