Problem: Too many #ifdefs.
Solution: Graduate the jumplist feature.
*CTRL-O*
CTRL-O Go to [count] Older cursor position in jump list
(not a motion command).
- {not available without the |+jumplist| feature}
<Tab> or *CTRL-I* *<Tab>*
CTRL-I Go to [count] newer cursor position in jump list
(not a motion command).
- {not available without the |+jumplist| feature}
NOTE: In the GUI and in a terminal supporting
|modifyOtherKeys|, CTRL-I can be mapped separately
*:ju* *:jumps*
:ju[mps] Print the jump list (not a motion command).
- {not available without the |+jumplist| feature}
*:cle* *:clearjumps*
:cle[arjumps] Clear the jump list of the current window.
- {not available without the |+jumplist| feature}
*jumplist*
Jumps are remembered in a jump list. With the CTRL-O and CTRL-I command you
can go to cursor positions before older jumps, and back again. Thus you can
move up and down the list. There is a separate jump list for each window.
The maximum number of entries is fixed at 100.
-{not available without the |+jumplist| feature}
For example, after three jump commands you have this jump list:
positions go to the oldest change.
If there is no older change an error message is given.
(not a motion command)
- {not available without the |+jumplist| feature}
*g,* *E663*
g, Go to [count] newer cursor position in change list.
Just like |g;| but in the opposite direction.
(not a motion command)
- {not available without the |+jumplist| feature}
When using a count you jump as far back or forward as possible. Thus you can
use "999g;" to go to the first change for which the position is still
T *+insert_expand* |insert_expand| Insert mode completion
m *+ipv6* Support for IPv6 networking |channel|
m *+job* starting and stopping jobs |job|
-S *+jumplist* |jumplist|
+T *+jumplist* |jumplist|; Always enabled since 8.2.3795
B *+keymap* |'keymap'|
N *+lambda* |lambda| and |closure|
B *+langmap* |'langmap'|
bp = NULL; // used when no loaded buffer found
if (au_new_curbuf.br_buf != NULL && bufref_valid(&au_new_curbuf))
buf = au_new_curbuf.br_buf;
-#ifdef FEAT_JUMPLIST
else if (curwin->w_jumplistlen > 0)
{
int jumpidx;
break;
}
}
-#endif
if (buf == NULL) // No previous buffer, Try 2'nd approach
{
win_T *wp;
tabpage_T *tp;
int i;
-#ifdef FEAT_JUMPLIST
int cols;
pos_T *p;
int add;
-#endif
// mark the buffer as modified
changed();
curbuf->b_last_change.lnum = lnum;
curbuf->b_last_change.col = col;
-#ifdef FEAT_JUMPLIST
// Create a new entry if a new undo-able change was started or we
// don't have an entry yet.
if (curbuf->b_new_change || curbuf->b_changelistlen == 0)
// The current window is always after the last change, so that "g,"
// takes you back to it.
curwin->w_changelistidx = curbuf->b_changelistlen;
-#endif
}
FOR_ALL_TAB_WINDOWS(tp, wp)
static void
f_getchangelist(typval_T *argvars, typval_T *rettv)
{
-#ifdef FEAT_JUMPLIST
buf_T *buf;
int i;
list_T *l;
dict_T *d;
-#endif
if (rettv_list_alloc(rettv) != OK)
return;
if (in_vim9script() && check_for_opt_buffer_arg(argvars, 0) == FAIL)
return;
-#ifdef FEAT_JUMPLIST
if (argvars[0].v_type == VAR_UNKNOWN)
buf = curbuf;
else
dict_add_number(d, "col", (long)buf->b_changelist[i].col);
dict_add_number(d, "coladd", (long)buf->b_changelist[i].coladd);
}
-#endif
}
static void
static void
f_getjumplist(typval_T *argvars, typval_T *rettv)
{
-#ifdef FEAT_JUMPLIST
win_T *wp;
int i;
list_T *l;
dict_T *d;
-#endif
if (rettv_list_alloc(rettv) != OK)
return;
&& check_for_opt_number_arg(argvars, 1) == FAIL)))
return;
-#ifdef FEAT_JUMPLIST
wp = find_tabwin(&argvars[0], &argvars[1], NULL);
if (wp == NULL)
return;
if (wp->w_jumplist[i].fname != NULL)
dict_add_string(d, "filename", wp->w_jumplist[i].fname);
}
-#endif
}
/*
0
#endif
},
- {"jumplist",
-#ifdef FEAT_JUMPLIST
- 1
-#else
- 0
-#endif
- },
+ {"jumplist", 1},
{"keymap",
#ifdef FEAT_KEYMAP
1
# define ex_nbstart ex_ni
#endif
-#ifndef FEAT_JUMPLIST
-# define ex_jumps ex_ni
-# define ex_clearjumps ex_ni
-# define ex_changes ex_ni
-#endif
-
#ifndef FEAT_PROFILE
# define ex_profile ex_ni
#endif
* +modify_fname modifiers for file name. E.g., "%:p:h".
* +comments 'comments' option.
* +title 'title' and 'icon' options
+ * +jumplist Jumplist, CTRL-O and CTRL-I commands.
*
* Obsolete:
* +tag_old_static Old style static tags: "file:tag file ..".
# define MAX_MSG_HIST_LEN 20
#endif
-/*
- * +jumplist Jumplist, CTRL-O and CTRL-I commands.
- */
-#ifdef FEAT_SMALL
-# define FEAT_JUMPLIST
-#endif
-
#if defined(FEAT_SMALL)
# define FEAT_CMDWIN
#endif
void
setpcmark(void)
{
-#ifdef FEAT_JUMPLIST
int i;
xfmark_T *fm;
-#endif
// for :global the mark is set only once
if (global_busy || listcmd_busy || (cmdmod.cmod_flags & CMOD_KEEPJUMPS))
curwin->w_prev_pcmark = curwin->w_pcmark;
curwin->w_pcmark = curwin->w_cursor;
-#ifdef FEAT_JUMPLIST
// If jumplist is full: remove oldest entry
if (++curwin->w_jumplistlen > JUMPLISTSIZE)
{
fm->fmark.mark = curwin->w_pcmark;
fm->fmark.fnum = curbuf->b_fnum;
fm->fname = NULL;
-# ifdef FEAT_VIMINFO
+#ifdef FEAT_VIMINFO
fm->time_set = vim_time();
-# endif
#endif
}
curwin->w_prev_pcmark.lnum = 0; // it has been checked
}
-#if defined(FEAT_JUMPLIST) || defined(PROTO)
/*
* move "count" positions in the jump list (count may be negative)
*/
curwin->w_changelistidx = n;
return curbuf->b_changelist + n;
}
-#endif
/*
* Find mark "c" in buffer pointed to by "buf".
{
char_u *name;
int i;
-#ifdef FEAT_JUMPLIST
win_T *wp;
-#endif
if (buf->b_ffname == NULL)
return;
for (i = 0; i < NMARKS + EXTRA_MARKS; ++i)
fmarks_check_one(&namedfm[i], name, buf);
-#ifdef FEAT_JUMPLIST
FOR_ALL_WINDOWS(wp)
{
for (i = 0; i < wp->w_jumplistlen; ++i)
fmarks_check_one(&wp->w_jumplist[i], name, buf);
}
-#endif
vim_free(name);
}
buf->b_last_cursor.coladd = 0;
buf->b_last_insert.lnum = 0; // '^ mark cleared
buf->b_last_change.lnum = 0; // '. mark cleared
-#ifdef FEAT_JUMPLIST
buf->b_changelistlen = 0;
-#endif
}
/*
}
}
-#if defined(FEAT_JUMPLIST) || defined(PROTO)
/*
* print the jumplist
*/
if (curwin->w_changelistidx == curbuf->b_changelistlen)
msg_puts("\n>");
}
-#endif
#define one_adjust(add) \
{ \
one_adjust(&(curbuf->b_last_cursor.lnum));
-#ifdef FEAT_JUMPLIST
// list of change positions
for (i = 0; i < curbuf->b_changelistlen; ++i)
one_adjust_nodel(&(curbuf->b_changelist[i].lnum));
-#endif
// Visual area
one_adjust_nodel(&(curbuf->b_visual.vi_start.lnum));
*/
FOR_ALL_TAB_WINDOWS(tab, win)
{
-#ifdef FEAT_JUMPLIST
if ((cmdmod.cmod_flags & CMOD_LOCKMARKS) == 0)
// Marks in the jumplist. When deleting lines, this may create
// duplicate marks in the jumplist, they will be removed later.
for (i = 0; i < win->w_jumplistlen; ++i)
if (win->w_jumplist[i].fmark.fnum == fnum)
one_adjust_nodel(&(win->w_jumplist[i].fmark.mark.lnum));
-#endif
if (win->w_buffer == curbuf)
{
// last change position
col_adjust(&(curbuf->b_last_change));
-#ifdef FEAT_JUMPLIST
// list of change positions
for (i = 0; i < curbuf->b_changelistlen; ++i)
col_adjust(&(curbuf->b_changelist[i]));
-#endif
// Visual area
col_adjust(&(curbuf->b_visual.vi_start));
*/
FOR_ALL_WINDOWS(win)
{
-#ifdef FEAT_JUMPLIST
// marks in the jumplist
for (i = 0; i < win->w_jumplistlen; ++i)
if (win->w_jumplist[i].fmark.fnum == fnum)
col_adjust(&(win->w_jumplist[i].fmark.mark));
-#endif
if (win->w_buffer == curbuf)
{
}
}
-#ifdef FEAT_JUMPLIST
/*
* When deleting lines, this may create duplicate marks in the
* jumplist. They will be removed here for the specified window.
for (i = 0; i < wp->w_jumplistlen; ++i)
vim_free(wp->w_jumplist[i].fname);
}
-#endif // FEAT_JUMPLIST
void
set_last_cursor(win_T *win)
static void
nv_pcmark(cmdarg_T *cap)
{
-#ifdef FEAT_JUMPLIST
pos_T *pos;
-# ifdef FEAT_FOLDING
+#ifdef FEAT_FOLDING
linenr_T lnum = curwin->w_cursor.lnum;
int old_KeyTyped = KeyTyped; // getting file may reset it
-# endif
+#endif
if (!checkclearopq(cap->oap))
{
foldOpenCursor();
# endif
}
-#else
- clearopbeep(cap->oap);
-#endif
}
/*
do_exmode(TRUE);
break;
-#ifdef FEAT_JUMPLIST
case ',':
nv_pcmark(cap);
break;
cap->count1 = -cap->count1;
nv_pcmark(cap);
break;
-#endif
case 't':
if (!checkclearop(oap))
pos_T b_last_insert; // where Insert mode was left
pos_T b_last_change; // position of last change: '. mark
-#ifdef FEAT_JUMPLIST
/*
* the changelist contains old change positions
*/
pos_T b_changelist[JUMPLISTSIZE];
int b_changelistlen; // number of active entries
int b_new_change; // set by u_savecommon()
-#endif
/*
* Character table, only used in charset.c for 'iskeyword'
pos_T w_pcmark; // previous context mark
pos_T w_prev_pcmark; // previous w_pcmark
-#ifdef FEAT_JUMPLIST
/*
* the jumplist contains old cursor positions
*/
int w_jumplistidx; // current position
int w_changelistidx; // current position in b_changelist
-#endif
#ifdef FEAT_SEARCH_EXTRA
matchitem_T *w_match_head; // head of match list
" Tests for the changelist functionality
-source check.vim
-
" Tests for the getchangelist() function
func Test_getchangelist()
- CheckFeature jumplist
-
bwipe!
enew
call assert_equal([], 10->getchangelist())
" Tests for the jumplist functionality
-source check.vim
-
" Tests for the getjumplist() function
func Test_getjumplist()
- CheckFeature jumplist
-
%bwipe
clearjumps
call assert_equal([[], 0], getjumplist())
" Test for g`, g;, g,, g&, gv, gk, gj, gJ, g0, g^, g_, gm, g$, gM, g CTRL-G,
" gi and gI commands
func Test_normal33_g_cmd2()
- CheckFeature jumplist
call Setup_NewWindow()
" Test for g`
clearjumps
" Tests for g cmds
func Test_normal_gdollar_cmd()
- CheckFeature jumplist
call Setup_NewWindow()
" Make long lines that will wrap
%s/$/\=repeat(' foobar', 10)/
/*
* Save the lines between "top" and "bot" for both the "u" and "U" command.
- * "top" may be 0 and bot may be curbuf->b_ml.ml_line_count + 1.
+ * "top" may be 0 and "bot" may be curbuf->b_ml.ml_line_count + 1.
* Careful: may trigger autocommands that reload the buffer.
* Returns FAIL when lines could not be saved, OK otherwise.
*/
*/
if (curbuf->b_u_synced)
{
-#ifdef FEAT_JUMPLIST
// Need to create new entry in b_changelist.
curbuf->b_new_change = TRUE;
-#endif
if (get_undolevel() >= 0)
{
#else
"-job",
#endif
-#ifdef FEAT_JUMPLIST
"+jumplist",
-#else
- "-jumplist",
-#endif
#ifdef FEAT_KEYMAP
"+keymap",
#else
static int included_patches[] =
{ /* Add new patch number below this line */
+/**/
+ 3795,
/**/
3794,
/**/
*/
static xfmark_T *vi_namedfm = NULL;
-#ifdef FEAT_JUMPLIST
static xfmark_T *vi_jumplist = NULL;
static int vi_jumplist_len = 0;
-#endif
static void
write_one_mark(FILE *fp_out, int c, pos_T *pos)
write_one_mark(fp_out, '"', &buf->b_last_cursor);
write_one_mark(fp_out, '^', &buf->b_last_insert);
write_one_mark(fp_out, '.', &buf->b_last_change);
-#ifdef FEAT_JUMPLIST
// changelist positions are stored oldest first
for (i = 0; i < buf->b_changelistlen; ++i)
{
buf->b_changelist[i]))
write_one_mark(fp_out, '+', &buf->b_changelist[i]);
}
-#endif
for (i = 0; i < NMARKS; i++)
write_one_mark(fp_out, 'a' + i, &buf->b_namedm[i]);
}
write_one_filemark(fp, fm, '\'', i - NMARKS + '0');
}
-#ifdef FEAT_JUMPLIST
// Write the jumplist with -'
fputs(_("\n# Jumplist (newest first):\n"), fp);
setpcmark(); // add current cursor position
&& !skip_for_viminfo(buf)))
write_one_filemark(fp, fm, '-', '\'');
}
-#endif
}
/*
case '^': curbuf->b_last_insert = pos; break;
case '.': curbuf->b_last_change = pos; break;
case '+':
-#ifdef FEAT_JUMPLIST
// changelist positions are stored oldest
// first
if (curbuf->b_changelistlen == JUMPLISTSIZE)
++curbuf->b_changelistlen;
curbuf->b_changelist[
curbuf->b_changelistlen - 1] = pos;
-#endif
break;
// Using the line number for the last-used
if (load_marks)
{
-#ifdef FEAT_JUMPLIST
win_T *wp;
FOR_ALL_WINDOWS(wp)
if (wp->w_buffer == curbuf)
wp->w_changelistidx = curbuf->b_changelistlen;
}
-#endif
if (flags & VIF_ONLY_CURBUF)
break;
}
{
if (*str == '\'')
{
-#ifdef FEAT_JUMPLIST
// If the jumplist isn't full insert fmark as oldest entry
if (curwin->w_jumplistlen == JUMPLISTSIZE)
fm = NULL;
fm->fmark.mark.lnum = 0;
fm->fname = NULL;
}
-#else
- fm = NULL;
-#endif
}
else if (VIM_ISDIGIT(*str))
fm = &namedfm_p[*str - '0' + NMARKS];
prepare_viminfo_marks(void)
{
vi_namedfm = ALLOC_CLEAR_MULT(xfmark_T, NMARKS + EXTRA_MARKS);
-#ifdef FEAT_JUMPLIST
vi_jumplist = ALLOC_CLEAR_MULT(xfmark_T, JUMPLISTSIZE);
vi_jumplist_len = 0;
-#endif
}
static void
vim_free(vi_namedfm[i].fname);
VIM_CLEAR(vi_namedfm);
}
-#ifdef FEAT_JUMPLIST
if (vi_jumplist != NULL)
{
for (i = 0; i < vi_jumplist_len; ++i)
vim_free(vi_jumplist[i].fname);
VIM_CLEAR(vi_jumplist);
}
-#endif
}
/*
if (name == '\'')
{
-#ifdef FEAT_JUMPLIST
if (vi_jumplist != NULL)
{
if (vi_jumplist_len < JUMPLISTSIZE)
fm->time_set = 0;
}
}
-#endif
}
else
{
p_wh = size;
}
-#ifdef FEAT_JUMPLIST
// Keep same changelist position in new window.
wp->w_changelistidx = oldwin->w_changelistidx;
-#endif
/*
* make the new window the current window
newp->w_wrow = oldp->w_wrow;
newp->w_fraction = oldp->w_fraction;
newp->w_prev_fraction_row = oldp->w_prev_fraction_row;
-#ifdef FEAT_JUMPLIST
copy_jumplist(oldp, newp);
-#endif
#ifdef FEAT_QUICKFIX
if (flags & WSP_NEWLOC)
{
clear_matches(wp);
#endif
-#ifdef FEAT_JUMPLIST
free_jumplist(wp);
-#endif
#ifdef FEAT_QUICKFIX
qf_free_all(wp);