From 66360675cf4d091b7460e4a8e1435c13216c1929 Mon Sep 17 00:00:00 2001 From: dundargoc Date: Sun, 11 Sep 2022 17:12:44 +0200 Subject: build: allow IWYU to fix includes for all .c files Allow Include What You Use to remove unnecessary includes and only include what is necessary. This helps with reducing compilation times and makes it easier to visualise which dependencies are actually required. Work on https://github.com/neovim/neovim/issues/549, but doesn't close it since this only works fully for .c files and not headers. --- src/nvim/ui_client.c | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) (limited to 'src/nvim/ui_client.c') diff --git a/src/nvim/ui_client.c b/src/nvim/ui_client.c index 265c54f72d..27c63433a7 100644 --- a/src/nvim/ui_client.c +++ b/src/nvim/ui_client.c @@ -1,26 +1,28 @@ // This is an open source non-commercial project. Dear PVS-Studio, please check // it. PVS-Studio Static Code Analyzer for C, C++ and C#: http://www.viva64.com -#include #include #include +#include -#include "nvim/api/private/dispatch.h" #include "nvim/api/private/helpers.h" +#include "nvim/event/loop.h" +#include "nvim/event/multiqueue.h" +#include "nvim/globals.h" #include "nvim/highlight.h" #include "nvim/log.h" -#include "nvim/map.h" +#include "nvim/main.h" +#include "nvim/memory.h" #include "nvim/msgpack_rpc/channel.h" -#include "nvim/screen.h" #include "nvim/ui.h" #include "nvim/ui_client.h" -#include "nvim/vim.h" +// uncrustify:off #ifdef INCLUDE_GENERATED_DECLARATIONS # include "ui_client.c.generated.h" - # include "ui_events_client.generated.h" #endif +// uncrustify:on void ui_client_init(uint64_t chan) { -- cgit From 24488169564c39a506c235bf6a33b8e23a8cb528 Mon Sep 17 00:00:00 2001 From: hlpr98 Date: Mon, 27 May 2019 22:04:24 +0530 Subject: feat(tui): run TUI as external process --- src/nvim/ui_client.c | 33 +++++++++++++++++++++++++++++++++ 1 file changed, 33 insertions(+) (limited to 'src/nvim/ui_client.c') diff --git a/src/nvim/ui_client.c b/src/nvim/ui_client.c index 27c63433a7..a56513f42f 100644 --- a/src/nvim/ui_client.c +++ b/src/nvim/ui_client.c @@ -9,6 +9,7 @@ #include "nvim/event/loop.h" #include "nvim/event/multiqueue.h" #include "nvim/globals.h" +#include "nvim/eval.h" #include "nvim/highlight.h" #include "nvim/log.h" #include "nvim/main.h" @@ -24,6 +25,31 @@ #endif // uncrustify:on +uint64_t ui_client_start_server(int argc, char **argv, bool pass_stdin) +{ + varnumber_T exit_status; + char **args = xmalloc(((size_t)(2 + argc)) * sizeof(char*)); + int args_idx = 0; + args[args_idx++] = xstrdup((const char*)get_vim_var_str(VV_PROGPATH)); + args[args_idx++] = xstrdup("--embed"); + for (int i = 1; i < argc; i++) { + args[args_idx++] = xstrdup(argv[i]); + } + args[args_idx++] = NULL; // last value of argv should be NULL + + Channel *channel = channel_job_start(args, CALLBACK_READER_INIT, + CALLBACK_READER_INIT, CALLBACK_NONE, + false, true, true, false, kChannelStdinPipe, + NULL, 0, 0, NULL, &exit_status); + if (pass_stdin && !stdin_isatty) { + close(0); + dup(2); + } + + ui_client_init(channel->id); + return channel->id;; +} + void ui_client_init(uint64_t chan) { Array args = ARRAY_DICT_INIT; @@ -35,6 +61,13 @@ void ui_client_init(uint64_t chan) PUT(opts, "ext_linegrid", BOOLEAN_OBJ(true)); PUT(opts, "ext_termcolors", BOOLEAN_OBJ(true)); + // TODO: PUT(opts, "term_name", STRING_OBJ(cstr_as_string(termname_local))); + PUT(opts, "term_colors", INTEGER_OBJ(t_colors)); + if (!is_remote_client) { + PUT(opts, "term_ttyin", INTEGER_OBJ(stdin_isatty)); + PUT(opts, "term_ttyout", INTEGER_OBJ(stdout_isatty)); + } + ADD(args, INTEGER_OBJ((int)width)); ADD(args, INTEGER_OBJ((int)height)); ADD(args, DICTIONARY_OBJ(opts)); -- cgit From 43e8ec92de9e0850e7d202cb7ff9051bc408447e Mon Sep 17 00:00:00 2001 From: bfredl Date: Mon, 2 May 2022 21:10:01 +0200 Subject: fix(tui): more work in the TUI --- src/nvim/ui_client.c | 98 +++++++++++++++++++++++++++------------------------- 1 file changed, 50 insertions(+), 48 deletions(-) (limited to 'src/nvim/ui_client.c') diff --git a/src/nvim/ui_client.c b/src/nvim/ui_client.c index a56513f42f..6fc3a05e96 100644 --- a/src/nvim/ui_client.c +++ b/src/nvim/ui_client.c @@ -6,10 +6,10 @@ #include #include "nvim/api/private/helpers.h" +#include "nvim/eval.h" #include "nvim/event/loop.h" #include "nvim/event/multiqueue.h" #include "nvim/globals.h" -#include "nvim/eval.h" #include "nvim/highlight.h" #include "nvim/log.h" #include "nvim/main.h" @@ -25,55 +25,71 @@ #endif // uncrustify:on -uint64_t ui_client_start_server(int argc, char **argv, bool pass_stdin) +uint64_t ui_client_start_server(int argc, char **argv) { - varnumber_T exit_status; - char **args = xmalloc(((size_t)(2 + argc)) * sizeof(char*)); - int args_idx = 0; - args[args_idx++] = xstrdup((const char*)get_vim_var_str(VV_PROGPATH)); - args[args_idx++] = xstrdup("--embed"); - for (int i = 1; i < argc; i++) { - args[args_idx++] = xstrdup(argv[i]); - } - args[args_idx++] = NULL; // last value of argv should be NULL - - Channel *channel = channel_job_start(args, CALLBACK_READER_INIT, - CALLBACK_READER_INIT, CALLBACK_NONE, - false, true, true, false, kChannelStdinPipe, - NULL, 0, 0, NULL, &exit_status); - if (pass_stdin && !stdin_isatty) { - close(0); - dup(2); - } + varnumber_T exit_status; + char **args = xmalloc(((size_t)(2 + argc)) * sizeof(char *)); + int args_idx = 0; + args[args_idx++] = xstrdup((const char *)get_vim_var_str(VV_PROGPATH)); + args[args_idx++] = xstrdup("--embed"); + for (int i = 1; i < argc; i++) { + args[args_idx++] = xstrdup(argv[i]); + } + args[args_idx++] = NULL; + + Channel *channel = channel_job_start(args, CALLBACK_READER_INIT, + CALLBACK_READER_INIT, CALLBACK_NONE, + false, true, true, false, kChannelStdinPipe, + NULL, 0, 0, NULL, &exit_status); + if (ui_client_forward_stdin) { + close(0); + dup(2); + } - ui_client_init(channel->id); - return channel->id;; + return channel->id; } -void ui_client_init(uint64_t chan) +void ui_client_run(bool remote_ui) + FUNC_ATTR_NORETURN { + ui_builtin_start(); + + loop_poll_events(&main_loop, 1); + Array args = ARRAY_DICT_INIT; - int width = Columns; - int height = Rows; Dictionary opts = ARRAY_DICT_INIT; PUT(opts, "rgb", BOOLEAN_OBJ(true)); PUT(opts, "ext_linegrid", BOOLEAN_OBJ(true)); PUT(opts, "ext_termcolors", BOOLEAN_OBJ(true)); - // TODO: PUT(opts, "term_name", STRING_OBJ(cstr_as_string(termname_local))); + if (ui_client_termname) { + PUT(opts, "term_name", STRING_OBJ(cstr_as_string(ui_client_termname))); + } + if (ui_client_bg_respose != kNone) { + bool is_dark = (ui_client_bg_respose == kTrue); + PUT(opts, "term_background", STRING_OBJ(cstr_as_string(is_dark ? "dark" : "light"))); + } PUT(opts, "term_colors", INTEGER_OBJ(t_colors)); - if (!is_remote_client) { - PUT(opts, "term_ttyin", INTEGER_OBJ(stdin_isatty)); - PUT(opts, "term_ttyout", INTEGER_OBJ(stdout_isatty)); + if (!remote_ui) { + PUT(opts, "stdin_tty", BOOLEAN_OBJ(stdin_isatty)); + PUT(opts, "stdout_tty", BOOLEAN_OBJ(stdout_isatty)); + if (ui_client_forward_stdin) { + PUT(opts, "stdin_fd", INTEGER_OBJ(UI_CLIENT_STDIN_FD)); + } } - ADD(args, INTEGER_OBJ((int)width)); - ADD(args, INTEGER_OBJ((int)height)); + ADD(args, INTEGER_OBJ(Columns)); + ADD(args, INTEGER_OBJ(Rows)); ADD(args, DICTIONARY_OBJ(opts)); - rpc_send_event(chan, "nvim_ui_attach", args); - ui_client_channel_id = chan; + rpc_send_event(ui_client_channel_id, "nvim_ui_attach", args); + ui_client_attached = true; + + // os_exit() will be invoked when the client channel detaches + while (true) { + LOOP_PROCESS_EVENTS(&main_loop, resize_events, -1); + } } UIClientHandler ui_client_get_redraw_handler(const char *name, size_t name_len, Error *error) @@ -96,20 +112,6 @@ Object handle_ui_client_redraw(uint64_t channel_id, Array args, Arena *arena, Er return NIL; } -/// run the main thread in ui client mode -/// -/// This is just a stub. the full version will handle input, resizing, etc -void ui_client_execute(uint64_t chan) - FUNC_ATTR_NORETURN -{ - while (true) { - loop_poll_events(&main_loop, -1); - multiqueue_process_events(resize_events); - } - - getout(0); -} - static HlAttrs ui_client_dict2hlattrs(Dictionary d, bool rgb) { Error err = ERROR_INIT; @@ -118,7 +120,7 @@ static HlAttrs ui_client_dict2hlattrs(Dictionary d, bool rgb) // TODO(bfredl): log "err" return HLATTRS_INIT; } - return dict2hlattrs(&dict, true, NULL, &err); + return dict2hlattrs(&dict, rgb, NULL, &err); } void ui_client_event_grid_resize(Array args) -- cgit From b2295ac4ec80e141628cea33ebee81c96e168989 Mon Sep 17 00:00:00 2001 From: bfredl Date: Tue, 3 Jan 2023 15:24:41 +0100 Subject: refactor(api): do not allocate temporaries for internal events --- src/nvim/ui_client.c | 33 +++++++++++++++------------------ 1 file changed, 15 insertions(+), 18 deletions(-) (limited to 'src/nvim/ui_client.c') diff --git a/src/nvim/ui_client.c b/src/nvim/ui_client.c index 6fc3a05e96..365a76de3f 100644 --- a/src/nvim/ui_client.c +++ b/src/nvim/ui_client.c @@ -56,33 +56,30 @@ void ui_client_run(bool remote_ui) loop_poll_events(&main_loop, 1); - Array args = ARRAY_DICT_INIT; - Dictionary opts = ARRAY_DICT_INIT; - - PUT(opts, "rgb", BOOLEAN_OBJ(true)); - PUT(opts, "ext_linegrid", BOOLEAN_OBJ(true)); - PUT(opts, "ext_termcolors", BOOLEAN_OBJ(true)); - + MAXSIZE_TEMP_ARRAY(args, 3); + ADD_C(args, INTEGER_OBJ(Columns)); + ADD_C(args, INTEGER_OBJ(Rows)); + + MAXSIZE_TEMP_DICT(opts, 9); + PUT_C(opts, "rgb", BOOLEAN_OBJ(true)); + PUT_C(opts, "ext_linegrid", BOOLEAN_OBJ(true)); + PUT_C(opts, "ext_termcolors", BOOLEAN_OBJ(true)); if (ui_client_termname) { - PUT(opts, "term_name", STRING_OBJ(cstr_as_string(ui_client_termname))); + PUT_C(opts, "term_name", STRING_OBJ(cstr_as_string(ui_client_termname))); } if (ui_client_bg_respose != kNone) { bool is_dark = (ui_client_bg_respose == kTrue); - PUT(opts, "term_background", STRING_OBJ(cstr_as_string(is_dark ? "dark" : "light"))); + PUT_C(opts, "term_background", STRING_OBJ(cstr_as_string(is_dark ? "dark" : "light"))); } - PUT(opts, "term_colors", INTEGER_OBJ(t_colors)); + PUT_C(opts, "term_colors", INTEGER_OBJ(t_colors)); if (!remote_ui) { - PUT(opts, "stdin_tty", BOOLEAN_OBJ(stdin_isatty)); - PUT(opts, "stdout_tty", BOOLEAN_OBJ(stdout_isatty)); + PUT_C(opts, "stdin_tty", BOOLEAN_OBJ(stdin_isatty)); + PUT_C(opts, "stdout_tty", BOOLEAN_OBJ(stdout_isatty)); if (ui_client_forward_stdin) { - PUT(opts, "stdin_fd", INTEGER_OBJ(UI_CLIENT_STDIN_FD)); + PUT_C(opts, "stdin_fd", INTEGER_OBJ(UI_CLIENT_STDIN_FD)); } } - - ADD(args, INTEGER_OBJ(Columns)); - ADD(args, INTEGER_OBJ(Rows)); - ADD(args, DICTIONARY_OBJ(opts)); - + ADD_C(args, DICTIONARY_OBJ(opts)); rpc_send_event(ui_client_channel_id, "nvim_ui_attach", args); ui_client_attached = true; -- cgit From 47ba78f89a1f0bba8168b4408bc55a3024d5ab97 Mon Sep 17 00:00:00 2001 From: bfredl Date: Fri, 30 Dec 2022 22:17:01 +0100 Subject: refactor(ui): devirtualize the ui layer - The defined interface for the UI is only the RPC protocol. The original UI interface as an array of function pointers fill no function. - On the server, all the UI:s are all RPC channels. - ui.c is only used on the server. - The compositor is a preprocessing step for single-grid UI:s - on the client, ui_client and tui talk directly to each other - we still do module separation, as ui_client.c could form the basis of a libnvim client module later. Items for later PR:s - vim.ui_attach is still an unhappy child, reconsider based on plugin experience. - the flags in ui_events.in.h are still a mess. Can be simplified now. - UX for remote attachment needs more work. - startup for client can be simplified further (think of the millisecs we can save) --- src/nvim/ui_client.c | 41 +++++++++++++++++++++++++++++++---------- 1 file changed, 31 insertions(+), 10 deletions(-) (limited to 'src/nvim/ui_client.c') diff --git a/src/nvim/ui_client.c b/src/nvim/ui_client.c index 365a76de3f..2821054909 100644 --- a/src/nvim/ui_client.c +++ b/src/nvim/ui_client.c @@ -15,15 +15,19 @@ #include "nvim/main.h" #include "nvim/memory.h" #include "nvim/msgpack_rpc/channel.h" +#include "nvim/tui/tui.h" #include "nvim/ui.h" #include "nvim/ui_client.h" +static TUIData *tui = NULL; + // uncrustify:off #ifdef INCLUDE_GENERATED_DECLARATIONS # include "ui_client.c.generated.h" # include "ui_events_client.generated.h" #endif // uncrustify:on +// uint64_t ui_client_start_server(int argc, char **argv) { @@ -52,20 +56,20 @@ uint64_t ui_client_start_server(int argc, char **argv) void ui_client_run(bool remote_ui) FUNC_ATTR_NORETURN { - ui_builtin_start(); - - loop_poll_events(&main_loop, 1); + int width, height; + char *term; + tui = tui_start(&width, &height, &term); MAXSIZE_TEMP_ARRAY(args, 3); - ADD_C(args, INTEGER_OBJ(Columns)); - ADD_C(args, INTEGER_OBJ(Rows)); + ADD_C(args, INTEGER_OBJ(width)); + ADD_C(args, INTEGER_OBJ(height)); MAXSIZE_TEMP_DICT(opts, 9); PUT_C(opts, "rgb", BOOLEAN_OBJ(true)); PUT_C(opts, "ext_linegrid", BOOLEAN_OBJ(true)); PUT_C(opts, "ext_termcolors", BOOLEAN_OBJ(true)); - if (ui_client_termname) { - PUT_C(opts, "term_name", STRING_OBJ(cstr_as_string(ui_client_termname))); + if (term) { + PUT(opts, "term_name", STRING_OBJ(cstr_to_string(term))); } if (ui_client_bg_respose != kNone) { bool is_dark = (ui_client_bg_respose == kTrue); @@ -80,6 +84,7 @@ void ui_client_run(bool remote_ui) } } ADD_C(args, DICTIONARY_OBJ(opts)); + rpc_send_event(ui_client_channel_id, "nvim_ui_attach", args); ui_client_attached = true; @@ -89,6 +94,22 @@ void ui_client_run(bool remote_ui) } } +void ui_client_stop(void) +{ + tui_stop(tui); +} + +void ui_client_set_size(int width, int height) +{ + // The currently known size will be sent when attaching + if (ui_client_attached) { + MAXSIZE_TEMP_ARRAY(args, 2); + ADD_C(args, INTEGER_OBJ((int)width)); + ADD_C(args, INTEGER_OBJ((int)height)); + rpc_send_event(ui_client_channel_id, "nvim_ui_try_resize", args); + } +} + UIClientHandler ui_client_get_redraw_handler(const char *name, size_t name_len, Error *error) { int hash = ui_client_handler_hash(name, name_len); @@ -133,7 +154,7 @@ void ui_client_event_grid_resize(Array args) Integer grid = args.items[0].data.integer; Integer width = args.items[1].data.integer; Integer height = args.items[2].data.integer; - ui_call_grid_resize(grid, width, height); + tui_grid_resize(tui, grid, width, height); if (grid_line_buf_size < (size_t)width) { xfree(grid_line_buf_char); @@ -159,6 +180,6 @@ void ui_client_event_raw_line(GridLineEvent *g) // TODO(hlpr98): Accommodate other LineFlags when included in grid_line LineFlags lineflags = 0; - ui_call_raw_line(grid, row, startcol, endcol, clearcol, g->cur_attr, lineflags, - (const schar_T *)grid_line_buf_char, grid_line_buf_attr); + tui_raw_line(tui, grid, row, startcol, endcol, clearcol, g->cur_attr, lineflags, + (const schar_T *)grid_line_buf_char, grid_line_buf_attr); } -- cgit From 1d16bba4d8b8b648d2dabd610924bcf3051a0f29 Mon Sep 17 00:00:00 2001 From: bfredl Date: Sat, 7 Jan 2023 10:06:03 +0100 Subject: fix(embed): handle stdio in server properly Rename stdin/stdout in the server, so that RPC data won't get corrupted. This also restores the use of stderr to write directly to the terminal. --- src/nvim/ui_client.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) (limited to 'src/nvim/ui_client.c') diff --git a/src/nvim/ui_client.c b/src/nvim/ui_client.c index 2821054909..ff82fd3239 100644 --- a/src/nvim/ui_client.c +++ b/src/nvim/ui_client.c @@ -41,8 +41,11 @@ uint64_t ui_client_start_server(int argc, char **argv) } args[args_idx++] = NULL; + CallbackReader on_err = CALLBACK_READER_INIT; + on_err.fwd_err = true; + Channel *channel = channel_job_start(args, CALLBACK_READER_INIT, - CALLBACK_READER_INIT, CALLBACK_NONE, + on_err, CALLBACK_NONE, false, true, true, false, kChannelStdinPipe, NULL, 0, 0, NULL, &exit_status); if (ui_client_forward_stdin) { -- cgit