lualine.nvim icon indicating copy to clipboard operation
lualine.nvim copied to clipboard

Bug: selectioncount component gives the wrong size

Open miguelbarao opened this issue 1 year ago • 7 comments

It's not working correctly for visual block mode with

vim.opt.virtualedit = { 'block', 'onemore' }

nvim-screenshot

neovim 0.9 on linux

miguelbarao avatar Apr 09 '23 20:04 miguelbarao

Should be fixed now

dmyTRUEk avatar Apr 17 '23 09:04 dmyTRUEk

Not yet fixed. It's also reporting wrong sizes when there are tabs, multibyte or wide characters.

Looking at the code, in the formula abs(start-end)+1, the +1 is assuming chars to be 1 byte which may not be the case.

In visual-block mode, the columns could be reported with the vim.fn.virtcol() function to fix the issue reported above. It almost works but still fails when the 1st char of the selected area starts is a wide character (e.g. emoji).

In visual mode, single line, the sizes should probably be reported by vim.fn.strchars() and vim.fn.strlen() functions to report the selected area size in chars and bytes.

miguelbarao avatar Apr 25 '23 12:04 miguelbarao

Just to mention (to keep things in one place) there is also #1032.

dmyTRUEk avatar Oct 14 '23 10:10 dmyTRUEk

I can confirm that #1042 works fine, but there are few things that i think should discussed:

  1. Should there be rectangular brackets?
  2. Maybe we should provide a user an option to configure formatting?

dmyTRUEk avatar Oct 14 '23 10:10 dmyTRUEk

I'm using brackets to group and easily distinguish the output from other information shown, but it's just personal preference. A configuration option would be great.

miguelbarao avatar Oct 14 '23 23:10 miguelbarao

Then I think we need 5 "things" for formatting this 5 cases:

  1. Single line, no multi-byte chars
  2. Single line, multi-byte chars
  3. Multi line, no multi-byte chars
  4. Multi line, multi-byte chars
  5. Visual block mode

As of what can be used as mentioned "things" i see three options:

  1. Simplest: strings for separators. Then config may look something like this (for the same result as now in your PR):
{
  'selectioncount',
  symbols = {
    first = '[',
    last = ']',
    bytecount_separator = '-',
    lines_separator = ' / ',
    visual_block_line_symbols_separator = 'x',
  },
}
  1. Cumbersome: functions, which will be pretty bulky for users, but (i think) pretty easy to implement. Config example:
{
  'selectioncount',
  format_functions = {
    single_line_no_multibyte = {
      function(chars)
        return string.format('[%i]', chars)
      end
    },
    single_line_multibyte = {
      function(chars, bytes)
        return string.format('[%i-%i]', chars, bytes)
      end
    },
    multi_line_no_multibyte = {
      function(chars, lines)
        return string.format('[%i / %i]', chars, lines)
      end
    },
    multi_line_multibyte = {
      function(chars, bytes, lines)
        return string.format('[%i-%i / %i]', chars, bytes, lines)
      end
    },
    visual_block_mode = {
      function(chars, lines)
        return string.format('[%ix%i]', chars, lines)
      end
    },
  },
}
  1. Perfect: user provides only format strings with named fields. But i understand that its pretty hard to implement. Config example:
{
  'selectioncount',
  format = {
    single_line_no_multibyte = '[%c]',
    single_line_multibyte = '[%c-%b]',
    multi_line_no_multibyte = '[%c / %l]',
    multi_line_multibyte = '[%c-%b / %l]',
    visual_block_mode = '[%cx%l]',
  },
}

Here %c stands for chars, %bbytes, %llines. Also, if we go this way, should we use % to indicate formatting or perhaps some other symbol, like $ (used in kotlin) or {varname} as used in python, c#, rust, or even something else?

dmyTRUEk avatar Oct 15 '23 09:10 dmyTRUEk

I think would vote for the 1st one, for simplicity. The 3rd would be perfect, and is my preferred one for its customizability, but requiring some kind of parsing is a bit overkill for such a simple feature. Maybe in a later version?

miguelbarao avatar Oct 16 '23 19:10 miguelbarao