Re: Getting the byte index (column) given the character column number

2022-11-20 Fir de Conversatie Yegappan Lakshmanan
Hi Bram,

On Sun, Nov 20, 2022 at 4:04 PM Bram Moolenaar  wrote:
>
>
> Yegappan wrote:
>
> > The language server protocol messages use character column number
> > whereas many of the built-in Vim functions (e.g. matchaddpos()) deal
> > with byte column number.
> >
> > Several built-in functions were added to convert between the character
> > and byte column numbers (byteidx(), charcol(), charidx(),
> > getcharpos(), getcursorcharpos(), etc,).
> > But these functions deal with strings, current cursor position or the
> > position of a mark.
> >
> > We currently don't have a function to return the byte number given the
> > character number in a line in a buffer.  The workaround is to use
> > getbufline() to get the entire buffer line and then use byteidx() to
> > get the byte number from the character number.
> >
> > I am thinking of introducing a new function named charcol2bytecol()
> > that accepts a buffer number, line number and the character number in
> > the line and returns the corresponding byte number.  Any
> > suggestions/comments on this?
> >
> > We should also modify the matchaddpos() function to accept character numbers
> > in a line in addition to the byte numbers.
>
> Just to make sure we understand what we are talking about: This is
> always about text in a buffer?  Thus the buffer text is somehow passed
> through the LSP to a server, which then returns information with
> character indexes.
>

Yes.  The location information returned by the LSP server is about the
text in the buffer.

>
> One detail that matters: Are composing characters counted separately, or
> not counted (part of the base character)?
>

I think composing counters are not counted.  But I couldn't find this mentioned
in the LSP specification:

https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification/#position

>
> Also, I assume a Tab is counted as just one character, not the number of
> display cells it occupies.
>

Yes. Tab is counted as one character.

>
> I wonder if it's really helpful to add a new function if it can
> currently be done with two.  You already mention that the text can be
> obtained with getbufline(), and then get the byte index from the
> character index with byteidx().  What is the problem with doing it that
> way?
>

If the conversion has to be done too many times then it is not efficient.

>
> Other message:
>
> > Another alternative is to extend the col() function.  The col()
> > function currently accepts a list with two numbers (a line number and
> > a byte number or "$") and returns the byte number.
> > This can be modified to also accept a list with three numbers (line
> > number, column number and a boolean indicating character column or
> > byte column) and return the byte number.
>
> I don't like this, the first line for the col() help is:
>
> The result is a Number, which is the byte index of the column
>
> When the boolean is true this would be the character index, that is hard
> to explain.  A user would have to look really hard to find this
> functionality.
>

The boolean doesn't change the return value of the col() function.  It just
changes how the col() function interprets the column number in the list.
If it is true, then the col() function will use the column number as the
character number.  If it is false or not specified, then the col() function
will use it as the byte number.  In both cases the col() function will always
return the byte index of the column.

>
> There is also charcol(), it appears to be doing what you want already.
>

The charcol() function returns the character number in a line.  This function
cannot be used to get the byte index given the character index.

Regards,
Yegappan

-- 
-- 
You received this message from the "vim_dev" maillist.
Do not top-post! Type your reply below the text you are replying to.
For more information, visit http://www.vim.org/maillist.php

--- 
You received this message because you are subscribed to the Google Groups 
"vim_dev" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to vim_dev+unsubscr...@googlegroups.com.
To view this discussion on the web visit 
https://groups.google.com/d/msgid/vim_dev/CAAW7x7kLMOszc%3DPSRVqoqw%3DuBkupgN4nNrkqUdrpepH%2Bt7qxhA%40mail.gmail.com.


Re: Getting the byte index (column) given the character column number

2022-11-20 Fir de Conversatie Bram Moolenaar


Yegappan wrote:

