# HG changeset patch # User Bram Moolenaar # Date 1560801609 -7200 # Node ID 4fb68abc770f801364d969a802a01dcdc72c817c # Parent ba266d95db3f7c59bcbc2e0d5629e48c932592c9 patch 8.1.1564: sign column takes up space commit https://github.com/vim/vim/commit/394c5d8870b15150fc91a4c058dc571fd5eaa97e Author: Bram Moolenaar Date: Mon Jun 17 21:48:05 2019 +0200 patch 8.1.1564: sign column takes up space Problem: Sign column takes up space. (Adam Stankiewicz) Solution: Optionally put signs in the number column. (Yegappan Lakshmanan, closes #4555, closes #4515) diff --git a/runtime/doc/options.txt b/runtime/doc/options.txt --- a/runtime/doc/options.txt +++ b/runtime/doc/options.txt @@ -6803,6 +6803,8 @@ A jump table for the options with a shor "auto" only when there is a sign to display "no" never "yes" always + "number" display signs in the 'number' column. If the number + column is not present, then behaves like 'auto'. *'smartcase'* *'scs'* *'nosmartcase'* *'noscs'* diff --git a/src/option.c b/src/option.c --- a/src/option.c +++ b/src/option.c @@ -3231,7 +3231,7 @@ static char *(p_fcl_values[]) = {"all", static char *(p_cot_values[]) = {"menu", "menuone", "longest", "preview", "noinsert", "noselect", NULL}; #endif #ifdef FEAT_SIGNS -static char *(p_scl_values[]) = {"yes", "no", "auto", NULL}; +static char *(p_scl_values[]) = {"yes", "no", "auto", "number", NULL}; #endif #if defined(MSWIN) && defined(FEAT_TERMINAL) static char *(p_twt_values[]) = {"winpty", "conpty", "", NULL}; @@ -13556,6 +13556,12 @@ get_bkc_value(buf_T *buf) int signcolumn_on(win_T *wp) { + // If 'signcolumn' is set to 'number', signs are displayed in the 'number' + // column (if present). Otherwise signs are to be displayed in the sign + // column. + if (*wp->w_p_scl == 'n' && *(wp->w_p_scl + 1) == 'u') + return wp->w_buffer->b_signlist != NULL && !wp->w_p_nu && !wp->w_p_rnu; + if (*wp->w_p_scl == 'n') return FALSE; if (*wp->w_p_scl == 'y') diff --git a/src/screen.c b/src/screen.c --- a/src/screen.c +++ b/src/screen.c @@ -3037,6 +3037,91 @@ text_prop_compare(const void *s1, const } #endif +#ifdef FEAT_SIGNS +/* + * Get information needed to display the sign in line 'lnum' in window 'wp'. + * If 'nrcol' is TRUE, the sign is going to be displayed in the number column. + * Otherwise the sign is going to be displayed in the sign column. + */ + static void +get_sign_display_info( + int nrcol, + win_T *wp, + linenr_T lnum, + int wcr_attr, + int row, + int startrow, + int filler_lines, + int filler_todo, + int *c_extrap, + int *c_finalp, + char_u *extra, + char_u **pp_extra, + int *n_extrap, + int *char_attrp) +{ + int text_sign; +# ifdef FEAT_SIGN_ICONS + int icon_sign; +# endif + + // Draw two cells with the sign value or blank. + *c_extrap = ' '; + *c_finalp = NUL; + if (nrcol) + *n_extrap = number_width(wp) + 1; + else + { + *char_attrp = hl_combine_attr(wcr_attr, HL_ATTR(HLF_SC)); + *n_extrap = 2; + } + + if (row == startrow +#ifdef FEAT_DIFF + + filler_lines && filler_todo <= 0 +#endif + ) + { + text_sign = buf_getsigntype(wp->w_buffer, lnum, SIGN_TEXT); +# ifdef FEAT_SIGN_ICONS + icon_sign = buf_getsigntype(wp->w_buffer, lnum, SIGN_ICON); + if (gui.in_use && icon_sign != 0) + { + // Use the image in this position. + *c_extrap = SIGN_BYTE; + *c_finalp = NUL; +# ifdef FEAT_NETBEANS_INTG + if (buf_signcount(wp->w_buffer, lnum) > 1) + { + *c_extrap = MULTISIGN_BYTE; + *c_finalp = NUL; + } +# endif + *char_attrp = icon_sign; + } + else +# endif + if (text_sign != 0) + { + *pp_extra = sign_get_text(text_sign); + if (*pp_extra != NULL) + { + if (nrcol) + { + sprintf((char *)extra, "%-*s ", number_width(wp), + *pp_extra); + *pp_extra = extra; + } + *c_extrap = NUL; + *c_finalp = NUL; + *n_extrap = (int)STRLEN(*pp_extra); + } + *char_attrp = sign_get_attr(text_sign, FALSE); + } + } +} +#endif + /* * Display line "lnum" of window 'wp' on the screen. * Start at row "startrow", stop when "endrow" is reached. @@ -3876,58 +3961,9 @@ win_line( /* Show the sign column when there are any signs in this * buffer or when using Netbeans. */ if (signcolumn_on(wp)) - { - int text_sign; -# ifdef FEAT_SIGN_ICONS - int icon_sign; -# endif - - /* Draw two cells with the sign value or blank. */ - c_extra = ' '; - c_final = NUL; - char_attr = hl_combine_attr(wcr_attr, HL_ATTR(HLF_SC)); - n_extra = 2; - - if (row == startrow -#ifdef FEAT_DIFF - + filler_lines && filler_todo <= 0 -#endif - ) - { - text_sign = buf_getsigntype(wp->w_buffer, lnum, - SIGN_TEXT); -# ifdef FEAT_SIGN_ICONS - icon_sign = buf_getsigntype(wp->w_buffer, lnum, - SIGN_ICON); - if (gui.in_use && icon_sign != 0) - { - /* Use the image in this position. */ - c_extra = SIGN_BYTE; - c_final = NUL; -# ifdef FEAT_NETBEANS_INTG - if (buf_signcount(wp->w_buffer, lnum) > 1) - { - c_extra = MULTISIGN_BYTE; - c_final = NUL; - } -# endif - char_attr = icon_sign; - } - else -# endif - if (text_sign != 0) - { - p_extra = sign_get_text(text_sign); - if (p_extra != NULL) - { - c_extra = NUL; - c_final = NUL; - n_extra = (int)STRLEN(p_extra); - } - char_attr = sign_get_attr(text_sign, FALSE); - } - } - } + get_sign_display_info(FALSE, wp, lnum, wcr_attr, row, + startrow, filler_lines, filler_todo, &c_extra, + &c_final, extra, &p_extra, &n_extra, &char_attr); } #endif @@ -3943,13 +3979,27 @@ win_line( #endif || vim_strchr(p_cpo, CPO_NUMCOL) == NULL)) { - /* Draw the line number (empty space after wrapping). */ - if (row == startrow +#ifdef FEAT_SIGNS + // If 'signcolumn' is set to 'number' and a sign is present + // in 'lnum', then display the sign instead of the line + // number. + if ((*wp->w_p_scl == 'n' && *(wp->w_p_scl + 1) == 'u') + && buf_findsign_id(wp->w_buffer, lnum, + (char_u *)"*") != 0) + get_sign_display_info(TRUE, wp, lnum, wcr_attr, row, + startrow, filler_lines, filler_todo, &c_extra, + &c_final, extra, &p_extra, &n_extra, + &char_attr); + else +#endif + { + /* Draw the line number (empty space after wrapping). */ + if (row == startrow #ifdef FEAT_DIFF + filler_lines #endif ) - { + { long num; char *fmt = "%*ld "; @@ -3992,23 +4042,24 @@ win_line( p_extra = extra; c_extra = NUL; c_final = NUL; - } - else - { + } + else + { c_extra = ' '; c_final = NUL; - } - n_extra = number_width(wp) + 1; - char_attr = hl_combine_attr(wcr_attr, HL_ATTR(HLF_N)); + } + n_extra = number_width(wp) + 1; + char_attr = hl_combine_attr(wcr_attr, HL_ATTR(HLF_N)); #ifdef FEAT_SYN_HL - /* When 'cursorline' is set highlight the line number of - * the current line differently. - * TODO: Can we use CursorLine instead of CursorLineNr - * when CursorLineNr isn't set? */ - if ((wp->w_p_cul || wp->w_p_rnu) + /* When 'cursorline' is set highlight the line number of + * the current line differently. + * TODO: Can we use CursorLine instead of CursorLineNr + * when CursorLineNr isn't set? */ + if ((wp->w_p_cul || wp->w_p_rnu) && lnum == wp->w_cursor.lnum) char_attr = hl_combine_attr(wcr_attr, HL_ATTR(HLF_CLN)); #endif + } } } diff --git a/src/testdir/test_signs.vim b/src/testdir/test_signs.vim --- a/src/testdir/test_signs.vim +++ b/src/testdir/test_signs.vim @@ -1736,3 +1736,60 @@ func Test_sign_cursor_position() call StopVimInTerminal(buf) call delete('XtestSigncolumn') endfunc + +" Return the 'len' characters in screen starting from (row,col) +func s:ScreenLine(row, col, len) + let s = '' + for i in range(a:len) + let s .= nr2char(screenchar(a:row, a:col + i)) + endfor + return s +endfunc + +" Test for 'signcolumn' set to 'number'. +func Test_sign_numcol() + new + call append(0, "01234") + " With 'signcolumn' set to 'number', make sure sign is displayed in the + " number column and line number is not displayed. + set numberwidth=2 + set number + set signcolumn=number + sign define sign1 text==> + sign place 10 line=1 name=sign1 + redraw! + call assert_equal("=> 01234", s:ScreenLine(1, 1, 8)) + + " With 'signcolumn' set to 'number', when there is no sign, make sure line + " number is displayed in the number column + sign unplace 10 + redraw! + call assert_equal("1 01234", s:ScreenLine(1, 1, 7)) + + " Disable number column. Check whether sign is displayed in the sign column + set numberwidth=4 + set nonumber + sign place 10 line=1 name=sign1 + redraw! + call assert_equal("=>01234", s:ScreenLine(1, 1, 7)) + + " Enable number column. Check whether sign is displayed in the number column + set number + redraw! + call assert_equal("=> 01234", s:ScreenLine(1, 1, 9)) + + " Disable sign column. Make sure line number is displayed + set signcolumn=no + redraw! + call assert_equal(" 1 01234", s:ScreenLine(1, 1, 9)) + + " Enable auto sign column. Make sure both sign and line number are displayed + set signcolumn=auto + redraw! + call assert_equal("=> 1 01234", s:ScreenLine(1, 1, 11)) + + sign undefine sign1 + set signcolumn& + set number& + enew! | close +endfunc diff --git a/src/version.c b/src/version.c --- a/src/version.c +++ b/src/version.c @@ -778,6 +778,8 @@ static char *(features[]) = static int included_patches[] = { /* Add new patch number below this line */ /**/ + 1564, +/**/ 1563, /**/ 1562,