forked from aniani/vim
patch 9.0.1921: not possible to use the jumplist like a stack
Problem: not possible to use the jumplist like a stack Solution: Add the 'jumpoptions' setting to make the jumplist a stack. Add an option for using jumplist like tag stack related: #7738 closes: #13134 ported from NeoVim: - https://neovim.io/doc/user/motion.html#jumplist-stack - neovim/neovim@39094b3 - neovim/neovim#11530 - https://vi.stackexchange.com/questions/18344/how-to-change-jumplist-behavior Based on the feedback in the previous PR, it looks like many people like this option. Signed-off-by: Christian Brabandt <cb@256bit.org> Co-authored-by: Yegappan Lakshmanan <yegappan@yahoo.com> Co-authored-by: butwerenotthereyet <58348703+butwerenotthereyet@users.noreply.github.com>
This commit is contained in:
parent
98e68c07ce
commit
87018255e3
@ -1135,7 +1135,46 @@ When you split a window, the jumplist will be copied to the new window.
|
||||
If you have included the ' item in the 'viminfo' option the jumplist will be
|
||||
stored in the viminfo file and restored when starting Vim.
|
||||
|
||||
*jumplist-stack*
|
||||
When 'jumpoptions' option includes "stack", the jumplist behaves like the tag
|
||||
stack. When jumping to a new location from the middle of the jumplist, the
|
||||
locations after the current position will be discarded. With this option set
|
||||
you can move through a tree of jump locations. When going back up a branch and
|
||||
then down another branch, CTRL-O still takes you further up the tree.
|
||||
|
||||
Given a jumplist like the following in which CTRL-O has been used to move back
|
||||
three times to location X: >
|
||||
|
||||
jump line col file/text
|
||||
2 1260 8 mark.c <-- location X-2
|
||||
1 685 0 eval.c <-- location X-1
|
||||
> 0 462 36 eval.c <-- location X
|
||||
1 479 39 eval.c
|
||||
2 213 2 mark.c
|
||||
3 181 0 mark.c
|
||||
<
|
||||
jumping to (new) location Y results in the locations after the current
|
||||
locations being removed: >
|
||||
|
||||
jump line col file/text
|
||||
3 1260 8 mark.c <-- location X-2
|
||||
2 685 0 eval.c <-- location X-1
|
||||
1 462 36 eval.c <-- location X
|
||||
>
|
||||
<
|
||||
|
||||
Then, when yet another location Z is jumped to, the new location Y appears
|
||||
directly after location X in the jumplist and location X remains in the same
|
||||
position relative to the locations (X-1, X-2, etc., ...) that had been before
|
||||
it prior to the original jump from X to Y: >
|
||||
|
||||
jump line col file/text
|
||||
4 1260 8 mark.c <-- location X-2
|
||||
3 685 0 eval.c <-- location X-1
|
||||
2 462 36 eval.c <-- location X
|
||||
1 100 0 buffer.c <-- location Y
|
||||
>
|
||||
<
|
||||
CHANGE LIST JUMPS *changelist* *change-list-jumps* *E664*
|
||||
|
||||
When making a change the cursor position is remembered. One position is
|
||||
|
@ -4899,6 +4899,16 @@ A jump table for the options with a short description can be found at |Q_op|.
|
||||
Otherwise only one space is inserted.
|
||||
NOTE: This option is set when 'compatible' is set.
|
||||
|
||||
*'jumpoptions'* *'jop'*
|
||||
'jumpoptions' 'jop' string (default "")
|
||||
global
|
||||
List of words that change the behavior of the |jumplist|.
|
||||
stack Make the jumplist behave like the tagstack.
|
||||
Relative location of entries in the jumplist is
|
||||
preserved at the cost of discarding subsequent entries
|
||||
when navigating backwards in the jumplist and then
|
||||
jumping to a location. |jumplist-stack|
|
||||
|
||||
*'key'*
|
||||
'key' string (default "")
|
||||
local to buffer
|
||||
|
@ -772,6 +772,7 @@ Short explanation of each option: *option-list*
|
||||
'iskeyword' 'isk' characters included in keywords
|
||||
'isprint' 'isp' printable characters
|
||||
'joinspaces' 'js' two spaces after a period with a join command
|
||||
'jumpoptions' 'jop' specifies how jumping is done
|
||||
'key' encryption key
|
||||
'keymap' 'kmp' name of a keyboard mapping
|
||||
'keymodel' 'km' enable starting/stopping selection with keys
|
||||
|
@ -433,7 +433,9 @@ $quote eval.txt /*$quote*
|
||||
'isp' options.txt /*'isp'*
|
||||
'isprint' options.txt /*'isprint'*
|
||||
'joinspaces' options.txt /*'joinspaces'*
|
||||
'jop' options.txt /*'jop'*
|
||||
'js' options.txt /*'js'*
|
||||
'jumpoptions' options.txt /*'jumpoptions'*
|
||||
'key' options.txt /*'key'*
|
||||
'keymap' options.txt /*'keymap'*
|
||||
'keymodel' options.txt /*'keymodel'*
|
||||
@ -8300,6 +8302,7 @@ json_encode() builtin.txt /*json_encode()*
|
||||
jtags tagsrch.txt /*jtags*
|
||||
jump-motions motion.txt /*jump-motions*
|
||||
jumplist motion.txt /*jumplist*
|
||||
jumplist-stack motion.txt /*jumplist-stack*
|
||||
jumpto-diffs diff.txt /*jumpto-diffs*
|
||||
k motion.txt /*k*
|
||||
kcc uganda.txt /*kcc*
|
||||
|
25
src/mark.c
25
src/mark.c
@ -146,6 +146,16 @@ setpcmark(void)
|
||||
curwin->w_prev_pcmark = curwin->w_pcmark;
|
||||
curwin->w_pcmark = curwin->w_cursor;
|
||||
|
||||
if (jop_flags & JOP_STACK)
|
||||
{
|
||||
// jumpoptions=stack: if we're somewhere in the middle of the jumplist
|
||||
// discard everything after the current index.
|
||||
if (curwin->w_jumplistidx < curwin->w_jumplistlen - 1)
|
||||
// Discard the rest of the jumplist by cutting the length down to
|
||||
// contain nothing beyond the current index.
|
||||
curwin->w_jumplistlen = curwin->w_jumplistidx + 1;
|
||||
}
|
||||
|
||||
// If jumplist is full: remove oldest entry
|
||||
if (++curwin->w_jumplistlen > JUMPLISTSIZE)
|
||||
{
|
||||
@ -1288,6 +1298,7 @@ cleanup_jumplist(win_T *wp, int loadfiles)
|
||||
{
|
||||
int i;
|
||||
int from, to;
|
||||
int mustfree;
|
||||
|
||||
if (loadfiles)
|
||||
{
|
||||
@ -1314,10 +1325,18 @@ cleanup_jumplist(win_T *wp, int loadfiles)
|
||||
&& wp->w_jumplist[i].fmark.mark.lnum
|
||||
== wp->w_jumplist[from].fmark.mark.lnum)
|
||||
break;
|
||||
if (i >= wp->w_jumplistlen) // no duplicate
|
||||
wp->w_jumplist[to++] = wp->w_jumplist[from];
|
||||
else
|
||||
if (i >= wp->w_jumplistlen) // not duplicate
|
||||
mustfree = FALSE;
|
||||
else if (i > from + 1) // non-adjacent duplicate
|
||||
// jumpoptions=stack: remove duplicates only when adjacent.
|
||||
mustfree = !(jop_flags & JOP_STACK);
|
||||
else // adjacent duplicate
|
||||
mustfree = TRUE;
|
||||
|
||||
if (mustfree)
|
||||
vim_free(wp->w_jumplist[from].fname);
|
||||
else
|
||||
wp->w_jumplist[to++] = wp->w_jumplist[from];
|
||||
}
|
||||
if (wp->w_jumplistidx == wp->w_jumplistlen)
|
||||
wp->w_jumplistidx = to;
|
||||
|
@ -601,6 +601,9 @@ EXTERN char_u *p_fp; // 'formatprg'
|
||||
EXTERN int p_fs; // 'fsync'
|
||||
#endif
|
||||
EXTERN int p_gd; // 'gdefault'
|
||||
EXTERN char_u *p_jop; // 'jumpoptions'
|
||||
EXTERN unsigned jop_flags; //
|
||||
#define JOP_STACK 0x001
|
||||
#ifdef FEAT_PROP_POPUP
|
||||
# ifdef FEAT_QUICKFIX
|
||||
EXTERN char_u *p_cpp; // 'completepopup'
|
||||
|
@ -1459,6 +1459,9 @@ static struct vimoption options[] =
|
||||
{"joinspaces", "js", P_BOOL|P_VI_DEF|P_VIM,
|
||||
(char_u *)&p_js, PV_NONE, NULL,
|
||||
{(char_u *)TRUE, (char_u *)0L} SCTX_INIT},
|
||||
{"jumpoptions", "jop", P_STRING|P_VI_DEF|P_VIM|P_ONECOMMA|P_NODUP,
|
||||
(char_u *)&p_jop, PV_NONE, did_set_jumpoptions,
|
||||
{(char_u *)"", (char_u *)0L} SCTX_INIT},
|
||||
{"key", NULL, P_STRING|P_ALLOCED|P_VI_DEF|P_NO_MKRC,
|
||||
#ifdef FEAT_CRYPT
|
||||
(char_u *)&p_key, PV_KEY, did_set_cryptkey,
|
||||
|
@ -35,6 +35,7 @@ static char *(p_cm_values[]) = {"zip", "blowfish", "blowfish2",
|
||||
#endif
|
||||
static char *(p_cmp_values[]) = {"internal", "keepascii", NULL};
|
||||
static char *(p_dy_values[]) = {"lastline", "truncate", "uhex", NULL};
|
||||
static char *(p_jop_values[]) = {"stack", NULL};
|
||||
#ifdef FEAT_FOLDING
|
||||
static char *(p_fdo_values[]) = {"all", "block", "hor", "mark", "percent",
|
||||
"quickfix", "search", "tag", "insert",
|
||||
@ -120,6 +121,7 @@ didset_string_options(void)
|
||||
(void)opt_strings_flags(p_fdo, p_fdo_values, &fdo_flags, TRUE);
|
||||
#endif
|
||||
(void)opt_strings_flags(p_dy, p_dy_values, &dy_flags, TRUE);
|
||||
(void)opt_strings_flags(p_jop, p_jop_values, &jop_flags, TRUE);
|
||||
(void)opt_strings_flags(p_tc, p_tc_values, &tc_flags, FALSE);
|
||||
(void)opt_strings_flags(p_ve, p_ve_values, &ve_flags, TRUE);
|
||||
#if defined(UNIX) || defined(VMS)
|
||||
@ -1852,6 +1854,18 @@ did_set_isopt(optset_T *args)
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/*
|
||||
* The 'jumpoptions' option is changed.
|
||||
*/
|
||||
char *
|
||||
did_set_jumpoptions(optset_T *args)
|
||||
{
|
||||
if (opt_strings_flags(p_jop, p_jop_values, &jop_flags, TRUE) != OK)
|
||||
return e_invalid_argument;
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
#if defined(FEAT_KEYMAP) || defined(PROTO)
|
||||
/*
|
||||
* The 'keymap' option is changed.
|
||||
|
@ -64,6 +64,7 @@ char *did_set_highlight(optset_T *args);
|
||||
char *did_set_iconstring(optset_T *args);
|
||||
char *did_set_imactivatekey(optset_T *args);
|
||||
char *did_set_isopt(optset_T *args);
|
||||
char *did_set_jumpoptions(optset_T *args);
|
||||
char *did_set_keymap(optset_T *args);
|
||||
char *did_set_keymodel(optset_T *args);
|
||||
char *did_set_keyprotocol(optset_T *args);
|
||||
|
@ -112,6 +112,7 @@ let test_values = {
|
||||
\ 'isident': [['', '@', '@,48-52'], ['xxx', '@48']],
|
||||
\ 'iskeyword': [['', '@', '@,48-52'], ['xxx', '@48']],
|
||||
\ 'isprint': [['', '@', '@,48-52'], ['xxx', '@48']],
|
||||
\ 'jumpoptions': [['', 'stack'], ['xxx']],
|
||||
\ 'keymap': [['', 'accents'], ['xxx']],
|
||||
\ 'keymodel': [['', 'startsel', 'startsel,stopsel'], ['xxx']],
|
||||
\ 'keyprotocol': [['', 'xxx:none', 'yyy:mok2', 'zzz:kitty'],
|
||||
|
@ -98,4 +98,68 @@ d
|
||||
bwipe!
|
||||
endfunc
|
||||
|
||||
" Test for 'jumpoptions'
|
||||
func Test_jumpoptions()
|
||||
new
|
||||
call setline(1, range(1, 200))
|
||||
clearjumps
|
||||
set jumpoptions=stack
|
||||
|
||||
" Jump around to add some locations to the jump list.
|
||||
normal 10G
|
||||
normal 20G
|
||||
normal 30G
|
||||
normal 40G
|
||||
normal 50G
|
||||
let bnr = bufnr()
|
||||
|
||||
" discards the tail when navigating from the middle
|
||||
exe "normal \<C-O>\<C-O>"
|
||||
call assert_equal([
|
||||
\ [{'lnum': 1, 'bufnr': bnr, 'col': 0, 'coladd': 0},
|
||||
\ {'lnum': 10, 'bufnr': bnr, 'col': 0, 'coladd': 0},
|
||||
\ {'lnum': 20, 'bufnr': bnr, 'col': 0, 'coladd': 0},
|
||||
\ {'lnum': 30, 'bufnr': bnr, 'col': 0, 'coladd': 0},
|
||||
\ {'lnum': 40, 'bufnr': bnr, 'col': 0, 'coladd': 0},
|
||||
\ {'lnum': 50, 'bufnr': bnr, 'col': 0, 'coladd': 0}
|
||||
\ ], 3], getjumplist())
|
||||
|
||||
" new jump location is added immediately after the last one
|
||||
normal 90G
|
||||
call assert_equal([
|
||||
\ [{'lnum': 1, 'bufnr': bnr, 'col': 0, 'coladd': 0},
|
||||
\ {'lnum': 10, 'bufnr': bnr, 'col': 0, 'coladd': 0},
|
||||
\ {'lnum': 20, 'bufnr': bnr, 'col': 0, 'coladd': 0},
|
||||
\ {'lnum': 30, 'bufnr': bnr, 'col': 0, 'coladd': 0},
|
||||
\ ], 4], getjumplist())
|
||||
|
||||
" does not add the same location twice adjacently
|
||||
normal 60G
|
||||
normal 60G
|
||||
call assert_equal([
|
||||
\ [{'lnum': 1, 'bufnr': bnr, 'col': 0, 'coladd': 0},
|
||||
\ {'lnum': 10, 'bufnr': bnr, 'col': 0, 'coladd': 0},
|
||||
\ {'lnum': 20, 'bufnr': bnr, 'col': 0, 'coladd': 0},
|
||||
\ {'lnum': 30, 'bufnr': bnr, 'col': 0, 'coladd': 0},
|
||||
\ {'lnum': 90, 'bufnr': bnr, 'col': 0, 'coladd': 0},
|
||||
\ {'lnum': 60, 'bufnr': bnr, 'col': 0, 'coladd': 0},
|
||||
\ ], 6], getjumplist())
|
||||
|
||||
" does add the same location twice non adjacently
|
||||
normal 10G
|
||||
normal 20G
|
||||
call assert_equal([
|
||||
\ [{'lnum': 1, 'bufnr': bnr, 'col': 0, 'coladd': 0},
|
||||
\ {'lnum': 10, 'bufnr': bnr, 'col': 0, 'coladd': 0},
|
||||
\ {'lnum': 20, 'bufnr': bnr, 'col': 0, 'coladd': 0},
|
||||
\ {'lnum': 30, 'bufnr': bnr, 'col': 0, 'coladd': 0},
|
||||
\ {'lnum': 90, 'bufnr': bnr, 'col': 0, 'coladd': 0},
|
||||
\ {'lnum': 60, 'bufnr': bnr, 'col': 0, 'coladd': 0},
|
||||
\ {'lnum': 10, 'bufnr': bnr, 'col': 0, 'coladd': 0},
|
||||
\ ], 7], getjumplist())
|
||||
|
||||
set jumpoptions&
|
||||
%bw!
|
||||
endfunc
|
||||
|
||||
" vim: shiftwidth=2 sts=2 expandtab
|
||||
|
@ -699,6 +699,8 @@ static char *(features[]) =
|
||||
|
||||
static int included_patches[] =
|
||||
{ /* Add new patch number below this line */
|
||||
/**/
|
||||
1921,
|
||||
/**/
|
||||
1920,
|
||||
/**/
|
||||
|
Loading…
x
Reference in New Issue
Block a user