From 8f27e780e1e6f166229d58e56081c925bc2ef260 Mon Sep 17 00:00:00 2001 From: Florian Fischer Date: Tue, 10 Jan 2023 13:56:22 +0100 Subject: [PATCH] allow lua to change line number styles Export the new function win:style_lineno(style, lineno) to lua. Line number styles are stored in a sorted doubly linked list in the corresponding UiTermWin struct. Setting a line number's style to win.STYLE_DEFAULT resets the style and frees the style descriptor. This is useful to present information to the user without cluttering or changing the interface to much. initial commit adding styles to line numbers --- ui-terminal.c | 120 +++++++++++++++++++++++++++++++++++++++++++++----- ui.h | 3 ++ vis-lua.c | 23 ++++++++++ 3 files changed, 135 insertions(+), 11 deletions(-) diff --git a/ui-terminal.c b/ui-terminal.c index 264c6d3c0..45dc7549a 100644 --- a/ui-terminal.c +++ b/ui-terminal.c @@ -51,16 +51,25 @@ typedef struct { bool doupdate; /* Whether to update the screen after refreshing contents */ } UiTerm; +typedef struct LinenoStyle LinenoStyle; + +struct LinenoStyle { + size_t lineno; /* linenumber to style */ + enum UiStyle style; /* style to use for the line number */ + LinenoStyle *next, *prev; /* pointer to the neighbouring descriptors */ +}; + struct UiTermWin { - UiWin uiwin; /* generic interface, has to be the first struct member */ - UiTerm *ui; /* ui which manages this window */ - Win *win; /* editor window being displayed */ - int id; /* unique identifier for this window */ - int width, height; /* window dimension including status bar */ - int x, y; /* window position */ - int sidebar_width; /* width of the sidebar showing line numbers etc. */ - UiTermWin *next, *prev; /* pointers to neighbouring windows */ - enum UiOption options; /* display settings for this window */ + UiWin uiwin; /* generic interface, has to be the first struct member */ + UiTerm *ui; /* ui which manages this window */ + Win *win; /* editor window being displayed */ + int id; /* unique identifier for this window */ + int width, height; /* window dimension including status bar */ + int x, y; /* window position */ + int sidebar_width; /* width of the sidebar showing line numbers etc. */ + LinenoStyle *lineno_styles; /* line number styles */ + UiTermWin *next, *prev; /* pointers to neighbouring windows */ + enum UiOption options; /* display settings for this window */ }; #if CONFIG_CURSES @@ -260,6 +269,10 @@ static void ui_window_draw(UiWin *w) { Cell *cells = ui->cells + y * ui->width; if (x + sidebar_width + view_width > ui->width) view_width = ui->width - x - sidebar_width; + LinenoStyle *lineno_style = win->lineno_styles; + while (line->lineno && lineno_style && line->lineno > lineno_style->lineno) + lineno_style = lineno_style->next; // skip not visible lineno styles + for (const Line *l = line; l; l = l->next, y++) { if (sidebar) { if (!l->lineno || !l->len || l->lineno == prev_lineno) { @@ -276,8 +289,15 @@ static void ui_window_draw(UiWin *w) { } snprintf(buf, sizeof buf, "%*zu ", sidebar_width-1, number); } - ui_draw_string(ui, x, y, buf, win, - (l->lineno == cursor_lineno) ? UI_STYLE_LINENUMBER_CURSOR : UI_STYLE_LINENUMBER); + + enum UiStyle style; + if (lineno_style && lineno_style->lineno == l->lineno) { + style = lineno_style->style; + lineno_style = lineno_style->next; + } else + style = (l->lineno == cursor_lineno) ? UI_STYLE_LINENUMBER_CURSOR : UI_STYLE_LINENUMBER; + + ui_draw_string(ui, x, y, buf, win, style); prev_lineno = l->lineno; } debug("draw-window: [%d][%d] ... cells[%d][%d]\n", y, x+sidebar_width, y, view_width); @@ -286,6 +306,84 @@ static void ui_window_draw(UiWin *w) { } } +static LinenoStyle* lineno_style_new(size_t lineno, enum UiStyle s) { + LinenoStyle* style = calloc(1, sizeof(LinenoStyle)); + if (!style) + return NULL; + style->lineno = lineno; + style->style = s; + return style; +} + +void ui_window_unstyle_lineno(UiWin *w, size_t lineno) { + UiTermWin *win = (UiTermWin*)w; + LinenoStyle *style = win->lineno_styles; + LinenoStyle *prev = NULL; + if (!style) + return; + + while (style && style->lineno != lineno) { + prev = style; + style = style->next; + } + + if (!style) + return; + + if (!prev) + win->lineno_styles = NULL; + else { + prev->next = style->next; + if (style->next) + style->next->prev = prev; + } + + free(style); +} + +void ui_window_style_lineno(UiWin *w, size_t lineno, enum UiStyle s) { + UiTermWin *win = (UiTermWin*)w; + LinenoStyle *style = win->lineno_styles; + LinenoStyle *prev = NULL; + + // First line number style + if (!style) { + win->lineno_styles = lineno_style_new(lineno, s); + return; + } + + while (style && style->lineno < lineno) { + prev = style; + style = style->next; + } + + if (style && style->lineno == lineno) { + style->style = s; + return; + } + + LinenoStyle *new = lineno_style_new(lineno, s); + if (!new) + return; + + // Append new style to list + if (!style) { + new->prev = prev; + prev->next = new; + } + else if (!prev) { // Prepend new style to list + win->lineno_styles = new; + new->next = style; + style->prev = new; + } else { // Insert new style into the list + new->prev = prev; + new->next = style; + + style->prev = new; + prev->next = new; + } +} + static CellStyle ui_window_style_get(UiWin *w, enum UiStyle style) { UiTermWin *win = (UiTermWin*)w; UiTerm *tui = win->ui; diff --git a/ui.h b/ui.h index ce98af1c1..b8a516019 100644 --- a/ui.h +++ b/ui.h @@ -119,4 +119,7 @@ struct UiWin { bool is_default_color(CellColor c); enum UiLayout ui_layout_get(Ui *ui); +void ui_window_unstyle_lineno(UiWin*, size_t); +void ui_window_style_lineno(UiWin*, size_t, enum UiStyle); + #endif diff --git a/vis-lua.c b/vis-lua.c index 98a524993..7868c98e7 100644 --- a/vis-lua.c +++ b/vis-lua.c @@ -2093,6 +2093,28 @@ static int window_style(lua_State *L) { return 0; } +/*** + * Style a window line number. + * + * The style will never be cleared and must be reset manually. + * @function style_lineno + * @tparam int id the display style as registered with @{style_define} + * @tparam int lineno the absolute file position in bytes + * @see style_define + * @usage + * win:style_lineno(win.STYLE_DEFAULT, 42) + */ +static int window_style_lineno(lua_State *L) { + Win *win = obj_ref_check(L, 1, VIS_LUA_TYPE_WINDOW); + enum UiStyle style = luaL_checkunsigned(L, 2); + size_t lineno = checkpos(L, 3); + if (style == UI_STYLE_DEFAULT) + ui_window_unstyle_lineno(win->ui, lineno); + else + ui_window_style_lineno(win->ui, lineno, style); + return 0; +} + /*** * Set window status line. * @@ -2162,6 +2184,7 @@ static const struct luaL_Reg window_funcs[] = { { "unmap", window_unmap }, { "style_define", window_style_define }, { "style", window_style }, + { "style_lineno", window_style_lineno }, { "status", window_status }, { "draw", window_draw }, { "close", window_close },