Compare commits

..

3 Commits

Author SHA1 Message Date
McAuley Penney
8ea0e7205c patch 9.1.2017: getregionpos() depends on 'linebreak' setting
Problem:  getregionpos() depends on 'linebreak' setting
Solution: Reset linebreak setting temporarily (McAuley Penney)

When a line is wrapped on word boundaries, getregionpos() may report a
different end column for a visual block than the cursor position used to
define the selection.

Update the blockwise calculation in getregionpos() to use the same
wrapping assumptions as visual block mode, so the reported region
matches the selection boundaries.

Add a regression test that forces wrapping and checks that the end
position stays consistent under "setlocal wrap" and "setlocal
linebreak".

closes: #19006

Signed-off-by: McAuley Penney <jacobmpenney@gmail.com>
Signed-off-by: Christian Brabandt <cb@256bit.org>
2025-12-23 20:51:25 +00:00
Anttoni Erkkilä
9d661b057e patch 9.1.2016: cindent wrong indentation after do-while loop
Problem:  At "if(0) do if(0); while(0); else", else should be aligned
          with outer if, but is aligned with inner if.
Solution: In function find_match, ignore "if" and "else" inside a
          do-while loop, when looking for "if". (Anttoni Erkkilä)

closes: #19004

Signed-off-by: Anttoni Erkkilä <anttoni.erkkila@protonmail.com>
Signed-off-by: Christian Brabandt <cb@256bit.org>
2025-12-23 20:42:57 +00:00
Foxe Chen
60c87056b4 patch 9.1.2015: blob2string() stopped after an empty line
Problem:  blob2string() stopped after an empty line
Solution: Specifically check for empty content (Foxe Chen)

closes: #19001

Signed-off-by: Foxe Chen <chen.foxe@gmail.com>
Signed-off-by: Christian Brabandt <cb@256bit.org>
2025-12-23 20:37:19 +00:00
9 changed files with 169 additions and 21 deletions

View File

@@ -2076,16 +2076,30 @@ find_match(int lookfor, linenr_T ourscope)
if (theirscope->lnum > ourscope)
continue;
// if it was an "else" (that's not an "else if")
// then we need to go back to another if, so
// increment elselevel
look = cin_skipcomment(ml_get_curline());
if (cin_iselse(look))
// When looking for if, we ignore "if" and "else" in a deeper do-while loop.
if (!(lookfor == LOOKFOR_IF && whilelevel))
{
mightbeif = cin_skipcomment(look + 4);
if (!cin_isif(mightbeif))
++elselevel;
continue;
// if it was an "else" (that's not an "else if")
// then we need to go back to another if, so
// increment elselevel
if (cin_iselse(look))
{
mightbeif = cin_skipcomment(look + 4);
if (!cin_isif(mightbeif))
++elselevel;
continue;
}
// If it's an "if" decrement elselevel
if (cin_isif(look))
{
elselevel--;
// When looking for an "if" ignore "while"s that
// get in the way.
if (elselevel == 0 && lookfor == LOOKFOR_IF)
whilelevel = 0;
}
}
// if it was a "while" then we need to go back to
@@ -2096,17 +2110,6 @@ find_match(int lookfor, linenr_T ourscope)
continue;
}
// If it's an "if" decrement elselevel
look = cin_skipcomment(ml_get_curline());
if (cin_isif(look))
{
elselevel--;
// When looking for an "if" ignore "while"s that
// get in the way.
if (elselevel == 0 && lookfor == LOOKFOR_IF)
whilelevel = 0;
}
// If it's a "do" decrement whilelevel
if (cin_isdo(look))
whilelevel--;

View File

