Re: [PATCH] feature: relative line numbers
Benno Schulenberg <[email protected]> Mon, 30 Jun 2025 15:27:35 +0200
| Newsgroups | gmane.editors.nano.devel |
|---|---|
| Message-ID | <[email protected]> |
Op 30-06-2025 om 00:26 schreef bsandro: > nano is my go-to code editor for several years now, but I still miss the > relative line numbers feature from vim that I was using before that. Interesting. I've tried it, but... don't like it. What is the point of relative line numbers when nano does not have the relative movement commands that vim has? Also, I find showing the absolute line number for the current line (instead of zero) confusing. So, I'm not going to apply the patch. (An improved version is attached, that updates the screen also when 'relativenumbers' is toggled. Also, I've renamed the option to 'relativenumbers', to stay in nano's style: no abbreviations in the option names.) But what I might apply is the other attached patch: allow nano to jump a relative amount of lines. Unfortunately, negative numbers already mean "from end of buffer", so the patch accepts double signs to mean "relative": ++100 will jump a hundred lines forward, --200 two hundred lines back. Anyone interested in having this? Benno
0001-out-of-tree-feature-relative-line-numbers.patch
(text/x-patch, 9.3 KB)
From 7996caeb1da22cb29c10b5ae6871578f2d660bd1 Mon Sep 17 00:00:00 2001 From: Brian Sandro <[email protected]> Date: Mon, 30 Jun 2025 01:10:25 +0300 Subject: [PATCH] out-of-tree feature: relative line numbers When line numbers are active, option 'set relativenumbers' in your nanorc file will cause `nano` to show relative instead of absolute line numbers. There is also the bindable function 'relativenumbers' (not bound by default) for toggling relative line numbers on and off. This is modeled on the corresponding vim/neovim feature. Signed-off-by: Brian Sandro <[email protected]> Signed-off-by: Benno Schulenberg <[email protected]> --- doc/nano.texi | 6 ++++++ doc/nanorc.5 | 6 ++++++ doc/sample.nanorc.in | 3 +++ src/definitions.h | 1 + src/global.c | 2 ++ src/nano.c | 8 ++++++++ src/rcfile.c | 3 +++ src/winio.c | 12 +++++++++++- syntax/nanorc.nanorc | 4 ++-- 9 files changed, 42 insertions(+), 3 deletions(-) diff --git a/doc/nano.texi b/doc/nano.texi index 9bfe049e..f3f7b64f 100644 --- a/doc/nano.texi +++ b/doc/nano.texi @@ -1155,6 +1155,9 @@ either @kbd{Backspace} acts like Delete or @kbd{Delete} acts like Backspace. Do regular-expression searches by default. Regular expressions in @command{nano} are of the extended type (ERE). +@item set relativenumbers +Display relative line numbers (when line numbers are enabled). + @item set saveonexit Save a changed buffer automatically on exit (@kbd{^X}); don't prompt. @@ -1844,6 +1847,9 @@ Toggles the displaying of overlong lines on multiple screen lines. @item linenumbers Toggles the display of line numbers in front of the text. +@item relativenumbers +Toggles relative line numbers. + @item whitespacedisplay Toggles the showing of whitespace. diff --git a/doc/nanorc.5 b/doc/nanorc.5 index d73de26f..ae3db6f1 100644 --- a/doc/nanorc.5 +++ b/doc/nanorc.5 @@ -303,6 +303,9 @@ system either Backspace acts like Delete or Delete acts like Backspace. Do regular-expression searches by default. Regular expressions in \fBnano\fR are of the extended type (ERE). .TP +.B set relativenumbers +Display relative line numbers when line numbers are enabled. +.TP .B set saveonexit Save a changed buffer automatically on exit (\fB^X\fR); don't prompt. .TP @@ -987,6 +990,9 @@ Toggles the displaying of overlong lines on multiple screen lines. .B linenumbers Toggles the display of line numbers in front of the text. .TP +.B relativenumbers +Toggles relative line numbers. +.TP .B whitespacedisplay Toggles the showing of whitespace. .TP diff --git a/doc/sample.nanorc.in b/doc/sample.nanorc.in index e559356f..0395af58 100644 --- a/doc/sample.nanorc.in +++ b/doc/sample.nanorc.in @@ -154,6 +154,9 @@ ## Regular expressions are of the extended type (ERE). # set regexp +## Display relative line numbers (when line numbers are enabled). +# set relativenumbers + ## Save a changed buffer automatically on exit; don't prompt. # set saveonexit diff --git a/src/definitions.h b/src/definitions.h index c73b4a82..5ab849c5 100644 --- a/src/definitions.h +++ b/src/definitions.h @@ -363,6 +363,7 @@ enum { TRIM_BLANKS, SHOW_CURSOR, LINE_NUMBERS, + RELATIVE_NUMBERS, AT_BLANKS, AFTER_ENDS, LET_THEM_ZAP, diff --git a/src/global.c b/src/global.c index a97ddf6a..3ac46424 100644 --- a/src/global.c +++ b/src/global.c @@ -1613,6 +1613,8 @@ const char *epithet_of_flag(int flag) return N_("Soft wrapping of overlong lines"); case LINE_NUMBERS: return N_("Line numbering"); + case RELATIVE_NUMBERS: + return N_("Relative line numbers"); case WHITESPACE_DISPLAY: return N_("Whitespace display"); case NO_SYNTAX: diff --git a/src/nano.c b/src/nano.c index b6146b72..f53737cf 100644 --- a/src/nano.c +++ b/src/nano.c @@ -1134,6 +1134,11 @@ void toggle_this(int flag) } break; #endif +#ifdef ENABLE_LINENUMBERS + case RELATIVE_NUMBERS: + refresh_needed = TRUE; + break; +#endif #ifdef ENABLE_MOUSE case USE_MOUSE: mouse_init(); @@ -1152,6 +1157,9 @@ void toggle_this(int flag) if (ISSET(MINIBAR) || ISSET(ZERO) || LINES == 1) return; + if (ISSET(LINE_NUMBERS) && flag == RELATIVE_NUMBERS) + return; + if (flag == NO_HELP || flag == NO_SYNTAX) enabled = !enabled; diff --git a/src/rcfile.c b/src/rcfile.c index 6143f5fc..d24deb23 100644 --- a/src/rcfile.c +++ b/src/rcfile.c @@ -56,6 +56,7 @@ static const rcoption rcopts[] = { #endif #ifdef ENABLE_LINENUMBERS {"linenumbers", LINE_NUMBERS}, + {"relativenumbers", RELATIVE_NUMBERS}, #endif #ifdef HAVE_LIBMAGIC {"magic", USE_MAGIC}, @@ -457,6 +458,8 @@ keystruct *strtosc(const char *input) #ifdef ENABLE_LINENUMBERS else if (!strcmp(input, "linenumbers")) s->toggle = LINE_NUMBERS; + else if (!strcmp(input, "relativenumbers")) + s->toggle = RELATIVE_NUMBERS; #endif else if (!strcmp(input, "whitespacedisplay")) s->toggle = WHITESPACE_DISPLAY; diff --git a/src/winio.c b/src/winio.c index baaa96f4..dd8c0efd 100644 --- a/src/winio.c +++ b/src/winio.c @@ -2547,13 +2547,17 @@ void draw_row(int row, const char *converted, linestruct *line, size_t from_col) /* If line numbering is switched on, put a line number in front of * the text -- but only for the parts that are not softwrapped. */ if (margin > 0) { + long int linenumber = line->lineno; + wattron(midwin, interface_color_pair[LINE_NUMBER]); + if (ISSET(RELATIVE_NUMBERS)) + linenumber = labs(openfile->current->lineno - linenumber); #ifndef NANO_TINY if (ISSET(SOFTWRAP) && from_col != 0) mvwprintw(midwin, row, 0, "%*s", margin - 1, " "); else #endif - mvwprintw(midwin, row, 0, "%*zd", margin - 1, line->lineno); + mvwprintw(midwin, row, 0, "%*zd", margin - 1, linenumber); wattroff(midwin, interface_color_pair[LINE_NUMBER]); #ifndef NANO_TINY if (line->has_anchor && (from_col == 0 || !ISSET(SOFTWRAP))) @@ -3336,6 +3340,12 @@ void edit_redraw(linestruct *old_current, update_type manner) openfile->placewewant = xplustabs(); +#ifdef ENABLE_LINENUMBERS + /* When doing relative line numbers, a full refresh is needed. */ + if (ISSET(LINE_NUMBERS) && ISSET(RELATIVE_NUMBERS) && openfile->current != old_current) + refresh_needed = TRUE; +#endif + /* If the current line is offscreen, scroll until it's onscreen. */ if (current_is_offscreen()) { adjust_viewport(ISSET(JUMPY_SCROLLING) ? CENTERING : manner); diff --git a/syntax/nanorc.nanorc b/syntax/nanorc.nanorc index 18c55292..7c272a6a 100644 --- a/syntax/nanorc.nanorc +++ b/syntax/nanorc.nanorc @@ -14,7 +14,7 @@ color bold,purple "^[[:blank:]]*include[[:blank:]]+[^[:blank:]"]+" color lime "^[[:blank:]]*extendsyntax[[:blank:]]+[[:alpha:]]+[[:blank:]]+(i?color|header|magic|comment|formatter|linter|tabgives)[[:blank:]]+.*" # The arguments of commands -color brightgreen "^[[:blank:]]*(set|unset)[[:blank:]]+(afterends|allow_insecure_backup|atblanks|autoindent|backup|boldtext|bookstyle|breaklonglines|casesensitive|colonparsing|constantshow|cutfromcursor|emptyline|historylog|indicator|jumpyscrolling|linenumbers|locking|magic|minibar|mouse|multibuffer|noconvert|nohelp|nonewlines|positionlog|preserve|quickblank|rawsequences|rebinddelete|regexp|saveonexit|showcursor|smarthome|softwrap|stateflags|tabstospaces|trimblanks|unix|whitespacedisplay|wordbounds|zap|zero)\>" +color brightgreen "^[[:blank:]]*(set|unset)[[:blank:]]+(afterends|allow_insecure_backup|atblanks|autoindent|backup|boldtext|bookstyle|breaklonglines|casesensitive|colonparsing|constantshow|cutfromcursor|emptyline|historylog|indicator|jumpyscrolling|linenumbers|relativenumbers|locking|magic|minibar|mouse|multibuffer|noconvert|nohelp|nonewlines|positionlog|preserve|quickblank|rawsequences|rebinddelete|regexp|saveonexit|showcursor|smarthome|softwrap|stateflags|tabstospaces|trimblanks|unix|whitespacedisplay|wordbounds|zap|zero)\>" color brightgreen "^[[:blank:]]*set[[:blank:]]+(backupdir|brackets|errorcolor|functioncolor|keycolor|matchbrackets|minicolor|numbercolor|operatingdir|promptcolor|punct|quotestr|scrollercolor|selectedcolor|speller|spotlightcolor|statuscolor|stripecolor|titlecolor|whitespace|wordchars)[[:blank:]]+" color brightgreen "^[[:blank:]]*set[[:blank:]]+(fill[[:blank:]]+-?[[:digit:]]+|(guidestripe|tabsize)[[:blank:]]+[1-9][0-9]*)\>" color brightgreen "^[[:blank:]]*bind[[:blank:]]+((\^([[:alpha:]]|[]/@\^_`-]|Space)|([Ss][Hh]-)?[Mm]-[[:alpha:]]|[Mm]-([][!"#$%&'()*+,./0-9:;<=>?@\^_`{|}~-]|Space))|F([1-9]|1[0-9]|2[0-4])|Ins|Del)[[:blank:]]+([[:lower:]]+|".*")[[:blank:]]+(main|help|search|replace(with)?|yesno|gotoline|writeout|insert|execute|browser|whereisfile|gotodir|spell|linter|all)\>" @@ -32,7 +32,7 @@ color crimson "\{(location|gotoline|(begin|end)para|comment|complete|(un)?indent color crimson "\{(left|right|up|down|home|end|(scroll|page)(up|down)|(top|bottom)row|center|cycle|(prev|next)(word|block|anchor|buf))\}" color crimson "\{(tab|enter|delete|backspace|verbatim|refresh|suspend|casesens|regexp|backwards|older|newer|(dos|mac)format)\}" color crimson "\{(append|prepend|backup|flip(goto|replace|execute|pipe|convert|newbuffer)|browser|gotodir|(first|last)(file|line))\}" -color crimson "\{(nohelp|constantshow|softwrap|linenumbers|whitespacedisplay|nosyntax|zero)\}" +color crimson "\{(nohelp|constantshow|softwrap|linenumbers|relativenumbers|whitespacedisplay|nosyntax|zero)\}" color crimson "\{(smarthome|autoindent|cutfromcursor|breaklonglines|tabstospaces|mouse|\{)\}" # Commands -- 2.48.1
jump-relative-double-plus-or-double-minus.patch
(text/x-patch, 739 B)
diff --git a/src/search.c b/src/search.c
index e2e6f685..af41cdd4 100644
--- a/src/search.c
+++ b/src/search.c
@@ -792,11 +792,19 @@ void goto_line_and_column(ssize_t line, ssize_t column, bool retain_answer,
if (response > 0)
return;
+ bool relative = (*answer == '-' && answer[1] == '-') || (*answer == '+' && answer[1] == '+');
+
+ if (relative)
+ memmove(answer, answer + 1, strlen(answer));
+
/* Try to extract one or two numbers from the user's response. */
if (!parse_line_column(answer, &line, &column)) {
statusline(AHEM, _("Invalid line or column number"));
return;
}
+
+ if (relative)
+ line = openfile->current->lineno + line;
} else {
if (line == 0)
line = openfile->current->lineno;
OpenPGP_signature.asc
(application/pgp-signature, 840 B)
-----BEGIN PGP SIGNATURE----- wsF5BAABCAAjFiEEFo5vQpe/16ea/USWUUu+Lrjhlh8FAmhikMcFAwAAAAAACgkQUUu+Lrjhlh8L 0A/+IyU73QxWZROk2Ui1DOhFcY3TPN+WLZ70u76/MrpR1dKNJfCMt2mvT+THOf3YZlIuBom0j2xt FAlt+FKcuE3LR4gKC2ar/QcPSEP7lIjHisCYV5R8e94CbqXgo6C2BFhS16avkcQN0SwyG+HylgbF yaE0LrPrRSMkyG0fM4oFaMdBO/6hhAEriZZ+qZWE1WrCIu8B/lsSklbQopZ5dHmYU8axhyYcEssy XPXFx0qZQTA1s+HjVvTTOocooi+dQWjqF5t8tOT+MwpHasaVV8xqrRo4P1DHRc416oRCTMBZ/4fe wXX+B5M+t/yD/jJKwCnjlcZv95ZWQp5hfTQTEGsHRQeTQfIodFcOxpqhIXcRg0bZUwysg2oOfhN2 KHj+7IKQULHrAwuz/Va2i59556+j7A94ALpMYZMz2YIO0F//3BaoCQLyUhwqyBMj/eLLngmsRrGJ w5pdCzTyGsE3abNifQB4VEkqipJ0ONGGPH7dYILPbs/HcOJxBAcGoYFAZW81HG81ML9P5w3FRo37 +nPJQzrfG2ViB6nDDWEWuMLwmzLxRjZBrD96AWIKJSzRCXBU6mZLEKisBIOIjyV8ikb1wY9V6XfO /w+gIElqbWhpL6rCePY6AIuh8vY6EZSdkbC1DHSCQFi9lH7lWTRhJiHqNulgG3S+ZUKUUCQf/nkV Ybk= =7rYw -----END PGP SIGNATURE-----