0
0
mirror of https://github.com/vim/vim.git synced 2025-09-26 04:04:07 -04:00

patch 9.1.1473: inconsistent range arg for :diffget/diffput

Problem:  inconsistent range arg for :diffget/diffput
Solution: fix the range specification, place the cursor for :diffput and
          :diffget consistently on the last line (Yee Cheng Chin)

Previously, `:<range>diffget` only allowed using 1 or above in the range
value, making it impossible to use the command for a diff block at the
beginning of the file. Fix the range specification so the user can now
use 0 to specify the space before the first line. This allows
`:0,$+1diffget` to work to retrieve all the changes from the other file
instead of missing the first diff block. Also do this for `:diffput`.

Also, make `:diffput` work more similar to `:diffget`. Make it so that
if the cursor is on the last line and a new line is inserted in the
other file, doing `:diffput` will select that diff block below the line,
just like `:diffget` would.

Also clean up the logic a little bit for edge cases and for handling
line matched diff blocks better.

closes: #17579

Signed-off-by: Yee Cheng Chin <ychin.git@gmail.com>
Signed-off-by: Christian Brabandt <cb@256bit.org>
This commit is contained in:
Yee Cheng Chin
2025-06-20 18:44:18 +02:00
committed by Christian Brabandt
parent 476b65ebac
commit d75ab0cbf5
6 changed files with 82 additions and 17 deletions

View File

@@ -3874,10 +3874,13 @@ ex_diffgetput(exarg_T *eap)
{
// Make it possible that ":diffget" on the last line gets line below
// the cursor line when there is no difference above the cursor.
if (eap->cmdidx == CMD_diffget
&& eap->line1 == curbuf->b_ml.ml_line_count
&& diff_check(curwin, eap->line1) == 0
&& (eap->line1 == 1 || diff_check(curwin, eap->line1 - 1) == 0))
int linestatus = 0;
if (eap->line1 == curbuf->b_ml.ml_line_count
&& (diff_check_with_linestatus(curwin, eap->line1, &linestatus) == 0
&& linestatus == 0)
&& (eap->line1 == 1 ||
(diff_check_with_linestatus(curwin, eap->line1 - 1, &linestatus) >= 0
&& linestatus == 0)))
++eap->line2;
else if (eap->line1 > 0)
--eap->line1;

View File

@@ -486,7 +486,7 @@ EXCMD(CMD_diffupdate, "diffupdate", ex_diffupdate,
EX_BANG|EX_TRLBAR,
ADDR_NONE),
EXCMD(CMD_diffget, "diffget", ex_diffgetput,
EX_RANGE|EX_EXTRA|EX_TRLBAR|EX_MODIFY,
EX_RANGE|EX_ZEROR|EX_EXTRA|EX_TRLBAR|EX_MODIFY,
ADDR_LINES),
EXCMD(CMD_diffoff, "diffoff", ex_diffoff,
EX_BANG|EX_TRLBAR,
@@ -495,7 +495,7 @@ EXCMD(CMD_diffpatch, "diffpatch", ex_diffpatch,
EX_EXTRA|EX_FILE1|EX_TRLBAR|EX_MODIFY,
ADDR_NONE),
EXCMD(CMD_diffput, "diffput", ex_diffgetput,
EX_RANGE|EX_EXTRA|EX_TRLBAR,
EX_RANGE|EX_ZEROR|EX_EXTRA|EX_TRLBAR,
ADDR_LINES),
EXCMD(CMD_diffsplit, "diffsplit", ex_diffsplit,
EX_EXTRA|EX_FILE1|EX_TRLBAR,

View File

@@ -4850,7 +4850,8 @@ invalid_range(exarg_T *eap)
case ADDR_LINES:
if (eap->line2 > curbuf->b_ml.ml_line_count
#ifdef FEAT_DIFF
+ (eap->cmdidx == CMD_diffget)
+ (eap->cmdidx == CMD_diffget ||
eap->cmdidx == CMD_diffput)
#endif
)
return _(e_invalid_range);

View File

@@ -288,6 +288,63 @@ func Test_diffget_diffput_range()
%bw!
endfunc
" Test :diffget/:diffput handling of added/deleted lines
func Test_diffget_diffput_deleted_lines()
call setline(1, ['2','4','6'])
diffthis
new
call setline(1, range(1,7))
diffthis
wincmd w
3,3diffget " get nothing
call assert_equal(['2', '4', '6'], getline(1, '$'))
3,4diffget " get the last insertion past the end of file
call assert_equal(['2', '4', '6', '7'], getline(1, '$'))
0,1diffget " get the first insertion above first line
call assert_equal(['1', '2', '4', '6', '7'], getline(1, '$'))
" When using non-range diffget on the last line, it should get the
" change above or at the line as usual, but if the only change is below the
" last line, diffget should get that instead.
1,$delete
call setline(1, ['2','4','6'])
diffupdate
norm Gdo
call assert_equal(['2', '4', '5', '6'], getline(1, '$'))
norm Gdo
call assert_equal(['2', '4', '5', '6', '7'], getline(1, '$'))
" Test non-range diffput on last line with the same logic
1,$delete
call setline(1, ['2','4','6'])
diffupdate
norm Gdp
wincmd w
call assert_equal(['1', '2', '3', '4', '6', '7'], getline(1, '$'))
wincmd w
norm Gdp
wincmd w
call assert_equal(['1', '2', '3', '4', '6'], getline(1, '$'))
call setline(1, range(1,7))
diffupdate
wincmd w
" Test that 0,$+1 will get/put all changes from/to the other buffer
1,$delete
call setline(1, ['2','4','6'])
diffupdate
0,$+1diffget
call assert_equal(['1', '2', '3', '4', '5', '6', '7'], getline(1, '$'))
1,$delete
call setline(1, ['2','4','6'])
diffupdate
0,$+1diffput
wincmd w
call assert_equal(['2', '4', '6'], getline(1, '$'))
%bw!
endfunc
" Test for :diffget/:diffput with an empty buffer and a non-empty buffer
func Test_diffget_diffput_empty_buffer()
%d _

View File

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