@@ -6175,8 +6175,17 @@ getregionpos(
{
colnr_T sc1, ec1, sc2, ec2;
#ifdef FEAT_LINEBREAK
int lbr_saved = reset_lbr();
#endif
getvvcol(curwin, p1, &sc1, NULL, &ec1);
getvvcol(curwin, p2, &sc2, NULL, &ec2);
#ifdef FEAT_LINEBREAK
restore_lbr(lbr_saved);
#endif
oap->motion_type = MBLOCK;
oap->inclusive = TRUE;
oap->op_type = OP_NOP;

View File

@@ -2398,7 +2398,7 @@ theend:
* Reset 'linebreak' and take care of side effects.
* Returns the previous value, to be passed to restore_lbr().
*/
static int
int
reset_lbr(void)
{
if (!curwin->w_p_lbr)
@@ -2412,7 +2412,7 @@ reset_lbr(void)
/*
* Restore 'linebreak' and take care of side effects.
*/
static void
void
restore_lbr(int lbr_saved)
{
if (curwin->w_p_lbr || !lbr_saved)

View File

@@ -22,4 +22,6 @@ char *did_set_operatorfunc(optset_T *args);
void free_operatorfunc_option(void);
int set_ref_in_opfunc(int copyID);
void do_pending_operator(cmdarg_T *cap, int old_col, int gui_yank);
int reset_lbr(void);
void restore_lbr(int lbr_saved);
/* vim: set ft=c : */

View File

@@ -1234,6 +1234,8 @@ blob_from_string(char_u *str, blob_T *blob)
* Return a string created from the bytes in blob starting at "start_idx".
* A NL character in the blob indicates end of string.
* A NUL character in the blob is translated to a NL.
* If a newline is followed by another newline (empty line), then an empty
* allocated string is returned and "start_idx" is moved forward by one byte.
* On return, "start_idx" points to next byte to process in blob.
*/
static char_u *
@@ -1265,6 +1267,8 @@ string_from_blob(blob_T *blob, long *start_idx)
if (str_ga.ga_data != NULL)
ret_str = vim_strnsave(str_ga.ga_data, str_ga.ga_len);
else
ret_str = vim_strsave((char_u *)"");
*start_idx = idx;
ga_clear(&str_ga);

View File

@@ -885,4 +885,17 @@ func Test_blob_byte_set_invalid_value()
call v9.CheckSourceLegacyAndVim9Failure(lines, 'E1239: Invalid value for blob:')
endfunc
" Test when converting a blob to a string, and there is an empty line (newline
" followed directly by another newline).
func Test_blob2str_empty_line()
let stuff =<< trim END
Hello
World!
END
let b = str2blob(stuff)
call assert_equal(['Hello', '', 'World!'], blob2str(b))
endfunc
" vim: shiftwidth=2 sts=2 expandtab

View File

@@ -1111,6 +1111,27 @@ def Test_cindent_1()
b;
}
void func() {
if (0)
do
if (0);
while (0);
else;
}
void func() {
if (0)
do
if (0)
do
if (0)
a();
while (0);
while (0);
else
a();
}
/* end of AUTO */
[CODE]
@@ -2093,6 +2114,27 @@ def Test_cindent_1()
b;
}
void func() {
if (0)
do
if (0);
while (0);
else;
}
void func() {
if (0)
do
if (0)
do
if (0)
a();
while (0);
while (0);
else
a();
}
/* end of AUTO */
[CODE]

View File

@@ -2835,4 +2835,73 @@ func Test_visual_block_pos_update()
bw!
endfunc
" Test that blockwise end position matches getpos('.')
" when 'wrap' and 'linebreak' are set
func Test_getregionpos_block_linebreak_matches_getpos()
CheckFeature linebreak
new
setlocal buftype=
setlocal bufhidden=wipe
setlocal noswapfile
setlocal wrap
setlocal linebreak
setlocal breakat=\ \t
setlocal nonumber norelativenumber
setlocal signcolumn=no
setlocal foldcolumn=0
call setline(1, '1111111111 2222222222 3333333333 4444444444 5555555555 6666666666 7777777777 8888888888')
" Force wrapping deterministically by shrinking the screen width.
let save_columns = &columns
let moved = 0
for c in [30, 20, 15, 10]
execute 'set columns=' .. c
redraw!
normal! gg0
let row0 = winline()
normal! gj
let row1 = winline()
if row1 > row0
let moved = 1
break
endif
endfor
call assert_true(moved)
" Move a bit right so we are not at column 1, then go back up one screen line.
normal! 5l
normal! gk
let row2 = winline()
call assert_equal(row0, row2)
" Start Visual block and move down one screen line to the previous position.
execute "normal! \<C-V>"
normal! gj
let row3 = winline()
call assert_equal(row1, row3)
let p1 = getpos('v')
let p2 = getpos('.')
" Sanity: block selection is within the same wrapped buffer line.
call assert_equal(1, p1[1])
call assert_equal(1, p2[1])
" For blockwise region, getregionpos() should not report an end position
" different from the {pos2} we passed in.
let segs = getregionpos(p1, p2, #{ type: "\<C-V>", exclusive: v:false })
call assert_equal(1, len(segs))
let endp = segs[0][1]
call assert_equal(p2[1], endp[1]) " lnum
call assert_equal(p2[2], endp[2]) " col
call assert_equal(p2[3], endp[3]) " off
let &columns = save_columns
bw!
endfunc
" vim: shiftwidth=2 sts=2 expandtab

View File

@@ -734,6 +734,12 @@ static char *(features[]) =
static int included_patches[] =
{ /* Add new patch number below this line */
/**/
2017,
/**/
2016,
/**/
2015,
/**/
2014,
/**/