> The language server protocol messages use character column number
> whereas many of the built-in Vim functions (e.g. matchaddpos()) deal
> with byte column number.
> 
> Several built-in functions were added to convert between the character
> and byte column numbers (byteidx(), charcol(), charidx(),
> getcharpos(), getcursorcharpos(), etc,).
> But these functions deal with strings, current cursor position or the
> position of a mark.
> 
> We currently don't have a function to return the byte number given the
> character number in a line in a buffer.  The workaround is to use
> getbufline() to get the entire buffer line and then use byteidx() to
> get the byte number from the character number.
> 
> I am thinking of introducing a new function named charcol2bytecol()
> that accepts a buffer number, line number and the character number in
> the line and returns the corresponding byte number.  Any
> suggestions/comments on this?
> 
> We should also modify the matchaddpos() function to accept character numbers
> in a line in addition to the byte numbers.

Just to make sure we understand what we are talking about: This is
always about text in a buffer?  Thus the buffer text is somehow passed
through the LSP to a server, which then returns information with
character indexes.

One detail that matters: Are composing characters counted separately, or
not counted (part of the base character)?

Also, I assume a Tab is counted as just one character, not the number of
display cells it occupies.

I wonder if it's really helpful to add a new function if it can
currently be done with two.  You already mention that the text can be
obtained with getbufline(), and then get the byte index from the
character index with byteidx().  What is the problem with doing it that
way?

Other message:

> Another alternative is to extend the col() function.  The col()
> function currently accepts a list with two numbers (a line number and
> a byte number or "$") and returns the byte number.
> This can be modified to also accept a list with three numbers (line
> number, column number and a boolean indicating character column or
> byte column) and return the byte number.

I don't like this, the first line for the col() help is:

The result is a Number, which is the byte index of the column

When the boolean is true this would be the character index, that is hard
to explain.  A user would have to look really hard to find this
functionality.

There is also charcol(), it appears to be doing what you want already.


-- 
hundred-and-one symptoms of being an internet addict:
92. It takes you two hours to check all 14 of your mailboxes.

 /// Bram Moolenaar -- b...@moolenaar.net -- http://www.Moolenaar.net   \\\
///  \\\
\\\sponsor Vim, vote for features -- http://www.Vim.org/sponsor/ ///
 \\\help me help AIDS victims -- http://ICCF-Holland.org///

-- 
-- 
You received this message from the "vim_dev" maillist.
Do not top-post! Type your reply below the text you are replying to.
For more information, visit http://www.vim.org/maillist.php

--- 
You received this message because you are subscribed to the Google Groups 
"vim_dev" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to vim_dev+unsubscr...@googlegroups.com.
To view this discussion on the web visit 
https://groups.google.com/d/msgid/vim_dev/20221121000400.7E0B41C12B9%40moolenaar.net.


Re: Getting the byte index (column) given the character column number

2022-11-20 Fir de Conversatie Yegappan Lakshmanan
On Sun, Nov 20, 2022 at 9:05 AM Yegappan Lakshmanan  wrote:
>
> Hi all,
>
> The language server protocol messages use character column number whereas many
> of the built-in Vim functions (e.g. matchaddpos()) deal with byte column 
> number.
>
> Several built-in functions were added to convert between the character and 
> byte
> column numbers (byteidx(), charcol(), charidx(), getcharpos(),
> getcursorcharpos(), etc,).
> But these functions deal with strings, current cursor position or the
> position of a mark.
>
> We currently don't have a function to return the byte number given the 
> character
> number in a line in a buffer.  The workaround is to use getbufline()
> to get the entire
> buffer line and then use byteidx() to get the byte number from the
> character number.
>
> I am thinking of introducing a new function named charcol2bytecol() that 
> accepts
> a buffer number, line number and the character number in the line and
> returns the
> corresponding byte number.  Any suggestions/comments on this?
>

Another alternative is to extend the col() function.  The col()
function currently accepts a
list with two numbers (a line number and a byte number or "$") and
returns the byte number.
This can be modified to also accept a list with three numbers (line
number, column number
and a boolean indicating character column or byte column) and return
the byte number.

- Yegappan

