mirror of
https://github.com/neovim/neovim.git
synced 2025-09-06 11:28:22 +00:00
feat(jumplist): allow opting out of removing unloaded buffers (#30419)
Problem: Cannot opt out of removing unloaded buffers from the jumplist. Solution: Only enable that with "clean" flag in 'jumpoptions'.
This commit is contained in:
@@ -3611,7 +3611,7 @@ A jump table for the options with a short description can be found at |Q_op|.
|
|||||||
Otherwise only one space is inserted.
|
Otherwise only one space is inserted.
|
||||||
|
|
||||||
*'jumpoptions'* *'jop'*
|
*'jumpoptions'* *'jop'*
|
||||||
'jumpoptions' 'jop' string (default "")
|
'jumpoptions' 'jop' string (default "clean")
|
||||||
global
|
global
|
||||||
List of words that change the behavior of the |jumplist|.
|
List of words that change the behavior of the |jumplist|.
|
||||||
stack Make the jumplist behave like the tagstack.
|
stack Make the jumplist behave like the tagstack.
|
||||||
@@ -3624,6 +3624,9 @@ A jump table for the options with a short description can be found at |Q_op|.
|
|||||||
|alternate-file| or using |mark-motions| try to
|
|alternate-file| or using |mark-motions| try to
|
||||||
restore the |mark-view| in which the action occurred.
|
restore the |mark-view| in which the action occurred.
|
||||||
|
|
||||||
|
clean Remove unloaded buffers from the jumplist.
|
||||||
|
EXPERIMENTAL: this flag may change in the future.
|
||||||
|
|
||||||
*'keymap'* *'kmp'*
|
*'keymap'* *'kmp'*
|
||||||
'keymap' 'kmp' string (default "")
|
'keymap' 'kmp' string (default "")
|
||||||
local to buffer
|
local to buffer
|
||||||
|
@@ -62,6 +62,7 @@ Defaults *nvim-defaults*
|
|||||||
- 'isfname' does not include ":" (on Windows). Drive letters are handled
|
- 'isfname' does not include ":" (on Windows). Drive letters are handled
|
||||||
correctly without it. (Use |gF| for filepaths suffixed with ":line:col").
|
correctly without it. (Use |gF| for filepaths suffixed with ":line:col").
|
||||||
- 'joinspaces' is disabled
|
- 'joinspaces' is disabled
|
||||||
|
- 'jumpoptions' defaults to "clean"
|
||||||
- 'langnoremap' is enabled
|
- 'langnoremap' is enabled
|
||||||
- 'langremap' is disabled
|
- 'langremap' is disabled
|
||||||
- 'laststatus' defaults to 2 (statusline is always shown)
|
- 'laststatus' defaults to 2 (statusline is always shown)
|
||||||
@@ -326,6 +327,7 @@ string options work.
|
|||||||
- 'inccommand' shows interactive results for |:substitute|-like commands
|
- 'inccommand' shows interactive results for |:substitute|-like commands
|
||||||
and |:command-preview| commands
|
and |:command-preview| commands
|
||||||
- 'jumpoptions' "view" tries to restore the |mark-view| when moving through
|
- 'jumpoptions' "view" tries to restore the |mark-view| when moving through
|
||||||
|
"clean" removes unloaded buffer from the jumplist
|
||||||
- the |jumplist|, |changelist|, |alternate-file| or using |mark-motions|.
|
- the |jumplist|, |changelist|, |alternate-file| or using |mark-motions|.
|
||||||
- 'laststatus' global statusline support
|
- 'laststatus' global statusline support
|
||||||
- 'mousescroll' amount to scroll by when scrolling with a mouse
|
- 'mousescroll' amount to scroll by when scrolling with a mouse
|
||||||
|
5
runtime/lua/vim/_meta/options.lua
generated
5
runtime/lua/vim/_meta/options.lua
generated
@@ -3541,8 +3541,11 @@ vim.go.js = vim.go.joinspaces
|
|||||||
--- |alternate-file` or using `mark-motions` try to
|
--- |alternate-file` or using `mark-motions` try to
|
||||||
--- restore the `mark-view` in which the action occurred.
|
--- restore the `mark-view` in which the action occurred.
|
||||||
---
|
---
|
||||||
|
--- clean Remove unloaded buffers from the jumplist.
|
||||||
|
--- EXPERIMENTAL: this flag may change in the future.
|
||||||
|
---
|
||||||
--- @type string
|
--- @type string
|
||||||
vim.o.jumpoptions = ""
|
vim.o.jumpoptions = "clean"
|
||||||
vim.o.jop = vim.o.jumpoptions
|
vim.o.jop = vim.o.jumpoptions
|
||||||
vim.go.jumpoptions = vim.o.jumpoptions
|
vim.go.jumpoptions = vim.o.jumpoptions
|
||||||
vim.go.jop = vim.go.jumpoptions
|
vim.go.jop = vim.go.jumpoptions
|
||||||
|
@@ -1395,8 +1395,10 @@ int do_buffer(int action, int start, int dir, int count, int forceit)
|
|||||||
|
|
||||||
// If the buffer to be deleted is not the current one, delete it here.
|
// If the buffer to be deleted is not the current one, delete it here.
|
||||||
if (buf != curbuf) {
|
if (buf != curbuf) {
|
||||||
// Remove the buffer to be deleted from the jump list.
|
if (jop_flags & JOP_CLEAN) {
|
||||||
buf_remove_from_jumplist(buf);
|
// Remove the buffer to be deleted from the jump list.
|
||||||
|
buf_remove_from_jumplist(buf);
|
||||||
|
}
|
||||||
|
|
||||||
close_windows(buf, false);
|
close_windows(buf, false);
|
||||||
|
|
||||||
@@ -1419,28 +1421,37 @@ int do_buffer(int action, int start, int dir, int count, int forceit)
|
|||||||
if (au_new_curbuf.br_buf != NULL && bufref_valid(&au_new_curbuf)) {
|
if (au_new_curbuf.br_buf != NULL && bufref_valid(&au_new_curbuf)) {
|
||||||
buf = au_new_curbuf.br_buf;
|
buf = au_new_curbuf.br_buf;
|
||||||
} else if (curwin->w_jumplistlen > 0) {
|
} else if (curwin->w_jumplistlen > 0) {
|
||||||
// Remove the current buffer from the jump list.
|
if (jop_flags & JOP_CLEAN) {
|
||||||
buf_remove_from_jumplist(curbuf);
|
// Remove the current buffer from the jump list.
|
||||||
|
buf_remove_from_jumplist(curbuf);
|
||||||
|
}
|
||||||
|
|
||||||
// It's possible that we removed all jump list entries, in that case we need to try another
|
// It's possible that we removed all jump list entries, in that case we need to try another
|
||||||
// approach
|
// approach
|
||||||
if (curwin->w_jumplistlen > 0) {
|
if (curwin->w_jumplistlen > 0) {
|
||||||
// If the index is the same as the length, the current position was not yet added to the jump
|
|
||||||
// list. So we can safely go back to the last entry and search from there.
|
|
||||||
if (curwin->w_jumplistidx == curwin->w_jumplistlen) {
|
|
||||||
curwin->w_jumplistidx = curwin->w_jumplistlen - 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
int jumpidx = curwin->w_jumplistidx;
|
int jumpidx = curwin->w_jumplistidx;
|
||||||
|
|
||||||
|
if (jop_flags & JOP_CLEAN) {
|
||||||
|
// If the index is the same as the length, the current position was not yet added to the
|
||||||
|
// jump list. So we can safely go back to the last entry and search from there.
|
||||||
|
if (jumpidx == curwin->w_jumplistlen) {
|
||||||
|
jumpidx = curwin->w_jumplistidx = curwin->w_jumplistlen - 1;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
jumpidx--;
|
||||||
|
if (jumpidx < 0) {
|
||||||
|
jumpidx = curwin->w_jumplistlen - 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
forward = jumpidx;
|
forward = jumpidx;
|
||||||
do {
|
while ((jop_flags & JOP_CLEAN) || jumpidx != curwin->w_jumplistidx) {
|
||||||
buf = buflist_findnr(curwin->w_jumplist[jumpidx].fmark.fnum);
|
buf = buflist_findnr(curwin->w_jumplist[jumpidx].fmark.fnum);
|
||||||
|
|
||||||
if (buf != NULL) {
|
if (buf != NULL) {
|
||||||
// Skip unlisted bufs. Also skip a quickfix
|
// Skip current and unlisted bufs. Also skip a quickfix
|
||||||
// buffer, it might be deleted soon.
|
// buffer, it might be deleted soon.
|
||||||
if (!buf->b_p_bl || bt_quickfix(buf)) {
|
if (buf == curbuf || !buf->b_p_bl || bt_quickfix(buf)) {
|
||||||
buf = NULL;
|
buf = NULL;
|
||||||
} else if (buf->b_ml.ml_mfp == NULL) {
|
} else if (buf->b_ml.ml_mfp == NULL) {
|
||||||
// skip unloaded buf, but may keep it for later
|
// skip unloaded buf, but may keep it for later
|
||||||
@@ -1451,8 +1462,10 @@ int do_buffer(int action, int start, int dir, int count, int forceit)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (buf != NULL) { // found a valid buffer: stop searching
|
if (buf != NULL) { // found a valid buffer: stop searching
|
||||||
curwin->w_jumplistidx = jumpidx;
|
if (jop_flags & JOP_CLEAN) {
|
||||||
update_jumplist = false;
|
curwin->w_jumplistidx = jumpidx;
|
||||||
|
update_jumplist = false;
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
// advance to older entry in jump list
|
// advance to older entry in jump list
|
||||||
@@ -1465,7 +1478,7 @@ int do_buffer(int action, int start, int dir, int count, int forceit)
|
|||||||
if (jumpidx == forward) { // List exhausted for sure
|
if (jumpidx == forward) { // List exhausted for sure
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
} while (jumpidx != curwin->w_jumplistidx);
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -3726,7 +3739,7 @@ void ex_buffer_all(exarg_T *eap)
|
|||||||
|
|
||||||
// Open the buffer in this window.
|
// Open the buffer in this window.
|
||||||
swap_exists_action = SEA_DIALOG;
|
swap_exists_action = SEA_DIALOG;
|
||||||
set_curbuf(buf, DOBUF_GOTO, false);
|
set_curbuf(buf, DOBUF_GOTO, !(jop_flags & JOP_CLEAN));
|
||||||
if (!bufref_valid(&bufref)) {
|
if (!bufref_valid(&bufref)) {
|
||||||
// Autocommands deleted the buffer.
|
// Autocommands deleted the buffer.
|
||||||
swap_exists_action = SEA_NONE;
|
swap_exists_action = SEA_NONE;
|
||||||
|
@@ -527,6 +527,7 @@ EXTERN char *p_jop; ///< 'jumpooptions'
|
|||||||
EXTERN unsigned jop_flags;
|
EXTERN unsigned jop_flags;
|
||||||
#define JOP_STACK 0x01
|
#define JOP_STACK 0x01
|
||||||
#define JOP_VIEW 0x02
|
#define JOP_VIEW 0x02
|
||||||
|
#define JOP_CLEAN 0x04
|
||||||
EXTERN char *p_keymap; ///< 'keymap'
|
EXTERN char *p_keymap; ///< 'keymap'
|
||||||
EXTERN char *p_kp; ///< 'keywordprg'
|
EXTERN char *p_kp; ///< 'keywordprg'
|
||||||
EXTERN char *p_km; ///< 'keymodel'
|
EXTERN char *p_km; ///< 'keymodel'
|
||||||
|
@@ -4484,7 +4484,7 @@ return {
|
|||||||
{
|
{
|
||||||
abbreviation = 'jop',
|
abbreviation = 'jop',
|
||||||
cb = 'did_set_jumpoptions',
|
cb = 'did_set_jumpoptions',
|
||||||
defaults = { if_true = '' },
|
defaults = { if_true = 'clean' },
|
||||||
deny_duplicates = true,
|
deny_duplicates = true,
|
||||||
desc = [=[
|
desc = [=[
|
||||||
List of words that change the behavior of the |jumplist|.
|
List of words that change the behavior of the |jumplist|.
|
||||||
@@ -4497,6 +4497,9 @@ return {
|
|||||||
view When moving through the jumplist, |changelist|,
|
view When moving through the jumplist, |changelist|,
|
||||||
|alternate-file| or using |mark-motions| try to
|
|alternate-file| or using |mark-motions| try to
|
||||||
restore the |mark-view| in which the action occurred.
|
restore the |mark-view| in which the action occurred.
|
||||||
|
|
||||||
|
clean Remove unloaded buffers from the jumplist.
|
||||||
|
EXPERIMENTAL: this flag may change in the future.
|
||||||
]=],
|
]=],
|
||||||
expand_cb = 'expand_set_jumpoptions',
|
expand_cb = 'expand_set_jumpoptions',
|
||||||
full_name = 'jumpoptions',
|
full_name = 'jumpoptions',
|
||||||
|
@@ -136,7 +136,7 @@ static char *(p_fdc_values[]) = { "auto", "auto:1", "auto:2", "auto:3", "auto:4"
|
|||||||
"5", "6", "7", "8", "9", NULL };
|
"5", "6", "7", "8", "9", NULL };
|
||||||
static char *(p_spo_values[]) = { "camel", "noplainbuffer", NULL };
|
static char *(p_spo_values[]) = { "camel", "noplainbuffer", NULL };
|
||||||
static char *(p_icm_values[]) = { "nosplit", "split", NULL };
|
static char *(p_icm_values[]) = { "nosplit", "split", NULL };
|
||||||
static char *(p_jop_values[]) = { "stack", "view", NULL };
|
static char *(p_jop_values[]) = { "stack", "view", "clean", NULL };
|
||||||
static char *(p_tpf_values[]) = { "BS", "HT", "FF", "ESC", "DEL", "C0", "C1", NULL };
|
static char *(p_tpf_values[]) = { "BS", "HT", "FF", "ESC", "DEL", "C0", "C1", NULL };
|
||||||
static char *(p_rdb_values[]) = { "compositor", "nothrottle", "invalid", "nodelta", "line",
|
static char *(p_rdb_values[]) = { "compositor", "nothrottle", "invalid", "nodelta", "line",
|
||||||
"flush", NULL };
|
"flush", NULL };
|
||||||
|
@@ -194,7 +194,7 @@ describe("jumpoptions=stack behaves like 'tagstack'", function()
|
|||||||
end)
|
end)
|
||||||
end)
|
end)
|
||||||
|
|
||||||
describe('buffer deletion', function()
|
describe('buffer deletion with jumpoptions+=clean', function()
|
||||||
local base_file = 'Xtest-functional-buffer-deletion'
|
local base_file = 'Xtest-functional-buffer-deletion'
|
||||||
local file1 = base_file .. '1'
|
local file1 = base_file .. '1'
|
||||||
local file2 = base_file .. '2'
|
local file2 = base_file .. '2'
|
||||||
@@ -227,6 +227,12 @@ describe('buffer deletion', function()
|
|||||||
command('edit ' .. file3)
|
command('edit ' .. file3)
|
||||||
end)
|
end)
|
||||||
|
|
||||||
|
after_each(function()
|
||||||
|
os.remove(file1)
|
||||||
|
os.remove(file2)
|
||||||
|
os.remove(file3)
|
||||||
|
end)
|
||||||
|
|
||||||
it('deletes jump list entries when the current buffer is deleted', function()
|
it('deletes jump list entries when the current buffer is deleted', function()
|
||||||
command('edit ' .. file1)
|
command('edit ' .. file1)
|
||||||
|
|
||||||
@@ -319,6 +325,44 @@ describe('buffer deletion', function()
|
|||||||
end)
|
end)
|
||||||
end)
|
end)
|
||||||
|
|
||||||
|
describe('buffer deletion with jumpoptions-=clean', function()
|
||||||
|
local base_file = 'Xtest-functional-buffer-deletion'
|
||||||
|
local file1 = base_file .. '1'
|
||||||
|
local file2 = base_file .. '2'
|
||||||
|
local base_content = 'text'
|
||||||
|
local content1 = base_content .. '1'
|
||||||
|
local content2 = base_content .. '2'
|
||||||
|
|
||||||
|
before_each(function()
|
||||||
|
clear()
|
||||||
|
command('clearjumps')
|
||||||
|
command('set jumpoptions-=clean')
|
||||||
|
|
||||||
|
write_file(file1, content1, false, false)
|
||||||
|
write_file(file2, content2, false, false)
|
||||||
|
|
||||||
|
command('edit ' .. file1)
|
||||||
|
command('edit ' .. file2)
|
||||||
|
end)
|
||||||
|
|
||||||
|
after_each(function()
|
||||||
|
os.remove(file1)
|
||||||
|
os.remove(file2)
|
||||||
|
end)
|
||||||
|
|
||||||
|
it('Ctrl-O reopens previous buffer with :bunload or :bdelete #28968', function()
|
||||||
|
eq(file2, fn.bufname(''))
|
||||||
|
command('bunload')
|
||||||
|
eq(file1, fn.bufname(''))
|
||||||
|
feed('<C-O>')
|
||||||
|
eq(file2, fn.bufname(''))
|
||||||
|
command('bdelete')
|
||||||
|
eq(file1, fn.bufname(''))
|
||||||
|
feed('<C-O>')
|
||||||
|
eq(file2, fn.bufname(''))
|
||||||
|
end)
|
||||||
|
end)
|
||||||
|
|
||||||
describe('jumpoptions=view', function()
|
describe('jumpoptions=view', function()
|
||||||
local file1 = 'Xtestfile-functional-editor-jumps'
|
local file1 = 'Xtestfile-functional-editor-jumps'
|
||||||
local file2 = 'Xtestfile-functional-editor-jumps-2'
|
local file2 = 'Xtestfile-functional-editor-jumps-2'
|
||||||
|
@@ -13,6 +13,7 @@ if exists('s:did_load')
|
|||||||
set laststatus=1
|
set laststatus=1
|
||||||
set listchars=eol:$
|
set listchars=eol:$
|
||||||
set joinspaces
|
set joinspaces
|
||||||
|
set jumpoptions=
|
||||||
set mousemodel=extend
|
set mousemodel=extend
|
||||||
set nohidden nosmarttab noautoindent noautoread noruler noshowcmd
|
set nohidden nosmarttab noautoindent noautoread noruler noshowcmd
|
||||||
set nohlsearch noincsearch
|
set nohlsearch noincsearch
|
||||||
|
Reference in New Issue
Block a user