mirror of
https://github.com/neovim/neovim
synced 2025-07-15 16:51:49 +00:00
vim-patch:9.1.1473: inconsistent range arg for :diffget/diffput (#34588)
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: vim/vim#17579
d75ab0cbf5
Co-authored-by: Yee Cheng Chin <ychin.git@gmail.com>
This commit is contained in:
@ -292,18 +292,20 @@ that the buffers will be equal within the specified range.
|
||||
|
||||
|
||||
When no [range] is given, the diff at the cursor position or just above it is
|
||||
affected. When [range] is used, Vim tries to only put or get the specified
|
||||
lines. When there are deleted lines, this may not always be possible.
|
||||
affected. There can be deleted lines below the last line of the buffer. When
|
||||
the cursor is on the last line in the buffer and there is no diff above this
|
||||
line, and no [range] is given, the diff below the cursor position will be used
|
||||
instead.
|
||||
|
||||
There can be deleted lines below the last line of the buffer. When the cursor
|
||||
is on the last line in the buffer and there is no diff above this line, the
|
||||
":diffget" and "do" commands will obtain lines from the other buffer.
|
||||
When [range] is used, Vim tries to only put or get the specified lines. When
|
||||
there are deleted lines, they will be used if they are between the lines
|
||||
specified by [range].
|
||||
|
||||
To be able to get those lines from another buffer in a [range] it's allowed to
|
||||
use the last line number plus one. This command gets all diffs from the other
|
||||
buffer: >
|
||||
To be able to put or get those lines to/from another buffer in a [range] it's
|
||||
allowed to use 0 and the last line number plus one. This command gets all
|
||||
diffs from the other buffer: >
|
||||
|
||||
:1,$+1diffget
|
||||
:0,$+1diffget
|
||||
|
||||
Note that deleted lines are displayed, but not counted as text lines. You
|
||||
can't move the cursor into them. To fill the deleted lines with the lines
|
||||
|
@ -3492,10 +3492,13 @@ void ex_diffgetput(exarg_T *eap)
|
||||
if (eap->addr_count == 0) {
|
||||
// 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--;
|
||||
|
@ -752,7 +752,7 @@ M.cmds = {
|
||||
},
|
||||
{
|
||||
command = 'diffget',
|
||||
flags = bit.bor(RANGE, EXTRA, TRLBAR, MODIFY),
|
||||
flags = bit.bor(RANGE, ZEROR, EXTRA, TRLBAR, MODIFY),
|
||||
addr_type = 'ADDR_LINES',
|
||||
func = 'ex_diffgetput',
|
||||
},
|
||||
@ -770,7 +770,7 @@ M.cmds = {
|
||||
},
|
||||
{
|
||||
command = 'diffput',
|
||||
flags = bit.bor(RANGE, EXTRA, TRLBAR),
|
||||
flags = bit.bor(RANGE, ZEROR, EXTRA, TRLBAR),
|
||||
addr_type = 'ADDR_LINES',
|
||||
func = 'ex_diffgetput',
|
||||
},
|
||||
|
@ -3728,8 +3728,9 @@ char *invalid_range(exarg_T *eap)
|
||||
if (eap->argt & EX_RANGE) {
|
||||
switch (eap->addr_type) {
|
||||
case ADDR_LINES:
|
||||
if (eap->line2 > (curbuf->b_ml.ml_line_count
|
||||
+ (eap->cmdidx == CMD_diffget))) {
|
||||
if (eap->line2 >
|
||||
(curbuf->b_ml.ml_line_count
|
||||
+ (eap->cmdidx == CMD_diffget || eap->cmdidx == CMD_diffput))) {
|
||||
return _(e_invrange);
|
||||
}
|
||||
break;
|
||||
|
@ -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 _
|
||||
|
Reference in New Issue
Block a user