> We should also modify the matchaddpos() function to accept character numbers
> in a line in addition to the byte numbers.
>
> Regards,
> Yegappan

-- 
-- 
You received this message from the "vim_dev" maillist.
Do not top-post! Type your reply below the text you are replying to.
For more information, visit http://www.vim.org/maillist.php

--- 
You received this message because you are subscribed to the Google Groups 
"vim_dev" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to vim_dev+unsubscr...@googlegroups.com.
To view this discussion on the web visit 
https://groups.google.com/d/msgid/vim_dev/CAAW7x7%3D7najhNxO%3Dn5LzQ6dmO-mPhLnrzn2iO-AXKF4%2BxfszVA%40mail.gmail.com.


Getting the byte index (column) given the character column number

2022-11-20 Fir de Conversatie Yegappan Lakshmanan
Hi all,

The language server protocol messages use character column number whereas many
of the built-in Vim functions (e.g. matchaddpos()) deal with byte column number.

Several built-in functions were added to convert between the character and byte
column numbers (byteidx(), charcol(), charidx(), getcharpos(),
getcursorcharpos(), etc,).
But these functions deal with strings, current cursor position or the
position of a mark.

We currently don't have a function to return the byte number given the character
number in a line in a buffer.  The workaround is to use getbufline()
to get the entire
buffer line and then use byteidx() to get the byte number from the
character number.

I am thinking of introducing a new function named charcol2bytecol() that accepts
a buffer number, line number and the character number in the line and
returns the
corresponding byte number.  Any suggestions/comments on this?

We should also modify the matchaddpos() function to accept character numbers
in a line in addition to the byte numbers.

Regards,
Yegappan

-- 
-- 
You received this message from the "vim_dev" maillist.
Do not top-post! Type your reply below the text you are replying to.
For more information, visit http://www.vim.org/maillist.php

--- 
You received this message because you are subscribed to the Google Groups 
"vim_dev" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to vim_dev+unsubscr...@googlegroups.com.
To view this discussion on the web visit 
https://groups.google.com/d/msgid/vim_dev/CAAW7x7%3DRz5kuO9h9Y9ksx7EbHOyLmWh%3DJv7UeCEq62hGA10BwA%40mail.gmail.com.


Re: Test Failure

2022-11-20 Fir de Conversatie Bram Moolenaar


> Environment: Linux
> Terminal: tmux
> Compiler: clang-15
> Version: 9.0.0915
> 
> There is a test failure:
> Found errors in Test_autocmd_user_clear_group():
> Run 1, 15:38:56 - 15:39:01:
> command line..script /source/vim/vim-9.0.0915/src/vim-motif/testdir=
> /runtest.vim[515]..function RunTheTest[52]..Test_autocmd_user_clear_group[1=
> 8]..StopVimInTerminal[14]..WaitForAssert[2]..5_WaitForCommon[11].. bda>47 line 1: Expected 'finished' but got 'running'

It does not fail for me in a similar setup, and CI also doesn't show
this failure.  Can you think of anything that matters?  I can't really
fix a test failure if I can't reproduce it.

You could try increasing the "50" argument of TermWait() in line 2239
and see if that makes a difference.

