From 62ccfe59ae63858dc5c21039e907a9277134d171 Mon Sep 17 00:00:00 2001 From: Rudy Dellomas III <dther@dther.xyz> Date: Sat, 20 Apr 2024 03:17:14 +1000 Subject: [PATCH 1/3] Add Lua function to Win for directly editing cell styling by position --- ui-terminal.c | 15 +++++++++++++++ ui.h | 1 + vis-lua.c | 27 +++++++++++++++++++++++++++ 3 files changed, 43 insertions(+) diff --git a/ui-terminal.c b/ui-terminal.c index dd04f7613..6ec1e413c 100644 --- a/ui-terminal.c +++ b/ui-terminal.c @@ -69,6 +69,9 @@ struct UiTermWin { #include "ui-terminal-vt100.c" #endif +/* helper macro for handling UiTerm.cells */ +#define CELL_AT_POS(UI, X, Y) (((UI)->cells) + (X) + ((Y) * (UI)->width)); + __attribute__((noreturn)) static void ui_die(Ui *ui, const char *msg, va_list ap) { UiTerm *tui = (UiTerm*)ui; ui_term_backend_free(tui); @@ -305,6 +308,17 @@ static void ui_window_style_set(UiWin *w, Cell *cell, enum UiStyle id) { memcpy(&cell->style, &set, sizeof(CellStyle)); } +static bool ui_window_style_set_pos(UiWin *w, int x, int y, enum UiStyle id) { + UiTermWin *win = (UiTermWin*)w; + UiTerm *tui = win->ui; + if (x < 0 || y < 0 || y >= win->height || x >= win->width) { + return false; + } + Cell *cell = CELL_AT_POS(tui, win->x + x, win->y + y) + ui_window_style_set(w, cell, id); + return true; +} + static void ui_window_status(UiWin *w, const char *status) { UiTermWin *win = (UiTermWin*)w; if (!(win->options & UI_OPTION_STATUSBAR)) @@ -534,6 +548,7 @@ static UiWin *ui_window_new(Ui *ui, Win *w, enum UiOption options) { win->uiwin = (UiWin) { .style_set = ui_window_style_set, + .style_set_pos = ui_window_style_set_pos, .status = ui_window_status, .options_set = ui_window_options_set, .options_get = ui_window_options_get, diff --git a/ui.h b/ui.h index 76bdcce33..45b6065eb 100644 --- a/ui.h +++ b/ui.h @@ -97,6 +97,7 @@ struct Ui { struct UiWin { void (*style_set)(UiWin*, Cell*, enum UiStyle); + bool (*style_set_pos)(UiWin*, int x, int y, enum UiStyle); void (*status)(UiWin*, const char *txt); void (*options_set)(UiWin*, enum UiOption); enum UiOption (*options_get)(UiWin*); diff --git a/vis-lua.c b/vis-lua.c index a3029fab4..3d80293ab 100644 --- a/vis-lua.c +++ b/vis-lua.c @@ -2106,6 +2106,32 @@ static int window_style(lua_State *L) { return 0; } +/*** + * Style the single terminal cell at the given coordinates, relative to this window. + * + * Completely independent of the file buffer, and can be used to style UI elements, + * such as the status bar. + * The style will be cleared after every window redraw. + * @function style_pos + * @tparam int id display style registered with @{style_define} + * @tparam int x 0-based x coordinate within Win, where (0,0) is the top left corner + * @tparam int y See above + * @treturn bool false if the coordinates would be outside the window's dimensions + * @see style_define + * @usage + * win:style_pos(win.STYLE_COLOR_COLUMN, 0, win.height - 1) + * -- Styles the first character of the status bar (or the last line, if disabled) + */ +static int window_style_pos(lua_State *L) { + Win *win = obj_ref_check(L, 1, VIS_LUA_TYPE_WINDOW); + enum UiStyle style = luaL_checkunsigned(L, 2); + size_t x = checkpos(L, 3); + size_t y = checkpos(L, 4); + bool ret = win->ui->style_set_pos(win->ui, (int)x, (int)y, style); + lua_pushboolean(L, ret); + return 1; +} + /*** * Set window status line. * @@ -2175,6 +2201,7 @@ static const struct luaL_Reg window_funcs[] = { { "unmap", window_unmap }, { "style_define", window_style_define }, { "style", window_style }, + { "style_pos", window_style_pos }, { "status", window_status }, { "draw", window_draw }, { "close", window_close }, From 596ec20dd81fc4a48a528bfed9e241343ee03eaa Mon Sep 17 00:00:00 2001 From: Rudy Dellomas III <dther@dther.xyz> Date: Sun, 21 Apr 2024 20:25:40 +1000 Subject: [PATCH 2/3] Emit an event (ui_draw) immediately before drawing the screen This allows better control over styling, as well as potential for entirely new UI elements implemented entirely using the Lua API. --- lua/vis.lua | 2 ++ main.c | 1 + ui-terminal.c | 1 + vis-core.h | 1 + vis-lua.c | 14 +++++++++++++- vis-lua.h | 1 + vis.c | 4 ++++ vis.h | 1 + 8 files changed, 24 insertions(+), 1 deletion(-) diff --git a/lua/vis.lua b/lua/vis.lua index 32fb2a12b..5473f17df 100644 --- a/lua/vis.lua +++ b/lua/vis.lua @@ -167,6 +167,7 @@ local events = { WIN_STATUS = "Event::WIN_STATUS", -- see @{win_status} TERM_CSI = "Event::TERM_CSI", -- see @{term_csi} PROCESS_RESPONSE = "Event::PROCESS_RESPONSE", -- see @{process_response} + UI_DRAW = "Event::UI_DRAW", -- see @{ui_draw} } events.file_close = function(...) events.emit(events.FILE_CLOSE, ...) end @@ -183,6 +184,7 @@ events.win_open = function(...) events.emit(events.WIN_OPEN, ...) end events.win_status = function(...) events.emit(events.WIN_STATUS, ...) end events.term_csi = function(...) events.emit(events.TERM_CSI, ...) end events.process_response = function(...) events.emit(events.PROCESS_RESPONSE, ...) end +events.ui_draw = function(...) events.emit(events.UI_DRAW, ...) end local handlers = {} diff --git a/main.c b/main.c index 8e5ad4287..8aa31c6b8 100644 --- a/main.c +++ b/main.c @@ -2229,6 +2229,7 @@ int main(int argc, char *argv[]) { .win_highlight = vis_lua_win_highlight, .win_status = vis_lua_win_status, .term_csi = vis_lua_term_csi, + .ui_draw = vis_lua_ui_draw, }; vis = vis_new(ui_term_new(), &event); diff --git a/ui-terminal.c b/ui-terminal.c index 6ec1e413c..09e618ea8 100644 --- a/ui-terminal.c +++ b/ui-terminal.c @@ -392,6 +392,7 @@ static void ui_draw(Ui *ui) { ui_window_draw((UiWin*)win); if (tui->info[0]) ui_draw_string(tui, 0, tui->height-1, tui->info, NULL, UI_STYLE_INFO); + vis_event_emit(tui->vis, VIS_EVENT_UI_DRAW); ui_term_backend_blit(tui); } diff --git a/vis-core.h b/vis-core.h index 8d3980cd9..4f81e4cbd 100644 --- a/vis-core.h +++ b/vis-core.h @@ -236,6 +236,7 @@ enum VisEvents { VIS_EVENT_WIN_HIGHLIGHT, VIS_EVENT_WIN_STATUS, VIS_EVENT_TERM_CSI, + VIS_EVENT_UI_DRAW, }; bool vis_event_emit(Vis*, enum VisEvents, ...); diff --git a/vis-lua.c b/vis-lua.c index 3d80293ab..91ee42894 100644 --- a/vis-lua.c +++ b/vis-lua.c @@ -166,7 +166,7 @@ void vis_lua_win_status(Vis *vis, Win *win) { window_status_update(vis, win); } void vis_lua_term_csi(Vis *vis, const long *csi) { } void vis_lua_process_response(Vis *vis, const char *name, char *buffer, size_t len, ResponseType rtype) { } - +void vis_lua_ui_draw(Vis *vis) { } #else @@ -3689,4 +3689,16 @@ void vis_lua_process_response(Vis *vis, const char *name, lua_pop(L, 1); } +/*** + * Emitted immediately before the UI is drawn to the screen. + * Allows last-minute overrides to the styling of UI elements. + * + * *WARNING:* This is emitted every screen draw! + * Use sparingly and check for `nil` values! + * @function ui_draw + */ +void vis_lua_ui_draw(Vis *vis) { + vis_lua_event_call(vis, "ui_draw"); +} + #endif diff --git a/vis-lua.h b/vis-lua.h index d622ff542..b4f3f51bb 100644 --- a/vis-lua.h +++ b/vis-lua.h @@ -42,5 +42,6 @@ void vis_lua_win_highlight(Vis*, Win*); void vis_lua_win_status(Vis*, Win*); void vis_lua_term_csi(Vis*, const long *); void vis_lua_process_response(Vis *, const char *, char *, size_t, ResponseType); +void vis_lua_ui_draw(Vis*); #endif diff --git a/vis.c b/vis.c index e28740539..0c05558a1 100644 --- a/vis.c +++ b/vis.c @@ -105,6 +105,10 @@ bool vis_event_emit(Vis *vis, enum VisEvents id, ...) { if (vis->event->term_csi) vis->event->term_csi(vis, va_arg(ap, const long *)); break; + case VIS_EVENT_UI_DRAW: + if (vis->event->ui_draw) + vis->event->ui_draw(vis); + break; } va_end(ap); diff --git a/vis.h b/vis.h index b67d3c5e0..8287a45a5 100644 --- a/vis.h +++ b/vis.h @@ -58,6 +58,7 @@ typedef struct { void (*win_highlight)(Vis*, Win*); void (*win_status)(Vis*, Win*); void (*term_csi)(Vis*, const long *); + void (*ui_draw)(Vis*); } VisEvent; /** Union used to pass arguments to key action functions. */ From 1d37e5c8930c7542855da0a864c02ee4fd88c092 Mon Sep 17 00:00:00 2001 From: Rudy Dellomas III <dther@dther.xyz> Date: Wed, 24 Apr 2024 19:12:28 +1000 Subject: [PATCH 3/3] lua: Serve viewport dimensions in viewport table These values are useful for calculating terminal positions. --- vis-lua.c | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) diff --git a/vis-lua.c b/vis-lua.c index 91ee42894..a62daf898 100644 --- a/vis-lua.c +++ b/vis-lua.c @@ -1833,8 +1833,10 @@ static const struct luaL_Reg registers_funcs[] = { * Viewport currently being displayed. * Changing these values will not move the viewport. * @table viewport - * @tfield Range bytes - * @tfield Range lines + * @tfield Range bytes file bytes, from 0, at the start and end of the viewport + * @tfield Range lines file lines, from 1, at the top and bottom of the viewport + * @tfield int height lines in viewport, accounting for window decoration + * @tfield int width columns in viewport, accounting for window decoration */ /*** * The window width. @@ -1875,13 +1877,19 @@ static int window_index(lua_State *L) { l.start = view_lines_first(win->view)->lineno; l.end = view_lines_last(win->view)->lineno; - lua_createtable(L, 0, 2); + lua_createtable(L, 0, 4); lua_pushstring(L, "bytes"); pushrange(L, &b); lua_settable(L, -3); lua_pushstring(L, "lines"); pushrange(L, &l); lua_settable(L, -3); + lua_pushstring(L, "width"); + lua_pushunsigned(L, view_width_get(win->view)); + lua_settable(L, -3); + lua_pushstring(L, "height"); + lua_pushunsigned(L, view_height_get(win->view)); + lua_settable(L, -3); return 1; }