datwaft / bubbly.nvim

Bubbly statusline for neovim
MIT License
184 stars 6 forks source link

Refactor statusline to use %{ } #100

Open datwaft opened 3 years ago

datwaft commented 3 years ago

This seems to be a full refactor.

cinghiopinghio commented 3 years ago

Hi, can you be more explicit? I was going to refactor all components in order to automatically pick per-component settings (such as right/left, pre/post)

Should I wait for this refactoring or will it involve only the status line factory?

Edit: undo autocorrection

datwaft commented 3 years ago

This is because when I first created the statusline I didn't know much about how statuslines worked, so the statusline currently is generated as a full string like:

NORMAL branch: master bla bla

And that gives a lot of problems, mainly because I need to pass if the statusline is active or not as an argument and because of there are multiple windows, every single one shares the same statusline with the same data (only difference is with inactive or active).

See this for an example.

To solve this I need to generate the statusline string as something like:

%{v:lua.bubbly_component_mode()} ...

And that probably needs a full refactor of a lot of the code.

I will probably need to modify the statusline and bubble factory, and each component with a new key called name, so that I can generate the Lua global variable containing the function when processing the statusline.

But don't worry yet, I will probably do this on my next vacation, I am currently very busy with university.

datwaft commented 3 years ago

Here is a quick demo about the changes I want to make:

local component_mode_data_matcher = {
  ['n'] = 'NORMAL',
  ['i'] = 'INSERT',
  ['v'] = 'VISUAL',
  ['V'] = 'VISUAL',
  [''] = 'VISUAL-BLOCK',
  ['c'] = 'COMMAND',
  ['t'] = 'TERMINAL',
  ['R'] = 'REPLACE',
}

local component_mode_color_matcher = {
  ['n'] = 'MoreMsg',
  ['i'] = 'SpecialKey',
  ['v'] = 'Directory',
  ['V'] = 'User4',
  [''] = 'User5',
  ['c'] = 'User6',
  ['t'] = 'User7',
  ['R'] = 'User0',
}

_G.statusline_component_mode_data = function()
  ---@type string
  local mode = vim.fn.mode()
  return component_mode_data_matcher[mode]
end

_G.statusline_component_mode_color = function()
  ---@type string
  local mode = vim.fn.mode()
  return component_mode_color_matcher[mode]
end

_G.statusline = function()
  return '%#'..statusline_component_mode_color()..'#'..'%{v:lua.statusline_component_mode_data()}'
end

vim.cmd[[set statusline=%!v:lua.statusline()]]

Basically, the colors stay the same, but the data instead of being returned as a string is added as a call for a function.

cinghiopinghio commented 3 years ago

Cool,

In some cases this is the only way out. I'm only afraid of a statusline calling functions at every keystroke...

Anyway, would it be possible for each component to pass a function with the data? and then in the bubble factory add %{v:lua.bubbly_whatever_function_is_passed()}?

That would require minimal changes to the code.

datwaft commented 3 years ago

I'm only afraid of a statusline calling functions at every keystroke...

About this, that is why we put the computation intensive operations in autocmd, so that the statusline is maintained fluid and responsive. And, currently it also does that, so the difference would be minimal, I think.

Anyway, would it be possible for each component to pass a function with the data? and then in the bubble factory add %{v:lua.bubbly_whatever_function_is_passed()}?

That would require minimal changes to the code.

That would be ideal, I am currently still thinking about how to do it. The way I am currently thinking of requires that the component returns a name and a function that would be the data, or if it returns a string we just show it as it is.

That would just require to refactor a lot of components to return data as a function, or as something like:

{
  name = 'statusline_component_mode',
  function = function() end
}

And adding an if to the factory.

But I am still thinking about how to the colors, maybe also as a function like in the demo.