-- 
>From "know your smileys":
 |-(Contact lenses, but has lost them

 /// Bram Moolenaar -- b...@moolenaar.net -- http://www.Moolenaar.net   \\\
///  \\\
\\\sponsor Vim, vote for features -- http://www.Vim.org/sponsor/ ///
 \\\help me help AIDS victims -- http://ICCF-Holland.org///

-- 
-- 
You received this message from the "vim_dev" maillist.
Do not top-post! Type your reply below the text you are replying to.
For more information, visit http://www.vim.org/maillist.php

--- 
You received this message because you are subscribed to the Google Groups 
"vim_dev" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to vim_dev+unsubscr...@googlegroups.com.
To view this discussion on the web visit 
https://groups.google.com/d/msgid/vim_dev/20221120152028.0FFC91C12B2%40moolenaar.net.


Test Failure

2022-11-20 Fir de Conversatie Elimar Riesebieter
Hi all,

Environment: Linux
Terminal: tmux
Compiler: clang-15
Version: 9.0.0915

There is a test failure:
Found errors in Test_autocmd_user_clear_group():
Run 1, 15:38:56 - 15:39:01:
command line..script 
/source/vim/vim-9.0.0915/src/vim-motif/testdir/runtest.vim[515]..function 
RunTheTest[52]..Test_autocmd_user_clear_group[18]..StopVimInTerminal[14]..WaitForAssert[2]..5_WaitForCommon[11]..47
 line 1: Expected 'finished' but got 'running'

Thanks for investigation
Elimar

-- 
  The path to source is always uphill!
-unknown-

-- 
-- 
You received this message from the "vim_dev" maillist.
Do not top-post! Type your reply below the text you are replying to.
For more information, visit http://www.vim.org/maillist.php

--- 
You received this message because you are subscribed to the Google Groups 
"vim_dev" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to vim_dev+unsubscr...@googlegroups.com.
To view this discussion on the web visit 
https://groups.google.com/d/msgid/vim_dev/20221120150518.cjvbewrxz2elv7ao%40baumbart.home.lxtec.de.


Patch 9.0.0915

2022-11-20 Fir de Conversatie Bram Moolenaar


Patch 9.0.0915
Problem:WinScrolled may trigger immediately when defined.
Solution:   Initialize the fields in all windows. (closes #11582)
Files:  src/autocmd.c, src/window.c, src/proto/window.pro,
src/testdir/test_autocmd.vim,
src/testdir/dumps/Test_winscrolled_not_when_defined_1.dump,
src/testdir/dumps/Test_winscrolled_not_when_defined_2.dump


*** ../vim-9.0.0914/src/autocmd.c   2022-11-13 17:53:42.283417583 +
--- src/autocmd.c   2022-11-20 12:10:13.844729626 +
***
*** 1264,1277 
get_mode(last_mode);
  #endif
// Initialize the fields checked by the WinScrolled trigger to
!   // stop it from firing right after the first autocmd is defined.
if (event == EVENT_WINSCROLLED && !has_winscrolled())
{
!   curwin->w_last_topline = curwin->w_topline;
!   curwin->w_last_leftcol = curwin->w_leftcol;
!   curwin->w_last_skipcol = curwin->w_skipcol;
!   curwin->w_last_width = curwin->w_width;
!   curwin->w_last_height = curwin->w_height;
}
  
if (is_buflocal)
--- 1264,1283 
get_mode(last_mode);
  #endif
// Initialize the fields checked by the WinScrolled trigger to
!   // prevent it from firing right after the first autocmd is
!   // defined.
if (event == EVENT_WINSCROLLED && !has_winscrolled())
{
!   tabpage_T *save_curtab = curtab;
!   tabpage_T *tp;
!   FOR_ALL_TABPAGES(tp)
!   {
!   unuse_tabpage(curtab);
!   use_tabpage(tp);
!   snapshot_windows_scroll_size();
!   }
!   unuse_tabpage(curtab);
!   use_tabpage(save_curtab);
}
  
if (is_buflocal)
*** ../vim-9.0.0914/src/window.c2022-11-19 21:17:48.841226535 +
--- src/window.c2022-11-20 12:01:47.440641805 +
***
*** 2846,2852 
   * Make a snapshot of all the window scroll positions and sizes of the current
   * tab page.
   */
! static void
  snapshot_windows_scroll_size(void)
  {
  win_T *wp;
--- 2846,2852 
   * Make a snapshot of all the window scroll positions and sizes of the current
   * tab page.
   */
! void
  snapshot_windows_scroll_size(void)
  {
  win_T *wp;
***
*** 3864,3869 
--- 3864,3896 
  }
  
  /*
+  * Store the relevant window pointers for tab page "tp".  To be used before
+  * use_tabpage().
+  */
+ void
+ unuse_tabpage(tabpage_T *tp)
+ {
+ tp->tp_topframe = topframe;
+ tp->tp_firstwin = firstwin;
+ tp->tp_lastwin = lastwin;
+ tp->tp_curwin = curwin;
+ }
+ 
+ /*
+  * Set the relevant pointers to use tab page "tp".  May want to call
+  * unuse_tabpage() first.
+  */
+ void
+ use_tabpage(tabpage_T *tp)
+ {
+ curtab = tp;
+ topframe = curtab->tp_topframe;
+ firstwin = curtab->tp_firstwin;
+ lastwin = curtab->tp_lastwin;
+ curwin = curtab->tp_curwin;
+ }
+ 
+ /*
   * Allocate the first window and put an empty buffer in it.
   * Called from main().
   * Return FAIL when something goes wrong (out of memory).
***
*** 3877,3887 
  first_tabpage = alloc_tabpage();
  if (first_tabpage == NULL)
return FAIL;
- first_tabpage->tp_topframe = topframe;
  curtab = first_tabpage;
! curtab->tp_firstwin = firstwin;
! curtab->tp_lastwin = lastwin;
! curtab->tp_curwin = curwin;
  
  return OK;
  }
--- 3904,3911 
  first_tabpage = alloc_tabpage();
  if (first_tabpage == NULL)
return FAIL;
  curtab = first_tabpage;
! unuse_tabpage(first_tabpage);
  
  return OK;
  }
***
*** 4389,4398 
  win_T *next_prevwin = tp->tp_prevwin;
  tabpage_T *last_tab = curtab;
  
! curtab = tp;
! firstwin = tp->tp_firstwin;
! lastwin = tp->tp_lastwin;
! topframe = tp->tp_topframe;
  
  // We would like doing the TabEnter event first, but we don't have a
  // valid current window yet, which may break some commands.
--- 4413,4419 
  win_T *next_prevwin = tp->tp_prevwin;
  tabpage_T *last_tab = curtab;
  
! use_tabpage(tp);
  
  // We would like doing the TabEnter event first, but we don't have a
  // valid current window yet, which may break some commands.
*** ../vim-9.0.0914/src/proto/window.pro2022-11-19 21:17:48.841226535 
+
--- src/proto/window.pro2022-11-20 11:53:02.444550244 +
***
*** 18,29 
--- 18,32 
  void close_windows(buf_T *buf, int keep_curwin);
  int one_window(void);
  int win_close(win_T *win, int free_buf);
+ void snapshot_windows_scroll_size(void);
  void 

Patch 9.0.0914

2022-11-20 Fir de Conversatie Bram Moolenaar


Patch 9.0.0914
Problem:deletebufline() may move marks in the wrong window.
Solution:   Find a window for the buffer being changed. (closes #11583)
Files:  src/evalbuffer.c, src/testdir/test_bufline.vim


*** ../vim-9.0.0913/src/evalbuffer.c2022-11-19 13:59:39.511861139 +
--- src/evalbuffer.c2022-11-20 11:12:50.860191314 +
***
*** 119,124 
--- 119,177 
  }
  }
  
+ typedef struct {
+ win_T *cob_curwin_save;
+ aco_save_Tcob_aco;
+ int   cob_using_aco;
+ int   cob_save_VIsual_active;
+ } cob_T;
+ 
+ /*
+  * Used before making a change in "buf", which is not the current one: Make
+  * "buf" the current buffer and find a window for this buffer, so that side
+  * effects are done correctly (e.g., adjusting marks).
+  *
+  * Information is saved in "cob" and MUST be restored by calling
+  * change_other_buffer_restore().
+  */
+ static void
+ change_other_buffer_prepare(cob_T *cob, buf_T *buf)
+ {
+ CLEAR_POINTER(cob);
+ 
+ // Set "curbuf" to the buffer being changed.  Then make sure there is a
+ // window for it to handle any side effects.
+ cob->cob_save_VIsual_active = VIsual_active;
+ VIsual_active = FALSE;
+ cob->cob_curwin_save = curwin;
+ curbuf = buf;
+ find_win_for_curbuf();  // simplest: find existing window for "buf"
+ 
+ if (curwin->w_buffer != buf)
+ {
+   // No existing window for this buffer.  It is dangerous to have
+   // curwin->w_buffer differ from "curbuf", use the autocmd window.
+   curbuf = curwin->w_buffer;
+   aucmd_prepbuf(>cob_aco, buf);
+   cob->cob_using_aco = TRUE;
+ }
+ }
+ 
+ static void
+ change_other_buffer_restore(cob_T *cob)
+ {
+ if (cob->cob_using_aco)
+ {
+   aucmd_restbuf(>cob_aco);
+ }
+ else
+ {
+   curwin = cob->cob_curwin_save;
+   curbuf = curwin->w_buffer;
+ }
+ VIsual_active = cob->cob_save_VIsual_active;
+ }
+ 
  /*
   * Set line or list of lines in buffer "buf" to "lines".
   * Any type is allowed and converted to a string.
***
*** 137,146 
  listitem_T*li = NULL;
  long  added = 0;
  linenr_T  append_lnum;
- win_T *curwin_save = NULL;
- aco_save_Taco;
- int   using_aco = FALSE;
- int   save_VIsual_active = VIsual_active;
  
  // When using the current buffer ml_mfp will be set if needed.  Useful 
when
  // setline() is used on startup.  For other buffers the buffer must be
--- 190,195 
***
*** 154,177 
return;
  }
  
  if (!is_curbuf)
! {
!   // Set "curbuf" to the buffer being changed.  Then make sure there is a
!   // window for it to handle any side effects.
!   VIsual_active = FALSE;
!   curwin_save = curwin;
!   curbuf = buf;
!   find_win_for_curbuf();  // simplest: find existing window for "buf"
! 
!   if (curwin->w_buffer != buf)
!   {
!   // No existing window for this buffer.  It is dangerous to have
!   // curwin->w_buffer differ from "curbuf", use the autocmd window.
!   curbuf = curwin->w_buffer;
!   aucmd_prepbuf(, buf);
!   using_aco = TRUE;
!   }
! }
  
  if (append)
// appendbufline() uses the line number below which we insert
--- 203,213 
return;
  }
  
+ // After this don't use "return", goto "cleanup"!
+ cob_T cob;
  if (!is_curbuf)
!   // set "curbuf" to "buf" and find a window for this buffer
!   change_other_buffer_prepare(, buf);
  
  if (append)
// appendbufline() uses the line number below which we insert
***
*** 272,289 
  
  done:
  if (!is_curbuf)
! {
!   if (using_aco)
!   {
!   aucmd_restbuf();
!   }
!   else
!   {
!   curwin = curwin_save;
!   curbuf = curwin->w_buffer;
!   }
!   VIsual_active = save_VIsual_active;
! }
  }
  
  /*
--- 308,314 
  
  done:
  if (!is_curbuf)
!   change_other_buffer_restore();
  }
  
  /*
***
*** 521,532 
  linenr_T  lnum;
  long  count;
  int   is_curbuf;
- buf_T *curbuf_save = NULL;
- win_T *curwin_save = NULL;
  tabpage_T *tp;
  win_T *wp;
  int   did_emsg_before = did_emsg;
- int   save_VIsual_active = VIsual_active;
  
  rettv->vval.v_number = 1; // FAIL by default
  
--- 546,554 
***
*** 539,545 
  buf = tv_get_buf([0], FALSE);
  if (buf == NULL)
return;
- is_curbuf = buf == curbuf;
  
  first = tv_get_lnum_buf([1], buf);
  if (did_emsg > did_emsg_before)
--- 561,566 
***
*** 554,567 
return;
  
  // After this don't use "return", goto "cleanup"!
  if (!is_curbuf)
! {
!   VIsual_active = FALSE;
!   curbuf_save = curbuf;
!