From 408cdceda01219b30920306fa483308f9b4e058a Mon Sep 17 00:00:00 2001 From: faissaloo Date: Tue, 6 Sep 2016 21:07:39 +0100 Subject: [PATCH] Added line number support --- configure.ac | 6 +++ doc/man/nanorc.5 | 5 +++ src/global.c | 9 ++++ src/nano.h | 4 +- src/proto.h | 1 + src/rcfile.c | 4 ++ src/utils.c | 6 +-- src/winio.c | 133 ++++++++++++++++++++++++++++++++++++++++++++----------- 8 files changed, 139 insertions(+), 29 deletions(-) diff --git a/configure.ac b/configure.ac index e024a1e..0076e4a 100644 --- a/configure.ac +++ b/configure.ac @@ -125,6 +125,12 @@ fi AC_ARG_ENABLE(libmagic, AS_HELP_STRING([--disable-libmagic], [Disable detection of file types via libmagic])) +AC_ARG_ENABLE(linenumbers, +AS_HELP_STRING([--disable-linenumbers], [Disable help functions])) +if test "x$enable_linenumbers" = xno; then + AC_DEFINE(DISABLE_LINE_NUM, 1, [Define this to disable linenumbering]) +fi + AC_ARG_ENABLE(mouse, AS_HELP_STRING([--disable-mouse], [Disable mouse support (and -m flag)])) if test "x$enable_mouse" = xno; then diff --git a/doc/man/nanorc.5 b/doc/man/nanorc.5 index 801f7f5..e3ea45c 100644 --- a/doc/man/nanorc.5 +++ b/doc/man/nanorc.5 @@ -104,6 +104,8 @@ Specify the color combination to use for the function descriptions in the two help lines at the bottom of the screen. See \fBset titlecolor\fR for more details. .TP +.B set hexlinenumbers +Like linenumbers but uses hexadecimal for the numbers in the ruler. .B set historylog Enable the use of \fB~/.nano/search_history\fP for saving and reading search/replace strings. @@ -116,6 +118,9 @@ Specify the color combination to use for the shortcut key combos in the two help lines at the bottom of the screen. See \fBset titlecolor\fR for more details. .TP +.B set linenumbers +When compiled with line numbering support will draw a line number 'ruler' +in the margin. .B set locking Enable vim-style lock-files for when editing files. .TP diff --git a/src/global.c b/src/global.c index 84d239d..da91e7b 100644 --- a/src/global.c +++ b/src/global.c @@ -48,6 +48,7 @@ bool focusing = TRUE; message_type lastmessage = HUSH; /* Messages of type HUSH should not overwrite type MILD nor ALERT. */ +int margin = 0; #ifndef NANO_TINY int controlleft, controlright, controlup, controldown; int shiftcontrolleft, shiftcontrolright, shiftcontrolup, shiftcontroldown; @@ -1172,6 +1173,10 @@ void shortcut_init(void) #ifndef NANO_TINY /* Group of "Appearance" toggles. */ + #ifndef DISABLE_LINE_NUM + add_to_sclist(MMAIN, "M-#", do_toggle_void, LINE_NUM); + add_to_sclist(MMAIN, "M-!", do_toggle_void, HEX_LINE_NUM); + #endif add_to_sclist(MMAIN, "M-X", do_toggle_void, NO_HELP); add_to_sclist(MMAIN, "M-C", do_toggle_void, CONST_UPDATE); add_to_sclist(MMAIN, "M-O", do_toggle_void, MORE_SPACE); @@ -1357,6 +1362,10 @@ const char *flagtostr(int flag) return N_("No conversion from DOS/Mac format"); case SUSPEND: return N_("Suspension"); + case LINE_NUM: + return N_("Line numbering"); + case HEX_LINE_NUM: + return N_("Hex line numbering"); default: return "?????"; } diff --git a/src/nano.h b/src/nano.h index 4e31f34..a45c997 100644 --- a/src/nano.h +++ b/src/nano.h @@ -535,7 +535,9 @@ enum LOCKING, NOREAD_MODE, MAKE_IT_UNIX, - JUSTIFY_TRIM + JUSTIFY_TRIM, + LINE_NUM, + HEX_LINE_NUM }; /* Flags for the menus in which a given function should be present. */ diff --git a/src/proto.h b/src/proto.h index 85e1db0..d4b4112 100644 --- a/src/proto.h +++ b/src/proto.h @@ -40,6 +40,7 @@ extern bool focusing; extern message_type lastmessage; +extern int margin; #ifndef NANO_TINY extern int controlleft; extern int controlright; diff --git a/src/rcfile.c b/src/rcfile.c index 1b1b5d3..b4f540a 100644 --- a/src/rcfile.c +++ b/src/rcfile.c @@ -35,6 +35,10 @@ static const rcoption rcopts[] = { {"boldtext", BOLD_TEXT}, +#ifndef DISABLE_LINE_NUM + {"linenumbers", LINE_NUM}, + {"hexlinenumbers", HEX_LINE_NUM}, +#endif #ifndef DISABLE_JUSTIFY {"brackets", 0}, #endif diff --git a/src/utils.c b/src/utils.c index dd29741..9f23ee8 100644 --- a/src/utils.c +++ b/src/utils.c @@ -439,12 +439,12 @@ char *free_and_assign(char *dest, char *src) * get_page_start(column) < COLS). */ size_t get_page_start(size_t column) { - if (column == 0 || column < COLS - 1) + if (column == 0 || column < COLS - 1 - margin) return 0; else if (COLS > 8) - return column - 7 - (column - 7) % (COLS - 8); + return column - 7 - (column - 7) % (COLS - 8 - margin); else - return column - (COLS - 2); + return column - (COLS - 2 - margin); } /* Return the placewewant associated with current_x, i.e. the zero-based diff --git a/src/winio.c b/src/winio.c index ab32c93..d29010e 100644 --- a/src/winio.c +++ b/src/winio.c @@ -1533,7 +1533,7 @@ int get_mouseinput(int *mouse_x, int *mouse_y, bool allow_shortcuts) return -1; /* Save the screen coordinates where the mouse event took place. */ - *mouse_x = mevent.x; + *mouse_x = mevent.x - margin; *mouse_y = mevent.y; in_bottomwin = wenclose(bottomwin, *mouse_y, *mouse_x); @@ -1563,7 +1563,7 @@ int get_mouseinput(int *mouse_x, int *mouse_y, bool allow_shortcuts) if (*mouse_y == 0) { /* Restore the untranslated mouse event coordinates, so * that they're relative to the entire screen again. */ - *mouse_x = mevent.x; + *mouse_x = mevent.x - margin; *mouse_y = mevent.y; return 0; @@ -1904,7 +1904,7 @@ char *display_string(const char *buf, size_t start_col, size_t span, converted[index] = '\0'; /* Make sure converted takes up no more than span columns. */ - index = actual_x(converted, span); + index = actual_x(converted, span - margin); null_at(&converted, index); return converted; @@ -2219,13 +2219,13 @@ void reset_cursor(void) openfile->current_y = 0; while (line != NULL && line != openfile->current) { - openfile->current_y += strlenpt(line->data) / COLS + 1; + openfile->current_y += (strlenpt(line->data)) / (COLS - margin) + 1; line = line->next; } - openfile->current_y += xpt / COLS; + openfile->current_y += xpt / (COLS - margin); if (openfile->current_y < editwinrows) - wmove(edit, openfile->current_y, xpt % COLS); + wmove(edit, openfile->current_y, (xpt % (COLS - margin)) + margin); } else #endif { @@ -2233,10 +2233,68 @@ void reset_cursor(void) openfile->edittop->lineno; if (openfile->current_y < editwinrows) - wmove(edit, openfile->current_y, xpt - get_page_start(xpt)); + wmove(edit, openfile->current_y, (xpt - get_page_start(xpt))+margin); } } +int intlen(int n) +{ + if (n < 100000) { + // 5 or less + if (n < 100) { + // 1 or 2 + if (n < 10) + return 1; + else + return 2; + } + else { + // 3 or 4 or 5 + if (n < 1000) + return 3; + else { + // 4 or 5 + if (n < 10000) + return 4; + else + return 5; + } + } + } + else + { + // 6 or more + if (n < 10000000) { + // 6 or 7 + if (n < 1000000) + return 6; + else + return 7; + } + else { + // 8 to 10 + if (n < 100000000) + return 8; + else { + // 9 or 10 + if (n < 1000000000) + return 9; + else + return 10; + } + } + } +} + +int hexlen(int n) +{ + int len=0; + while (n!=0) { + n>>=4; //One hex digit = one nibble + len++; + } + return len; +} /* edit_draw() takes care of the job of actually painting a line into * the edit window. fileptr is the line to be painted, at row line of * the window. converted is the actual string to be written to the @@ -2248,6 +2306,31 @@ void reset_cursor(void) void edit_draw(filestruct *fileptr, const char *converted, int line, size_t start) { + #ifndef DISABLE_LINE_NUM + if (ISSET(LINE_NUM)) { + if (margin != intlen(openfile->filebot->lineno) + 3) { + refresh_needed = TRUE; + margin = intlen(openfile->filebot->lineno) + 3; + } + + mvwprintw(edit,line, + margin - (intlen(fileptr->lineno) + 2), + "%i│", fileptr->lineno); + } else if (ISSET(HEX_LINE_NUM)) { + if (margin != hexlen(openfile->filebot->lineno) + 3) { + refresh_needed = TRUE; + margin = hexlen(openfile->filebot->lineno) + 3; + } + + mvwprintw(edit, line, + margin - (hexlen(fileptr->lineno) + 2), + "%X│", fileptr->lineno); + } + else + { + margin = 0; + } + #endif #if !defined(NANO_TINY) || !defined(DISABLE_COLOR) size_t startpos = actual_x(fileptr->data, start); /* The position in fileptr->data of the leftmost character @@ -2265,7 +2348,7 @@ void edit_draw(filestruct *fileptr, const char *converted, int /* First simply paint the line -- then we'll add colors or the * marking highlight on just the pieces that need it. */ - mvwaddstr(edit, line, 0, converted); + mvwaddstr(edit, line, margin, converted); #ifdef USING_OLD_NCURSES /* Tell ncurses to really redraw the line without trying to optimize @@ -2343,7 +2426,7 @@ void edit_draw(filestruct *fileptr, const char *converted, int assert(0 <= x_start && 0 <= paintlen); - mvwaddnstr(edit, line, x_start, converted + + mvwaddnstr(edit, line, x_start + margin, converted + index, paintlen); } k = startmatch.rm_eo; @@ -2360,7 +2443,7 @@ void edit_draw(filestruct *fileptr, const char *converted, int if (fileptr->multidata[varnish->id] == CNONE) goto tail_of_loop; else if (fileptr->multidata[varnish->id] == CWHOLELINE) { - mvwaddnstr(edit, line, 0, converted, -1); + mvwaddnstr(edit, line, margin, converted, -1); goto tail_of_loop; } else if (fileptr->multidata[varnish->id] == CBEGINBEFORE) { regexec(varnish->end, fileptr->data, 1, &endmatch, 0); @@ -2369,7 +2452,7 @@ void edit_draw(filestruct *fileptr, const char *converted, int goto tail_of_loop; paintlen = actual_x(converted, strnlenpt(fileptr->data, endmatch.rm_eo) - start); - mvwaddnstr(edit, line, 0, converted, paintlen); + mvwaddnstr(edit, line, margin, converted, paintlen); goto tail_of_loop; } if (fileptr->multidata[varnish->id] == -1) /* Assume this until proven otherwise below. */ @@ -2465,7 +2548,7 @@ void edit_draw(filestruct *fileptr, const char *converted, int fprintf(stderr, " Marking for id %i line %i as CBEGINBEFORE\n", varnish->id, line); #endif } - mvwaddnstr(edit, line, 0, converted, paintlen); + mvwaddnstr(edit, line, margin, converted, paintlen); /* If the whole line has been painted, don't bother looking * for any more starts. */ if (paintlen < 0) @@ -2513,7 +2596,7 @@ void edit_draw(filestruct *fileptr, const char *converted, int assert(0 <= x_start && x_start < COLS); - mvwaddnstr(edit, line, x_start, + mvwaddnstr(edit, line, x_start + margin, converted + index, paintlen); if (paintlen > 0) { fileptr->multidata[varnish->id] = CSTARTENDHERE; @@ -2543,7 +2626,7 @@ void edit_draw(filestruct *fileptr, const char *converted, int assert(0 <= x_start && x_start < COLS); /* Paint the rest of the line. */ - mvwaddnstr(edit, line, x_start, converted + index, -1); + mvwaddnstr(edit, line, x_start + margin, converted + index, -1); fileptr->multidata[varnish->id] = CENDAFTER; #ifdef DEBUG fprintf(stderr, " Marking for id %i line %i as CENDAFTER\n", varnish->id, line); @@ -2618,10 +2701,10 @@ void edit_draw(filestruct *fileptr, const char *converted, int index = actual_x(converted, x_start); if (paintlen > 0) - paintlen = actual_x(converted + index, paintlen); + paintlen = actual_x(converted + index + margin, paintlen); wattron(edit, hilite_attribute); - mvwaddnstr(edit, line, x_start, converted + index, paintlen); + mvwaddnstr(edit, line, x_start + margin, converted + index, paintlen); wattroff(edit, hilite_attribute); } } @@ -2649,7 +2732,7 @@ int update_line(filestruct *fileptr, size_t index) filestruct *tmp; for (tmp = openfile->edittop; tmp && tmp != fileptr; tmp = tmp->next) - line += (strlenpt(tmp->data) / COLS) + 1; + line += ((strlenpt(tmp->data) + margin) / COLS) + 1; } else #endif line = fileptr->lineno - openfile->edittop->lineno; @@ -2673,9 +2756,9 @@ int update_line(filestruct *fileptr, size_t index) /* Expand the line, replacing tabs with spaces, and control * characters with their displayed forms. */ #ifdef NANO_TINY - converted = display_string(fileptr->data, page_start, COLS, TRUE); + converted = display_string(fileptr->data, page_start, COLS + 1, TRUE); #else - converted = display_string(fileptr->data, page_start, COLS, !ISSET(SOFTWRAP)); + converted = display_string(fileptr->data, page_start, COLS + 1, !ISSET(SOFTWRAP)); #ifdef DEBUG if (ISSET(SOFTWRAP) && strlen(converted) >= COLS - 2) fprintf(stderr, "update_line(): converted(1) line = %s\n", converted); @@ -2690,13 +2773,13 @@ int update_line(filestruct *fileptr, size_t index) if (!ISSET(SOFTWRAP)) { #endif if (page_start > 0) - mvwaddch(edit, line, 0, '$'); - if (strlenpt(fileptr->data) > page_start + COLS) + mvwaddch(edit, line, margin, '$'); + if (strlenpt(fileptr->data) > page_start + COLS - margin) mvwaddch(edit, line, COLS - 1, '$'); #ifndef NANO_TINY } else { size_t full_length = strlenpt(fileptr->data); - for (index += COLS; index <= full_length && line < editwinrows - 1; index += COLS) { + for (index += COLS - margin; index <= full_length && line < editwinrows - 1; index += COLS - margin) { line++; #ifdef DEBUG fprintf(stderr, "update_line(): softwrap code, moving to %d index %lu\n", line, (unsigned long)index); @@ -2748,7 +2831,7 @@ void compute_maxrows(void) maxrows = 0; for (n = 0; n < editwinrows && foo; n++) { maxrows++; - n += strlenpt(foo->data) / COLS; + n += (strlenpt(foo->data) + margin) / COLS; foo = foo->next; } @@ -2793,7 +2876,7 @@ void edit_scroll(scroll_dir direction, ssize_t nlines) #ifndef NANO_TINY /* Don't over-scroll on long lines. */ if (ISSET(SOFTWRAP) && direction == UPWARD) { - ssize_t len = strlenpt(openfile->edittop->data) / COLS; + ssize_t len = (strlenpt(openfile->edittop->data) + margin) / COLS; i -= len; if (len > 0) refresh_needed = TRUE; @@ -2982,7 +3065,7 @@ void edit_update(update_type manner) goal --; #ifndef NANO_TINY if (ISSET(SOFTWRAP)) - goal -= strlenpt(openfile->edittop->data) / COLS; + goal -= (strlenpt(openfile->edittop->data) + margin) / COLS; #endif } #ifdef DEBUG -- 2.7.4