summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/edit.c2
-rw-r--r--src/ex_cmds.c1
-rw-r--r--src/gui.c2
-rw-r--r--src/misc1.c4
-rw-r--r--src/misc2.c51
-rw-r--r--src/move.c32
-rw-r--r--src/netbeans.c3
-rw-r--r--src/normal.c5
-rw-r--r--src/option.c16
-rw-r--r--src/option.h1
-rw-r--r--src/proto/misc2.pro1
-rw-r--r--src/screen.c64
-rw-r--r--src/structs.h5
13 files changed, 148 insertions, 39 deletions
diff --git a/src/edit.c b/src/edit.c
index 33e580f1b..88943cd7f 100644
--- a/src/edit.c
+++ b/src/edit.c
@@ -6272,7 +6272,7 @@ comp_textwidth(ff)
)
textwidth -= 1;
#endif
- if (curwin->w_p_nu)
+ if (curwin->w_p_nu || curwin->w_p_rnu)
textwidth -= 8;
}
if (textwidth < 0)
diff --git a/src/ex_cmds.c b/src/ex_cmds.c
index 2296c332b..1f9a7f217 100644
--- a/src/ex_cmds.c
+++ b/src/ex_cmds.c
@@ -3488,6 +3488,7 @@ do_ecmd(fnum, ffname, sfname, eap, newlnum, flags, oldwin)
curbuf->b_p_ma = FALSE; /* not modifiable */
curbuf->b_p_bin = FALSE; /* reset 'bin' before reading file */
curwin->w_p_nu = 0; /* no line numbers */
+ curwin->w_p_rnu = 0; /* no relative line numbers */
#ifdef FEAT_SCROLLBIND
curwin->w_p_scb = FALSE; /* no scroll binding */
#endif
diff --git a/src/gui.c b/src/gui.c
index 2c307faaa..5b1a2ae08 100644
--- a/src/gui.c
+++ b/src/gui.c
@@ -4412,7 +4412,7 @@ gui_update_horiz_scrollbar(force)
max += W_WIDTH(curwin) - 1;
#endif
/* The line number isn't scrolled, thus there is less space when
- * 'number' is set (also for 'foldcolumn'). */
+ * 'number' or 'relativenumber' is set (also for 'foldcolumn'). */
size -= curwin_col_off();
#ifndef SCROLL_PAST_END
max -= curwin_col_off();
diff --git a/src/misc1.c b/src/misc1.c
index d476f31ed..69bfe7dbe 100644
--- a/src/misc1.c
+++ b/src/misc1.c
@@ -1742,7 +1742,7 @@ plines_win_nofold(wp, lnum)
col += 1;
/*
- * Add column offset for 'number' and 'foldcolumn'.
+ * Add column offset for 'number', 'relativenumber' and 'foldcolumn'.
*/
width = W_WIDTH(wp) - win_col_off(wp);
if (width <= 0)
@@ -1803,7 +1803,7 @@ plines_win_col(wp, lnum, column)
col += win_lbr_chartabsize(wp, s, (colnr_T)col, NULL) - 1;
/*
- * Add column offset for 'number', 'foldcolumn', etc.
+ * Add column offset for 'number', 'relativenumber', 'foldcolumn', etc.
*/
width = W_WIDTH(wp) - win_col_off(wp);
if (width <= 0)
diff --git a/src/misc2.c b/src/misc2.c
index 949d7e21a..8cd568304 100644
--- a/src/misc2.c
+++ b/src/misc2.c
@@ -469,6 +469,57 @@ decl(lp)
}
/*
+ * Get the line number relative to the current cursor position, i.e. the
+ * difference between line number and cursor position. Only look for lines that
+ * can be visible, folded lines don't count.
+ */
+ linenr_T
+get_cursor_rel_lnum(wp, lnum)
+ win_T *wp;
+ linenr_T lnum; /* line number to get the result for */
+{
+ linenr_T cursor = wp->w_cursor.lnum;
+ linenr_T retval = 0;
+
+#ifdef FEAT_FOLDING
+ if (hasAnyFolding(wp))
+ {
+ if (lnum > cursor)
+ {
+ while (lnum > cursor)
+ {
+ (void)hasFolding(lnum, &lnum, NULL);
+ /* if lnum and cursor are in the same fold,
+ * now lnum <= cursor */
+ if (lnum > cursor)
+ retval++;
+ lnum--;
+ }
+ }
+ else if (lnum < cursor)
+ {
+ while (lnum < cursor)
+ {
+ (void)hasFolding(lnum, NULL, &lnum);
+ /* if lnum and cursor are in the same fold,
+ * now lnum >= cursor */
+ if (lnum < cursor)
+ retval--;
+ lnum++;
+ }
+ }
+ /* else if (lnum == cursor)
+ * retval = 0;
+ */
+ }
+ else
+#endif
+ retval = lnum - cursor;
+
+ return retval;
+}
+
+/*
* Make sure curwin->w_cursor.lnum is valid.
*/
void
diff --git a/src/move.c b/src/move.c
index de1a9e4de..4bdb69471 100644
--- a/src/move.c
+++ b/src/move.c
@@ -916,14 +916,14 @@ validate_cursor_col()
}
/*
- * Compute offset of a window, occupied by line number, fold column and sign
- * column (these don't move when scrolling horizontally).
+ * Compute offset of a window, occupied by absolute or relative line number,
+ * fold column and sign column (these don't move when scrolling horizontally).
*/
int
win_col_off(wp)
win_T *wp;
{
- return ((wp->w_p_nu ? number_width(wp) + 1 : 0)
+ return (((wp->w_p_nu || wp->w_p_rnu) ? number_width(wp) + 1 : 0)
#ifdef FEAT_CMDWIN
+ (cmdwin_type == 0 || wp != curwin ? 0 : 1)
#endif
@@ -949,13 +949,14 @@ curwin_col_off()
/*
* Return the difference in column offset for the second screen line of a
- * wrapped line. It's 8 if 'number' is on and 'n' is in 'cpoptions'.
+ * wrapped line. It's 8 if 'number' or 'relativenumber' is on and 'n' is in
+ * 'cpoptions'.
*/
int
win_col_off2(wp)
win_T *wp;
{
- if (wp->w_p_nu && vim_strchr(p_cpo, CPO_NUMCOL) != NULL)
+ if ((wp->w_p_nu || wp->w_p_rnu) && vim_strchr(p_cpo, CPO_NUMCOL) != NULL)
return number_width(wp) + 1;
return 0;
}
@@ -1218,17 +1219,22 @@ curs_columns(scroll)
if (prev_skipcol != curwin->w_skipcol)
redraw_later(NOT_VALID);
+ /* Redraw when w_row changes and 'relativenumber' is set */
+ if (((curwin->w_valid & VALID_WROW) == 0 && (curwin->w_p_rnu
#ifdef FEAT_SYN_HL
- /* Redraw when w_virtcol changes and 'cursorcolumn' is set, or when w_row
- * changes and 'cursorline' is set. */
- if (((curwin->w_p_cuc && (curwin->w_valid & VALID_VIRTCOL) == 0)
- || (curwin->w_p_cul && (curwin->w_valid & VALID_WROW) == 0))
+ /* or when w_row changes and 'cursorline' is set. */
+ || curwin->w_p_cul
+#endif
+ ))
+#ifdef FEAT_SYN_HL
+ /* or when w_virtcol changes and 'cursorcolumn' is set */
+ || (curwin->w_p_cuc && (curwin->w_valid & VALID_VIRTCOL) == 0)
+#endif
+ )
# ifdef FEAT_INS_EXPAND
- && !pum_visible()
+ if (!pum_visible())
# endif
- )
- redraw_later(SOME_VALID);
-#endif
+ redraw_later(SOME_VALID);
curwin->w_valid |= VALID_WCOL|VALID_WROW|VALID_VIRTCOL;
}
diff --git a/src/netbeans.c b/src/netbeans.c
index 94c1aaadf..93a9aea75 100644
--- a/src/netbeans.c
+++ b/src/netbeans.c
@@ -3143,7 +3143,8 @@ netbeans_button_release(int button)
if (bufno >= 0 && curwin != NULL && curwin->w_buffer == curbuf)
{
- int col = mouse_col - W_WINCOL(curwin) - (curwin->w_p_nu ? 9 : 1);
+ int col = mouse_col - W_WINCOL(curwin)
+ - ((curwin->w_p_nu || curwin->w_p_rnu) ? 9 : 1);
long off = pos2off(curbuf, &curwin->w_cursor);
/* sync the cursor position */
diff --git a/src/normal.c b/src/normal.c
index a19771b4f..e02c81781 100644
--- a/src/normal.c
+++ b/src/normal.c
@@ -7845,8 +7845,9 @@ nv_g_cmd(cap)
}
else
i = curwin->w_leftcol;
- /* Go to the middle of the screen line. When 'number' is on and lines
- * are wrapping the middle can be more to the left. */
+ /* Go to the middle of the screen line. When 'number' or
+ * 'relativenumber' is on and lines are wrapping the middle can be more
+ * to the left. */
if (cap->nchar == 'm')
i += (W_WIDTH(curwin) - curwin_col_off()
+ ((curwin->w_p_wrap && i > 0)
diff --git a/src/option.c b/src/option.c
index f93d839cc..c9cad3208 100644
--- a/src/option.c
+++ b/src/option.c
@@ -207,6 +207,7 @@
# define PV_LBR OPT_WIN(WV_LBR)
#endif
#define PV_NU OPT_WIN(WV_NU)
+#define PV_RNU OPT_WIN(WV_RNU)
#ifdef FEAT_LINEBREAK
# define PV_NUW OPT_WIN(WV_NUW)
#endif
@@ -2015,6 +2016,9 @@ static struct vimoption
(char_u *)NULL, PV_NONE,
#endif
{(char_u *)2000L, (char_u *)0L} SCRIPTID_INIT},
+ {"relativenumber", "rnu", P_BOOL|P_VI_DEF|P_RWIN,
+ (char_u *)VAR_WIN, PV_RNU,
+ {(char_u *)FALSE, (char_u *)0L} SCRIPTID_INIT},
{"remap", NULL, P_BOOL|P_VI_DEF,
(char_u *)&p_remap, PV_NONE,
{(char_u *)TRUE, (char_u *)0L} SCRIPTID_INIT},
@@ -7230,10 +7234,18 @@ set_bool_option(opt_idx, varp, value, opt_flags)
/* 'list', 'number' */
else if ((int *)varp == &curwin->w_p_list
- || (int *)varp == &curwin->w_p_nu)
+ || (int *)varp == &curwin->w_p_nu
+ || (int *)varp == &curwin->w_p_rnu)
{
if (curwin->w_curswant != MAXCOL)
curwin->w_set_curswant = TRUE;
+
+ /* If 'number' is set, reset 'relativenumber'. */
+ /* If 'relativenumber' is set, reset 'number'. */
+ if ((int *)varp == &curwin->w_p_nu && curwin->w_p_nu)
+ curwin->w_p_rnu = FALSE;
+ if ((int *)varp == &curwin->w_p_rnu && curwin->w_p_rnu)
+ curwin->w_p_nu = FALSE;
}
else if ((int *)varp == &curbuf->b_p_ro)
@@ -9232,6 +9244,7 @@ get_varp(p)
case PV_FMR: return (char_u *)&(curwin->w_p_fmr);
#endif
case PV_NU: return (char_u *)&(curwin->w_p_nu);
+ case PV_RNU: return (char_u *)&(curwin->w_p_rnu);
#ifdef FEAT_LINEBREAK
case PV_NUW: return (char_u *)&(curwin->w_p_nuw);
#endif
@@ -9417,6 +9430,7 @@ copy_winopt(from, to)
#endif
to->wo_list = from->wo_list;
to->wo_nu = from->wo_nu;
+ to->wo_rnu = from->wo_rnu;
#ifdef FEAT_LINEBREAK
to->wo_nuw = from->wo_nuw;
#endif
diff --git a/src/option.h b/src/option.h
index cfa7692cb..b635db175 100644
--- a/src/option.h
+++ b/src/option.h
@@ -1039,6 +1039,7 @@ enum
, WV_LBR
#endif
, WV_NU
+ , WV_RNU
#ifdef FEAT_LINEBREAK
, WV_NUW
#endif
diff --git a/src/proto/misc2.pro b/src/proto/misc2.pro
index 261ec8226..5c4cc4210 100644
--- a/src/proto/misc2.pro
+++ b/src/proto/misc2.pro
@@ -11,6 +11,7 @@ int incl __ARGS((pos_T *lp));
int dec_cursor __ARGS((void));
int dec __ARGS((pos_T *lp));
int decl __ARGS((pos_T *lp));
+linenr_T get_cursor_rel_lnum __ARGS((win_T *wp, linenr_T lnum));
void check_cursor_lnum __ARGS((void));
void check_cursor_col __ARGS((void));
void check_cursor __ARGS((void));
diff --git a/src/screen.c b/src/screen.c
index 7f929ac0f..72a93da64 100644
--- a/src/screen.c
+++ b/src/screen.c
@@ -423,9 +423,11 @@ update_screen(type)
check_for_delay(FALSE);
#ifdef FEAT_LINEBREAK
- /* Force redraw when width of 'number' column changes. */
+ /* Force redraw when width of 'number' or 'relativenumber' column
+ * changes. */
if (curwin->w_redr_type < NOT_VALID
- && curwin->w_nrwidth != (curwin->w_p_nu ? number_width(curwin) : 0))
+ && curwin->w_nrwidth != ((curwin->w_p_nu || curwin->w_p_rnu)
+ ? number_width(curwin) : 0))
curwin->w_redr_type = NOT_VALID;
#endif
@@ -871,8 +873,9 @@ win_update(wp)
#endif
#ifdef FEAT_LINEBREAK
- /* Force redraw when width of 'number' column changes. */
- i = wp->w_p_nu ? number_width(wp) : 0;
+ /* Force redraw when width of 'number' or 'relativenumber' column
+ * changes. */
+ i = (wp->w_p_nu || wp->w_p_rnu) ? number_width(wp) : 0;
if (wp->w_nrwidth != i)
{
type = NOT_VALID;
@@ -2118,7 +2121,7 @@ fold_line(wp, fold_count, foldinfo, lnum, row)
/* Build the fold line:
* 1. Add the cmdwin_type for the command-line window
* 2. Add the 'foldcolumn'
- * 3. Add the 'number' column
+ * 3. Add the 'number' or 'relativenumber' column
* 4. Compose the text
* 5. Add the text
* 6. set highlighting for the Visual area an other text
@@ -2180,7 +2183,8 @@ fold_line(wp, fold_count, foldinfo, lnum, row)
ScreenAttrs[off + (p) + ri] = v
#endif
- /* Set all attributes of the 'number' column and the text */
+ /* Set all attributes of the 'number' or 'relativenumber' column and the
+ * text */
RL_MEMSET(col, hl_attr(HLF_FL), W_WIDTH(wp) - col);
#ifdef FEAT_SIGNS
@@ -2206,18 +2210,27 @@ fold_line(wp, fold_count, foldinfo, lnum, row)
#endif
/*
- * 3. Add the 'number' column
+ * 3. Add the 'number' or 'relativenumber' column
*/
- if (wp->w_p_nu)
+ if (wp->w_p_nu || wp->w_p_rnu)
{
len = W_WIDTH(wp) - col;
if (len > 0)
{
int w = number_width(wp);
+ long num;
if (len > w + 1)
len = w + 1;
- sprintf((char *)buf, "%*ld ", w, (long)lnum);
+
+ if (wp->w_p_nu)
+ /* 'number' */
+ num = (long)lnum;
+ else
+ /* 'relativenumber', don't use negative numbers */
+ num = (long)abs((int)get_cursor_rel_lnum(wp, lnum));
+
+ sprintf((char *)buf, "%*ld ", w, num);
#ifdef FEAT_RIGHTLEFT
if (wp->w_p_rl)
/* the line number isn't reversed */
@@ -3327,9 +3340,9 @@ win_line(wp, lnum, startrow, endrow, nochange)
if (draw_state == WL_NR - 1 && n_extra == 0)
{
draw_state = WL_NR;
- /* Display the line number. After the first fill with blanks
- * when the 'n' flag isn't in 'cpo' */
- if (wp->w_p_nu
+ /* Display the absolute or relative line number. After the
+ * first fill with blanks when the 'n' flag isn't in 'cpo' */
+ if ((wp->w_p_nu || wp->w_p_rnu)
&& (row == startrow
#ifdef FEAT_DIFF
+ filler_lines
@@ -3343,8 +3356,18 @@ win_line(wp, lnum, startrow, endrow, nochange)
#endif
)
{
+ long num;
+
+ if (wp->w_p_nu)
+ /* 'number' */
+ num = (long)lnum;
+ else
+ /* 'relativenumber', don't use negative numbers */
+ num = (long)abs((int)get_cursor_rel_lnum(wp,
+ lnum));
+
sprintf((char *)extra, "%*ld ",
- number_width(wp), (long)lnum);
+ number_width(wp), num);
if (wp->w_skipcol > 0)
for (p_extra = extra; *p_extra == ' '; ++p_extra)
*p_extra = '-';
@@ -4707,7 +4730,8 @@ win_line(wp, lnum, startrow, endrow, nochange)
else
--n_skip;
- /* Only advance the "vcol" when after the 'number' column. */
+ /* Only advance the "vcol" when after the 'number' or 'relativenumber'
+ * column. */
if (draw_state > WL_NR
#ifdef FEAT_DIFF
&& filler_todo <= 0
@@ -9770,8 +9794,8 @@ win_redr_ruler(wp, always)
#if defined(FEAT_LINEBREAK) || defined(PROTO)
/*
- * Return the width of the 'number' column.
- * Caller may need to check if 'number' is set.
+ * Return the width of the 'number' and 'relativenumber' column.
+ * Caller may need to check if 'number' or 'relativenumber' is set.
* Otherwise it depends on 'numberwidth' and the line count.
*/
int
@@ -9781,7 +9805,13 @@ number_width(wp)
int n;
linenr_T lnum;
- lnum = wp->w_buffer->b_ml.ml_line_count;
+ if (wp->w_p_nu)
+ /* 'number' */
+ lnum = wp->w_buffer->b_ml.ml_line_count;
+ else
+ /* 'relativenumber' */
+ lnum = wp->w_height;
+
if (lnum == wp->w_nrwidth_line_count)
return wp->w_nrwidth_width;
wp->w_nrwidth_line_count = lnum;
diff --git a/src/structs.h b/src/structs.h
index d434bfee4..72bd96cd4 100644
--- a/src/structs.h
+++ b/src/structs.h
@@ -169,6 +169,8 @@ typedef struct
#define w_p_list w_onebuf_opt.wo_list /* 'list' */
int wo_nu;
#define w_p_nu w_onebuf_opt.wo_nu /* 'number' */
+ int wo_rnu;
+#define w_p_rnu w_onebuf_opt.wo_rnu /* 'relativenumber' */
#ifdef FEAT_LINEBREAK
long wo_nuw;
# define w_p_nuw w_onebuf_opt.wo_nuw /* 'numberwidth' */
@@ -1907,7 +1909,8 @@ struct window_S
recomputed */
#endif
#ifdef FEAT_LINEBREAK
- int w_nrwidth; /* width of 'number' column being used */
+ int w_nrwidth; /* width of 'number' and 'relativenumber'
+ column being used */
#endif
/*