0
0
mirror of https://github.com/vim/vim.git synced 2025-09-25 03:54:15 -04:00

patch 9.0.0861: solution for "!!sort" in closed fold is not optimal

Problem:    Solution for "!!sort" in closed fold is not optimal.
Solution:   Use a different range instead of the subtle difference in handling
            a range with an offset. (issue #11487)
This commit is contained in:
Bram Moolenaar
2022-11-11 22:58:36 +00:00
parent a20be06f97
commit 9954dc39ea
5 changed files with 114 additions and 21 deletions

View File

@@ -736,7 +736,9 @@ Line numbers may be specified with: *:range* *{address}*
'T position of mark T (uppercase); when the mark is in 'T position of mark T (uppercase); when the mark is in
another file it cannot be used in a range another file it cannot be used in a range
/{pattern}[/] the next line where {pattern} matches *:/* /{pattern}[/] the next line where {pattern} matches *:/*
also see |:range-pattern| below
?{pattern}[?] the previous line where {pattern} matches *:?* ?{pattern}[?] the previous line where {pattern} matches *:?*
also see |:range-pattern| below
\/ the next line where the previously used search \/ the next line where the previously used search
pattern matches pattern matches
\? the previous line where the previously used search \? the previous line where the previously used search
@@ -744,11 +746,49 @@ Line numbers may be specified with: *:range* *{address}*
\& the next line where the previously used substitute \& the next line where the previously used substitute
pattern matches pattern matches
*:range-offset*
Each may be followed (several times) by '+' or '-' and an optional number. Each may be followed (several times) by '+' or '-' and an optional number.
This number is added or subtracted from the preceding line number. If the This number is added or subtracted from the preceding line number. If the
number is omitted, 1 is used. If there is nothing before the '+' or '-' then number is omitted, 1 is used. If there is nothing before the '+' or '-' then
the current line is used. the current line is used.
*:range-closed-fold*
When a line number after the comma is in a closed fold it is adjusted to the
last line of the fold, thus the whole fold is included.
When a number is added this is done after the adjustment to the last line of
the fold. This means these lines are additionally included in the range. For
example: >
:3,4+2print
On this text:
1 one ~
2 two ~
3 three ~
4 four FOLDED ~
5 five FOLDED ~
6 six ~
7 seven ~
8 eight ~
Where lines four and five are a closed fold, ends up printing lines 3 to 7.
The 7 comes from the "4" in the range, which is adjusted to the end of the
closed fold, which is 5, and then the offset 2 is added.
An example for subtracting (which isn't very useful): >
:2,4-1print
On this text:
1 one ~
2 two ~
3 three FOLDED~
4 four FOLDED ~
5 five FOLDED ~
6 six FOLDED ~
7 seven ~
8 eight ~
Where lines three to six are a closed fold, ends up printing lines 2 to 6.
The 6 comes from the "4" in the range, which is adjusted to the end of the
closed fold, which is 6, and then 1 is subtracted, then this is still in the
closed fold and the last line of that fold is used, which is 6.
*:range-pattern*
The "/" and "?" after {pattern} are required to separate the pattern from The "/" and "?" after {pattern} are required to separate the pattern from
anything that follows. anything that follows.

View File

@@ -4308,9 +4308,6 @@ get_address(
lnum = MAXLNUM; lnum = MAXLNUM;
do do
{ {
#ifdef FEAT_FOLDING
int base_char = *cmd;
#endif
switch (*cmd) switch (*cmd)
{ {
case '.': // '.' - Cursor position case '.': // '.' - Cursor position
@@ -4631,16 +4628,10 @@ get_address(
else else
{ {
#ifdef FEAT_FOLDING #ifdef FEAT_FOLDING
// Relative line addressing: need to adjust for closed folds // Relative line addressing: need to adjust for lines in a
// after the first address. // closed fold after the first address.
// Subtle difference: "number,+number" and "number,-number" if (addr_type == ADDR_LINES && (i == '-' || i == '+')
// adjusts to end of closed fold before adding/subtracting, && address_count >= 2)
// while "number,.+number" adjusts to end of closed fold after
// adding to make "!!" expanded into ".,.+N" work correctly.
int adjust_for_folding = addr_type == ADDR_LINES
&& (i == '-' || i == '+')
&& address_count >= 2;
if (adjust_for_folding && (i == '-' || base_char != '.'))
(void)hasFolding(lnum, NULL, &lnum); (void)hasFolding(lnum, NULL, &lnum);
#endif #endif
if (i == '-') if (i == '-')
@@ -4653,12 +4644,6 @@ get_address(
goto error; goto error;
} }
lnum += n; lnum += n;
#ifdef FEAT_FOLDING
// ".+number" rounds up to the end of a closed fold after
// adding, so that ":!!sort" sorts one closed fold.
if (adjust_for_folding && base_char == '.')
(void)hasFolding(lnum, NULL, &lnum);
#endif
} }
} }
} }

View File

@@ -3333,14 +3333,32 @@ op_colon(oparg_T *oap)
stuffcharReadbuff('.'); stuffcharReadbuff('.');
else else
stuffnumReadbuff((long)oap->start.lnum); stuffnumReadbuff((long)oap->start.lnum);
if (oap->end.lnum != oap->start.lnum)
#ifdef FEAT_FOLDING
// When using !! on a closed fold the range ".!" works best to operate
// on, it will be made the whole closed fold later.
linenr_T endOfStartFold = oap->start.lnum;
(void)hasFolding(oap->start.lnum, NULL, &endOfStartFold);
#endif
if (oap->end.lnum != oap->start.lnum
#ifdef FEAT_FOLDING
&& oap->end.lnum != endOfStartFold
#endif
)
{ {
// Make it a range with the end line.
stuffcharReadbuff(','); stuffcharReadbuff(',');
if (oap->end.lnum == curwin->w_cursor.lnum) if (oap->end.lnum == curwin->w_cursor.lnum)
stuffcharReadbuff('.'); stuffcharReadbuff('.');
else if (oap->end.lnum == curbuf->b_ml.ml_line_count) else if (oap->end.lnum == curbuf->b_ml.ml_line_count)
stuffcharReadbuff('$'); stuffcharReadbuff('$');
else if (oap->start.lnum == curwin->w_cursor.lnum) else if (oap->start.lnum == curwin->w_cursor.lnum
#ifdef FEAT_FOLDING
// do not use ".+number" for a closed fold, it would count
// folded lines twice
&& !hasFolding(oap->end.lnum, NULL, NULL)
#endif
)
{ {
stuffReadbuff((char_u *)".+"); stuffReadbuff((char_u *)".+");
stuffnumReadbuff((long)oap->line_count - 1); stuffnumReadbuff((long)oap->line_count - 1);

View File

@@ -72,6 +72,54 @@ func Test_address_fold()
quit! quit!
endfunc endfunc
func Test_address_offsets()
" check the help for :range-closed-fold
enew
call setline(1, [
\ '1 one',
\ '2 two',
\ '3 three',
\ '4 four FOLDED',
\ '5 five FOLDED',
\ '6 six',
\ '7 seven',
\ '8 eight',
\])
set foldmethod=manual
normal 4Gvjzf
3,4+2yank
call assert_equal([
\ '3 three',
\ '4 four FOLDED',
\ '5 five FOLDED',
\ '6 six',
\ '7 seven',
\ ], getreg(0,1,1))
enew!
call setline(1, [
\ '1 one',
\ '2 two',
\ '3 three FOLDED',
\ '4 four FOLDED',
\ '5 five FOLDED',
\ '6 six FOLDED',
\ '7 seven',
\ '8 eight',
\])
normal 3Gv3jzf
2,4-1yank
call assert_equal([
\ '2 two',
\ '3 three FOLDED',
\ '4 four FOLDED',
\ '5 five FOLDED',
\ '6 six FOLDED',
\ ], getreg(0,1,1))
bwipe!
endfunc
func Test_indent_fold() func Test_indent_fold()
new new
call setline(1, ['', 'a', ' b', ' c']) call setline(1, ['', 'a', ' b', ' c'])

View File

@@ -695,6 +695,8 @@ static char *(features[]) =
static int included_patches[] = static int included_patches[] =
{ /* Add new patch number below this line */ { /* Add new patch number below this line */
/**/
861,
/**/ /**/
860, 860,
/**/ /**/