# HG changeset patch # User Christian Brabandt # Date 1709757903 -3600 # Node ID 7cc0b2479fada8ba8a3017b7957bf7e4ce76b14c # Parent 51554a08c105cd60d12ccedb9bf8ee3e6abe03e5 patch 9.1.0155: can only get getregion() from current buffer Commit: https://github.com/vim/vim/commit/84bf6e658da51126bdd2e50af1f40cabd149343f Author: Shougo Matsushita Date: Wed Mar 6 21:10:18 2024 +0100 patch 9.1.0155: can only get getregion() from current buffer Problem: can only call getregion() for current buffer Solution: Allow to retrieve selections from different buffers (Shougo Matsushita) closes: #14131 Co-authored-by: zeertzjq Signed-off-by: Shougo Matsushita Signed-off-by: Christian Brabandt diff --git a/runtime/doc/builtin.txt b/runtime/doc/builtin.txt --- a/runtime/doc/builtin.txt +++ b/runtime/doc/builtin.txt @@ -1,4 +1,4 @@ -*builtin.txt* For Vim version 9.1. Last change: 2024 Mar 03 +*builtin.txt* For Vim version 9.1. Last change: 2024 Mar 06 VIM REFERENCE MANUAL by Bram Moolenaar @@ -4274,11 +4274,13 @@ getreginfo([{regname}]) *getreginfo( GetRegname()->getreginfo() getregion({pos1}, {pos2} [, {opts}]) *getregion()* - Returns the list of strings from {pos1} to {pos2} in current + Returns the list of strings from {pos1} to {pos2} from a buffer. {pos1} and {pos2} must both be |List|s with four numbers. - See |getpos()| for the format of the list. + See |getpos()| for the format of the list. It's possible + to specify positions from a different buffer, but please + note the limitations at |getregion-notes| The optional argument {opts} is a Dict and supports the following items: @@ -4299,6 +4301,7 @@ getregion({pos1}, {pos2} [, {opts}]) * This function is useful to get text starting and ending in different columns, such as a |characterwise-visual| selection. + *getregion-notes* Note that: - Order of {pos1} and {pos2} doesn't matter, it will always return content from the upper left position to the lower @@ -4308,8 +4311,12 @@ getregion({pos1}, {pos2} [, {opts}]) * - If the region is blockwise and it starts or ends in the middle of a multi-cell character, it is not included but its selected part is substituted with spaces. - - If {pos1} or {pos2} is not current in the buffer, an empty + - If {pos1} and {pos2} are not in the same buffer, an empty list is returned. + - {pos1} and {pos2} must belong to a |bufloaded()| buffer. + - It is evaluated in current window context, this makes a + different if a buffer is displayed in a different window and + 'virtualedit' or 'list' is set Examples: > :xnoremap diff --git a/runtime/doc/tags b/runtime/doc/tags --- a/runtime/doc/tags +++ b/runtime/doc/tags @@ -7767,6 +7767,7 @@ getqflist-examples quickfix.txt /*getqfl getreg() builtin.txt /*getreg()* getreginfo() builtin.txt /*getreginfo()* getregion() builtin.txt /*getregion()* +getregion-notes builtin.txt /*getregion-notes* getregtype() builtin.txt /*getregtype()* getscript pi_getscript.txt /*getscript* getscript-autoinstall pi_getscript.txt /*getscript-autoinstall* diff --git a/src/evalfunc.c b/src/evalfunc.c --- a/src/evalfunc.c +++ b/src/evalfunc.c @@ -5491,9 +5491,10 @@ f_getregion(typval_T *argvars, typval_T struct block_def bd; char_u *akt = NULL; int inclusive = TRUE; - int fnum = -1; + int fnum1 = -1, fnum2 = -1; pos_T p1, p2; char_u *type; + buf_T *save_curbuf = curbuf; char_u default_type[] = "v"; int save_virtual = -1; int l; @@ -5508,12 +5509,9 @@ f_getregion(typval_T *argvars, typval_T || check_for_opt_dict_arg(argvars, 2) == FAIL) return; - if (list2fpos(&argvars[0], &p1, &fnum, NULL, FALSE) != OK - || (fnum >= 0 && fnum != curbuf->b_fnum)) - return; - - if (list2fpos(&argvars[1], &p2, &fnum, NULL, FALSE) != OK - || (fnum >= 0 && fnum != curbuf->b_fnum)) + if (list2fpos(&argvars[0], &p1, &fnum1, NULL, FALSE) != OK + || list2fpos(&argvars[1], &p2, &fnum2, NULL, FALSE) != OK + || fnum1 != fnum2) return; if (argvars[2].v_type == VAR_DICT) @@ -5540,6 +5538,18 @@ f_getregion(typval_T *argvars, typval_T else return; + if (fnum1 != 0) + { + buf_T *findbuf; + + findbuf = buflist_findnr(fnum1); + // buffer not loaded + if (findbuf == NULL || findbuf->b_ml.ml_mfp == NULL) + return; + save_curbuf = curbuf; + curbuf = findbuf; + } + save_virtual = virtual_op; virtual_op = virtual_active(); @@ -5642,6 +5652,9 @@ f_getregion(typval_T *argvars, typval_T } } + if (curbuf != save_curbuf) + curbuf = save_curbuf; + virtual_op = save_virtual; } diff --git a/src/testdir/test_visual.vim b/src/testdir/test_visual.vim --- a/src/testdir/test_visual.vim +++ b/src/testdir/test_visual.vim @@ -1747,7 +1747,7 @@ func Test_visual_getregion() #" using the wrong type call assert_fails(':echo "."->getpos()->getregion("$", [])', 'E1211:') - #" using a mark in another buffer + #" using a mark from another buffer to current buffer new VAR newbuf = bufnr() call setline(1, range(10)) @@ -1757,6 +1757,20 @@ func Test_visual_getregion() call assert_equal([], getregion(getpos('.'), getpos("'A"), {'type': 'v' })) call assert_equal([], getregion(getpos("'A"), getpos('.'), {'type': 'v' })) exe $':{newbuf}bwipe!' + + #" using a mark from another buffer to another buffer + new + VAR anotherbuf = bufnr() + call setline(1, range(10)) + normal! GmA + normal! GmB + wincmd p + call assert_equal([anotherbuf, 10, 1, 0], getpos("'A")) + call assert_equal(['9'], getregion(getpos("'B"), getpos("'A"), {'type': 'v' })) + exe $':{anotherbuf}bwipe!' + + #" using invalid buffer + call assert_equal([], getregion([10000, 10, 1, 0], [10000, 10, 1, 0])) END call v9.CheckLegacyAndVim9Success(lines) @@ -1907,4 +1921,18 @@ func Test_visual_getregion() call v9.CheckLegacyAndVim9Success(lines) endfunc +func Test_getregion_invalid_buf() + new + help + call cursor(5, 7) + norm! mA + call cursor(5, 18) + norm! mB + call assert_equal(['Move around:'], getregion(getpos("'A"), getpos("'B"))) + " close the help window + q + call assert_equal([], getregion(getpos("'A"), getpos("'B"))) + bwipe! +endfunc + " vim: shiftwidth=2 sts=2 expandtab diff --git a/src/version.c b/src/version.c --- a/src/version.c +++ b/src/version.c @@ -705,6 +705,8 @@ static char *(features[]) = static int included_patches[] = { /* Add new patch number below this line */ /**/ + 155, +/**/ 154, /**/ 153,